diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java index 246f0a132cb9..345eef5f2531 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java @@ -46,7 +46,7 @@ class JavaPredefinedConfigurations { // Class based createSearchTemplateInfo( SSRBundle.message("predefined.configuration.methods.of.the.class"), - "class '_Class { \n '_ReturnType+ 'MethodName+('_ParameterType* '_Parameter*);\n}", + "'_ReturnType+ '_MethodName+('_ParameterType* '_Parameter*);", CLASS_TYPE ), createSearchTemplateInfo( @@ -126,7 +126,7 @@ class JavaPredefinedConfigurations { ), createSearchTemplateInfo( SSRBundle.message("predefined.configuration.class.instance.initialization.blocks"), - "class '_A {\n @Modifier(\"Instance\") {\n 'Statement*;\n }\n}", + "@Modifier(\"Instance\") {\n '_Statement*;\n}", CLASS_TYPE ), createSearchTemplateInfo( @@ -161,7 +161,7 @@ class JavaPredefinedConfigurations { // Generics createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.classes"),"class 'GenericClass<'_TypeParameter+> {} ", GENERICS_TYPE), - createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.methods"),"class '_Class {\n <'_TypeParameter+> '_Type+ 'Method+('_ParameterType* '_ParameterDcl*);\n}", GENERICS_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.methods"),"<'_TypeParameter+> '_Type+ '_Method+('_ParameterType* '_ParameterDcl*);", GENERICS_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.typed.symbol"),"'Symbol <'_GenericArgument+>", GENERICS_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.casts"),"( '_Type <'_GenericArgument+> ) '_Expr", GENERICS_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.type.var.substitutions.in.intanceof.with.generic.types"),"'_Expr instanceof '_Type <'Substitutions+> ", GENERICS_TYPE), @@ -171,7 +171,7 @@ class JavaPredefinedConfigurations { // Add comments and metadata createSearchTemplateInfo(SSRBundle.message("predefined.configuration.comments"),"/* 'CommentContent */", METADATA_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.annotated.class"),"/** @'_Tag+ '_TagValue* */\nclass '_Class {\n}", METADATA_TYPE), - createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.annotated.methods"),"class '_Class {\n /** @'_Tag+ '_TagValue* */\n '_Type+ 'Method+('_ParameterType* '_ParameterDcl*);\n}", METADATA_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.annotated.methods"),"/** @'_Tag+ '_TagValue* */\n'_Type+ '_Method+('_ParameterType* '_ParameterDcl*);", METADATA_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.annotated.fields"),"class '_Class {\n /** @'_Tag+ '_TagValue* */\n '_Type+ 'Field+ = '_Init*;\n}", METADATA_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.tags"),"/** @'Tag+ '_TagValue* */", METADATA_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.xdoclet.metadata"),"/** @'Tag \n '_Property+\n*/", METADATA_TYPE), @@ -186,16 +186,10 @@ class JavaPredefinedConfigurations { " '_FieldType+ 'FieldName+ = '_FieldInitial*;\n" + "}", METADATA_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.annotated.methods"), - "class '_Class {\n" + - " @'_Annotation+( )\n" + - " '_MethodType+ 'MethodName+('_ParameterType* '_ParameterName*);\n" + - "}", METADATA_TYPE), + "@'_Annotation+( )\n'_MethodType+ '_MethodName+('_ParameterType* '_ParameterName*);", METADATA_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.not.annotated.methods"), - "class '_Class {\n" + - " @'_Annotation{0,0}\n" + - " '_MethodType+ 'MethodName+('_ParameterType* '_ParameterName*);\n" + - "}", METADATA_TYPE), + "@'_Annotation{0,0}\n'_MethodType+ '_MethodName+('_ParameterType* '_ParameterName*);", METADATA_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.annotation.declarations"), "@interface 'Interface {}", METADATA_TYPE), @@ -268,16 +262,15 @@ class JavaPredefinedConfigurations { " return '_Instance;\n" + " }\n"+ "}",MISC_TYPE), - createSearchTemplateInfo(SSRBundle.message("predefined.configuration.similar.methods.structure"),"class '_Class {\n" + - " '_RetType 'Method+('_ParameterType* '_Parameter) throws 'ExceptionType {\n" + - " try {\n" + - " '_OtherStatements+;\n" + - " } catch('_SomeException '_ExceptionDcl) {\n" + - " '_CatchStatement*;\n" + - " throw new 'ExceptionType('_ExceptionConstructorArgs*);\n" + - " }\n" + - " }\n" + - "}",MISC_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.similar.methods.structure"), + "'_RetType '_Method+('_ParameterType* '_Parameter) throws 'ExceptionType {\n" + + " try {\n" + + " '_OtherStatements+;\n" + + " } catch('_SomeException '_ExceptionDcl) {\n" + + " '_CatchStatement*;\n" + + " throw new 'ExceptionType('_ExceptionConstructorArgs*);\n" + + " }\n" + + "}", MISC_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.bean.info.classes"),"class 'A implements '_:*java\\.beans\\.BeanInfo {\n" + "}",MISC_TYPE), diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index 86e535f1702a..19cc9566f5a9 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -194,9 +194,9 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { if (physical) { throw new UnsupportedOperationException(getClass() + " cannot create physical PSI"); } - PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory(); + final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory(); if (context == PatternTreeContext.Block) { - PsiElement element = elementFactory.createStatementFromText("{\n" + text + "\n}", null); + final PsiElement element = elementFactory.createStatementFromText("{\n" + text + "\n}", null); final PsiElement[] children = ((PsiBlockStatement)element).getCodeBlock().getChildren(); final int extraChildCount = 4; @@ -204,6 +204,14 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { PsiElement[] result = new PsiElement[children.length - extraChildCount]; final int extraChildStart = 2; System.arraycopy(children, extraChildStart, result, 0, children.length - extraChildCount); + + if (shouldTryClassPattern(result)) { + final PsiElement[] classPattern = + createPatternTree(text, PatternTreeContext.Class, fileType, language, contextName, extension, project, false); + if (classPattern.length == 1) { + result = classPattern; + } + } return result; } else { @@ -211,8 +219,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { } } else if (context == PatternTreeContext.Class) { - PsiElement element = elementFactory.createStatementFromText("class A {\n" + text + "\n}", null); - PsiClass clazz = (PsiClass)((PsiDeclarationStatement)element).getDeclaredElements()[0]; + final PsiClass clazz = elementFactory.createClassFromText(text, null); PsiElement startChild = clazz.getLBrace(); if (startChild != null) startChild = startChild.getNextSibling(); @@ -220,11 +227,12 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { if (endChild != null) endChild = endChild.getPrevSibling(); if (startChild == endChild) return PsiElement.EMPTY_ARRAY; // nothing produced + final PsiCodeBlock codeBlock = elementFactory.createCodeBlock(); final List result = new ArrayList(3); assert startChild != null; for (PsiElement el = startChild.getNextSibling(); el != endChild && el != null; el = el.getNextSibling()) { if (el instanceof PsiErrorElement) continue; - result.add(el); + result.add(codeBlock.add(el)); } return PsiUtilCore.toPsiElementArray(result); @@ -234,6 +242,19 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { } } + private static boolean shouldTryClassPattern(PsiElement[] result) { + if (result.length == 3 && PsiModifier.STATIC.equals(result[0].getText()) && result[1] instanceof PsiWhiteSpace && + result[2] instanceof PsiBlockStatement) { + // looks like static initializer + return true; + } + else if (result.length > 1 && result[0] instanceof PsiDeclarationStatement && !result[0].getText().endsWith(";")) { + // might be method + return true; + } + return false; + } + @NotNull @Override public Editor createEditor(@NotNull SearchContext searchContext, diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java index f0cb8ebb9646..26f77d163a51 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java @@ -350,7 +350,7 @@ public class JavaMatchingVisitor extends JavaElementVisitor { } // check if element is declared in current class (not in ancestors) - return element.getContainingClass() == myClazz; + return myClazz == null || element.getContainingClass() == myClazz; } @Override diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java index 5baf840e9c4a..871724bf9f3a 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java @@ -136,19 +136,6 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor { super.visitLiteralExpression(expression); } - @Override - public void visitClassInitializer(final PsiClassInitializer initializer) { - super.visitClassInitializer(initializer); - PsiStatement[] psiStatements = initializer.getBody().getStatements(); - if (psiStatements.length == 1 && psiStatements[0] instanceof PsiExpressionStatement) { - MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(psiStatements[0]); - - if (handler instanceof SubstitutionHandler) { - myCompilingVisitor.getContext().getPattern().setHandler(initializer, new SubstitutionHandler((SubstitutionHandler)handler)); - } - } - } - @Override public void visitField(PsiField psiField) { super.visitField(psiField); diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java index ffb67bb2bda3..c9ecfa7ff420 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java @@ -2403,5 +2403,14 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { " System.out.println();\n" + " }\n" + "}\n", replacer.testReplace(in, what, by, options)); + + final String what2 = "void '_a:[regex( test.* )]();"; + final String by2 = "@org.junit.Test void $a$();"; + assertEquals("class A extends TestCase {\n" + + " @org.junit.Test void testOne(){\n" + + " System.out.println();\n" + + " }\n" + + "}\n", + replacer.testReplace(in, what2, by2, options)); } } \ No newline at end of file diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index e8b23ffd922c..a74d35d7cb7b 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -3327,4 +3327,22 @@ public class StructuralSearchTest extends StructuralSearchTestCase { "}"; assertEquals("find incomplete code", 1, findMatchesCount(source2, "'_a '_b{2,100};")); } + + public void testFindWithSimpleMemberPattern() { + String source = "class X {" + + " static {}" + + " static {}" + + " static {" + + " System.out.println();" + + " }" + + " void one() {}" + + " void two() {" + + " System.out.println();" + + " }" + + "}"; + + assertEquals("find with simple method pattern", 2, findMatchesCount(source, "void '_a();")); + assertEquals("find with simple method pattern 2", 1, findMatchesCount(source, "void one();")); + assertEquals("find with simple static initializer pattern", 3, findMatchesCount(source, "static { '_statement*;}")); + } }