From 9ecde83fc9d1721dcc6eb4f41dae9beea8420e05 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 7 Mar 2016 14:32:40 +0100 Subject: [PATCH] SSR: report many more java pattern problems in search dialog (IDEA-126794) --- .../JavaPredefinedConfigurations.java | 6 ++-- .../JavaStructuralSearchProfile.java | 35 ++++++++++++++---- .../StructuralReplaceTest.java | 10 +++--- .../StructuralSearchTest.java | 36 +++++++++++-------- 4 files changed, 58 insertions(+), 29 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java index 345eef5f2531..dba551260f4a 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java @@ -24,7 +24,7 @@ class JavaPredefinedConfigurations { // Expression patterns createSearchTemplateInfo(SSRBundle.message("predefined.configuration.method.calls"), "'_Instance?.'MethodCall('_Parameter*)", EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.new.expressions"), "new 'Constructor('_Argument*)", EXPRESSION_TYPE), - createSearchTemplateInfo(SSRBundle.message("predefined.configuration.lambdas"), "('_Parameter*) -> ", EXPRESSION_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.lambdas"), "('_Parameter*) -> {}", EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.field.selections"),"'_Instance?.'Field",EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.array.access"),"'_Field['_Index]",EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.assignments"),"'_Inst = '_Expr",EXPRESSION_TYPE), @@ -279,8 +279,8 @@ class JavaPredefinedConfigurations { createSearchTemplateInfo(SSRBundle.message("predefined.configuration.fields.variables.read"),"'Symbol:[read]",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.fields_variables.with.given.name.pattern.updated"),"'Symbol:[regex( name ) && write]",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.usage.of.derived.type.in.cast"),"('CastType:*[regex( Base )]) '_Expr",INTERESTING_TYPE), - createSearchTemplateInfo(SSRBundle.message("predefined.configuration.boxing.in.declarations"),"'_Type:Object|Integer|Boolean|Long|Character|Short|Byte 'Var = '_Value:[exprtype( int|boolean|long|char|short|byte )]",INTERESTING_TYPE), - createSearchTemplateInfo(SSRBundle.message("predefined.configuration.unboxing.in.declarations"),"'_Type:int|boolean|long|char|short|byte 'Var = '_Value:[exprtype( Integer|Boolean|Long|Character|Short|Byte )]",INTERESTING_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.boxing.in.declarations"),"'_Type:Object|Integer|Boolean|Long|Character|Short|Byte 'Var = '_Value:[exprtype( int|boolean|long|char|short|byte )];",INTERESTING_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.unboxing.in.declarations"),"'_Type:int|boolean|long|char|short|byte 'Var = '_Value:[exprtype( Integer|Boolean|Long|Character|Short|Byte )];",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.boxing.in.method.calls"),"'_Instance?.'Call('_BeforeParam*,'_Param:[ exprtype( int|boolean|long|char|short|byte ) && formal( Object|Integer|Boolean|Long|Character|Short|Byte )],'_AfterParam*)",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.unboxing.in.method.calls"), "'_Instance?.'Call('_BeforeParam*,'_Param:[ formal( int|boolean|long|char|short|byte ) && exprtype( Integer|Boolean|Long|Character|Short|Byte )],'_AfterParam*)",INTERESTING_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.any.boxing"), "'_expression:[ exprtype( int|boolean|long|char|short|byte ) && formal( Object|Integer|Boolean|Long|Character|Short|Byte )]", INTERESTING_TYPE), diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index fa5025b35a81..7ffb5814678c 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -407,13 +407,35 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { @Override public void visitErrorElement(PsiErrorElement element) { super.visitErrorElement(element); - //final PsiElement parent = element.getParent(); - //if (parent != myCurrent || !"';' expected".equals(element.getErrorDescription())) { - // throw new MalformedPatternException(element.getErrorDescription()); - //} + final PsiElement parent = element.getParent(); + final String errorDescription = element.getErrorDescription(); + if (parent instanceof PsiClass && "Identifier expected".equals(errorDescription)) { + // other class content variable. + return; + } + if (parent instanceof PsiTryStatement && "'catch' or 'finally' expected".equals(errorDescription)) { + // searching for naked try allowed + return; + } + if (parent == myCurrent) { + // search for expression, type, annotation or symbol + if ("';' expected".equals(errorDescription)) { + // expression + return; + } + if ("Identifier or type expected".equals(errorDescription)) { + // annotation + return; + } + if ("Identifier expected".equals(errorDescription)) { + // type + return; + } + } + throw new MalformedPatternException(errorDescription); } - public void setCurrent(PsiElement current) { + void setCurrent(PsiElement current) { myCurrent = current; } } @@ -423,7 +445,8 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { final NodeIterator nodes = compiledPattern.getNodes(); while (nodes.hasNext()) { final PsiElement current = nodes.current(); - visitor.setCurrent(nodeCount == 1 && current instanceof PsiExpressionStatement ? current : null); + visitor.setCurrent((nodeCount == 1 && (current instanceof PsiExpressionStatement|| current instanceof PsiDeclarationStatement)) + ? current : null); current.accept(visitor); nodes.advance(); } diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java index 8f71f339bad6..002045385084 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java @@ -584,8 +584,8 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { public void testReplaceParameter() { String s1 = "class A { void b(int c, int d, int e) {} }"; - String s2 = "int d"; - String s3 = "int d2"; + String s2 = "int d;"; + String s3 = "int d2;"; String expectedResult = "class A { void b(int c, int d2, int e) {} }"; actualResult = replacer.testReplace(s1,s2,s3,options); @@ -2194,12 +2194,12 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " final int x = 5;\n" + " }\n" + "}"; - String s2 = "final '_type 'var = '_init?"; - String s3 = "$type$ $var$ = $init$"; + String s2 = "final '_type 'var = '_init?;"; + String s3 = "$type$ $var$ = $init$;"; String expected = "class Foo {\n" + " void foo(int i, int i2, int i3) {\n" + - " int x = 5\n" + + " int x = 5;\n" + " }\n" + "}"; diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index f331b8555f52..74c99ef65de0 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -680,9 +680,9 @@ public class StructuralSearchTest extends StructuralSearchTestCase { " void main(String argv[]);" + " void main(String argv);" + "}"; - String s12 = "'_t:[regex( *Object\\[\\] ) ] '_t2"; - String s12_2 = "'_t:[regex( *Object ) ] '_t2 []"; - String s12_3 = "'_t:[regex( *Object ) ] '_t2"; + String s12 = "'_t:[regex( *Object\\[\\] ) ] '_t2;"; + String s12_2 = "'_t:[regex( *Object ) ] '_t2 [];"; + String s12_3 = "'_t:[regex( *Object ) ] '_t2;"; assertEquals( "Find array covariant types", @@ -725,10 +725,10 @@ public class StructuralSearchTest extends StructuralSearchTestCase { " void y(String... ss) {}" + " void y(boolean b) {}" + "}"; - assertEquals("find ellipsis type 1", 1, findMatchesCount(source2, "String[] '_a")); - assertEquals("find ellipsis type 2", 1, findMatchesCount(source2, "int[] '_a")); + assertEquals("find ellipsis type 1", 1, findMatchesCount(source2, "String[] '_a;")); + assertEquals("find ellipsis type 2", 1, findMatchesCount(source2, "int[] '_a;")); assertEquals("find ellipsis type 3", 1, findMatchesCount(source2, "class '_X { void '_m(int... '_a); }")); - assertEquals("find ellipsis type 4", 2, findMatchesCount(source2, "'_T[] '_a")); + assertEquals("find ellipsis type 4", 2, findMatchesCount(source2, "'_T[] '_a;")); String source3 = "class A {" + " private int[] is;" + @@ -1200,7 +1200,7 @@ public class StructuralSearchTest extends StructuralSearchTestCase { "class '_a {" + " '_b '_c = '_d;" + " '_e '_f() {" + - " '_g '_h = '_i" + + " '_g '_h = '_i;" + " return '_j;" + " }" + "}")); @@ -1621,7 +1621,13 @@ public class StructuralSearchTest extends StructuralSearchTestCase { // typed var with instanceof assertEquals("typed instanceof",findMatchesCount(s65,s66),1); - assertEquals("don't throw exception on incomplete instanceof expression", findMatchesCount(s65, "'_T instanceof"), 2); + try { + // warn on incomplete instanceof + findMatchesCount(s65, "'_T instanceof"); + fail(); + } catch (MalformedPatternException e) { + assertEquals("Type expected", e.getMessage()); + } // typed vars with arrays assertEquals("typed pattern with array",findMatchesCount(s23,s24_1),2); @@ -3054,22 +3060,22 @@ public class StructuralSearchTest extends StructuralSearchTestCase { "}"; String pattern1 = "class '_A {" + - " '_type+ 'method+ () throws '_E{0,0}" + + " '_type+ 'method+ () throws '_E{0,0};" + "}"; assertEquals(1, findMatchesCount(source, pattern1)); String pattern2 = "class '_A {" + - " '_type+ 'method+ () throws '_E{1,2}" + + " '_type+ 'method+ () throws '_E{1,2};" + "}"; assertEquals(2, findMatchesCount(source, pattern2)); String pattern3 = "class '_A {" + - " '_type+ 'method+ () throws '_E{2,2}" + + " '_type+ 'method+ () throws '_E{2,2};" + "}"; assertEquals(1, findMatchesCount(source, pattern3)); String pattern4 = "class '_A {" + - " '_type+ 'method+ () throws '_E{0,0}:[ regex( E2 )]" + + " '_type+ 'method+ () throws '_E{0,0}:[ regex( E2 )];" + "}"; assertEquals(2, findMatchesCount(source, pattern4)); } @@ -3146,8 +3152,8 @@ public class StructuralSearchTest extends StructuralSearchTestCase { " }" + "}"; - String pattern1 = "() ->"; - assertEquals("should find lamdas", 4, findMatchesCount(source, pattern1)); + String pattern1 = "() -> {}"; + assertEquals("should find lambdas", 4, findMatchesCount(source, pattern1)); String pattern2 = "(int '_a) -> {}"; assertEquals("should find lambdas with specific parameter type", 1, findMatchesCount(source, pattern2)); @@ -3330,7 +3336,7 @@ public class StructuralSearchTest extends StructuralSearchTestCase { " } finally {}\n" + "}}"; - String pattern1 = "try ('_ResourceType '_Var) { '_Statement*; }"; + String pattern1 = "try ('_ResourceType '_Var = '_exp) { '_Statement*; }"; assertEquals("Find try-with-resources", 1, findMatchesCount(source, pattern1)); String pattern2 = "try { '_St1*; } catch ('_ExceptionType1 '_e1) { '_St2*; } catch ('_ExceptionType2 '_e2) { '_St3*; }";