diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java index a1d505a40259..8c1c9a3b4986 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java @@ -176,6 +176,7 @@ class JavaPredefinedConfigurations { createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.tags"),"/** @'Tag+ '_TagValue* */", METADATA_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.xdoclet.metadata"),"/** @'Tag \n '_Property+\n*/", METADATA_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.annotations"), "@'_Annotation", METADATA_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.annotated.class"), "@'_Annotation( )\n" + "class 'Class {}", METADATA_TYPE), 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 b87310881749..a30cff344ae6 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 @@ -285,14 +285,26 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor { return; } } + else if (firstChild instanceof PsiModifierList) { + final PsiModifierList modifierList = (PsiModifierList)firstChild; + final PsiAnnotation[] annotations = modifierList.getAnnotations(); + if (annotations.length != 1) { + throw new UnsupportedPatternException("Pattern is malformed"); + } + for (String modifier : PsiModifier.MODIFIERS) { + if (modifierList.hasExplicitModifier(modifier)) { + throw new UnsupportedPatternException("Pattern is malformed"); + } + } + myCompilingVisitor.setHandler(psiDeclarationStatement, new AnnotationHandler()); + final MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(psiDeclarationStatement); + handler.setFilter(AnnotationFilter.getInstance()); + return; + } final MatchingHandler handler = new DeclarationStatementHandler(); myCompilingVisitor.getContext().getPattern().setHandler(psiDeclarationStatement, handler); - PsiElement previousNonWhiteSpace = psiDeclarationStatement.getPrevSibling(); - - while (previousNonWhiteSpace instanceof PsiWhiteSpace) { - previousNonWhiteSpace = previousNonWhiteSpace.getPrevSibling(); - } + final PsiElement previousNonWhiteSpace = PsiTreeUtil.skipSiblingsBackward(psiDeclarationStatement, PsiWhiteSpace.class); if (previousNonWhiteSpace instanceof PsiComment) { ((DeclarationStatementHandler)handler) @@ -460,6 +472,7 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor { } private static void handleReferenceText(String refname, CompileContext compileContext) { + System.out.println("JavaCompilingVisitor" + ".handleReferenceText(" + refname + ", " + compileContext + ")"); if (refname == null) return; if (compileContext.getPattern().isTypedVar(refname)) { diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/filters/AnnotationFilter.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/filters/AnnotationFilter.java new file mode 100644 index 000000000000..82cb4baadb20 --- /dev/null +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/filters/AnnotationFilter.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.structuralsearch.impl.matcher.filters; + +import com.intellij.dupLocator.util.NodeFilter; +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiElement; + +/** + * @author Bas + */ +public class AnnotationFilter implements NodeFilter { + + private static class NodeFilterHolder { + private static final NodeFilter instance = new AnnotationFilter(); + } + + public static NodeFilter getInstance() { + return NodeFilterHolder.instance; + } + + private AnnotationFilter() {} + + public boolean accepts(PsiElement element) { + return element instanceof PsiAnnotation; + } +} diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/handlers/AnnotationHandler.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/handlers/AnnotationHandler.java new file mode 100644 index 000000000000..b94db3dea319 --- /dev/null +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/handlers/AnnotationHandler.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.structuralsearch.impl.matcher.handlers; + +import com.intellij.psi.PsiElement; +import com.intellij.structuralsearch.impl.matcher.MatchContext; +import com.intellij.structuralsearch.impl.matcher.filters.AnnotationFilter; + +/** + * @author Bas + */ +public class AnnotationHandler extends MatchingHandler { + + public AnnotationHandler() { + setFilter(AnnotationFilter.getInstance()); + } + + public boolean match(PsiElement patternNode, PsiElement matchedNode, MatchContext context) { + if (!super.match(patternNode,matchedNode,context)) { + return false; + } + + final PsiElement element = patternNode.getFirstChild().getFirstChild(); + return context.getMatcher().match(element, matchedNode); + } +} diff --git a/platform/structuralsearch/source/messages/SSRBundle.properties b/platform/structuralsearch/source/messages/SSRBundle.properties index 9cf09ff14739..d65271e16c46 100644 --- a/platform/structuralsearch/source/messages/SSRBundle.properties +++ b/platform/structuralsearch/source/messages/SSRBundle.properties @@ -117,7 +117,8 @@ predefined.configuration.usage.of.derived.type.in.cast=usage of derived type in predefined.configuration.annotated.methods=annotated methods predefined.configuration.not.annotated.methods=not annotated methods predefined.configuration.annotation.declarations=annotation declarations -predefined.configuration.annotated.class=annotated class +predefined.configuration.annotations=annotations +predefined.configuration.annotated.class=annotated classes predefined.configuration.entity.ejb=entity ejb predefined.configuration.generic.methods=generic methods predefined.configuration.cloneable.implementations=Cloneable implementations diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index 8914b301f4cc..3de78a14a9f7 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -2427,6 +2427,15 @@ public class StructuralSearchTest extends StructuralSearchTestCase { assertEquals("Find annotated new expression", 1, findMatchesCount(source1, "new Object()")); assertEquals("Find annotated new expression", 1, findMatchesCount(source1, "new @B Object()")); assertEquals("Find annotated new expression", 0, findMatchesCount(source1, "new @C Object()")); + + String source2 = "@X\n" + + "class A {\n" + + " @Y int value;" + + " @Y int void m(@Z int i) {\n" + + " return 1;\n" + + " }\n" + + "}\n"; + assertEquals("Find all annotations", 4, findMatchesCount(source2, "@'_Annotation")); } public void testBoxingAndUnboxing() {