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