IDEA-146951 (Structural Search fails with '<' in search in pattern)
[idea/community.git] / platform / structuralsearch / testSource / com / intellij / structuralsearch / StructuralSearchTest.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.structuralsearch;
17
18 import com.intellij.openapi.fileTypes.StdFileTypes;
19 import com.intellij.psi.*;
20 import com.intellij.structuralsearch.impl.matcher.MatcherImplUtil;
21 import com.intellij.testFramework.PlatformTestUtil;
22 import org.jetbrains.annotations.NotNull;
23
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 /**
29  * @author Maxim.Mossienko
30  */
31 @SuppressWarnings({"HardCodedStringLiteral"})
32 public class StructuralSearchTest extends StructuralSearchTestCase {
33   private static final String s1 =
34     "debug(\"In action performed:\"+event);"+
35     "project = (Project)event.getDataContext().getData(DataConstants.PROJECT);" +
36     "CodeEditorManager.getInstance(project).commitAllToPsiFile();" +
37     "file = (PsiFile) event.getDataContext().getData(\"psi.File\"); " +
38     "((dialog==null)?" +
39     "  (dialog = new SearchDialog()):" +
40     "  dialog" +
41     ").show();";
42
43   private static final String s2 = "((dialog==null)? (dialog = new SearchDialog()): dialog).show();";
44   private static final String s3 = "dialog = new SearchDialog()";
45
46   private static final String s4 =
47                 " do { " +
48                 "  pattern = pattern.getNextSibling(); " +
49                 " } " +
50                 " while (pattern!=null && filterLexicalNodes(pattern));";
51
52   private static final String s5 =
53                 "{ System.out.println();" +
54                 "  while(false) { " +
55                 "    do { " +
56                 "       pattern = pattern.getNextSibling(); " +
57                 "    } " +
58                 "      while (pattern!=null && filterLexicalNodes(pattern)); " +
59                 "  } " +
60                 " do { " +
61                 "  pattern = pattern.getNextSibling(); " +
62                 " } while (pattern!=null && filterLexicalNodes(pattern));" +
63                 " { { " +
64                 "   do { " +
65                 "     pattern = pattern.getNextSibling(); " +
66                 "   } while (pattern!=null && filterLexicalNodes(pattern));" +
67                 " } }" +
68                 "}";
69
70   private static final String s6 =
71                 " do { " +
72                 "  pattern.getNextSibling(); " +
73                 " } " +
74                 " while (pattern!=null && filterLexicalNodes(pattern));";
75
76   private static final String s7 =
77                 " if (true) throw new UnsupportedPatternException(statement.toString());" +
78                 " if (true) { " +
79                 "   throw new UnsupportedPatternException(statement.toString());" +
80                 " } ";
81
82   private static final String s8 =
83                 " if (true) { " +
84                 "   throw new UnsupportedPatternException(statement.toString());" +
85                 " } ";
86
87   private static final String s9 = " if (true) throw new UnsupportedPatternException(statement.toString());";
88
89   private static final String s10 = "listener.add(new Runnable() { public void run() {} });";
90   private static final String s11 = " new XXX()";
91
92   private static final String s12 =
93                  "new Runnable() {" +
94                  "  public void run() {" +
95                  "   matchContext.getSink().matchingFinished();" +
96                  "   } " +
97                  " }";
98
99   private static final String s13 = "new Runnable() {}";
100   private static final String s14_1 = "if (true) { aaa(var); }";
101   private static final String s14_2 = "if (true) { aaa(var); bbb(var2); }\n if(1==1) { system.out.println('o'); }";
102   private static final String s15 = "'T;";
103   private static final String s16 = "if('_T) { '_T2; }";
104   private static final String s17 =
105     "token.getText().equals(token2.getText());" +
106     "token.getText().equals(token2.getText2());" +
107     "token.a.equals(token2.b);" +
108     "token.a.equals(token2.a);";
109   private static final String s18_1 = "'_T1.'_T2.equals('_T3.'_T2);";
110   private static final String s18_2 = "'_T1.'_T2().equals('_T3.'_T2());";
111   private static final String s18_3 = "'_T1.'_T2";
112   private static final String s19 = "Aaa a = (Aaa)b; Aaa c = (Bbb)d;";
113   private static final String s20 = "'_T1 'T2 = ('_T1)'_T3;";
114   private static final String s20_2 = "'_T1 '_T2 = ('_T1)'_T3;";
115   private static final String s21_1 = "'_T1:Aa* 'T2 = ('_T1)'_T3;";
116   private static final String s21_2 = "'_T1:A* 'T2 = ( '_T1:A+ )'_T3;";
117   private static final String s21_3 = "'_T1:Aa* 'T2 = ( '_T1 )'_T3;";
118
119   private static final String s22 = "Aaa a = (Aaa)b; Bbb c = (Bbb)d;";
120
121   private static final String s23 = "a[i] = 1; b[a[i]] = f(); if (a[i]==1) return b[c[i]];";
122   private static final String s24_1 = "'T['_T2:.*i.* ] = '_T3;";
123   private static final String s24_2  = "'T['_T2:.*i.* ]";
124   private static final String s25  = "class MatcherImpl {  void doMatch(int a) {} }\n" +
125                                      "class Matcher { abstract void doMatch(int a);}\n " +
126                                      "class Matcher2Impl { void doMatch(int a, int b) {} } ";
127   private static final String s26  = "class 'T:.*Impl { '_T2 '_T3('_T4 '_T5) {\n\n} } ";
128   private static final String s27 = "class A {} interface B {}";
129   private static final String s28 = "interface 'T {}";
130
131   private static final String s29 = "class A { void B(int C) {} } class D { void E(double e) {} }";
132   private static final String s30 = "class '_ { void '_('_:int '_); } ";
133
134   private static final String s31 = "class A extends B { } class D extends B { } class C extends C {}";
135   private static final String s32 = "class '_ extends B {  } ";
136
137   private static final String s33 = "class A implements B,C { } class D implements B,D { } class C2 implements C,B {}";
138   private static final String s34 = "class '_ implements B,C {  } ";
139
140   private static final String s35 = "class A { int b; double c; void d() {} int e() {} } " +
141                                     "class A2 { int b; void d() {} }";
142   private static final String s36 = "class '_ { double '_; int '_; int '_() {} void '_() {} } ";
143
144   private static final String s37 = "class A { void d() throws B,C,D {} } class A2 { void d() throws B,C {} }";
145   private static final String s38 = "class 'T { '_ '_() throws D,C {} } ";
146
147   private static final String s39 = "class A extends B { } class A2 {  }";
148   private static final String s40 = "class 'T { } ";
149
150   private static final String s41 = "class A extends B { int a = 1; } class B { int[] c= new int[2]; } " +
151                                     "class D { double e; } class E { int d; } ";
152   private static final String s42_1 = "class '_ { '_T '_T2 = '_T3; } ";
153   private static final String s42_2 = "class '_ { '_T '_T2; } ";
154
155   private static final String s43 = "interface A extends B { int B = 1; } " +
156                                     "interface D { public final static double e = 1; } " +
157                                     "interface E { final static ind d = 2; } " +
158                                     "interface F {  } ";
159   private static final String s44 = "interface '_ { '_T 'T2 = '_T3; } ";
160   private static final String s45 = "class A extends B { private static final int B = 1; } " +
161                                     "class C extends D { int B = 1; }" +
162                                     "class E { }";
163
164   private static final String s46 = "class '_ { final static private '_T 'T2 = '_T3; } ";
165   private static final String s46_2 = "class '_ { '_T 'T2 = '_T3; } ";
166
167   private static final String s47 = "class C { java.lang.String t; } class B { BufferedString t2;} class A { String p;} ";
168   private static final String s48 = "class '_ { String '_; }";
169
170   private static final String s49 = "class C { void a() throws java.lang.RuntimeException {} } class B { BufferedString t2;}";
171   private static final String s50 = "class '_ { '_ '_() throws RuntimeException; }";
172
173   private static final String s51 = "class C extends B { } class B extends A { } class E {}";
174   private static final String s52 = "class '_ extends '_ {  }";
175
176   private static final String s53 = "class C { " +
177                                     "   String a = System.getProperty(\"abcd\"); " +
178                                     "  static { String s = System.getProperty(a); }" +
179                                     "  static void b() { String s = System.getProperty(a); }" +
180                                     " }";
181   private static final String s54 = "System.getProperty('T)";
182
183   private static final String s55 = " a = b.class; ";
184   private static final String s56 = "'T.class";
185
186   private static final String s57 = "/** @author Maxim */ class C {" +
187                                     "  private int value; " +
188                                     "} " +
189                                     "class D {" +
190                                     "  /** @serializable */ private int value;" +
191                                     "private int value2; " +
192                                     "  /** @since 1.4 */ void a() {} "+
193                                     "}" +
194                                     "class F { " +
195                                     "  /** @since 1.4 */ void a() {} "+
196                                     "  /** @serializable */ private int value2; " +
197                                     "}" +
198                                     "class G { /** @param a*/ void a() {} }";
199   private static final String s57_2 = "/** @author Maxim */ class C { " +
200                                       "} " +
201                                       "class D {" +
202                                       "/** @serializable */ private int value; " +
203                                       "/** @since 1.4 */ void a() {} "+
204                                       "}" +
205                                       "class F { " +
206                                       "/** @since 1.4 */ void a() {} "+
207                                       "/** @serializable */ private int value2; " +
208                                       "}" +
209                                       "class G { /** @param a*/ void a() {} }";
210   private static final String s58 = "/** @'T '_T2 */ class '_ { }";
211   private static final String s58_2 = "class '_ { /** @serializable '_* */ '_ '_; }";
212   private static final String s58_3 = "class '_ { /** @'T 1.4 */ '_ '_() {} }";
213   private static final String s58_4 = "/** @'T '_T2 */";
214   private static final String s58_5 = "/** @'T '_T2? */";
215
216   private static final String s59 = "interface A { void B(); }";
217   private static final String s60 = "interface '_ { void '_(); }";
218
219   private static final String s61 = "{ a=b; c=d; return; } { e=f; } {}";
220   private static final String s62_1 = "{ 'T*; }";
221   private static final String s62_2 = "{ 'T+; }";
222   private static final String s62_3 = "{ 'T?; }";
223
224   private static final String s62_4 = "{ '_*; }";
225   private static final String s62_5 = "{ '_+; }";
226   private static final String s62_6 = "{ '_?; }";
227
228   private static final String s63 = " class A { A() {} } class B { public void run() {} }";
229   private static final String s63_2 = " class A { A() {} " +
230                                       "class B { public void run() {} } " +
231                                       "class D { public void run() {} } " +
232                                       "} " +
233                                       "class C {}";
234   private static final String s64 = " class 'T { public void '_T2:run () {} }";
235   private static final String s64_2 = "class '_ { class 'T { public void '_T2:run () {} } }";
236
237   private static final String s65 = " if (A instanceof B) {} else if (B instanceof C) {}";
238   private static final String s66 = " '_T instanceof '_T2:B";
239
240   private static final String s67 = " buf.append((VirtualFile)a);";
241   private static final String s68 = " (VirtualFile)'T";
242
243   private static final String s69 = " System.getProperties(); System.out.println(); java.lang.System.out.println(); some.other.System.out.println();";
244   private static final String s70 = " System.out ";
245   private static final String s70_2 = " java.lang.System.out ";
246
247   private static final String s71 = " class A { " +
248                                     "class D { D() { c(); } }" +
249                                     "void a() { c(); new MouseListenener() { void b() { c(); } } }" +
250                                     " }";
251   private static final String s72 = " c(); ";
252
253   private static final String s73 = " class A { int A; static int B=5; public abstract void a(int c); void q() { ind d=7; } }";
254   private static final String s74 = " '_Type 'Var = '_Init?; ";
255   private static final String s75 = "/** @class aClass\n @author the author */ class A {}\n" +
256                                     "/** */ class B {}\n" +
257                                     "/** @class aClass */ class C {}";
258   private static final String s76 = " /** @'_tag+ '_value+ */";
259   private static final String s76_2 = " /** @'_tag* '_value* */";
260   private static final String s76_3 = " /** @'_tag? '_value? */ class 't {}";
261
262   private static final String s77 = " new ActionListener() {} ";
263   private static final String s78 = " class 'T:.*aaa {} ";
264
265   private static final String s79 = " class A { static { int c; } void a() { int b; b=1; }} ";
266   private static final String s80 = " { '_T 'T3 = '_T2?; '_*; } ";
267
268   private static final String s81 = "class Pair<First,Second> {" +
269                                     "  <C,F> void a(B<C> b, D<F> e) throws C {" +
270                                     "    P<Q> r = (S<T>)null;"+
271                                     "    Q q = null; "+
272                                     "    if (r instanceof S<T>) {}"+
273                                     "  } " +
274                                     "} class Q { void b() {} } ";
275
276   private static final String s81_2 = "class Double<T> {} class T {} class Single<First extends A & B> {}";
277
278   private static final String s82 = "class '_<'T+> {}";
279   private static final String s82_2 = "'_Expr instanceof '_Type<'_Parameter+>";
280   private static final String s82_3 = "( '_Type<'_Parameter+> ) '_Expr";
281   private static final String s82_4 = "'_Type<'_Parameter+> 'a = '_Init?;";
282   private static final String s82_5 = "class '_ { <'_+> '_Type 'Method('_* '_*); }";
283   private static final String s82_6 = "class '_<'_+ extends 'res+> {}";
284   private static final String s82_7 = "'Type";
285
286   private static final String s83 = "/**\n" +
287                                     " * @hibernate.class\n" +
288                                     " *  table=\"CATS\"\n" +
289                                     " */\n" +
290                                     "public class Cat {\n" +
291                                     "    private Long id; // identifier\n" +
292                                     "    private Date birthdate;\n" +
293                                     "    /**\n" +
294                                     "     * @hibernate.id\n" +
295                                     "     *  generator-class=\"native\"\n" +
296                                     "     *  column=\"CAT_ID\"\n" +
297                                     "     */\n" +
298                                     "    public Long getId() {\n" +
299                                     "        return id;\n" +
300                                     "    }\n" +
301                                     "    private void setId(Long id) {\n" +
302                                     "        this.id=id;\n" +
303                                     "    }\n" +
304                                     "\n" +
305                                     "    /**\n" +
306                                     "     * @hibernate.property\n" +
307                                     "     *  column=\"BIRTH_DATE\"\n" +
308                                     "     */\n" +
309                                     "    public Date getBirthdate() {\n" +
310                                     "        return birthdate;\n" +
311                                     "    }\n" +
312                                     "    void setBirthdate(Date date) {\n" +
313                                     "        birthdate = date;\n" +
314                                     "    }\n" +
315                                     "    /**\n" +
316                                     "     * @hibernate.property\n" +
317                                     "     *  column=\"SEX\"\n" +
318                                     "     *  not-null=\"true\"\n" +
319                                     "     *  update=\"false\"\n" +
320                                     "     */\n" +
321                                     "    public char getSex() {\n" +
322                                     "        return sex;\n" +
323                                     "    }\n" +
324                                     "    void setSex(char sex) {\n" +
325                                     "        this.sex=sex;\n" +
326                                     "    }\n" +
327                                     "}";
328
329     private static final String s84 = "    /**\n" +
330                                       "     * @hibernate.property\n" +
331                                       "     *  'Property+\n" +
332                                       "     */\n";
333
334   private static final String s84_2 = "    /**\n" +
335                                       "     * @hibernate.property\n" +
336                                       "     *  update=\"fa.se\"\n" +
337                                       "     */\n";
338
339   private static final String s85 = "{ int a; a=1; a=1; return a; }";
340   private static final String s86 = "'T; 'T;";
341
342   private static final String s87 = " getSomething(\"1\"); a.call(); ";
343   private static final String s88 = " '_Instance.'Call('_*); ";
344   private static final String s88_2 = " 'Call('_*); ";
345   private static final String s88_3 = " '_Instance?.'Call('_*); ";
346   private static final String s89 = "{ a = 1; b = 2; c=3; }";
347   private static final String s90 = "{ '_T*; '_T2*; }";
348   private static final String s90_2 = " { '_T*; '_T2*; '_T3+; } ";
349   private static final String s90_3 = " { '_T+; '_T2+; '_T3+; '_T4+; } ";
350   private static final String s90_4 = " { '_T{1,3}; '_T2{2}; } ";
351   private static final String s90_5 = " { '_T{1}?; '_T2*?; '_T3+?; } ";
352   private static final String s90_6 = " { '_T{1}?; '_T2{1,2}?; '_T3+?; '_T4+?; } ";
353
354   private static final String s91 = "class a {\n" +
355                                     "  void b() {\n" +
356                                     "    int c;\n" +
357                                     "\n" +
358                                     "    c = 1;\n" +
359                                     "    b();\n" +
360                                     "    a a1;\n" +
361                                     "  }\n" +
362                                     "}";
363   private static final String s92 = "'T:a";
364   private static final String s92_2 = "'T:b";
365   private static final String s92_3 = "'T:c";
366
367   private static final String s93 = " class A {" +
368                                     "private int field;" +
369                                     "public void b() {}" +
370                                     "}";
371   private static final String s94 = " class '_ {" +
372                                     "private void b() {}" +
373                                     "}";
374   private static final String s94_2 = " class '_ {" +
375                                       "public void b() {}" +
376                                       "}";
377   private static final String s94_3 = " class '_ {" +
378                                       "protected int field;" +
379                                       "}";
380   private static final String s94_4 = " class '_ {" +
381                                       "private int field;" +
382                                       "}";
383
384   private static final String s95 = " class Clazz {" +
385                                     "private int field;" +
386                                     "private int field2;" +
387                                     "private int fiel-d2;" +
388                                     "}";
389
390   private static final String  s96 = " class '_ {" +
391                                      "private int 'T+:field.* ;" +
392                                      "}";
393
394   public void testSearchExpressions() {
395     assertFalse("subexpr match",findMatchesCount(s2,s3)==0);
396     assertEquals("search for new ",findMatchesCount(s10,s11),0);
397     assertEquals("search for anonymous classes",findMatchesCount(s12,s13),1);
398     // expr in definition initializer
399     assertEquals(
400       "expr in def initializer",
401       3,
402       findMatchesCount(s53,s54)
403     );
404
405     // a.class expression search
406     assertEquals(
407       "a.class pattern",
408       findMatchesCount(s55,s56),
409       1
410     );
411
412     String complexCode = "interface I { void b(); } interface I2 extends I {} class I3 extends I {} " +
413                          "class A implements I2 {  void b() {} } class B implements I3 { void b() {}} " +
414                          "I2 a; I3 b; a.b(); b.b(); b.b(); A c; B d; c.b(); d.b(); d.b(); ";
415
416     String exprTypePattern1 = "'t:[exprtype( I2 )].b();";
417     String exprTypePattern2 = "'t:[!exprtype( I2 )].b();";
418
419     String exprTypePattern3 = "'t:[exprtype( *I2 )].b();";
420     String exprTypePattern4 = "'t:[!exprtype( *I2 )].b();";
421
422     assertEquals(
423       "expr type condition",
424       findMatchesCount(complexCode,exprTypePattern1),
425       1
426     );
427
428     assertEquals(
429       "expr type condition 2",
430       5,
431       findMatchesCount(complexCode,exprTypePattern2)
432     );
433
434     assertEquals(
435       "expr type condition 3",
436       findMatchesCount(complexCode,exprTypePattern3),
437       2
438     );
439
440     assertEquals(
441       "expr type condition 4",
442       findMatchesCount(complexCode,exprTypePattern4),
443       4
444     );
445
446     String complexCode2 = "enum X { XXX, YYY }\n class C { static void ordinal() {} void test() { C c; c.ordinal(); c.ordinal(); X.XXX.ordinal(); } }";
447     assertEquals(
448       "expr type condition with enums",
449       findMatchesCount(complexCode2, "'t:[exprtype( *java\\.lang\\.Enum )].ordinal()"),
450       1
451     );
452
453     assertEquals(
454       "no smart detection of search target",
455       findMatchesCount("processInheritors(1,2,3,4); processInheritors(1,2,3); processInheritors(1,2,3,4,5,6);","'instance?.processInheritors('_param1{1,6});"),
456       3
457     );
458
459     String arrays = "int[] a = new int[20];\n" +
460                     "byte[] b = new byte[30]";
461     String arrayPattern = "new int[$a$]";
462     assertEquals(
463       "Improper array search",
464       1,
465       findMatchesCount(arrays,arrayPattern)
466     );
467
468     String someCode = "a *= 2; a+=2;";
469     String otherCode = "a *= 2;";
470
471     assertEquals(
472       "Improper *= 2 search",
473       1,
474       findMatchesCount(someCode,otherCode)
475     );
476
477     String s1 = "Thread t = new Thread(\"my thread\",\"my another thread\") {\n" +
478                 "    public void run() {\n" +
479                 "        // do stuff\n" +
480                 "    }\n" +
481                 "}";
482     String s2 = "new Thread('args*) { '_Other* }";
483
484     assertEquals(
485       "Find inner class parameters",
486       2,
487       findMatchesCount(s1,s2)
488     );
489
490     String s3 = "Thread t = new Thread(\"my thread\") {\n" +
491                 "    public void run() {\n" +
492                 "        // do stuff\n" +
493                 "    }\n" +
494                 "};";
495     String s4 = "new Thread($args$)";
496
497     assertEquals(
498       "Find inner class by new",
499       1,
500       findMatchesCount(s3,s4)
501     );
502
503     String s5 = "class A {\n" +
504                 "public static <T> T[] copy(T[] array, Class<T> aClass) {\n" +
505                 "    int i = (int)0;\n" +
506                 "    int b = (int)0;\n" +
507                 "    return (T[])array.clone();\n" +
508                 "  }\n" +
509                 "}";
510     String s6 = "($T$[])$expr$";
511
512     assertEquals(
513       "Find cast to array",
514       1,
515       findMatchesCount(s5,s6)
516     );
517
518     String s7 = "import java.math.BigDecimal;\n" +
519                 "\n" +
520                 "public class Prorator {\n" +
521                 "        public void prorate(BigDecimal[] array) {\n" +
522                 "                // do nothing\n" +
523                 "        }\n" +
524                 "        public void prorate2(java.math.BigDecimal[] array) {\n" +
525                 "                // do nothing\n" +
526                 "        }\n" +
527                 "        public void prorate(BigDecimal bd) {\n" +
528                 "                // do nothing\n" +
529                 "        }\n" +
530                 "\n" +
531                 "        public static void main(String[] args) {\n" +
532                 "                BigDecimal[] something = new BigDecimal[2];\n" +
533                 "                java.math.BigDecimal[] something2 = new BigDecimal[2];\n" +
534                 "                something[0] = new BigDecimal(1.0);\n" +
535                 "                something[1] = new BigDecimal(1.0);\n" +
536                 "\n" +
537                 "                Prorator prorator = new Prorator();\n" +
538                 "\n" +
539                 "// ---------------------------------------------------\n" +
540                 "// the line below should've been found, in my opinion.\n" +
541                 "// --------------------------------------------------\n" +
542                 "                prorator.prorate(something);\n" +
543                 "                prorator.prorate(something2);\n" +
544
545                 "                prorator.prorate(something[0]);\n" +
546                 "                prorator.prorate(something[1]);\n" +
547                 "                prorator.prorate(something[0]);\n" +
548                 "        }\n" +
549                 "}";
550     String s8 = "'_Instance.'_MethodCall:[regex( prorate )]('_Param:[exprtype( BigDecimal\\[\\] )]) ";
551
552     assertEquals(
553       "Find method call with array for parameter expr type",
554       2,
555       findMatchesCount(s7,s8,true)
556     );
557
558     String s13 = "try { } catch(Exception e) { e.printStackTrace(); }";
559     String s14 = "'_Instance.'_MethodCall('_Parameter*)";
560
561     assertEquals(
562       "Find statement in catch",
563       1,
564       findMatchesCount(s13,s14)
565     );
566
567     String s9 = "int a[] = new int[] { 1,2,3,4};\n" +
568                 "int b[] = { 2,3,4,5 };\n" +
569                 "Object[] c = new Object[] { \"\", null};\n" +
570                 "Object[] d = {null, null};\n" +
571                 "Object[] e = {};\n" +
572                 "Object[] f = new Object[]{}\n" +
573                 "String[] g = new String[]{}\n" +
574                 "String[] h = new String[]{new String()}";
575
576     assertEquals("Find new array expressions, but no array initializer expressions", 5,
577                  findMatchesCount(s9, "new '_ []{ '_* }"));
578
579     assertEquals("Find new int array expressions, including array initializer expressions", 2,
580                  findMatchesCount(s9, "new int []{ '_* }"));
581
582     assertEquals("Find new int array expressions, including array initializer expressions using variable ", 2,
583                  findMatchesCount(s9, "new 'a?:int [] { '_* }"));
584
585     assertEquals("Find all new array expressions, including array initializers", 8,
586                  findMatchesCount(s9, "new '_? []{ '_* }"));
587
588     assertEquals("Find new Object array expressions, including array initializer expressions", 4,
589                  findMatchesCount(s9, "new Object[] { '_* }"));
590
591     assertEquals("Find only array initializer expressions", 3,
592                  findMatchesCount(s9, "new '_{0,0}[] { '_* }"));
593
594     assertEquals("Find only int array initializer expressions", 1,
595                  findMatchesCount(s9, "new '_{0,0}:int [] { '_* }"));
596
597     assertEquals("Try to find String array initializer expressions", 0,
598                  findMatchesCount(s9, "new '_{0,0}:String [] { '_* }"));
599
600     String s10 = "int time = 99;\n" +
601                  "String str = time < 0 ? \"\" : \"\";" +
602                  "String str2 = time < time ? \"\" : \"\";";
603
604     assertEquals("Find expressions mistaken for declarations by parser in block mode", 1,
605                  findMatchesCount(s10, "time < time"));
606
607     assertEquals("Find expressions mistaken for declarations by parser in block mode 2", 1,
608                  findMatchesCount(s10, "time < 0"));
609
610     assertEquals("Find expressions mistaken for declarations by parser in block mode 3", 1,
611                  findMatchesCount(s10, "time < 0 ? '_a : '_b"));
612
613     assertEquals("Find expressions mistaken for declarations by parser in block mode 4", 2,
614                  findMatchesCount(s10, "'_a < '_b"));
615   }
616
617   public void testLiteral() {
618     String s = "class A {\n" +
619                "  static String a = 1;\n" +
620                "  static String s = \"aaa\";\n" +
621                "  static String s2;\n" +
622                "}";
623     String s2 = "static String '_FieldName = '_Init?:[!regex( \".*\" )];";
624     String s2_2 = "static String '_FieldName = '_Init:[!regex( \".*\" )];";
625
626     assertEquals(
627       "Literal",
628       2,
629       findMatchesCount(s,s2)
630     );
631
632     assertEquals(
633       "Literal, 2",
634       1,
635       findMatchesCount(s,s2_2)
636     );
637
638     String pattern3 = "\"'String\"";
639     assertEquals("String literal", 1, findMatchesCount(s, pattern3));
640
641     String pattern4 = "\"test\"";
642     String source = "@SuppressWarnings(\"test\") class A {" +
643                     "  @SuppressWarnings({\"other\", \"test\"}) String field;" +
644                     "}";
645     assertEquals("String literal in annotation", 2, findMatchesCount(source, pattern4));
646   }
647
648   public void testCovariantArraySearch() {
649     String s1 = "String[] argv;";
650     String s2 = "String argv;";
651     String s3 = "'T[] argv;";
652     String s3_2 = "'T:*Object [] argv;";
653
654     assertEquals(
655       "Find array types",
656       0,
657       findMatchesCount(s1,s2)
658     );
659
660     assertEquals(
661       "Find array types, 2",
662       0,
663       findMatchesCount(s2,s1)
664     );
665
666     assertEquals(
667       "Find array types, 3",
668       0,
669       findMatchesCount(s2,s3)
670     );
671
672     assertEquals(
673       "Find array types, 3",
674       1,
675       findMatchesCount(s1,s3_2)
676     );
677
678     String s11 = "class A {\n" +
679                  "  void main(String[] argv);" +
680                  "  void main(String argv[]);" +
681                  "  void main(String argv);" +
682                  "}";
683     String s12 = "'_t:[regex( *Object\\[\\] ) ] '_t2";
684     String s12_2 = "'_t:[regex( *Object ) ] '_t2 []";
685     String s12_3 = "'_t:[regex( *Object ) ] '_t2";
686
687     assertEquals(
688       "Find array covariant types",
689       2,
690       findMatchesCount(s11,s12)
691     );
692
693     assertEquals(
694       "Find array covariant types, 2",
695       2,
696       findMatchesCount(s11,s12_2)
697     );
698
699     assertEquals(
700       "Find array covariant types, 3",
701       1,
702       findMatchesCount(s11,s12_3)
703     );
704   }
705
706   public void testFindArrayDeclarations() {
707     String source = "class A {" +
708                     "  String ss[][];" +
709                     "  int f()[] {" +
710                     "    return null;" +
711                     "  }" +
712                     "}";
713
714     String target = "String[][] $s$;";
715     assertEquals("should find multi-dimensional c-style array declarations", 1, findMatchesCount(source, target));
716
717     String target2 = "class '_A { int[] 'f(); }";
718     assertEquals("should find c-style method return type declarations", 1, findMatchesCount(source, target2));
719
720     String target3 = "class '_A { int 'f(); }";
721     assertEquals("should not find methods with array return types",0, findMatchesCount(source, target3));
722
723     String source2 = "class A {" +
724                      "  void y(int... i) {}" +
725                      "  void y(String... ss) {}" +
726                      "  void y(boolean b) {}" +
727                      "}";
728     assertEquals("find ellipsis type 1", 1, findMatchesCount(source2, "String[] '_a"));
729     assertEquals("find ellipsis type 2", 1, findMatchesCount(source2, "int[] '_a"));
730     assertEquals("find ellipsis type 3", 1, findMatchesCount(source2, "class '_X { void '_m(int... '_a); }"));
731     assertEquals("find ellipsis type 4", 2, findMatchesCount(source2, "'_T[] '_a"));
732
733     String source3 = "class A {" +
734                      "  private int[] is;" +
735                      "}";
736     assertEquals("find primitive array 1", 1, findMatchesCount(source3, "int[] '_a;"));
737     assertEquals("find primitive array 2", 1, findMatchesCount(source3, "'_T[] '_a;"));
738     assertEquals("find primitive array 3", 1, findMatchesCount(source3, "'_T:[regex( int )][] '_a;"));
739     assertEquals("find primitive array 4", 1, findMatchesCount(source3, "'_T:[regex( int\\[\\] )] '_a;"));
740   }
741
742   // @todo support back references (\1 in another reg exp or as fild member)
743   //private static final String s1002 = " setSSS( instance.getSSS() ); " +
744   //                                    " setSSS( instance.SSS ); ";
745   //private static final String s1003 = " 't:set(.+) ( '_.get't_1() ); ";
746   //private static final String s1003_2 = " 't:set(.+) ( '_.'t_1 ); ";
747
748   public void testSearchStatements() {
749     assertEquals("statement search",findMatchesCount(s1,s2),1);
750     assertEquals("several constructions match",findMatchesCount(s5,s4),3);
751     assertFalse("several constructions 2",(findMatchesCount(s5,s6))!=0);
752
753     assertEquals("several constructions 3",findMatchesCount(s7,s8),2);
754     assertEquals("several constructions 4",findMatchesCount(s7,s9),2);
755
756     final String s1000 = "{ lastTest = \"search for parameterized pattern\";\n" +
757                          "      matches = testMatcher.findMatches(s14_1,s15, options);\n" +
758                          "      if (matches.size()!=2 ) return false;\n" +
759                          "lastTest = \"search for parameterized pattern\";\n" +
760                          "      matches = testMatcher.findMatches(s14_1,s15, options);\n" +
761                          "      if (matches.size()!=2 ) return false; }";
762     final String s1001 = "lastTest = '_Descr; " +
763                          "      matches = testMatcher.findMatches('_In,'_Pattern, options);\n" +
764                          "      if (matches.size()!='_Number ) return false;";
765
766     assertEquals("several operators 5",findMatchesCount(s1000,s1001),2);
767
768     assertEquals(
769       "two the same statements search",
770       findMatchesCount(s85,s86),
771       1
772     );
773
774     assertEquals(
775       "search for simple call",
776       findMatchesCount(s87,s88),
777       1
778     );
779
780     assertEquals(
781       "search for simple call 2",
782       findMatchesCount(s87,s88_2),
783       1
784     );
785
786     assertEquals(
787       "search for simple call 3",
788       findMatchesCount(s87,s88_3),
789       2
790     );
791
792     String s10015 = "DocumentListener[] listeners = getCachedListeners();";
793     String s10016 = "'_Type 'Var = '_Call();";
794
795     assertEquals(
796       "search for definition with init",
797       1,
798       findMatchesCount(s10015,s10016)
799     );
800
801     String s10017 = "a = b; b = c; a=a; c=c;";
802     String s10018 = "'_a = '_a;";
803
804     assertEquals(
805       "search silly assignments",
806       2,
807       findMatchesCount(s10017,s10018)
808     );
809
810     String s10019 = "a.b(); a.b(null); a.b(null, 1);";
811     String s10020 = "a.b(null);";
812
813     assertEquals(
814       "search parameter",
815       1,
816       findMatchesCount(s10019,s10020)
817     );
818
819     String s1008 = "int a, b, c, d; int a,b,c; int c,d; int e;";
820     String s1009 = "int '_a{3,4};";
821
822     assertEquals(
823       "search many declarations",
824       2,
825       findMatchesCount(s1008,s1009)
826     );
827
828     String s1 = "super(1,1);  call(1,1); call(2,2);";
829     String s2 = "super('_t*);";
830
831     assertEquals(
832       "search super",
833       1,
834       findMatchesCount(s1,s2)
835     );
836
837     String s10021 = "short a = 1;\n" +
838                     "short b = 2;\n" +
839                     "short c = a.b();";
840     String s10022 = "short '_a = '_b.b();";
841
842     assertEquals(
843       "search def init bug",
844       1,
845       findMatchesCount(s10021,s10022)
846     );
847
848     String s10023 = "abstract class A { public abstract short getType(); }\n" +
849                     "A a;\n" +
850                     "switch(a.getType()) {\n" +
851                     "  default:\n" +
852                     "  return 0;\n" +
853                     "}\n" +
854                     "switch(a.getType()) {\n" +
855                     "  case 1:\n" +
856                     "  { return 0; }\n" +
857                     "}";
858     String s10024 = "switch('_a:[exprtype( short )]) { '_statement*; }";
859     assertEquals(
860       "finding switch",
861       2,
862       findMatchesCount(s10023,s10024)
863     );
864
865     String s10025 = "A[] a;\n" +
866                     "A b[];\n" +
867                     "A c;";
868     String s10026 = "A[] 'a;";
869     String s10026_2 = "A 'a[];";
870
871     assertEquals(
872       "array types in dcl",
873       2,
874       findMatchesCount(s10025,s10026)
875     );
876
877     assertEquals(
878       "array types in dcl 2",
879       2,
880       findMatchesCount(s10025,s10026_2)
881     );
882
883     String s10027 = "try { a(); } catch(Exception ex) {}\n" +
884                     "try { a(); } finally {}\n" +
885                     "try { a(); } catch(Exception ex) {} finally {} \n";
886     String s10028 = "try { a(); } finally {}\n";
887     assertEquals(
888       "finally matching",
889       2,
890       findMatchesCount(s10027,s10028)
891     );
892
893     String s10029 = "for(String a:b) { System.out.println(a); }";
894     String s10030 = "for(String a:b) { '_a; }";
895     assertEquals(
896       "for each matching",
897       1,
898       findMatchesCount(s10029,s10030)
899     );
900
901     String s10031 = "try { a(); } catch(Exception ex) {} catch(Error error) { 1=1; }\n" +
902                     "try { a(); } catch(Exception ex) {}";
903     String s10032 = "try { a(); } catch('_Type+ 'Arg+) { '_Statements*; }\n";
904     assertEquals(
905       "finally matching",
906       2,
907       findMatchesCount(s10031,s10032)
908     );
909
910     String s10033 = "return x;\n" +
911                     "return !x;\n" +
912                     "return (x);\n" +
913                     "return (x);\n" +
914                     "return !(x);";
915     String s10034 = "return ('a);";
916     assertEquals("Find statement with parenthesized expr",2,findMatchesCount(s10033,s10034));
917
918     String in = "if (true) {" +
919                 "  System.out.println();" +
920                 "} else {" +
921                 "  System.out.println();" +
922                 "}" +
923                 "if (true) System.out.println();";
924     String pattern1 = "if ('_exp) { '_statement*; }";
925     assertEquals("Find if statement with else", 2, findMatchesCount(in, pattern1));
926
927     String pattern2 = "if ('_exp) { '_statement*; } else { '_statement2{0,0}; }";
928     assertEquals("Find if statement without else", 1, findMatchesCount(in, pattern2));
929   }
930
931   public void testSearchClass() {
932     // no modifier list in interface vars
933     assertEquals(
934       "no modifier for interface vars",
935       findMatchesCount(s43,s44),
936       3
937     );
938
939     // different order of access modifiers
940     assertEquals(
941       "different order of access modifiers",
942       findMatchesCount(s45,s46),
943       1
944     );
945
946     // no access modifiers
947     assertEquals(
948       "no access modifier",
949       findMatchesCount(s45,s46_2),
950       2
951     );
952
953     // type could differ with package
954     assertEquals(
955       "type differs with package",
956       findMatchesCount(s47,s48),
957       2
958     );
959
960     // reference element could differ in package
961     assertEquals(
962       "reference could differ in package",
963       findMatchesCount(s49,s50),
964       1
965     );
966
967     String s51 = "class C extends java.awt.List {} class A extends java.util.List {} class B extends java.awt.List {} ";
968     String s52 = "class 'B extends '_C:java\\.awt\\.List {}";
969
970     assertEquals(
971       "reference could differ in package 2",
972       findMatchesCount(s51,s52),
973       2
974     );
975
976     assertEquals(
977       "method access modifier",
978       findMatchesCount(s93,s94),
979       0
980     );
981
982     assertEquals(
983       "method access modifier 2",
984       findMatchesCount(s93,s94_2),
985       1
986     );
987
988     assertEquals(
989       "field access modifier",
990       findMatchesCount(s93,s94_3),
991       0
992     );
993
994     assertEquals(
995       "field access modifier 2",
996       findMatchesCount(s93,s94_4),
997       1
998     );
999
1000     final String s127 = "class a { void b() { new c() {}; } }";
1001       final String s128 = "class 't {}";
1002     assertEquals(
1003       "class finds anonymous class",
1004       findMatchesCount(s127,s128),
1005       2
1006     );
1007
1008     final String s129 = "class a { public void run() {} }\n" +
1009                         "class a2 { public void run() { run(); } }\n" +
1010                         "class a3 { public void run() { run(); } }\n" +
1011                         "class a4 { public void run(); }";
1012
1013     final String s130 = "class 'a { public void run() {} }";
1014     final String s130_2 = "class 'a { public void run() { '_statement; } }";
1015     final String s130_3 = "class 'a { public void run(); }";
1016
1017     assertEquals(
1018       "empty method finds empty method only",
1019       findMatchesCount(s129,s130),
1020       1
1021     );
1022
1023     assertEquals(
1024       "nonempty method finds nonempty method",
1025       findMatchesCount(s129,s130_2),
1026       2
1027     );
1028
1029     assertEquals(
1030       "nonempty method finds nonempty method",
1031       findMatchesCount(s129,s130_3),
1032       4
1033     );
1034
1035     final String s133 = "class S {\n" +
1036                         "void cc() {\n" +
1037                         "        new Runnable() {\n" +
1038                         "            public void run() {\n" +
1039                         "                f();\n" +
1040                         "            }\n" +
1041                         "            private void f() {\n" +
1042                         "                //To change body of created methods use File | Settings | File Templates.\n" +
1043                         "            }\n" +
1044                         "        };\n" +
1045                         "        new Runnable() {\n" +
1046                         "            public void run() {\n" +
1047                         "                f();\n" +
1048                         "            }\n" +
1049                         "            private void g() {\n" +
1050                         "                //To change body of created methods use File | Settings | File Templates.\n" +
1051                         "            }\n" +
1052                         "        };\n" +
1053                         "        new Runnable() {\n" +
1054                         "            public void run() {\n" +
1055                         "                f();\n" +
1056                         "            }\n" +
1057                         "        };\n" +
1058                         "    }\n" +
1059                         "    private void f() {\n" +
1060                         "        //To change body of created methods use File | Settings | File Templates.\n" +
1061                         "    }\n" +
1062                         "} ";
1063     final String s134 = "new Runnable() {\n" +
1064                         "            public void run() {\n" +
1065                         "                '_f ();\n" +
1066                         "            }\n" +
1067                         "            private void '_f ();\n" +
1068                         "        }";
1069     assertEquals(
1070       "complex expr matching",
1071       1,
1072       findMatchesCount(s133,s134)
1073     );
1074
1075     final String s135 = "abstract class My {\n" +
1076                         "    abstract void f();\n" +
1077                         "}\n" +
1078                         "abstract class My2 {\n" +
1079                         "    abstract void f();\n" +
1080                         "    void fg() {}\n" +
1081                         "}";
1082     final String s136 = "class 'm {\n" +
1083                         "    void f();\n" +
1084                         "    '_type '_method{0,0} ('_paramtype* '_paramname* );\n" +
1085                         "}";
1086     assertEquals(
1087       "reject method with 0 max occurence",
1088       findMatchesCount(s135,s136),
1089       1
1090     );
1091
1092     final String s137 = "abstract class My {\n" +
1093                         "  int a;\n" +
1094                         "}\n" +
1095                         "abstract class My2 {\n" +
1096                         "    Project b;\n" +
1097                         "}" +
1098                         "abstract class My3 {\n" +
1099                         "    Class clazz;"+
1100                         "    Project b = null;\n" +
1101                         "}" +
1102                         "abstract class My {\n" +
1103                         "  int a = 1;\n" +
1104                         "}\n";
1105     final String s138 = "class 'm {\n" +
1106                         "    Project '_f{0,0} = '_t?;\n" +
1107                         "}";
1108     assertEquals(
1109       "reject field with 0 max occurence",
1110       findMatchesCount(s137,s138),
1111       2
1112     );
1113
1114     final String s139 = "class My { boolean equals(Object o); int hashCode(); }";
1115     final String s139_2 = "class My { boolean equals(Object o); }";
1116     final String s140 = "class 'A { boolean equals(Object '_o ); int '_hashCode{0,0}:hashCode (); }";
1117
1118     assertEquals(
1119       "reject method with constraint",
1120       findMatchesCount(s139,s140),
1121       0
1122     );
1123
1124     assertEquals(
1125       "reject field with 0 max occurence",
1126       findMatchesCount(s139_2,s140),
1127       1
1128     );
1129
1130     final String s141 = "class A { static { a = 10 } }\n" +
1131                         "class B { { a = 10; } }\n" +
1132                         "class C { { a = 10; } }";
1133     final String s142 = "class '_ { static { a = 10; } } ";
1134     assertEquals(
1135       "static block search",
1136       findMatchesCount(s141,s142),
1137       1
1138     );
1139   }
1140
1141   public void testParameterlessContructorSearch() {
1142     final String s143 = "class A { A() {} };\n" +
1143                         "class B { B(int a) {} };\n" +
1144                         "class C { C() {} C(int a) {} };\n" +
1145                         "class D {}\n" +
1146                         "class E {}";
1147     final String s144 = "class '_a { '_d{0,0}:[ script( \"__context__.constructor\" ) ]('_b+ '_c+); }";
1148     assertEquals(
1149       "parameterless contructor search",
1150       3,
1151       findMatchesCount(s143,s144)
1152     );
1153   }
1154
1155   public void testCheckScriptValidation() {
1156     final String s1 = "";
1157     final String s2 = "'_b:[script( \"^^^\" )]";
1158
1159     try {
1160       final int count = findMatchesCount(s1, s2);
1161       assertFalse("Validation does not work", true);
1162     } catch (MalformedPatternException ex) {}
1163   }
1164
1165   //public void testRelationBetweenVars() {
1166   //  final String s1 = "public class Foo {\n" +
1167   //                      "    public static final Logger log = Logger.getInstance(Foo.class);\n" +
1168   //                      "    public static final Logger log2 = Logger.getInstance(Foo2.class);\n" +
1169   //                      "    public static final Logger log3 = Logger.getInstance(Foo2.class);\n" +
1170   //                      "}";
1171   //  final String s2 = "class '_a { static Logger 'log+ = Logger.getInstance('_b:[script( \"_a != _b\" )].class); }";
1172   //  assertEquals(
1173   //    "relation between vars in script",
1174   //    2,
1175   //    findMatchesCount(s1,s2)
1176   //  );
1177   //}
1178
1179   public void testExprTypeWithObject() {
1180     String s1 = "import java.util.*;\n" +
1181                 "class A {\n" +
1182                 "  void b() {\n" +
1183                 "    Map map = new HashMap();" +
1184                 "    class AppPreferences {}\n" +
1185                 "    String key = \"key\";\n" +
1186                 "    AppPreferences value = new AppPreferences();\n" +
1187                 "    map.put(key, value );\n" +
1188                 "    map.put(value, value );\n" +
1189                 "    map.put(\"key\", value );\n" +
1190                 "    map.put(\"key\", new AppPreferences());\n" +
1191                 "  }\n" +
1192                 "}";
1193     String s2 = "'_map:[exprtype( *java\\.util\\.Map )].put('_key:[ exprtype( *Object ) ], '_value:[ exprtype( *AppPreferences ) ]);";
1194
1195     assertEquals(
1196       "expr type with object",
1197       4,
1198       findMatchesCount(s1,s2,true)
1199     );
1200   }
1201
1202   public void testInterfaceImplementationsSearch() {
1203     String in = "class A implements Cloneable {\n" +
1204                 "    \n" +
1205                 "  }\n" +
1206                 "  \n" +
1207                 "  class B implements Serializable {\n" +
1208                 "    \n" +
1209                 "  }\n" +
1210                 "  \n" +
1211                 "  class C implements Cloneable,Serializable {\n" +
1212                 "    \n" +
1213                 "  }\n" +
1214                 "  class C2 implements Serializable,Cloneable {\n" +
1215                 "    \n" +
1216                 "  }\n" +
1217                 "  \n" +
1218                 "  class E extends B implements Cloneable {\n" +
1219                 "    \n" +
1220                 "  }\n" +
1221                 "  \n" +
1222                 "  class F extends A implements Serializable {\n" +
1223                 "    \n" +
1224                 "  }\n" +
1225                 "  \n" +
1226                 "  class D extends C {\n" +
1227                 "    \n" +
1228                 "  }";
1229     String what = "class 'A implements '_B:*Serializable , '_C:*Cloneable {}";
1230     assertEquals(
1231       "search interface within hierarchy",
1232       5,
1233       findMatchesCount(in, what)
1234     );
1235   }
1236
1237   public void testSearchBacktracking() {
1238     assertEquals(
1239       "backtracking greedy regexp",
1240       findMatchesCount(s89,s90),
1241       1
1242     );
1243
1244     assertEquals(
1245       "backtracking greedy regexp 2",
1246       findMatchesCount(s89,s90_2),
1247       1
1248     );
1249
1250     assertEquals(
1251       "backtracking greedy regexp 3",
1252       findMatchesCount(s89,s90_3),
1253       0
1254     );
1255
1256     assertEquals(
1257       "counted regexp (with back tracking)",
1258       findMatchesCount(s89,s90_4),
1259       1
1260     );
1261
1262     assertEquals(
1263       "nongreedy regexp (counted, with back tracking)",
1264       findMatchesCount(s89,s90_5),
1265       1
1266     );
1267
1268     assertEquals(
1269       "nongreedy regexp (counted, with back tracking) 2",
1270       findMatchesCount(s89,s90_6),
1271       0
1272     );
1273
1274     String s1000 = "class A {\n" +
1275                    "      void _() {}\n" +
1276                    "      void a(String in, String pattern) {}\n" +
1277                    "    }";
1278     String s1001 = "class '_Class { \n" +
1279                    "  '_ReturnType+ 'MethodName+ ('_ParameterType* '_Parameter* );\n" +
1280                    "}";
1281     assertEquals(
1282       "handling of no match",
1283       findMatchesCount(s1000,s1001),
1284       2
1285     );
1286   }
1287
1288   public void testSearchSymbol() {
1289     final String s131 = "a.b(); c.d = 1; ";
1290     final String s132 = "'T:b|d";
1291
1292     assertEquals(
1293       "symbol match",
1294       2,
1295       findMatchesCount(s131,s132)
1296     );
1297
1298     final String s129 = "A a = new A();";
1299     final String s130 = "'Sym:A";
1300
1301     options.setCaseSensitiveMatch(true);
1302     assertEquals(
1303       "case sensitive match",
1304       findMatchesCount(s129,s130),
1305       2
1306     );
1307
1308     final String s133 = "class C { int a; int A() { a = 1; }} void c(int a) { a = 2; }";
1309     final String s133_2 = "class C { int a() {} int A() { a(1); }}";
1310     final String s134 = "a";
1311
1312     List<MatchResult> results = findMatches(s133, s134, true, StdFileTypes.JAVA);
1313     assertEquals(
1314       "find sym finds declaration",
1315       4, results.size()
1316     );
1317
1318     assertEquals(
1319       "find sym finds declaration",
1320       2, findMatchesCount(s133_2, s134, true)
1321     );
1322     final String in = "class C {" +
1323                       "  {" +
1324                       "    int i = 0;" +
1325                       "    i += 1;" +
1326                       "    i = 3;" +
1327                       "    int j = i;" +
1328                       "    i();" +
1329                       "  }" +
1330                       "  void i() {}" +
1331                       "}";
1332     final String pattern1 = "'_:[read]";
1333     assertEquals("Find reads of symbol (including operator assignment)", 2, findMatchesCount(in, pattern1));
1334
1335     final String pattern2 = "'_:[write && regex( i )]";
1336     assertEquals("Find writes of symbol", 3, findMatchesCount(in, pattern2));
1337   }
1338
1339   public void testSearchGenerics() {
1340     assertEquals(
1341       "parameterized class match",
1342       findMatchesCount(s81,s82),
1343       2
1344     );
1345
1346     assertEquals(
1347       "parameterized instanceof match",
1348       findMatchesCount(s81,s82_2),
1349       1
1350     );
1351
1352     assertEquals(
1353       "parameterized cast match",
1354       findMatchesCount(s81,s82_3),
1355       1
1356     );
1357
1358     assertEquals(
1359       "parameterized symbol without variables matching",
1360       findMatchesCount(s81, "S<T>"),
1361       2
1362     );
1363
1364     assertEquals(
1365       "parameterized definition match",
1366       findMatchesCount(s81,s82_4),
1367       3
1368     );
1369
1370     assertEquals(
1371       "parameterized method match",
1372       findMatchesCount(s81,s82_5),
1373       1
1374     );
1375
1376     assertEquals(
1377       "parameterized constraint match",
1378       findMatchesCount(s81_2,s82_6),
1379       2
1380     );
1381
1382     assertEquals(
1383       "symbol matches parameterization",
1384       findMatchesCount(s81,s82_7),
1385       29
1386     );
1387
1388     assertEquals(
1389       "symbol matches parameterization 2",
1390       findMatchesCount(s81_2,s82_7),
1391       7
1392     );
1393
1394     String s81_3 = " class A {\n" +
1395                    "  public static <T> Collection<T> unmodifiableCollection(int c) {\n" +
1396                    "    return new d<T>(c);\n" +
1397                    "  }\n" +
1398                    "  static class d<E> implements Collection<E>, Serializable {\n" +
1399                    "    public <T> T[] toArray(T[] a)       {return c.toArray(a);}\n" +
1400                    "  }\n" +
1401                    "}";
1402     assertEquals(
1403       "typed symbol symbol",
1404       findMatchesCount(s81_3,s82_5),
1405       2
1406     );
1407
1408     String s81_4="class A<B> { \n" +
1409                  "  static <C> void c(D<E> f) throws R<S> {\n" +
1410                  "    if ( f instanceof G<H>) {\n" +
1411                  "      ((I<G<K>>)l).a();\n" +
1412                  "      throw new P<Q>();" +
1413                  "    }\n" +
1414                  "  }\n" +
1415                  "} " +
1416                  "class C {\n" +
1417                  "  void d(E f) throws Q {\n" +
1418                  "    if (g instanceof H) { a.c(); b.d(new A() {}); throw new Exception(((I)k)); }"+
1419                  "  }\n" +
1420                  "}";
1421     String s82_8 = "'T<'_Subst+>";
1422     assertEquals(
1423       "typed symbol",
1424       8,
1425       findMatchesCount(s81_4,s82_8)
1426     );
1427
1428     String s81_5 = "class A { HashMap<String, Integer> variable = new HashMap<String, Integer>(\"aaa\");}";
1429     String s82_9 = "'_Type<'_GType, '_GType2> '_instance = new '_Type<'_GType, '_GType2>('_Param);";
1430     assertEquals(
1431       "generic vars in new",
1432       findMatchesCount(s81_5,s82_9),
1433       1
1434     );
1435     assertEquals(
1436       "no exception on searching for diamond operator",
1437       findMatchesCount(s81_5, "new 'Type<>('_Param)"),
1438       0
1439     );
1440     assertEquals(
1441       "order of parameters matters",
1442       0,
1443       findMatchesCount(s81_5, "HashMap<Integer, String>")
1444     );
1445     assertEquals(
1446       "order of parameters matters 2",
1447       2,
1448       findMatchesCount(s81_5, "HashMap<String, Integer>")
1449     );
1450
1451     String source1 = "class Comparator<T> { private Comparator<String> c; private Comparator d; private Comparator e; }";
1452     String target1 = "java.util.Comparator 'a;";
1453     assertEquals(
1454       "qualified type should not match 1",
1455       0,
1456       findMatchesCount(source1, target1)
1457     );
1458
1459     String target2 = "java.util.Comparator<String> 'a;";
1460     assertEquals(
1461       "qualified type should not match 2",
1462       0,
1463       findMatchesCount(source1, target2)
1464     );
1465
1466     assertEquals(
1467       "unparameterized type query should match",
1468       3,
1469       findMatchesCount(source1, "Comparator 'a;")
1470     );
1471
1472     assertEquals(
1473       "parameterized type query should only match parameterized",
1474       1,
1475       findMatchesCount(source1, "Comparator<'_a> 'b;")
1476     );
1477
1478     assertEquals(
1479       "should find unparameterized only",
1480       2,
1481       findMatchesCount(source1, "Comparator<'_a{0,0}> 'b;")
1482     );
1483
1484     String source2 = "class A<@Q T> {}\n" +
1485                      "class B<T> {}";
1486     assertEquals(
1487       "find annotated type parameter",
1488       1,
1489       findMatchesCount(source2, "class $A$<@Q $T$> {}")
1490     );
1491
1492     // @todo typed vars constrains (super),
1493     // @todo generic method invocation
1494
1495     //String s83 = "class A {} List<A> a; List b;";
1496     //String s84 = "'a:List 'c;";
1497     //String s84_2 = "'a:List\\<'_\\> 'c;";
1498     //String s84_3 = "'a:List(?>\\<'_\\>) 'c;";
1499     //
1500     //assertEquals(
1501     //  "finding list",
1502     //  findMatchesCount(s83,s84),
1503     //  2
1504     //);
1505     //
1506     //assertEquals(
1507     //  "finding list 2",
1508     //  findMatchesCount(s83,s84_2),
1509     //  1
1510     //);
1511     //
1512     //assertEquals(
1513     //  "finding list 3",
1514     //  findMatchesCount(s83,s84_3),
1515     //  1
1516     //);
1517   }
1518
1519   public void testSearchSubstitutions() {
1520     // searching for parameterized pattern
1521     assertEquals("search for parameterized pattern",findMatchesCount(s14_1,s15),2);
1522
1523     assertEquals("search for parameterized pattern 2",findMatchesCount(s14_2,s15),5);
1524
1525     options.setRecursiveSearch(false);
1526
1527     assertEquals("search for parameterized pattern-non-recursive",findMatchesCount(s14_1,s15),1);
1528
1529     assertEquals("search for parameterized pattern 2-non-recursive",findMatchesCount(s14_2,s15),2);
1530
1531     // typed vars with arrays
1532     assertEquals("typed pattern with array 2-non-recursive",findMatchesCount(s23,s24_2),4);
1533
1534     options.setRecursiveSearch(true);
1535
1536       // searching for parameterized pattern
1537     assertEquals("search for parameterized pattern 3",findMatchesCount(s14_2,s16),1);
1538
1539     // searching for parameterized pattern in complex expr (with field selection)
1540     assertEquals("search for parameterized pattern in field selection",findMatchesCount(s17,s18_1),1);
1541
1542     // searching for parameterized pattern in complex expr (with method call)
1543     assertEquals("search for parameterized pattern with method call",findMatchesCount(s17,s18_2),1);
1544
1545     // searching for parameterized pattern in complex expr (with method call)
1546     assertEquals("search for parameterized pattern with method call ep.2",findMatchesCount(s17,s18_3),4);
1547
1548     // searching for parameterized pattern in definition with initializer
1549     assertEquals("search for same var constraint",findMatchesCount(s19,s20),1);
1550
1551     // searching for semi anonymous parameterized pattern in definition with initializer
1552     assertEquals("search for same var constraint for semi anonymous typed vars",findMatchesCount(s19,s20_2),1);
1553
1554     // support for type var constraint
1555     assertEquals("search for typed var constraint",findMatchesCount(s22,s21_1),1);
1556
1557     // noncompatible same typed var constraints
1558     try {
1559       findMatchesCount(s22,s21_2);
1560       assertFalse("search for noncompatible typed var constraint",false);
1561     } catch(MalformedPatternException e) {
1562     }
1563
1564       // compatible same typed var constraints
1565     assertEquals("search for same typed var constraint",findMatchesCount(s22,s21_3),1);
1566
1567     // typed var with instanceof
1568     assertEquals("typed instanceof",findMatchesCount(s65,s66),1);
1569
1570     assertEquals("don't throw exception on incomplete instanceof expression", findMatchesCount(s65, "'_T instanceof"), 2);
1571
1572     // typed vars with arrays
1573     assertEquals("typed pattern with array",findMatchesCount(s23,s24_1),2);
1574
1575     // typed vars with arrays
1576     assertEquals("typed pattern with array 2",findMatchesCount(s23,s24_2),6);
1577
1578     // typed vars in class name, method name, its return type, parameter type and name
1579     assertEquals("typed pattern in class name, method name, return type, parameter type and name",findMatchesCount(s25,s26),1);
1580
1581     assertEquals(
1582       "finding interface",
1583       findMatchesCount(s27,s28),
1584       1
1585     );
1586
1587     // finding anonymous type vars
1588     assertEquals(
1589       "anonymous typed vars",
1590       findMatchesCount(s29,s30),
1591       1
1592     );
1593
1594     // finding descedants
1595     assertEquals(
1596       "finding class descendants",
1597       findMatchesCount(s31,s32),
1598       2
1599     );
1600
1601     // finding interface implementation
1602     assertEquals(
1603       "interface implementation",
1604       findMatchesCount(s33,s34),
1605       2
1606     );
1607
1608     // different order of fields and methods
1609     assertEquals(
1610       "different order of fields and methods",
1611       findMatchesCount(s35,s36),
1612       1
1613     );
1614
1615     // different order of exceptions in throws
1616     assertEquals(
1617       "differend order in throws",
1618       findMatchesCount(s37,s38),
1619       1
1620     );
1621
1622     // class pattern without extends matches pattern with extends
1623     assertEquals(
1624       "match of class without extends to class with it",
1625       findMatchesCount(s39,s40),
1626       2
1627     );
1628
1629     // class pattern without extends matches pattern with extends
1630     assertEquals(
1631       "match of class without extends to class with it, ep. 2",
1632       findMatchesCount(s41,s42_1),
1633       2
1634     );
1635
1636     // class pattern without extends matches pattern with extends
1637     assertEquals(
1638       "match of class without extends to class with it, ep 3",
1639       4,
1640       findMatchesCount(s41,s42_2)
1641     );
1642
1643     assertEquals("match class with fields without initializers", 2, findMatchesCount(s41, "class '_ { '_T '_T2 = '_T3{0,0}; } "));
1644
1645     // typed reference element
1646     assertEquals(
1647       "typed reference element",
1648       findMatchesCount(s51,s52),
1649       2
1650     );
1651
1652     // empty name of type var
1653     assertEquals(
1654       "empty name for typed var",
1655       findMatchesCount(s59,s60),
1656       1
1657     );
1658
1659     // comparing method with constructor
1660     assertEquals(
1661       "comparing method with constructor",
1662       findMatchesCount(s63,s64),
1663       1
1664     );
1665
1666     // comparing method with constructor
1667     assertEquals(
1668       "finding nested class",
1669       findMatchesCount(s63_2,s64),
1670       2
1671     );
1672
1673     // comparing method with constructor
1674     assertEquals(
1675       "finded nested class by special pattern",
1676       findMatchesCount(s63_2,s64_2),
1677       1
1678     );
1679
1680     assertEquals(
1681       "* regexp for typed var",
1682       findMatchesCount(s61,s62_1),
1683       5
1684     );
1685
1686     assertEquals(
1687       "+ regexp for typed var",
1688       findMatchesCount(s61,s62_2),
1689       4
1690     );
1691
1692     assertEquals(
1693       "? regexp for typed var",
1694       findMatchesCount(s61,s62_3),
1695       2
1696     );
1697
1698     assertEquals(
1699       "cast in method parameters",
1700       findMatchesCount(s67,s68),
1701       1
1702     );
1703
1704     assertEquals(
1705       "searching for static field in static call",
1706       2,
1707       findMatchesCount(s69,s70)
1708     );
1709
1710     assertEquals(
1711       "searching for static field in static call, 2",
1712       2,
1713       findMatchesCount(s69,s70_2)
1714     );
1715
1716     assertEquals(
1717       "* regexp for anonymous typed var",
1718       findMatchesCount(s61,s62_4),
1719       3
1720     );
1721
1722     assertEquals(
1723       "+ regexp for anonymous typed var",
1724       findMatchesCount(s61,s62_5),
1725       2
1726     );
1727
1728     assertEquals(
1729       "? regexp for anonymous typed var",
1730       findMatchesCount(s61,s62_6),
1731       2
1732     );
1733
1734     assertEquals(
1735       "statement inside anonymous class",
1736       findMatchesCount(s71,s72),
1737       3
1738     );
1739
1740     assertEquals(
1741       "clever regexp match",
1742       findMatchesCount(s91,s92),
1743       2
1744     );
1745
1746     assertEquals(
1747       "clever regexp match 2",
1748       findMatchesCount(s91,s92_2),
1749       2
1750     );
1751
1752     assertEquals(
1753       "clever regexp match 3",
1754       findMatchesCount(s91,s92_3),
1755       2
1756     );
1757   }
1758
1759   public void testSearchJavaDoc() {
1760     // javadoc comment in class
1761     assertEquals(
1762       "java doc comment in class",
1763       1,
1764       findMatchesCount(s57,s58)
1765     );
1766
1767     assertEquals(
1768       "java doc comment in class in file",
1769       1,
1770       findMatchesCount(s57_2,s58,true)
1771     );
1772
1773     // javadoc comment for field
1774     assertEquals(
1775       "javadoc comment for field",
1776       2,
1777       findMatchesCount(s57, s58_2)
1778     );
1779
1780     // javadoc comment for method
1781     assertEquals(
1782       "javadoc comment for method",
1783       2,
1784       findMatchesCount(s57, s58_3)
1785     );
1786
1787     // just javadoc comment search
1788     assertEquals(
1789       "just javadoc comment search",
1790       4,
1791       findMatchesCount(s57,s58_4)
1792     );
1793
1794     assertEquals(
1795     "XDoclet metadata",
1796       2,
1797       findMatchesCount(s83,s84)
1798     );
1799
1800     assertEquals(
1801     "XDoclet metadata 2",
1802       1,
1803       findMatchesCount(s83,s84_2)
1804     );
1805
1806     assertEquals(
1807       "optional tag value match",
1808       6,
1809       findMatchesCount(s57, s58_5)
1810     );
1811
1812     assertEquals(
1813       "multiple tags match +",
1814       2,
1815       findMatchesCount(s75,s76)
1816     );
1817
1818     assertEquals(
1819       "multiple tags match *",
1820       3,
1821       findMatchesCount(s75, s76_2)
1822     );
1823
1824     assertEquals(
1825       "multiple tags match ?",
1826       3,
1827       findMatchesCount(s75, s76_3)
1828     );
1829
1830     assertEquals("no infinite loop on javadoc matching", 1, findMatchesCount(s57, "/** 'Text */ class '_ { }"));
1831   }
1832
1833   public void testNamedPatterns() {
1834     String s133 = "class String1 implements java.io.Serializable { " +
1835                   "private static final long serialVersionUID = -6849794470754667710L;" +
1836                   "private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];" +
1837                   "}" +
1838                   "class StringBuilder1 implements java.io.Serializable {" +
1839                   "    private void writeObject(java.io.ObjectOutputStream s)\n" +
1840                   "        throws java.io.IOException {\n" +
1841                   "        s.defaultWriteObject();\n" +
1842                   "    }" +
1843                   "private void readObject(java.io.ObjectInputStream s)\n" +
1844                   "        throws java.io.IOException, ClassNotFoundException {\n" +
1845                   "        s.defaultReadObject();\n" +
1846                   "    }" +
1847                   "    static final long serialVersionUID = 4383685877147921099L;" +
1848                   "}";
1849     String s134 = "class '_ implements '_:*Serializable {\n" +
1850                   "  static final long 'VersionField?:serialVersionUID = '_?;\n" +
1851                   "  private static final ObjectStreamField[] '_?:serialPersistentFields = '_?; \n" +
1852                   "  private void '_SerializationWriteHandler?:writeObject (ObjectOutputStream s) throws IOException;\n" +
1853                   "  private void '_SerializationReadHandler?:readObject (ObjectInputStream s) throws IOException, ClassNotFoundException;\n" +
1854                   "  Object '_SpecialSerializationReadHandler?:readResolve () throws ObjectStreamException;" +
1855                   "  Object '_SpecialSerializationWriteHandler?:writeReplace () throws ObjectStreamException;" +
1856                   "}";
1857
1858     assertEquals(
1859       "serialization match",
1860       findMatchesCount(s133,s134),
1861       2
1862     );
1863
1864     String s135 = "class SimpleStudentEventActionImpl extends Action { " +
1865                   "  public ActionForward execute(ActionMapping mapping,\n" +
1866                   "         ActionForm _form,\n" +
1867                   "         HttpServletRequest _request,\n" +
1868                   "         HttpServletResponse _response)" +
1869                   "  throws Exception {}" +
1870                   "} " +
1871                   "public class DoEnrollStudent extends SimpleStudentEventActionImpl { }" +
1872                   "public class DoCancelStudent extends SimpleStudentEventActionImpl { }";
1873     String s136 = "public class 'StrutsActionClass extends '_*:Action {" +
1874                   "  public ActionForward '_AnActionMethod:*execute (ActionMapping '_,\n" +
1875                   "                                 ActionForm '_,\n" +
1876                   "                                 HttpServletRequest '_,\n" +
1877                   "                                 HttpServletResponse '_);" +
1878                   "}";
1879
1880     assertEquals(
1881       "Struts actions",
1882       findMatchesCount(s135,s136),
1883       2
1884     );
1885
1886     final String s123 = "class NodeFilter {} public class MethodFilter extends NodeFilter {\n" +
1887                         "  private MethodFilter() {}\n" +
1888                         "\n" +
1889                         "  public static NodeFilter getInstance() {\n" +
1890                         "    if (instance==null) instance = new MethodFilter();\n" +
1891                         "    return instance;\n" +
1892                         "  }\n" +
1893                         "  private static NodeFilter instance;\n" +
1894                         "}";
1895     final String s124 = "class 'Class {\n" +
1896                         "  private 'Class('_* '_*) {\n" +
1897                         "   '_*;\n" +
1898                         "  }\n" +
1899                         "  private static '_Class2:* '_Instance;\n" +
1900                         "  static '_Class2 '_GetInstance() {\n" +
1901                         "    '_*;\n" +
1902                         "    return '_Instance;\n" +
1903                         "  }\n" +
1904                         "}";
1905
1906     assertEquals(
1907       "singleton search",
1908       findMatchesCount(s123,s124),
1909       1
1910     );
1911
1912     String s1111 = "if (true) { a=1; b=1; } else { a=1; }\n" +
1913                    "if(true) { a=1; } else { a=1; b=1; }\n" +
1914                    "if(true) { a=1; b=2; } else { a = 1; b=2; }";
1915     String s1112 = "if (true) { '_a{1,2}; } else { '_a; }";
1916
1917     assertEquals(
1918       "same multiple name pattern",
1919       findMatchesCount(s1111,s1112),
1920       1
1921     );
1922   }
1923
1924   public void testHierarchy() {
1925     final String s105 = "class B {} class A extends B { }";
1926     final String s106 = "class '_ extends '_:[ref('T)] {}";
1927     assertEquals(
1928       "extends match",
1929       findMatchesCount(s105,s106),
1930       1
1931     );
1932
1933     final String s107 = "interface IA {} interface IB extends IA { } interface IC extends IB {} interface ID extends IC {}" +
1934                         "class A implements IA {} class B extends A { } class C extends B implements IC {} class D extends C {}";
1935     final String s108 = "class '_ extends 'Type:+A {}";
1936     final String s108_2 = "class '_ implements 'Type:+IA {}";
1937
1938     assertEquals(
1939       "extends navigation match",
1940       findMatchesCount(s107,s108),
1941       2
1942     );
1943
1944     assertEquals(
1945       "implements navigation match",
1946       3,
1947       findMatchesCount(s107,s108_2)
1948     );
1949
1950     final String s109 = "interface I {} interface I2 extends I {} class A implements I2 {} class B extends A { } class C extends B {} class D { void e() { C c; B b; A a;} }";
1951     final String s110 = "'_:*A '_;";
1952     final String s110_2 = "'_:*I '_;";
1953     final String s110_3 = "'_:*[regex( I ) && ref('T)] '_;";
1954     final String s110_4 = "'_:*[regex( I ) && ref2('T)] '_;";
1955     assertEquals(
1956       "extends navigation match in definition",
1957       findMatchesCount(s109,s110),
1958       3
1959     );
1960
1961     assertEquals(
1962       "implements navigation match in definition 2",
1963       findMatchesCount(s109,s110_2),
1964       3
1965     );
1966
1967     assertEquals(
1968       "implements navigation match in definition 2 with nested conditions",
1969       findMatchesCount(s109,s110_3),
1970       1
1971     );
1972
1973     try {
1974       findMatchesCount(s109,s110_4);
1975       assertFalse("implements navigation match in definition 2 with nested conditions - incorrect cond",false);
1976     } catch(UnsupportedPatternException ex) {}
1977
1978     final String s111 = "interface E {} class A implements E {} class B extends A { int f = 0; } class C extends B {} class D { void e() { C c; B b; A a;} }";
1979     final String s112 = "'_";
1980     assertEquals(
1981       "symbol match",
1982       findMatchesCount(s111,s112),
1983       17
1984     );
1985
1986     final String s113 = "class B {int c; void d() {} } int a; B b; a = 1; b.d(); ++a; int c=a; System.out.println(a); " +
1987                         "b.c = 1; System.out.println(b.c); b.c++;";
1988     final String s114 = "'_:[read]";
1989     final String s114_2 = "'_:[write]";
1990     assertEquals(
1991       "read symbol match",
1992       findMatchesCount(s113,s114),
1993       11
1994     );
1995
1996     assertEquals(
1997       "write symbol match",
1998       findMatchesCount(s113,s114_2),
1999       5
2000     );
2001
2002     final String s115 = "class B {} public class C {}";
2003     final String s116 = "public class '_ {}";
2004     assertEquals(
2005       "public modifier for class",
2006       findMatchesCount(s115,s116),
2007       1
2008     );
2009
2010     final String s117 = "class A { int b; void c() { int e; b=1; this.b=1; e=5; " +
2011                         "System.out.println(e); " +
2012                         "System.out.println(b); System.out.println(this.b);} }";
2013     final String s118 = "this.'Field";
2014     final String s118_2 = "this.'Field:[read]";
2015     final String s118_3 = "this.'Field:[write]";
2016
2017     assertEquals(
2018       "fields of class",
2019       4,
2020       findMatchesCount(s117,s118)
2021     );
2022
2023     assertEquals(
2024       "fields of class read",
2025       2,
2026       findMatchesCount(s117,s118_2)
2027     );
2028
2029     assertEquals(
2030       "fields of class written",
2031       2,
2032       findMatchesCount(s117,s118_3)
2033     );
2034
2035     final String s119 = "try { a.b(); } catch(IOException e) { c(); } catch(Exception ex) { d(); }";
2036     final String s120 = "try { '_; } catch('_ '_) { '_; }";
2037     final String s120_2 = "try { '_; } catch(Throwable '_) { '_; }";
2038     assertEquals(
2039       "catches loose matching",
2040       findMatchesCount(s119,s120),
2041       1
2042     );
2043
2044     assertEquals(
2045       "catches loose matching 2",
2046       findMatchesCount(s119,s120_2),
2047       0
2048     );
2049
2050     final String s121 = "class A { private int a; class Inner {} } " +
2051                         "class B extends A { private int a; class Inner2 {} }";
2052     final String s122 = "class '_ { int '_:* ; }";
2053     final String s122_2 = "class '_ { int '_:+hashCode (); }";
2054     final String s122_3 = "class '_ { class '_:* {} }";
2055     assertEquals(
2056       "hierarchical matching",
2057       findMatchesCount(s121,s122),
2058       2
2059     );
2060
2061     assertEquals(
2062       "hierarchical matching 2",
2063       findMatchesCount(s121,s122_2),
2064       4
2065     );
2066
2067     assertEquals(
2068       "hierarchical matching 3",
2069       findMatchesCount(s121,s122_3),
2070       2
2071     );
2072   }
2073
2074   public void testSearchInCommentsAndLiterals() {
2075     String s1 = "{" +
2076                 "// This is some comment\n" +
2077                 "/* This is another\n comment*/\n" +
2078                 "// Some garbage\n"+
2079                 "/** And now third comment*/\n" +
2080                 "/** Some garbage*/ }";
2081     String s2 = "// 'Comment:[regex( .*(?:comment).* )]";
2082     String s3 = "/** 'Comment:[regex( .*(?:comment).* )] */";
2083     String s2_2 = "/* 'Comment:[regex( .*(?:comment).* )] */";
2084
2085     assertEquals(
2086       "Comment matching",
2087       findMatchesCount(s1,s2),
2088       3
2089     );
2090
2091     assertEquals(
2092       "Comment matching, 2",
2093       3,
2094       findMatchesCount(s1,s2_2)
2095     );
2096
2097     assertEquals(
2098       "Java doc matching",
2099       findMatchesCount(s1,s3),
2100       1
2101     );
2102
2103     String s4 = "\"'test\", \"another test\", \"garbage\"";
2104     String s5 = "\"'test:[regex( .*test.* )]\"";
2105     String s6 = "\"''test\"";
2106
2107     assertEquals(
2108       "Literal content",
2109       findMatchesCount(s4,s5),
2110       2
2111     );
2112
2113     assertEquals(
2114       "Literal content with escaping",
2115       findMatchesCount(s4,s6),
2116       1
2117     );
2118
2119     String s7 = "\"aaa\"";
2120     String s8 = "\"'test:[regex( aaa )]\"";
2121
2122     assertEquals(
2123       "Simple literal content",
2124       findMatchesCount(s7,s8),
2125       1
2126     );
2127
2128     String s9 = "\" aaa \" \" bbb \" \" ccc ccc aaa\"";
2129     String s10 = "\"'test:[regexw( aaa|ccc )]\"";
2130     String s11 = "\"'test:[regexw( bbb )]\"";
2131
2132     assertEquals(
2133       "Whole word literal content with alternations",
2134       findMatchesCount(s9,s10),
2135       2
2136     );
2137
2138     assertEquals(
2139       "Whole word literal content",
2140       findMatchesCount(s9,s11),
2141       1
2142     );
2143
2144     String s12 = "assert agentInfo != null : \"agentInfo is null\";\n" +
2145                  "assert addresses != null : \"addresses is null\";";
2146     String s13 = "assert $exp$ != null : \"$exp$ is null\";";
2147
2148     assertEquals(
2149       "reference to substitution in comment",
2150       findMatchesCount(s12,s13),
2151       2
2152     );
2153
2154     String s14 = "\"(some text with special chars)\"," +
2155                  "\" some\"," +
2156                  "\"(some)\"";
2157     String s15 = "\"('a:[regexw( some )])\"";
2158
2159     assertEquals(
2160       "meta char in literal",
2161       2,
2162       findMatchesCount(s14,s15)
2163     );
2164
2165     String s16 = "/**\n" +
2166                  "* Created by IntelliJ IDEA.\n" +
2167                  "* User: cdr\n" +
2168                  "* Date: Nov 15, 2005\n" +
2169                  "* Time: 4:23:29 PM\n" +
2170                  "* To change this template use File | Settings | File Templates.\n" +
2171                  "*/\n" +
2172                  "public class Y {\n" +
2173                  "}";
2174     String s17 = "/**\n" +
2175                  "* Created by IntelliJ IDEA.\n" +
2176                  "* User: '_USER\n" +
2177                  "* Date: '_DATE\n" +
2178                  "* Time: '_TIME\n" +
2179                  "* To change this template use File | Settings | File Templates.\n" +
2180                  "*/\n" +
2181                  "class 'c {\n" +
2182                  "}";
2183     assertEquals(
2184       "complete comment match",
2185       1,
2186       findMatchesCount(s16,s17,true)
2187     );
2188
2189     String s18 = "public class A {\n" +
2190                  "   private void f(int i) {\n" +
2191                  "       int g=0; //sss\n" +
2192                  "   }\n" +
2193                  "}";
2194     String s19 = "class $c$ {\n" +
2195                  "   $type$ $f$($t$ $p$){\n" +
2196                  "       $s$; // sss\n" +
2197                  "   }\n" +
2198                  "}";
2199     assertEquals(
2200       "statement match with comment",
2201       1,
2202       findMatchesCount(s18,s19)
2203     );
2204   }
2205
2206   public void testOther() {
2207     assertEquals(
2208       "optional init match in definition",
2209       findMatchesCount(s73,s74),
2210       4
2211     );
2212
2213     assertEquals(
2214       "null match",
2215       findMatchesCount(s77,s78),
2216       0
2217     );
2218
2219     assertEquals(
2220       "body of method by block search",
2221       findMatchesCount(s79,s80),
2222       2
2223     );
2224
2225
2226     assertEquals(
2227       "first matches, next not",
2228       findMatchesCount(s95,s96),
2229       2
2230     );
2231
2232     final String s97 = "class A { int c; void b() { C d; } } class C { C() { A a; a.b(); a.c=1; } }";
2233     final String s98 = "'_.'_:[ref('T)] ()";
2234     final String s98_2 = "'_.'_:[ref('T)]";
2235     final String s98_3 = "'_:[ref('T)].'_ ();";
2236     final String s98_4 = "'_:[ref('T)] '_;";
2237
2238     assertEquals(
2239       "method predicate match",
2240       findMatchesCount(s97,s98),
2241       1
2242     );
2243
2244     assertEquals(
2245       "field predicate match",
2246       findMatchesCount(s97,s98_2),
2247       1
2248     );
2249
2250     assertEquals(
2251       "dcl predicate match",
2252       findMatchesCount(s97,s98_3),
2253       1
2254     );
2255
2256     final String s99 = " char s = '\\u1111';  char s1 = '\\n'; ";
2257     final String s100 = " char 'var = '\\u1111'; ";
2258     final String s100_2 = " char 'var = '\\n'; ";
2259     assertEquals(
2260       "char constants in pattern",
2261       findMatchesCount(s99,s100),
2262       1
2263     );
2264
2265     assertEquals(
2266       "char constants in pattern 2",
2267       findMatchesCount(s99,s100_2),
2268       1
2269     );
2270
2271     assertEquals(
2272       "class predicate match (from definition)",
2273       findMatchesCount(s97,s98_4),
2274       3
2275     );
2276
2277     final String s125 = "a=1;";
2278     final String s126 = "'t:[regex(a)]";
2279
2280     try {
2281       findMatchesCount(s125,s126);
2282       assertFalse("spaces around reg exp check",false);
2283     } catch(MalformedPatternException ex) {}
2284
2285     final String s101 = "class A { void b() { String d; String e; String[] f; f.length=1; f.length=1; } }";
2286     final String s102 = "'_:[ref('T)] '_;";
2287
2288     assertEquals(
2289       "distinct match",
2290       findMatchesCount(s101,s102),
2291       1
2292     );
2293
2294     final String s103 = " a=1; ";
2295     final String s104 = "'T:{ ;";
2296     try {
2297       findMatchesCount(s103,s104);
2298       assertFalse("incorrect reg exp",false);
2299     } catch(MalformedPatternException ex) {
2300     }
2301
2302     final String s106 = "$_ReturnType$ $MethodName$($_ParameterType$ $_Parameter$);";
2303     final String s105 = " aaa; ";
2304
2305     try {
2306       findMatchesCount(s105,s106);
2307       assertFalse("incorrect reg exp 2",false);
2308     } catch(UnsupportedPatternException ex) {
2309     }
2310
2311     String s107 = "class A {\n" +
2312                   "  /* */\n" +
2313                   "  void a() {\n" +
2314                   "  }" +
2315                   "  /* */\n" +
2316                   "  int b = 1;\n" +
2317                   "  /*" +
2318                   "   *" +
2319                   "   */\n" +
2320                   "   class C {}" +
2321                   "}";
2322     String s108 = "  /*" +
2323                   "   *" +
2324                   "   */";
2325
2326     assertEquals("finding comments without typed var", 1, findMatchesCount(s107,s108));
2327
2328     String s109 = "class A { void b(); int b(int c); char d(char e); }\n" +
2329                   "A a; a.b(1); a.b(2); a.b(); a.d('e'); a.d('f'); a.d('g');";
2330     String s110 = "'_a.'_b:[exprtype( int ) ]('_c*);";
2331     assertEquals("caring about method return type", 2, findMatchesCount(s109,s110));
2332
2333     String s111 = "class A { void getManager() { getManager(); } };\n" +
2334                   "class B { void getManager() { getManager(); getManager(); } };";
2335     String s112 = "'Instance?:[exprtype( B )].getManager()";
2336     assertEquals("caring about missing qualifier type", 2, findMatchesCount(s111,s112));
2337
2338     String s112a = "'Instance?:[regex( B )].getManager()";
2339     assertEquals("static query should not match instance method", 0, findMatchesCount(s111, s112a));
2340
2341     String s112b = "B.getManager()";
2342     assertEquals("static query should not match instance method 2", 0, findMatchesCount(s111, s112b));
2343
2344     String s113 = "class A { static void a() { a(); }}\n" +
2345                   "class B { static void a() { a(); a(); }}\n";
2346     String s114 = "'_Q?:[regex( B )].a()";
2347     assertEquals("should care about implicit class qualifier", 2, findMatchesCount(s113, s114));
2348
2349     String s114a = "B.a()";
2350     assertEquals("should match simple implicit class qualifier query", 2, findMatchesCount(s113, s114a));
2351
2352     String s114b = "'_Q?:[exprtype( B )].a()";
2353     assertEquals("instance query should not match static method", 0, findMatchesCount(s113, s114b));
2354
2355     String s115 = "class A { int a; int f() { return a; }}\n" +
2356                   "class B { int a; int g() { return a + a; }}\n";
2357     String s116 = "'_Instance?:[exprtype( B )].a";
2358     assertEquals("should care about implicit instance qualifier", 2, findMatchesCount(s115, s116));
2359
2360     String s116a = "A.a";
2361     assertEquals("should not match instance method", 0, findMatchesCount(s115, s116a));
2362
2363     String s117 = "class A { static int a; static int f() { return a; }}\n" +
2364                   "class B { static int a; static int g() { return a + a; }}\n";
2365     String s118 = "'_Q?:[regex( B )].a";
2366     assertEquals("should care about implicit class qualifier for field", 2, findMatchesCount(s117, s118));
2367
2368     // b) hierarchy navigation support
2369     // c) or search support
2370
2371     // e) xml search (down-up, nested query), navigation from xml representation <-> java code
2372     // f) impl data conversion (jdk 1.5 style) <-> other from (replace support)
2373
2374     // Directions:
2375     // @todo different navigation on sub/supertyping relation (fixed depth), methods implementing interface,
2376     // g.  like predicates
2377     // i. performance
2378     // more context for top level classes, difference with interface, etc
2379
2380     // global issues:
2381     // @todo matches out of context
2382     // @todo proper regexp support
2383
2384     // @todo define strict equality of the matches
2385     // @todo search for field selection retrieves packages also
2386   }
2387
2388   public void testFQNInPatternAndVariableConstraints() {
2389     String s1 = "import java.awt.List;\n" +
2390                 "class A { List l; }";
2391     String s1_2 = "import java.util.List;\n" +
2392                   "class A { List l; }";
2393     String s2 = "class '_ { 'Type:java\\.util\\.List '_Field; }";
2394
2395     assertEquals("No matches for qualified class",findMatchesCount(s1,s2,true),0);
2396     assertEquals("Matches for qualified class",findMatchesCount(s1_2,s2,true),1);
2397
2398     String s3 = "import java.util.ArrayList;\n" +
2399                 "class A { ArrayList l; }";
2400     String s4 = "class '_ { 'Type:*java\\.util\\.Collection '_Field; }";
2401     assertEquals("Matches for qualified class in hierarchy",findMatchesCount(s3,s4,true),1);
2402
2403     String s5 = "import java.util.List;\n" +
2404                 "class A { { List l = new List(); l.add(\"1\"); }  }";
2405     String s5_2 = "import java.awt.List;\n" +
2406                   "class A { { List l = new List(); l.add(\"1\"); } }";
2407     String s6 = "'a:[exprtype( java\\.util\\.List )]";
2408     String s6_2 = "'a:[exprtype( *java\\.util\\.Collection )]";
2409     String s6_3 = "java.util.List '_a = '_b?;";
2410
2411     assertEquals("Matches for qualified expr type",findMatchesCount(s5,s6,true), 2);
2412     assertEquals("No matches for qualified expr type",findMatchesCount(s5_2,s6,true),0);
2413     assertEquals("Matches for qualified expr type in hierarchy",findMatchesCount(s5,s6_2,true), 2);
2414
2415     assertEquals("Matches for qualified var type in pattern",findMatchesCount(s5,s6_3,true),1);
2416     assertEquals("No matches for qualified var type in pattern",findMatchesCount(s5_2,s6_3,true),0);
2417
2418     String s7 = "import java.util.List;\n" +
2419                 "class A extends List { }";
2420     String s7_2 = "import java.awt.List;\n" +
2421                   "class A extends List {}";
2422
2423     String s8 = "class 'a extends java.util.List {}";
2424
2425     assertEquals("Matches for qualified type in pattern",findMatchesCount(s7,s8,true),1);
2426     assertEquals("No matches for qualified type in pattern",findMatchesCount(s7_2,s8,true),0);
2427
2428     String s9 = "String.intern(\"1\");\n" +
2429                 "java.util.Collections.sort(null);" +
2430                 "java.util.Collections.sort(null);";
2431     String s10 = "java.lang.String.'_method ( '_params* )";
2432     assertEquals("FQN in class name",1,findMatchesCount(s9,s10,false));
2433   }
2434
2435   public void testAnnotations() throws Exception {
2436     String s1 = "@MyBean(\"\")\n" +
2437                 "@MyBean2(\"\")\n" +
2438                 "public class TestBean {}\n" +
2439                 "@MyBean2(\"\")\n" +
2440                 "@MyBean(value=\"\")\n" +
2441                 "public class TestBean2 {}\n" +
2442                 "public class TestBean3 {}\n" +
2443                 "@MyBean(\"a\")\n" +
2444                 "@MyBean2(\"a\")\n" +
2445                 "public class TestBean4";
2446     String s2 = "@MyBean(\"\")\n" +
2447                 "@MyBean2(\"\")\n" +
2448                 "public class $a$ {}\n";
2449
2450     assertEquals("Simple find annotated class",2,findMatchesCount(s1,s2,false));
2451     assertEquals("Match value of anonymous name value pair 1", 1, findMatchesCount(s1, "@MyBean(\"a\") class $a$ {}"));
2452     assertEquals("Match value of anonymous name value pair 2", 2, findMatchesCount(s1, "@MyBean(\"\") class $a$ {}"));
2453
2454     String s3 = "@VisualBean(\"????????? ?????????? ? ??\")\n" +
2455                 "public class TestBean\n" +
2456                 "{\n" +
2457                 "    @VisualBeanField(\n" +
2458                 "            name = \"??? ????????????\",\n" +
2459                 "            initialValue = \"?????????????\"\n" +
2460                 "            )\n" +
2461                 "    public String user;\n" +
2462                 "\n" +
2463                 "    @VisualBeanField(\n" +
2464                 "            name = \"??????\",\n" +
2465                 "            initialValue = \"\",\n" +
2466                 "            fieldType = FieldTypeEnum.PASSWORD_FIELD\n" +
2467                 "            )\n" +
2468                 "    public String password;\n" +
2469                 "\n" +
2470                 "    @VisualBeanField(\n" +
2471                 "            initialValue = \"User\",\n" +
2472                 "            name = \"????? ???????\",\n" +
2473                 "            name = \"Second name\",\n" +
2474                 "            fieldType = FieldTypeEnum.COMBOBOX_FIELD,\n" +
2475                 "            comboValues = {\n" +
2476                 "               @ComboFieldValue(\"Administrator\"),\n" +
2477                 "               @ComboFieldValue(\"User\"),\n" +
2478                 "               @ComboFieldValue(\"Guest\")}\n" +
2479                 "            )    \n" +
2480                 "    public String accessRights;\n" +
2481                 "    \n" +
2482                 "    public String otherField;\n" +
2483                 "}";
2484     String s4 = "class '_a {\n" +
2485                 "  @'_Annotation+ ( 'AnnotationMember*:name = '_AnnotationValue* )\n" +
2486                 "  String '_field* ;\n" +
2487                 "}";
2488     String s4_2 = "class '_a {\n" +
2489                   "  @'_Annotation+ ()\n" +
2490                   "  String 'field* ;\n" +
2491                   "}";
2492
2493     assertEquals("Find annotation members of annotated field class",4,findMatchesCount(s3,s4,false));
2494     assertEquals("Find annotation fields",3,findMatchesCount(s3,s4_2,false));
2495
2496     String s5 = "class A {" +
2497                 "  @NotNull private static Collection<PsiElement> resolveElements(final PsiReference reference, final Project project) {}\n" +
2498                 "  @NotNull private static Collection resolveElements2(final PsiReference reference, final Project project) {}\n" +
2499                 "}";
2500     String s6 = "class '_c {@NotNull '_rt 'method* ('_pt* '_p*){ '_inst*; } }";
2501     String s6_2 = "class '_c {@'_:NotNull '_rt 'method* ('_pt* '_p*){ '_inst*; } }";
2502
2503     assertEquals("Find annotated methods",2,findMatchesCount(s5,s6));
2504     assertEquals("Find annotated methods, 2",2,findMatchesCount(s5,s6_2));
2505
2506     String s7 = "class A { void message(@NonNls String msg); }\n" +
2507                 "class B { void message2(String msg); }\n" +
2508                 "class C { void message2(String msg); }";
2509     String s8 = "class '_A { void 'b( @'_Ann{0,0}:NonNls String  '_); }";
2510     assertEquals("Find not annotated methods",2,findMatchesCount(s7,s8));
2511
2512     String s9 = "class A {\n" +
2513                 "  Object[] method1() {}\n" +
2514                 "  Object method1_2() {}\n" +
2515                 "  Object method1_3() {}\n" +
2516                 "  Object method1_4() {}\n" +
2517                 "  @MyAnnotation Object[] method2(int a) {}\n" +
2518                 "  @NonNls Object[] method3() {}\n" +
2519                 "}";
2520     String s10 = "class '_A { @'_Ann{0,0}:NonNls '_Type:Object\\[\\] 'b+( '_pt* '_p* ); }";
2521     String s10_2 = "class '_A { @'_Ann{0,0}:NonNls '_Type [] 'b+( '_pt* '_p* ); }";
2522     String s10_3 = "class '_A { @'_Ann{0,0}:NonNls '_Type:Object [] 'b+( '_pt* '_p* ); }";
2523     assertEquals("Find not annotated methods, 2",2,findMatchesCount(s9,s10));
2524     assertEquals("Find not annotated methods, 2",2,findMatchesCount(s9,s10_2));
2525     assertEquals("Find not annotated methods, 2",2,findMatchesCount(s9,s10_3));
2526
2527     String s11 = "class A {\n" +
2528                  "@Foo(value=baz) int a;\n" +
2529                  "@Foo(value=baz2) int a2;\n" +
2530                  "@Foo(value=baz2) int a3;\n" +
2531                  "@Foo(value2=baz3) int a3;\n" +
2532                  "@Foo(value2=baz3) int a3;\n" +
2533                  "@Foo(value2=baz3) int a3;\n" +
2534                  "@Foo(value2=baz4) int a3;\n" +
2535                  "}";
2536     String s12 = "@Foo(value=baz) int 'a;)";
2537     String s12_2 = "@Foo(value='baz:baz2 ) int '_a;)";
2538     String s12_3 = "@Foo('value:value2 = baz3 ) int '_a;)";
2539     String s12_4 = "@Foo('value:value2 = '_baz3:baz3 ) int '_a;)";
2540     String s12_5 = "@Foo('value:value2 = '_baz3:baz ) int '_a;)";
2541     String s12_6 = "@Foo('value:value2 = '_baz3 ) int '_a;)";
2542     String s12_7 = "@Foo('value:value2 = ) int '_a;";
2543
2544     assertEquals("Find anno parameter value",1,findMatchesCount(s11,s12));
2545     assertEquals("Find anno parameter value",2,findMatchesCount(s11,s12_2));
2546     assertEquals("Find anno parameter value",3,findMatchesCount(s11,s12_3));
2547     assertEquals("Find anno parameter value",3,findMatchesCount(s11,s12_4));
2548     assertEquals("Find anno parameter value",0,findMatchesCount(s11,s12_5));
2549     assertEquals("Find anno parameter value",4,findMatchesCount(s11,s12_6));
2550     assertEquals("Find anno parameter value",4,findMatchesCount(s11,s12_7));