From fd80f6c26d74c0b37196c0ab056161effa92e2c1 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 22 Feb 2013 17:13:59 +0400 Subject: [PATCH] IDEA-100100 Groovy 2.1: applicability of annotation aliases is not checked if annotations are passed to @AnnotationCollector as a list --- .../annotator/GrAliasAnnotationChecker.java | 33 +++------- .../groovy/annotator/GroovyAnnotator.java | 2 +- .../GrAnnotationNameValuePairImpl.java | 14 +++-- .../modifiers/GrAnnotationCollector.java | 23 +++++-- .../GrAnnotationHighlightingTest.groovy | 62 ++++++++++++++++++- .../GroovyHighlightingTest.groovy | 39 ------------ 6 files changed, 96 insertions(+), 77 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAliasAnnotationChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAliasAnnotationChecker.java index a379b76cda3b..fc1071d13a40 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAliasAnnotationChecker.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrAliasAnnotationChecker.java @@ -21,12 +21,9 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyBundle; -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.modifiers.GrAnnotationCollector; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; @@ -39,32 +36,20 @@ import java.util.Set; * @author Max Medvedev */ public class GrAliasAnnotationChecker extends CustomAnnotationChecker { - @Nullable - private static GrTypeDefinition resolveAlias(@NotNull GrAnnotation annotation) { - final GrCodeReferenceElement ref = annotation.getClassReference(); - - final PsiElement resolved = ref.resolve(); - if (GrAnnotationCollector.findAnnotationCollector(resolved) != null) { - assert resolved instanceof GrTypeDefinition; - return ((GrTypeDefinition)(resolved)); - } - - - return null; - } @Override public boolean checkApplicability(@NotNull AnnotationHolder holder, @NotNull GrAnnotation annotation) { - final GrTypeDefinition alias = resolveAlias(annotation); - if (alias == null) { + final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation); + if (annotationCollector == null) { return false; } final GrCodeReferenceElement ref = annotation.getClassReference(); - final GrModifierList list = alias.getModifierList(); - assert list != null; - for (GrAnnotation anno : list.getRawAnnotations()) { + final ArrayList aliasedAnnotations = ContainerUtil.newArrayList(); + GrAnnotationCollector.collectAnnotations(aliasedAnnotations, annotation, annotationCollector); + + for (GrAnnotation anno : aliasedAnnotations) { if (GroovyCommonClassNames.GROOVY_TRANSFORM_ANNOTATION_COLLECTOR.equals(anno.getQualifiedName())) continue; final String description = CustomAnnotationChecker.isAnnotationApplicable(anno, annotation.getParent()); if (description != null) { @@ -77,14 +62,12 @@ public class GrAliasAnnotationChecker extends CustomAnnotationChecker { @Override public boolean checkArgumentList(@NotNull AnnotationHolder holder, @NotNull GrAnnotation annotation) { - final GrTypeDefinition alias = resolveAlias(annotation); - if (alias == null) { + final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation); + if (annotationCollector == null) { return false; } final ArrayList annotations = ContainerUtil.newArrayList(); - final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(alias); - assert annotationCollector != null; final Set usedAttributes = GrAnnotationCollector.collectAnnotations(annotations, annotation, annotationCollector); final GrCodeReferenceElement ref = annotation.getClassReference(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 8e1810d0a3dc..bc09365a7ce3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -799,7 +799,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { PsiElement resolved = refElement.resolve(); if (resolved instanceof PsiClass && (((PsiClass)resolved).isAnnotationType() || - GrAnnotationCollector.findAnnotationCollector(resolved) != null && + GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved) != null && refElement.getParent() instanceof GrAnnotation)) { myHolder.createInfoAnnotation(refElement, null).setTextAttributes(ANNOTATION); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java index 85ecc72a93ad..3d074c17f6c0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationNameValuePairImpl.java @@ -178,13 +178,15 @@ public class GrAnnotationNameValuePairImpl extends GroovyPsiElementImpl implemen String declaredName = getName(); String name = declaredName == null ? PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME : declaredName; - final GrAnnotation collector = GrAnnotationCollector.findAnnotationCollector(resolved); - if (collector != null) { - return multiResolveFromAlias(annotation, name, collector); - } + if (resolved instanceof PsiClass) { + final GrAnnotation collector = GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved); + if (collector != null) { + return multiResolveFromAlias(annotation, name, collector); + } - if (resolved instanceof PsiClass && ((PsiClass)resolved).isAnnotationType()) { - return multiResolveFromAnnotationType((PsiClass)resolved, name); + if (((PsiClass)resolved).isAnnotationType()) { + return multiResolveFromAnnotationType((PsiClass)resolved, name); + } } } return GroovyResolveResult.EMPTY_ARRAY; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrAnnotationCollector.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrAnnotationCollector.java index 0175323e7e9d..7b9710e932e4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrAnnotationCollector.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrAnnotationCollector.java @@ -26,6 +26,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation. import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightAnnotation; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; @@ -42,8 +43,7 @@ public class GrAnnotationCollector { List result = ContainerUtil.newArrayList(); for (GrAnnotation annotation : rawAnnotations) { - final PsiElement resolved = annotation.getClassReference().resolve(); - final GrAnnotation annotationCollector = findAnnotationCollector(resolved); + final GrAnnotation annotationCollector = findAnnotationCollector(annotation); if (annotationCollector != null) { collectAnnotations(result, annotation, annotationCollector); } @@ -58,8 +58,7 @@ public class GrAnnotationCollector { private static boolean hasAliases(GrAnnotation[] rawAnnotations) { for (GrAnnotation annotation : rawAnnotations) { - final PsiElement resolved = annotation.getClassReference().resolve(); - final GrAnnotation annotationCollector = findAnnotationCollector(resolved); + final GrAnnotation annotationCollector = findAnnotationCollector(annotation); if (annotationCollector != null) { return true; } @@ -164,7 +163,7 @@ public class GrAnnotationCollector { } @Nullable - public static GrAnnotation findAnnotationCollector(PsiElement clazz) { + public static GrAnnotation findAnnotationCollector(PsiClass clazz) { if (clazz instanceof GrTypeDefinition) { final GrModifierList modifierList = ((GrTypeDefinition)clazz).getModifierList(); if (modifierList != null) { @@ -178,4 +177,18 @@ public class GrAnnotationCollector { return null; } + + + @Nullable + public static GrAnnotation findAnnotationCollector(@NotNull GrAnnotation annotation) { + final GrCodeReferenceElement ref = annotation.getClassReference(); + + final PsiElement resolved = ref.resolve(); + if (resolved instanceof PsiClass) { + return findAnnotationCollector((PsiClass)resolved); + } + else { + return null; + } + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/aliasAnnotations/GrAnnotationHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/aliasAnnotations/GrAnnotationHighlightingTest.groovy index 91b136bd0f6f..9beb849df765 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/aliasAnnotations/GrAnnotationHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/aliasAnnotations/GrAnnotationHighlightingTest.groovy @@ -81,7 +81,7 @@ import groovy.transform.* @AnnotationCollector([EqualsAndHashCode, Immutable]) @interface Alias {} -@Alias(excludes = ['a']) +@Alias(excludes = ['a']) int foo ''') } @@ -137,6 +137,66 @@ import groovy.transform.* class Foo { Integer a, b } +''') + } + + public void testAnnotationCollectorInterfaceWithAttrs() { + testHighlighting('''\ +@interface Foo { + int foo() +} + + +@groovy.transform.AnnotationCollector +@Foo +@interface A { + int bar() +} + +@A(foo = 2) +class X{} +''') + } + + public void testAnnotationCollectorClass() { + testHighlighting(''' +@interface Foo { + int foo() +} + +@groovy.transform.AnnotationCollector +@Foo +class A { + int bar() {} +} + +class B{} + +@A(foo = 2) +@B +class X {} +''') + } + + void testInapplicableAlias2() { + testHighlighting('''\ +import groovy.transform.AnnotationCollector +import groovy.transform.Immutable +import groovy.transform.ToString + +@AnnotationCollector([Immutable, ToString]) +@interface Alias4 {} + +@Immutable +@ToString +@AnnotationCollector +@interface Alias5 {} + +@Alias4 +def aaa() {} + +@Alias5 +def bbb() {} ''') } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy index bd64b661cac2..e580466e0d0a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy @@ -1120,43 +1120,4 @@ print(A { - int bar() -} - -@A(foo = 2) -class X{} -''') - } - - public void testAnnotationCollectorClass() { - testHighlighting(''' -@interface Foo { - int foo() -} - -@groovy.transform.AnnotationCollector -@Foo -class A { - int bar() {} -} - -class B{} - -@A(foo = 2) -@B -class X {} -''') - - - } } \ No newline at end of file