Remove duplication
[idea/community.git] / platform / structuralsearch / testSource / com / intellij / structuralsearch / StructuralSearchTest.java
1 /*
2  * Copyright 2000-2016 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 testScriptSearch() {
1156     final String source = "package a;" +
1157                           "class BX extends java.util.List {" +
1158                           "  private static final java.util.List VALUE = new BX();" +
1159                           "}" +
1160                           "class CX extends java.util.List {" +
1161                           "  private static final String S = \"\";" +
1162                           "}";
1163     // find static final fields whose type is a proper ancestor of the class declaring their fields
1164     assertEquals("all variables accessible from script", 1,
1165                  findMatchesCount(source,
1166                                   "[script(\""                                                         +
1167                                   "import com.intellij.psi.util.InheritanceUtil\n"                     +
1168                                   "import com.intellij.psi.util.PsiTreeUtil\n"                         +
1169                                   "import com.intellij.psi.PsiClass\n"                                 +
1170                                   "init != null &&"                                                    + // redundant reference to '_init
1171                                   "InheritanceUtil.isInheritor(\n"                                     +
1172                                   "        PsiTreeUtil.getParentOfType(variable, PsiClass.class),\n"   + // reference to 'variable
1173                                   "        true, \n"                                                   +
1174                                   "        Type.type.canonicalText\n"                                  + // reference to '_Type
1175                                   ")\n\")]"                                                            +
1176                                   "static final '_Type 'variable = '_init;"));
1177
1178     final String source2 = "class A {" +
1179                            "  String s = new String();" +
1180                            "  @SuppressWarnings(\"\") int m() {" +
1181                            "    n();" +
1182                            "    int i = 2+1;" +
1183                            "    return i;" +
1184                            "  }" +
1185                            "  void n() {}" +
1186                            "}";
1187     assertEquals("type of variables in script are as expected", 1,
1188                  findMatchesCount(source2,
1189                                   "[script(\"" +
1190                                   "import com.intellij.psi.*\n" +
1191                                   "__context__ instanceof PsiElement &&" +
1192                                   "a instanceof PsiClass &&" +
1193                                   "b instanceof PsiTypeElement &&" +
1194                                   "c instanceof PsiField &&" +
1195                                   "d instanceof PsiNewExpression &&" +
1196                                   "e instanceof PsiTypeElement &&" +
1197                                   "f instanceof PsiMethod &&" +
1198                                   "g instanceof PsiTypeElement &&" +
1199                                   "h instanceof PsiLocalVariable &&" +
1200                                   "i instanceof PsiPolyadicExpression &&" +
1201                                   "j instanceof PsiReferenceExpression &&" +
1202                                   "k instanceof PsiMethodCallExpression &&" +
1203                                   "l instanceof PsiAnnotation\n" +
1204                                   "\")]" +
1205                                   "class '_a {" +
1206                                   "  '_b '_c = new '_d();" +
1207                                   "  @'_l '_e '_f() {" +
1208                                   "    '_k();" +
1209                                   "    '_g '_h = '_i;" +
1210                                   "    return '_j;" +
1211                                   "  }" +
1212                                   "}"));
1213
1214     assertEquals("Current variable should be available under own name", 1,
1215                  findMatchesCount(source2,
1216                                   "'_a + '_b:[script(\"__log__.info(b)\n__log__.info(__context__)\ntrue\")]"));
1217   }
1218
1219   public void testCheckScriptValidation() {
1220     final String s1 = "";
1221     final String s2 = "'_b:[script( \"^^^\" )]";
1222
1223     try {
1224       final int count = findMatchesCount(s1, s2);
1225       assertFalse("Validation does not work", true);
1226     } catch (MalformedPatternException ex) {}
1227   }
1228
1229   //public void testRelationBetweenVars() {
1230   //  final String s1 = "public class Foo {\n" +
1231   //                      "    public static final Logger log = Logger.getInstance(Foo.class);\n" +
1232   //                      "    public static final Logger log2 = Logger.getInstance(Foo2.class);\n" +
1233   //                      "    public static final Logger log3 = Logger.getInstance(Foo2.class);\n" +
1234   //                      "}";
1235   //  final String s2 = "class '_a { static Logger 'log+ = Logger.getInstance('_b:[script( \"_a != _b\" )].class); }";
1236   //  assertEquals(
1237   //    "relation between vars in script",
1238   //    2,
1239   //    findMatchesCount(s1,s2)
1240   //  );
1241   //}
1242
1243   public void testExprTypeWithObject() {
1244     String s1 = "import java.util.*;\n" +
1245                 "class A {\n" +
1246                 "  void b() {\n" +
1247                 "    Map map = new HashMap();" +
1248                 "    class AppPreferences {}\n" +
1249                 "    String key = \"key\";\n" +
1250                 "    AppPreferences value = new AppPreferences();\n" +
1251                 "    map.put(key, value );\n" +
1252                 "    map.put(value, value );\n" +
1253                 "    map.put(\"key\", value );\n" +
1254                 "    map.put(\"key\", new AppPreferences());\n" +
1255                 "  }\n" +
1256                 "}";
1257     String s2 = "'_map:[exprtype( *java\\.util\\.Map )].put('_key:[ exprtype( *Object ) ], '_value:[ exprtype( *AppPreferences ) ]);";
1258
1259     assertEquals(
1260       "expr type with object",
1261       4,
1262       findMatchesCount(s1,s2,true)
1263     );
1264   }
1265
1266   public void testInterfaceImplementationsSearch() {
1267     String in = "class A implements Cloneable {\n" +
1268                 "    \n" +
1269                 "  }\n" +
1270                 "  \n" +
1271                 "  class B implements Serializable {\n" +
1272                 "    \n" +
1273                 "  }\n" +
1274                 "  \n" +
1275                 "  class C implements Cloneable,Serializable {\n" +
1276                 "    \n" +
1277                 "  }\n" +
1278                 "  class C2 implements Serializable,Cloneable {\n" +
1279                 "    \n" +
1280                 "  }\n" +
1281                 "  \n" +
1282                 "  class E extends B implements Cloneable {\n" +
1283                 "    \n" +
1284                 "  }\n" +
1285                 "  \n" +
1286                 "  class F extends A implements Serializable {\n" +
1287                 "    \n" +
1288                 "  }\n" +
1289                 "  \n" +
1290                 "  class D extends C {\n" +
1291                 "    \n" +
1292                 "  }";
1293     String what = "class 'A implements '_B:*Serializable , '_C:*Cloneable {}";
1294     assertEquals(
1295       "search interface within hierarchy",
1296       5,
1297       findMatchesCount(in, what)
1298     );
1299   }
1300
1301   public void testSearchBacktracking() {
1302     assertEquals(
1303       "backtracking greedy regexp",
1304       findMatchesCount(s89,s90),
1305       1
1306     );
1307
1308     assertEquals(
1309       "backtracking greedy regexp 2",
1310       findMatchesCount(s89,s90_2),
1311       1
1312     );
1313
1314     assertEquals(
1315       "backtracking greedy regexp 3",
1316       findMatchesCount(s89,s90_3),
1317       0
1318     );
1319
1320     assertEquals(
1321       "counted regexp (with back tracking)",
1322       findMatchesCount(s89,s90_4),
1323       1
1324     );
1325
1326     assertEquals(
1327       "nongreedy regexp (counted, with back tracking)",
1328       findMatchesCount(s89,s90_5),
1329       1
1330     );
1331
1332     assertEquals(
1333       "nongreedy regexp (counted, with back tracking) 2",
1334       findMatchesCount(s89,s90_6),
1335       0
1336     );
1337
1338     String s1000 = "class A {\n" +
1339                    "      void _() {}\n" +
1340                    "      void a(String in, String pattern) {}\n" +
1341                    "    }";
1342     String s1001 = "class '_Class { \n" +
1343                    "  '_ReturnType+ 'MethodName+ ('_ParameterType* '_Parameter* );\n" +
1344                    "}";
1345     assertEquals(
1346       "handling of no match",
1347       findMatchesCount(s1000,s1001),
1348       2
1349     );
1350   }
1351
1352   public void testSearchSymbol() {
1353     final String s131 = "a.b(); c.d = 1; ";
1354     final String s132 = "'T:b|d";
1355
1356     assertEquals(
1357       "symbol match",
1358       2,
1359       findMatchesCount(s131,s132)
1360     );
1361
1362     final String s129 = "A a = new A();";
1363     final String s130 = "'Sym:A";
1364
1365     options.setCaseSensitiveMatch(true);
1366     assertEquals(
1367       "case sensitive match",
1368       findMatchesCount(s129,s130),
1369       2
1370     );
1371
1372     final String s133 = "class C { int a; int A() { a = 1; }} void c(int a) { a = 2; }";
1373     final String s133_2 = "class C { int a() {} int A() { a(1); }}";
1374     final String s134 = "a";
1375
1376     List<MatchResult> results = findMatches(s133, s134, true, StdFileTypes.JAVA);
1377     assertEquals(
1378       "find sym finds declaration",
1379       4, results.size()
1380     );
1381
1382     assertEquals(
1383       "find sym finds declaration",
1384       2, findMatchesCount(s133_2, s134, true)
1385     );
1386     final String in = "class C {" +
1387                       "  {" +
1388                       "    int i = 0;" +
1389                       "    i += 1;" +
1390                       "    (i) = 3;" +
1391                       "    int j = i;" +
1392                       "    i();" +
1393                       "  }" +
1394                       "  void i() {}" +
1395                       "}";
1396     final String pattern1 = "'_:[read]";
1397     assertEquals("Find reads of symbol (including operator assignment)", 2, findMatchesCount(in, pattern1));
1398
1399     final String pattern2 = "'_:[write && regex( i )]";
1400     assertEquals("Find writes of symbol", 3, findMatchesCount(in, pattern2));
1401
1402     final String source = "class A {" +
1403                           "  static A a() {};" +
1404                           "  void m() {" +
1405                           "    A a = A.a();" +
1406                           "  }" +
1407                           "}";
1408     final String pattern3 = "A";
1409     assertEquals("No duplicate results", 4, findMatchesCount(source, pattern3));
1410   }
1411
1412   public void testSearchGenerics() {
1413     assertEquals(
1414       "parameterized class match",
1415       findMatchesCount(s81,s82),
1416       2
1417     );
1418
1419     assertEquals(
1420       "parameterized instanceof match",
1421       findMatchesCount(s81,s82_2),
1422       1
1423     );
1424
1425     assertEquals(
1426       "parameterized cast match",
1427       findMatchesCount(s81,s82_3),
1428       1
1429     );
1430
1431     assertEquals(
1432       "parameterized symbol without variables matching",
1433       findMatchesCount(s81, "S<T>"),
1434       2
1435     );
1436
1437     assertEquals(
1438       "parameterized definition match",
1439       findMatchesCount(s81,s82_4),
1440       3
1441     );
1442
1443     assertEquals(
1444       "parameterized method match",
1445       findMatchesCount(s81,s82_5),
1446       1
1447     );
1448
1449     assertEquals(
1450       "parameterized constraint match",
1451       findMatchesCount(s81_2,s82_6),
1452       2
1453     );
1454
1455     assertEquals(
1456       "symbol matches parameterization",
1457       findMatchesCount(s81,s82_7),
1458       29
1459     );
1460
1461     assertEquals(
1462       "symbol matches parameterization 2",
1463       findMatchesCount(s81_2,s82_7),
1464       7
1465     );
1466
1467     String s81_3 = " class A {\n" +
1468                    "  public static <T> Collection<T> unmodifiableCollection(int c) {\n" +
1469                    "    return new d<T>(c);\n" +
1470                    "  }\n" +
1471                    "  static class d<E> implements Collection<E>, Serializable {\n" +
1472                    "    public <T> T[] toArray(T[] a)       {return c.toArray(a);}\n" +
1473                    "  }\n" +
1474                    "}";
1475     assertEquals(
1476       "typed symbol symbol",
1477       findMatchesCount(s81_3,s82_5),
1478       2
1479     );
1480
1481     String s81_4="class A<B> { \n" +
1482                  "  static <C> void c(D<E> f) throws R<S> {\n" +
1483                  "    if ( f instanceof G<H>) {\n" +
1484                  "      ((I<G<K>>)l).a();\n" +
1485                  "      throw new P<Q>();" +
1486                  "    }\n" +
1487                  "  }\n" +
1488                  "} " +
1489                  "class C {\n" +
1490                  "  void d(E f) throws Q {\n" +
1491                  "    if (g instanceof H) { a.c(); b.d(new A() {}); throw new Exception(((I)k)); }"+
1492                  "  }\n" +
1493                  "}";
1494     String s82_8 = "'T<'_Subst+>";
1495     assertEquals(
1496       "typed symbol",
1497       8,
1498       findMatchesCount(s81_4,s82_8)
1499     );
1500
1501     String s81_5 = "class A { HashMap<String, Integer> variable = new HashMap<String, Integer>(\"aaa\");}";
1502     String s82_9 = "'_Type<'_GType, '_GType2> '_instance = new '_Type<'_GType, '_GType2>('_Param);";
1503     assertEquals(
1504       "generic vars in new",
1505       findMatchesCount(s81_5,s82_9),
1506       1
1507     );
1508     assertEquals(
1509       "no exception on searching for diamond operator",
1510       findMatchesCount(s81_5, "new 'Type<>('_Param)"),
1511       0
1512     );
1513     assertEquals(
1514       "order of parameters matters",
1515       0,
1516       findMatchesCount(s81_5, "HashMap<Integer, String>")
1517     );
1518     assertEquals(
1519       "order of parameters matters 2",
1520       2,
1521       findMatchesCount(s81_5, "HashMap<String, Integer>")
1522     );
1523
1524     String source1 = "class Comparator<T> { private Comparator<String> c; private Comparator d; private Comparator e; }";
1525     String target1 = "java.util.Comparator 'a;";
1526     assertEquals(
1527       "qualified type should not match 1",
1528       0,
1529       findMatchesCount(source1, target1)
1530     );
1531
1532     String target2 = "java.util.Comparator<String> 'a;";
1533     assertEquals(
1534       "qualified type should not match 2",
1535       0,
1536       findMatchesCount(source1, target2)
1537     );
1538
1539     assertEquals(
1540       "unparameterized type query should match",
1541       3,
1542       findMatchesCount(source1, "Comparator 'a;")
1543     );
1544
1545     assertEquals(
1546       "parameterized type query should only match parameterized",
1547       1,
1548       findMatchesCount(source1, "Comparator<'_a> 'b;")
1549     );
1550
1551     assertEquals(
1552       "should find unparameterized only",
1553       2,
1554       findMatchesCount(source1, "Comparator<'_a{0,0}> 'b;")
1555     );
1556
1557     String source2 = "class A<@Q T> {}\n" +
1558                      "class B<T> {}";
1559     assertEquals(
1560       "find annotated type parameter",
1561       1,
1562       findMatchesCount(source2, "class '_A<@Q '_T> {}")
1563     );
1564
1565     // @todo typed vars constrains (super),
1566     // @todo generic method invocation
1567
1568     //String s83 = "class A {} List<A> a; List b;";
1569     //String s84 = "'a:List 'c;";
1570     //String s84_2 = "'a:List\\<'_\\> 'c;";
1571     //String s84_3 = "'a:List(?>\\<'_\\>) 'c;";
1572     //
1573     //assertEquals(
1574     //  "finding list",
1575     //  findMatchesCount(s83,s84),
1576     //  2
1577     //);
1578     //
1579     //assertEquals(
1580     //  "finding list 2",
1581     //  findMatchesCount(s83,s84_2),
1582     //  1
1583     //);
1584     //
1585     //assertEquals(
1586     //  "finding list 3",
1587     //  findMatchesCount(s83,s84_3),
1588     //  1
1589     //);
1590   }
1591
1592   public void testSearchSubstitutions() {
1593     // searching for parameterized pattern
1594     assertEquals("search for parameterized pattern",findMatchesCount(s14_1,s15),2);
1595
1596     assertEquals("search for parameterized pattern 2",findMatchesCount(s14_2,s15),5);
1597
1598     options.setRecursiveSearch(false);
1599
1600     assertEquals("search for parameterized pattern-non-recursive",findMatchesCount(s14_1,s15),1);
1601
1602     assertEquals("search for parameterized pattern 2-non-recursive",findMatchesCount(s14_2,s15),2);
1603
1604     // typed vars with arrays
1605     assertEquals("typed pattern with array 2-non-recursive",findMatchesCount(s23,s24_2),4);
1606
1607     options.setRecursiveSearch(true);
1608
1609       // searching for parameterized pattern
1610     assertEquals("search for parameterized pattern 3",findMatchesCount(s14_2,s16),1);
1611
1612     // searching for parameterized pattern in complex expr (with field selection)
1613     assertEquals("search for parameterized pattern in field selection",findMatchesCount(s17,s18_1),1);
1614
1615     // searching for parameterized pattern in complex expr (with method call)
1616     assertEquals("search for parameterized pattern with method call",findMatchesCount(s17,s18_2),1);
1617
1618     // searching for parameterized pattern in complex expr (with method call)
1619     assertEquals("search for parameterized pattern with method call ep.2",findMatchesCount(s17,s18_3),4);
1620
1621     // searching for parameterized pattern in definition with initializer
1622     assertEquals("search for same var constraint",findMatchesCount(s19,s20),1);
1623
1624     // searching for semi anonymous parameterized pattern in definition with initializer
1625     assertEquals("search for same var constraint for semi anonymous typed vars",findMatchesCount(s19,s20_2),1);
1626
1627     // support for type var constraint
1628     assertEquals("search for typed var constraint",findMatchesCount(s22,s21_1),1);
1629
1630     // noncompatible same typed var constraints
1631     try {
1632       findMatchesCount(s22,s21_2);
1633       assertFalse("search for noncompatible typed var constraint",false);
1634     } catch(MalformedPatternException e) {
1635     }
1636
1637       // compatible same typed var constraints
1638     assertEquals("search for same typed var constraint",findMatchesCount(s22,s21_3),1);
1639
1640     // typed var with instanceof
1641     assertEquals("typed instanceof",findMatchesCount(s65,s66),1);
1642
1643     try {
1644       // warn on incomplete instanceof
1645       findMatchesCount(s65, "'_T instanceof");
1646       fail();
1647     } catch (MalformedPatternException e) {
1648       assertEquals("Type expected", e.getMessage());
1649     }
1650
1651     // typed vars with arrays
1652     assertEquals("typed pattern with array",findMatchesCount(s23,s24_1),2);
1653
1654     // typed vars with arrays
1655     assertEquals("typed pattern with array 2",findMatchesCount(s23,s24_2),6);
1656
1657     // typed vars in class name, method name, its return type, parameter type and name
1658     assertEquals("typed pattern in class name, method name, return type, parameter type and name",findMatchesCount(s25,s26),1);
1659
1660     assertEquals(
1661       "finding interface",
1662       findMatchesCount(s27,s28),
1663       1
1664     );
1665
1666     // finding anonymous type vars
1667     assertEquals(
1668       "anonymous typed vars",
1669       findMatchesCount(s29,s30),
1670       1
1671     );
1672
1673     // finding descedants
1674     assertEquals(
1675       "finding class descendants",
1676       findMatchesCount(s31,s32),
1677       2
1678     );
1679
1680     // finding interface implementation
1681     assertEquals(
1682       "interface implementation",
1683       findMatchesCount(s33,s34),
1684       2
1685     );
1686
1687     // different order of fields and methods
1688     assertEquals(
1689       "different order of fields and methods",
1690       findMatchesCount(s35,s36),
1691       1
1692     );
1693
1694     // different order of exceptions in throws
1695     assertEquals(
1696       "differend order in throws",
1697       findMatchesCount(s37,s38),
1698       1
1699     );
1700
1701     // class pattern without extends matches pattern with extends
1702     assertEquals(
1703       "match of class without extends to class with it",
1704       findMatchesCount(s39,s40),
1705       2
1706     );
1707
1708     // class pattern without extends matches pattern with extends
1709     assertEquals(
1710       "match of class without extends to class with it, ep. 2",
1711       findMatchesCount(s41,s42_1),
1712       2
1713     );
1714
1715     // class pattern without extends matches pattern with extends
1716     assertEquals(
1717       "match of class without extends to class with it, ep 3",
1718       4,
1719       findMatchesCount(s41,s42_2)
1720     );
1721
1722     assertEquals("match class with fields without initializers", 2, findMatchesCount(s41, "class '_ { '_T '_T2 = '_T3{0,0}; } "));
1723
1724     // typed reference element
1725     assertEquals(
1726       "typed reference element",
1727       findMatchesCount(s51,s52),
1728       2
1729     );
1730
1731     // empty name of type var
1732     assertEquals(
1733       "empty name for typed var",
1734       findMatchesCount(s59,s60),
1735       1
1736     );
1737
1738     // comparing method with constructor
1739     assertEquals(
1740       "comparing method with constructor",
1741       findMatchesCount(s63,s64),
1742       1
1743     );
1744
1745     // comparing method with constructor
1746     assertEquals(
1747       "finding nested class",
1748       findMatchesCount(s63_2,s64),
1749       2
1750     );
1751
1752     // comparing method with constructor
1753     assertEquals(
1754       "finded nested class by special pattern",
1755       findMatchesCount(s63_2,s64_2),
1756       1
1757     );
1758
1759     assertEquals(
1760       "* regexp for typed var",
1761       findMatchesCount(s61,s62_1),
1762       5
1763     );
1764
1765     assertEquals(
1766       "+ regexp for typed var",
1767       findMatchesCount(s61,s62_2),
1768       4
1769     );
1770
1771     assertEquals(
1772       "? regexp for typed var",
1773       findMatchesCount(s61,s62_3),
1774       2
1775     );
1776
1777     assertEquals(
1778       "cast in method parameters",
1779       findMatchesCount(s67,s68),
1780       1
1781     );
1782
1783     assertEquals(
1784       "searching for static field in static call",
1785       2,
1786       findMatchesCount(s69,s70)
1787     );
1788
1789     assertEquals(
1790       "searching for static field in static call, 2",
1791       2,
1792       findMatchesCount(s69,s70_2)
1793     );
1794
1795     assertEquals(
1796       "* regexp for anonymous typed var",
1797       findMatchesCount(s61,s62_4),
1798       3
1799     );
1800
1801     assertEquals(
1802       "+ regexp for anonymous typed var",
1803       findMatchesCount(s61,s62_5),
1804       2
1805     );
1806
1807     assertEquals(
1808       "? regexp for anonymous typed var",
1809       findMatchesCount(s61,s62_6),
1810       2
1811     );
1812
1813     assertEquals(
1814       "statement inside anonymous class",
1815       findMatchesCount(s71,s72),
1816       3
1817     );
1818
1819     assertEquals(
1820       "clever regexp match",
1821       findMatchesCount(s91,s92),
1822       2
1823     );
1824
1825     assertEquals(
1826       "clever regexp match 2",
1827       findMatchesCount(s91,s92_2),
1828       2
1829     );
1830
1831     assertEquals(
1832       "clever regexp match 3",
1833       findMatchesCount(s91,s92_3),
1834       2
1835     );
1836   }
1837
1838   public void testSearchJavaDoc() {
1839     // javadoc comment in class
1840     assertEquals(
1841       "java doc comment in class",
1842       1,
1843       findMatchesCount(s57,s58)
1844     );
1845
1846     assertEquals(
1847       "java doc comment in class in file",
1848       1,
1849       findMatchesCount(s57_2,s58,true)
1850     );
1851
1852     // javadoc comment for field
1853     assertEquals(
1854       "javadoc comment for field",
1855       2,
1856       findMatchesCount(s57, s58_2)
1857     );
1858
1859     // javadoc comment for method
1860     assertEquals(
1861       "javadoc comment for method",
1862       2,
1863       findMatchesCount(s57, s58_3)
1864     );
1865
1866     // just javadoc comment search
1867     assertEquals(
1868       "just javadoc comment search",
1869       4,
1870       findMatchesCount(s57,s58_4)
1871     );
1872
1873     assertEquals(
1874     "XDoclet metadata",
1875       2,
1876       findMatchesCount(s83,s84)
1877     );
1878
1879     assertEquals(
1880     "XDoclet metadata 2",
1881       1,
1882       findMatchesCount(s83,s84_2)
1883     );
1884
1885     assertEquals(
1886       "optional tag value match",
1887       6,
1888       findMatchesCount(s57, s58_5)
1889     );
1890
1891     assertEquals(
1892       "multiple tags match +",
1893       2,
1894       findMatchesCount(s75,s76)
1895     );
1896
1897     assertEquals(
1898       "multiple tags match *",
1899       3,
1900       findMatchesCount(s75, s76_2)
1901     );
1902
1903     assertEquals(
1904       "multiple tags match ?",
1905       3,
1906       findMatchesCount(s75, s76_3)
1907     );
1908
1909     assertEquals("no infinite loop on javadoc matching", 1, findMatchesCount(s57, "/** 'Text */ class '_ { }"));
1910   }
1911
1912   public void testNamedPatterns() {
1913     String s133 = "class String1 implements java.io.Serializable { " +
1914                   "private static final long serialVersionUID = -6849794470754667710L;" +
1915                   "private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];" +
1916                   "}" +
1917                   "class StringBuilder1 implements java.io.Serializable {" +
1918                   "    private void writeObject(java.io.ObjectOutputStream s)\n" +
1919                   "        throws java.io.IOException {\n" +
1920                   "        s.defaultWriteObject();\n" +
1921                   "    }" +
1922                   "private void readObject(java.io.ObjectInputStream s)\n" +
1923                   "        throws java.io.IOException, ClassNotFoundException {\n" +
1924                   "        s.defaultReadObject();\n" +
1925                   "    }" +
1926                   "    static final long serialVersionUID = 4383685877147921099L;" +
1927                   "}";
1928     String s134 = "class '_ implements '_:*Serializable {\n" +
1929                   "  static final long 'VersionField?:serialVersionUID = '_?;\n" +
1930                   "  private static final ObjectStreamField[] '_?:serialPersistentFields = '_?; \n" +
1931                   "  private void '_SerializationWriteHandler?:writeObject (ObjectOutputStream s) throws IOException;\n" +
1932                   "  private void '_SerializationReadHandler?:readObject (ObjectInputStream s) throws IOException, ClassNotFoundException;\n" +
1933                   "  Object '_SpecialSerializationReadHandler?:readResolve () throws ObjectStreamException;" +
1934                   "  Object '_SpecialSerializationWriteHandler?:writeReplace () throws ObjectStreamException;" +
1935                   "}";
1936
1937     assertEquals(
1938       "serialization match",
1939       findMatchesCount(s133,s134),
1940       2
1941     );
1942
1943     String s135 = "class SimpleStudentEventActionImpl extends Action { " +
1944                   "  public ActionForward execute(ActionMapping mapping,\n" +
1945                   "         ActionForm _form,\n" +
1946                   "         HttpServletRequest _request,\n" +
1947                   "         HttpServletResponse _response)" +
1948                   "  throws Exception {}" +
1949                   "} " +
1950                   "public class DoEnrollStudent extends SimpleStudentEventActionImpl { }" +
1951                   "public class DoCancelStudent extends SimpleStudentEventActionImpl { }";
1952     String s136 = "public class 'StrutsActionClass extends '_*:Action {" +
1953                   "  public ActionForward '_AnActionMethod:*execute (ActionMapping '_,\n" +
1954                   "                                 ActionForm '_,\n" +
1955                   "                                 HttpServletRequest '_,\n" +
1956                   "                                 HttpServletResponse '_);" +
1957                   "}";
1958
1959     assertEquals(
1960       "Struts actions",
1961       findMatchesCount(s135,s136),
1962       2
1963     );
1964
1965     final String s123 = "class NodeFilter {} public class MethodFilter extends NodeFilter {\n" +
1966                         "  private MethodFilter() {}\n" +
1967                         "\n" +
1968                         "  public static NodeFilter getInstance() {\n" +
1969                         "    if (instance==null) instance = new MethodFilter();\n" +
1970                         "    return instance;\n" +
1971                         "  }\n" +
1972                         "  private static NodeFilter instance;\n" +
1973                         "}";
1974     final String s124 = "class 'Class {\n" +
1975                         "  private 'Class('_* '_*) {\n" +
1976                         "   '_*;\n" +
1977                         "  }\n" +
1978                         "  private static '_Class2:* '_Instance;\n" +
1979                         "  static '_Class2 '_GetInstance() {\n" +
1980                         "    '_*;\n" +
1981                         "    return '_Instance;\n" +
1982                         "  }\n" +
1983                         "}";
1984
1985     assertEquals(
1986       "singleton search",
1987       findMatchesCount(s123,s124),
1988       1
1989     );
1990
1991     String s1111 = "if (true) { a=1; b=1; } else { a=1; }\n" +
1992                    "if(true) { a=1; } else { a=1; b=1; }\n" +
1993                    "if(true) { a=1; b=2; } else { a = 1; b=2; }";
1994     String s1112 = "if (true) { '_a{1,2}; } else { '_a; }";
1995
1996     assertEquals(
1997       "same multiple name pattern",
1998       findMatchesCount(s1111,s1112),
1999       1
2000     );
2001   }
2002
2003   public void testHierarchy() {
2004     final String s105 = "class B {} class A extends B { }";
2005     final String s106 = "class '_ extends '_:[ref('T)] {}";
2006     assertEquals(
2007       "extends match",
2008       findMatchesCount(s105,s106),
2009       1
2010     );
2011
2012     final String s107 = "interface IA {} interface IB extends IA { } interface IC extends IB {} interface ID extends IC {}" +
2013                         "class A implements IA {} class B extends A { } class C extends B implements IC {} class D extends C {}";
2014     final String s108 = "class '_ extends 'Type:+A {}";
2015     final String s108_2 = "class '_ implements 'Type:+IA {}";
2016
2017     assertEquals(
2018       "extends navigation match",
2019       findMatchesCount(s107,s108),
2020       2
2021     );
2022
2023     assertEquals(
2024       "implements navigation match",
2025       3,
2026       findMatchesCount(s107,s108_2)
2027     );
2028
2029     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;} }";
2030     final String s110 = "'_:*A '_;";
2031     final String s110_2 = "'_:*I '_;";
2032     final String s110_3 = "'_:*[regex( I ) && ref('T)] '_;";
2033     final String s110_4 = "'_:*[regex( I ) && ref2('T)] '_;";
2034     assertEquals(
2035       "extends navigation match in definition",
2036       findMatchesCount(s109,s110),
2037       3
2038     );
2039
2040     assertEquals(
2041       "implements navigation match in definition 2",
2042       findMatchesCount(s109,s110_2),
2043       3
2044     );
2045
2046     assertEquals(
2047       "implements navigation match in definition 2 with nested conditions",
2048       findMatchesCount(s109,s110_3),
2049       1
2050     );
2051
2052     try {
2053       findMatchesCount(s109,s110_4);
2054       assertFalse("implements navigation match in definition 2 with nested conditions - incorrect cond",false);
2055     } catch(UnsupportedPatternException ex) {}
2056
2057     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;} }";
2058     final String s112 = "'_";
2059     assertEquals(
2060       "symbol match",
2061       findMatchesCount(s111,s112),
2062       17
2063     );
2064
2065     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); " +
2066                         "b.c = 1; System.out.println(b.c); b.c++;";
2067     final String s114 = "'_:[read]";
2068     final String s114_2 = "'_:[write]";
2069     assertEquals(
2070       "read symbol match",
2071       findMatchesCount(s113,s114),
2072       11
2073     );
2074
2075     assertEquals(
2076       "write symbol match",
2077       findMatchesCount(s113,s114_2),
2078       5
2079     );
2080
2081     final String s115 = "class B {} public class C {}";
2082     final String s116 = "public class '_ {}";
2083     assertEquals(
2084       "public modifier for class",
2085       findMatchesCount(s115,s116),
2086       1
2087     );
2088
2089     final String s117 = "class A { int b; void c() { int e; b=1; this.b=1; e=5; " +
2090                         "System.out.println(e); " +
2091                         "System.out.println(b); System.out.println(this.b);} }";
2092     final String s118 = "this.'Field";
2093     final String s118_2 = "this.'Field:[read]";
2094     final String s118_3 = "this.'Field:[write]";
2095
2096     assertEquals(
2097       "fields of class",
2098       4,
2099       findMatchesCount(s117,s118)
2100     );
2101
2102     assertEquals(
2103       "fields of class read",
2104       2,
2105       findMatchesCount(s117,s118_2)
2106     );
2107
2108     assertEquals(
2109       "fields of class written",
2110       2,
2111       findMatchesCount(s117,s118_3)
2112     );
2113
2114     final String s119 = "try { a.b(); } catch(IOException e) { c(); } catch(Exception ex) { d(); }";
2115     final String s120 = "try { '_; } catch('_ '_) { '_; }";
2116     final String s120_2 = "try { '_; } catch(Throwable '_) { '_; }";
2117     assertEquals(
2118       "catches loose matching",
2119       findMatchesCount(s119,s120),
2120       1
2121     );
2122
2123     assertEquals(
2124       "catches loose matching 2",
2125       findMatchesCount(s119,s120_2),
2126       0
2127     );
2128
2129     final String s121 = "class A { private int a; class Inner {} } " +
2130                         "class B extends A { private int a; class Inner2 {} }";
2131     final String s122 = "class '_ { int '_:* ; }";
2132     final String s122_2 = "class '_ { int '_:+hashCode (); }";
2133     final String s122_3 = "class '_ { class '_:* {} }";
2134     assertEquals(
2135       "hierarchical matching",
2136       findMatchesCount(s121,s122),
2137       2
2138     );
2139
2140     assertEquals(
2141       "hierarchical matching 2",
2142       findMatchesCount(s121,s122_2),
2143       4
2144     );
2145
2146     assertEquals(
2147       "hierarchical matching 3",
2148       findMatchesCount(s121,s122_3),
2149       2
2150     );
2151   }
2152
2153   public void testSearchInCommentsAndLiterals() {
2154     String s1 = "{" +
2155                 "// This is some comment\n" +
2156                 "/* This is another\n comment*/\n" +
2157                 "// Some garbage\n"+
2158                 "/** And now third comment*/\n" +
2159                 "/** Some garbage*/ }";
2160     String s2 = "// 'Comment:[regex( .*(?:comment).* )]";
2161     String s3 = "/** 'Comment:[regex( .*(?:comment).* )] */";
2162     String s2_2 = "/* 'Comment:[regex( .*(?:comment).* )] */";
2163
2164     assertEquals(
2165       "Comment matching",
2166       findMatchesCount(s1,s2),
2167       3
2168     );
2169
2170     assertEquals(
2171       "Comment matching, 2",
2172       3,
2173       findMatchesCount(s1,s2_2)
2174     );
2175
2176     assertEquals(
2177       "Java doc matching",
2178       findMatchesCount(s1,s3),
2179       1
2180     );
2181
2182     String s4 = "\"'test\", \"another test\", \"garbage\"";
2183     String s5 = "\"'test:[regex( .*test.* )]\"";
2184     String s6 = "\"''test\"";
2185
2186     assertEquals(
2187       "Literal content",
2188       findMatchesCount(s4,s5),
2189       2
2190     );
2191
2192     assertEquals(
2193       "Literal content with escaping",
2194       findMatchesCount(s4,s6),
2195       1
2196     );
2197
2198     String s7 = "\"aaa\"";
2199     String s8 = "\"'test:[regex( aaa )]\"";
2200
2201     assertEquals(
2202       "Simple literal content",
2203       findMatchesCount(s7,s8),
2204       1
2205     );
2206
2207     String s9 = "\" aaa \" \" bbb \" \" ccc ccc aaa\"";
2208     String s10 = "\"'test:[regexw( aaa|ccc )]\"";
2209     String s11 = "\"'test:[regexw( bbb )]\"";
2210
2211     assertEquals(
2212       "Whole word literal content with alternations",
2213       findMatchesCount(s9,s10),
2214       2
2215     );
2216
2217     assertEquals(
2218       "Whole word literal content",
2219       findMatchesCount(s9,s11),
2220       1
2221     );
2222
2223     String s12 = "assert agentInfo != null : \"agentInfo is null\";\n" +
2224                  "assert addresses != null : \"addresses is null\";";
2225     String s13 = "assert '_exp != null : \"'_exp is null\";";
2226
2227     assertEquals(
2228       "reference to substitution in comment",
2229       findMatchesCount(s12,s13),
2230       2
2231     );
2232
2233     String s14 = "\"(some text with special chars)\"," +
2234                  "\" some\"," +
2235                  "\"(some)\"";
2236     String s15 = "\"('a:[regexw( some )])\"";
2237
2238     assertEquals(
2239       "meta char in literal",
2240       2,
2241       findMatchesCount(s14,s15)
2242     );
2243
2244     String s16 = "/**\n" +
2245                  "* Created by IntelliJ IDEA.\n" +
2246                  "* User: cdr\n" +
2247                  "* Date: Nov 15, 2005\n" +
2248                  "* Time: 4:23:29 PM\n" +
2249                  "* To change this template use File | Settings | File Templates.\n" +
2250                  "*/\n" +
2251                  "public class Y {\n" +
2252                  "}";
2253     String s17 = "/**\n" +
2254                  "* Created by IntelliJ IDEA.\n" +
2255                  "* User: '_USER\n" +
2256                  "* Date: '_DATE\n" +
2257                  "* Time: '_TIME\n" +
2258                  "* To change this template use File | Settings | File Templates.\n" +
2259                  "*/\n" +
2260                  "class 'c {\n" +
2261                  "}";
2262     assertEquals(
2263       "complete comment match",
2264       1,
2265       findMatchesCount(s16,s17,true)
2266     );
2267
2268     String s18 = "public class A {\n" +
2269                  "   private void f(int i) {\n" +
2270                  "       int g=0; //sss\n" +
2271                  "   }\n" +
2272                  "}";
2273     String s19 = "class '_c {\n" +
2274                  "   '_type '_f('_t '_p){\n" +
2275                  "       '_s; // sss\n" +
2276                  "   }\n" +
2277                  "}";
2278     assertEquals(
2279       "statement match with comment",
2280       1,
2281       findMatchesCount(s18,s19)
2282     );
2283   }
2284
2285   public void testOther() {
2286     assertEquals(
2287       "optional init match in definition",
2288       findMatchesCount(s73,s74),
2289       4
2290     );
2291
2292     assertEquals(
2293       "null match",
2294       findMatchesCount(s77,s78),
2295       0
2296     );
2297
2298     assertEquals(
2299       "body of method by block search",
2300       findMatchesCount(s79,s80),
2301       2
2302     );
2303
2304
2305     assertEquals(
2306       "first matches, next not",
2307       findMatchesCount(s95,s96),
2308       2
2309     );
2310
2311     final String s97 = "class A { int c; void b() { C d; } } class C { C() { A a; a.b(); a.c=1; } }";
2312     final String s98 = "'_.'_:[ref('T)] ()";
2313     final String s98_2 = "'_.'_:[ref('T)]";
2314     final String s98_3 = "'_:[ref('T)].'_ ();";
2315     final String s98_4 = "'_:[ref('T)] '_;";
2316
2317     assertEquals(
2318       "method predicate match",
2319       findMatchesCount(s97,s98),
2320       1
2321     );
2322
2323     assertEquals(
2324       "field predicate match",
2325       findMatchesCount(s97,s98_2),
2326       1
2327     );
2328
2329     assertEquals(
2330       "dcl predicate match",
2331       findMatchesCount(s97,s98_3),
2332       1
2333     );
2334
2335     final String s99 = " char s = '\\u1111';  char s1 = '\\n'; ";
2336     final String s100 = " char 'var = '\\u1111'; ";
2337     final String s100_2 = " char 'var = '\\n'; ";
2338     assertEquals(
2339       "char constants in pattern",
2340       findMatchesCount(s99,s100),
2341       1
2342     );
2343
2344     assertEquals(
2345       "char constants in pattern 2",
2346       findMatchesCount(s99,s100_2),
2347       1
2348     );
2349
2350     assertEquals(
2351       "class predicate match (from definition)",
2352       findMatchesCount(s97,s98_4),
2353       3
2354     );
2355
2356     final String s125 = "a=1;";
2357     final String s126 = "'t:[regex(a)]";
2358
2359     try {
2360       findMatchesCount(s125,s126);
2361       assertFalse("spaces around reg exp check",false);
2362     } catch(MalformedPatternException ex) {}
2363
2364     final String s101 = "class A { void b() { String d; String e; String[] f; f.length=1; f.length=1; } }";
2365     final String s102 = "'_:[ref('T)] '_;";
2366
2367     assertEquals(
2368       "distinct match",
2369       findMatchesCount(s101,s102),
2370       1
2371     );
2372
2373     final String s103 = " a=1; ";
2374     final String s104 = "'T:{ ;";
2375     try {
2376       findMatchesCount(s103,s104);
2377       assertFalse("incorrect reg exp",false);
2378     } catch(MalformedPatternException ex) {
2379     }
2380
2381     final String s106 = "'_ReturnType 'MethodName('_ParameterType '_Parameter);";
2382     final String s105 = " aaa; ";
2383
2384     try {
2385       findMatchesCount(s105,s106);
2386       assertFalse("incorrect reg exp 2",false);
2387     } catch(UnsupportedPatternException ex) {
2388     }
2389
2390     String s107 = "class A {\n" +
2391                   "  /* */\n" +
2392                   "  void a() {\n" +
2393                   "  }" +
2394                   "  /* */\n" +
2395                   "  int b = 1;\n" +
2396                   "  /*" +
2397                   "   *" +
2398                   "   */\n" +
2399                   "   class C {}" +
2400                   "}";
2401     String s108 = "  /*" +
2402                   "   *" +
2403                   "   */";
2404
2405     assertEquals("finding comments without typed var", 1, findMatchesCount(s107,s108));
2406
2407     String s109 = "class A { void b(); int b(int c); char d(char e); }\n" +
2408                   "A a; a.b(1); a.b(2); a.b(); a.d('e'); a.d('f'); a.d('g');";
2409     String s110 = "'_a.'_b:[exprtype( int ) ]('_c*);";
2410     assertEquals("caring about method return type", 2, findMatchesCount(s109,s110));
2411
2412     String s111 = "class A { void getManager() { getManager(); } };\n" +
2413                   "class B { void getManager() { getManager(); getManager(); } };";
2414     String s112 = "'Instance?:[exprtype( B )].getManager()";
2415     assertEquals("caring about missing qualifier type", 2, findMatchesCount(s111,s112));
2416
2417     String s112a = "'Instance?:[regex( B )].getManager()";
2418     assertEquals("static query should not match instance method", 0, findMatchesCount(s111, s112a));
2419
2420     String s112b = "B.getManager()";
2421     assertEquals("static query should not match instance method 2", 0, findMatchesCount(s111, s112b));
2422
2423     String s113 = "class A { static void a() { a(); }}\n" +
2424                   "class B { static void a() { a(); a(); }}\n";
2425     String s114 = "'_Q?:[regex( B )].a()";
2426     assertEquals("should care about implicit class qualifier", 2, findMatchesCount(s113, s114));
2427
2428     String s114a = "B.a()";
2429     assertEquals("should match simple implicit class qualifier query", 2, findMatchesCount(s113, s114a));
2430
2431     String s114b = "'_Q?:[exprtype( B )].a()";
2432     assertEquals("instance query should not match static method", 0, findMatchesCount(s113, s114b));
2433
2434     String s115 = "class A { int a; int f() { return a; }}\n" +
2435                   "class B { int a; int g() { return a + a; }}\n";
2436     String s116 = "'_Instance?:[exprtype( B )].a";
2437     assertEquals("should care about implicit instance qualifier", 2, findMatchesCount(s115, s116));
2438
2439     String s116a = "A.a";
2440     assertEquals("should not match instance method", 0, findMatchesCount(s115, s116a));
2441
2442     String s117 = "class A { static int a; static int f() { return a; }}\n" +
2443                   "class B { static int a; static int g() { return a + a; }}\n";
2444     String s118 = "'_Q?:[regex( B )].a";
2445     assertEquals("should care about implicit class qualifier for field", 2, findMatchesCount(s117, s118));
2446
2447     // b) hierarchy navigation support
2448     // c) or search support
2449
2450     // e) xml search (down-up, nested query), navigation from xml representation <-> java code
2451     // f) impl data conversion (jdk 1.5 style) <-> other from (replace support)
2452
2453     // Directions:
2454     // @todo different navigation on sub/supertyping relation (fixed depth), methods implementing interface,
2455     // g.  like predicates
2456     // i. performance
2457     // more context for top level classes, difference with interface, etc
2458
2459     // global issues:
2460     // @todo matches out of context
2461     // @todo proper regexp support
2462
2463     // @todo define strict equality of the matches
2464     // @todo search for field selection retrieves packages also
2465   }
2466
2467   public void testFQNInPatternAndVariableConstraints() {
2468     String s1 = "import java.awt.List;\n" +
2469                 "class A { List l; }";
2470     String s1_2 = "import java.util.List;\n" +
2471                   "class A { List l; }";
2472     String s2 = "class '_ { 'Type:java\\.util\\.List '_Field; }";
2473
2474     assertEquals("No matches for qualified class",findMatchesCount(s1,s2,true),0);
2475     assertEquals("Matches for qualified class",findMatchesCount(s1_2,s2,true),1);
2476
2477     String s3 = "import java.util.ArrayList;\n" +
2478                 "class A { ArrayList l; }";
2479     String s4 = "class '_ { 'Type:*java\\.util\\.Collection '_Field; }";
2480     assertEquals("Matches for qualified class in hierarchy",findMatchesCount(s3,s4,true),1);
2481
2482     String s5 = "import java.util.List;\n" +
2483                 "class A { { List l = new List(); l.add(\"1\"); }  }";
2484     String s5_2 = "import java.awt.List;\n" +
2485                   "class A { { List l = new List(); l.add(\"1\"); } }";
2486     String s6 = "'a:[exprtype( java\\.util\\.List )]";
2487     String s6_2 = "'a:[exprtype( *java\\.util\\.Collection )]";
2488     String s6_3 = "java.util.List '_a = '_b?;";
2489
2490     assertEquals("Matches for qualified expr type",findMatchesCount(s5,s6,true), 2);
2491     assertEquals("No matches for qualified expr type",findMatchesCount(s5_2,s6,true),0);
2492     assertEquals("Matches for qualified expr type in hierarchy",findMatchesCount(s5,s6_2,true), 2);
2493
2494     assertEquals("Matches for qualified var type in pattern",findMatchesCount(s5,s6_3,true),1);
2495     assertEquals("No matches for qualified var type in pattern",findMatchesCount(s5_2,s6_3,true),0);
2496
2497     String s7 = "import java.util.List;\n" +
2498                 "class A extends List { }";
2499     String s7_2 = "import java.awt.List;\n" +
2500                   "class A extends List {}";
2501
2502     String s8 = "class 'a extends java.util.List {}";
2503
2504     assertEquals("Matches for qualified type in pattern",findMatchesCount(s7,s8,true),1);
2505     assertEquals("No matches for qualified type in pattern",findMatchesCount(s7_2,s8,true),0);
2506
2507     String s9 = "String.intern(\"1\");\n" +
2508                 "java.util.Collections.sort(null);" +
2509                 "java.util.Collections.sort(null);";
2510     String s10 = "java.lang.String.'_method ( '_params* )";
2511     assertEquals("FQN in class name",1,findMatchesCount(s9,s10,false));
2512   }
2513
2514   public void testAnnotations() throws Exception {
2515     String s1 = "@MyBean(\"\")\n" +
2516                 "@MyBean2(\"\")\n" +
2517                 "public class TestBean {}\n" +
2518                 "@MyBean2(\"\")\n" +
2519                 "@MyBean(value=\"\")\n" +
2520                 "public class TestBean2 {}\n" +
2521                 "public class TestBean3 {}\n" +
2522                 "@MyBean(\"a\")\n" +
2523                 "@MyBean2(\"a\")\n" +
2524                 "public class TestBean4";
2525     String s2 = "@MyBean(\"\")\n" +
2526                 "@MyBean2(\"\")\n" +
2527                 "public class '_a {}\n";
2528
2529     assertEquals("Simple find annotated class",2,findMatchesCount(s1,s2,false));
2530     assertEquals("Match value of anonymous name value pair 1", 1, findMatchesCount(s1, "@MyBean(\"a\") class '_a {}"));
2531     assertEquals("Match value of anonymous name value pair 2", 2, findMatchesCount(s1, "@MyBean(\"\") class '_a {}"));
2532
2533     String s3 = "@VisualBean(\"????????? ?????????? ? ??\")\n" +
2534                 "public class TestBean\n" +
2535                 "{\n" +
2536                 "    @VisualBeanField(\n" +
2537                 &q