mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-100100 Groovy 2.1: applicability of annotation aliases is not checked if annotations are passed to @AnnotationCollector as a list
This commit is contained in:
+8
-25
@@ -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<GrAnnotation> 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<GrAnnotation> annotations = ContainerUtil.newArrayList();
|
||||
final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(alias);
|
||||
assert annotationCollector != null;
|
||||
final Set<String> usedAttributes = GrAnnotationCollector.collectAnnotations(annotations, annotation, annotationCollector);
|
||||
|
||||
final GrCodeReferenceElement ref = annotation.getClassReference();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+8
-6
@@ -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;
|
||||
|
||||
+18
-5
@@ -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<GrAnnotation> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+61
-1
@@ -81,7 +81,7 @@ import groovy.transform.*
|
||||
@AnnotationCollector([EqualsAndHashCode, Immutable])
|
||||
@interface Alias {}
|
||||
|
||||
@<error descr="'@ToString' not applicable to local variable">Alias</error>(excludes = ['a'])
|
||||
@<error descr="'@groovy.transform.EqualsAndHashCode' not applicable to local variable"><error descr="'@groovy.transform.Immutable' not applicable to local variable"><error descr="'@groovy.transform.ToString' not applicable to local variable">Alias</error></error></error>(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 <error descr="Annotation type annotated with @AnnotationCollector cannot have attributes">A</error> {
|
||||
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)
|
||||
@<error descr="'B' is not an annotation">B</error>
|
||||
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 {}
|
||||
|
||||
@<error descr="'@groovy.transform.Immutable' not applicable to method"><error descr="'@groovy.transform.ToString' not applicable to method">Alias4</error></error>
|
||||
def aaa() {}
|
||||
|
||||
@<error descr="'@groovy.transform.Immutable' not applicable to method"><error descr="'@groovy.transform.ToString' not applicable to method">Alias5</error></error>
|
||||
def bbb() {}
|
||||
''')
|
||||
}
|
||||
}
|
||||
|
||||
-39
@@ -1120,43 +1120,4 @@ print(<error descr="Collection literal contains named and expression arguments a
|
||||
''')
|
||||
}
|
||||
|
||||
public void testAnnotationCollectorInterfaceWithAttrs() {
|
||||
testHighlighting('''\
|
||||
@interface Foo {
|
||||
int foo()
|
||||
}
|
||||
|
||||
|
||||
@groovy.transform.AnnotationCollector
|
||||
@Foo
|
||||
@interface <error descr="Annotation type annotated with @AnnotationCollector cannot have attributes">A</error> {
|
||||
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)
|
||||
@<error descr="'B' is not an annotation">B</error>
|
||||
class X {}
|
||||
''')
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user