IDEA-111989 Groovy @CompileDynamic not recognised as an AST annotation

This commit is contained in:
Max Medvedev
2013-08-19 18:20:18 +04:00
parent 2c15c5bd74
commit 5de2d3cd05
10 changed files with 87 additions and 37 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.annotator;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
@@ -39,7 +40,7 @@ public class GrAliasAnnotationChecker extends CustomAnnotationChecker {
@Override
public boolean checkApplicability(@NotNull AnnotationHolder holder, @NotNull GrAnnotation annotation) {
final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation);
final PsiAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation);
if (annotationCollector == null) {
return false;
}
@@ -62,7 +63,7 @@ public class GrAliasAnnotationChecker extends CustomAnnotationChecker {
@Override
public boolean checkArgumentList(@NotNull AnnotationHolder holder, @NotNull GrAnnotation annotation) {
final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation);
final PsiAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector(annotation);
if (annotationCollector == null) {
return false;
}
@@ -591,7 +591,7 @@ public class GroovyCompletionUtil {
PsiElement resolved = ref.resolve();
if (resolved instanceof PsiClass) {
final GrAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved);
final PsiAnnotation annotationCollector = GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved);
if (annotationCollector != null) {
final ArrayList<GrAnnotation> annotations = ContainerUtil.newArrayList();
@@ -180,7 +180,7 @@ public class GrAnnotationNameValuePairImpl extends GroovyPsiElementImpl implemen
String name = declaredName == null ? PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME : declaredName;
if (resolved instanceof PsiClass) {
final GrAnnotation collector = GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved);
final PsiAnnotation collector = GrAnnotationCollector.findAnnotationCollector((PsiClass)resolved);
if (collector != null) {
return multiResolveFromAlias(annotation, name, collector);
}
@@ -205,7 +205,7 @@ public class GrAnnotationNameValuePairImpl extends GroovyPsiElementImpl implemen
return results;
}
private static GroovyResolveResult[] multiResolveFromAlias(@NotNull GrAnnotation alias, @NotNull String name, @NotNull GrAnnotation annotationCollector) {
private static GroovyResolveResult[] multiResolveFromAlias(@NotNull GrAnnotation alias, @NotNull String name, @NotNull PsiAnnotation annotationCollector) {
List<GroovyResolveResult> result = ContainerUtilRt.newArrayList();
List<GrAnnotation> annotations = ContainerUtilRt.newArrayList();
@@ -19,13 +19,13 @@ import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
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.GrAnnotationArrayInitializer;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationMemberValue;
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;
@@ -36,6 +36,7 @@ import java.util.Map;
import java.util.Set;
public class GrAnnotationCollector {
@NotNull
public static GrAnnotation[] getResolvedAnnotations(@NotNull GrModifierList modifierList) {
final GrAnnotation[] rawAnnotations = modifierList.getRawAnnotations();
@@ -44,7 +45,7 @@ public class GrAnnotationCollector {
List<GrAnnotation> result = ContainerUtil.newArrayList();
for (GrAnnotation annotation : rawAnnotations) {
final GrAnnotation annotationCollector = findAnnotationCollector(annotation);
final PsiAnnotation annotationCollector = findAnnotationCollector(annotation);
if (annotationCollector != null) {
collectAnnotations(result, annotation, annotationCollector);
}
@@ -59,7 +60,7 @@ public class GrAnnotationCollector {
private static boolean hasAliases(@NotNull GrAnnotation[] rawAnnotations) {
for (GrAnnotation annotation : rawAnnotations) {
final GrAnnotation annotationCollector = findAnnotationCollector(annotation);
final PsiAnnotation annotationCollector = findAnnotationCollector(annotation);
if (annotationCollector != null) {
return true;
}
@@ -78,21 +79,19 @@ public class GrAnnotationCollector {
@NotNull
public static Set<String> collectAnnotations(@NotNull List<GrAnnotation> list,
@NotNull GrAnnotation alias,
@NotNull GrAnnotation annotationCollector) {
@NotNull PsiAnnotation annotationCollector) {
final GrModifierList modifierList = (GrModifierList)annotationCollector.getParent();
final PsiModifierList modifierList = (PsiModifierList)annotationCollector.getParent();
Map<String, Map<String, GrAnnotationNameValuePair>> annotations = ContainerUtil.newHashMap();
collectAliasedAnnotationsFromAnnotationCollectorValueAttribute(annotationCollector,
(HashMap<String, Map<String, GrAnnotationNameValuePair>>)annotations);
collectAliasedAnnotationsFromAnnotationCollectorAnnotations(modifierList,
(HashMap<String, Map<String, GrAnnotationNameValuePair>>)annotations);
Map<String, Map<String, PsiNameValuePair>> annotations = ContainerUtil.newHashMap();
collectAliasedAnnotationsFromAnnotationCollectorValueAttribute(annotationCollector, (HashMap<String, Map<String, PsiNameValuePair>>)annotations);
collectAliasedAnnotationsFromAnnotationCollectorAnnotations(modifierList, (HashMap<String, Map<String, PsiNameValuePair>>)annotations);
final PsiManager manager = alias.getManager();
final GrAnnotationNameValuePair[] attributes = alias.getParameterList().getAttributes();
Set<String> allUsedAttrs = ContainerUtil.newHashSet();
for (Map.Entry<String, Map<String, GrAnnotationNameValuePair>> entry : annotations.entrySet()) {
for (Map.Entry<String, Map<String, PsiNameValuePair>> entry : annotations.entrySet()) {
final String qname = entry.getKey();
final PsiClass resolved = JavaPsiFacade.getInstance(alias.getProject()).findClass(qname, alias.getResolveScope());
if (resolved == null) continue;
@@ -110,8 +109,8 @@ public class GrAnnotationCollector {
}
final Map<String, GrAnnotationNameValuePair> defaults = entry.getValue();
for (Map.Entry<String, GrAnnotationNameValuePair> defa : defaults.entrySet()) {
final Map<String, PsiNameValuePair> defaults = entry.getValue();
for (Map.Entry<String, PsiNameValuePair> defa : defaults.entrySet()) {
if (!usedAttrs.contains(defa.getKey())) {
annotation.addAttribute(defa.getValue());
}
@@ -124,16 +123,29 @@ public class GrAnnotationCollector {
return allUsedAttrs;
}
private static void collectAliasedAnnotationsFromAnnotationCollectorAnnotations(@NotNull GrModifierList modifierList,
@NotNull HashMap<String, Map<String, GrAnnotationNameValuePair>> annotations) {
for (GrAnnotation annotation : modifierList.getRawAnnotations()) {
private static void collectAliasedAnnotationsFromAnnotationCollectorAnnotations(@NotNull PsiModifierList modifierList,
@NotNull HashMap<String, Map<String, PsiNameValuePair>> annotations) {
PsiElement parent = modifierList.getParent();
if (parent instanceof PsiClass &&
GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_DYNAMIC.equals(((PsiClass)parent).getQualifiedName())) {
HashMap<String, PsiNameValuePair> params = ContainerUtil.newHashMap();
annotations.put(GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_STATIC, params);
GrAnnotation annotation =
GroovyPsiElementFactory.getInstance(modifierList.getProject()).createAnnotationFromText("@CompileStatic(TypeCheckingMode.SKIP)");
params.put("value", annotation.getParameterList().getAttributes()[0]);
return;
}
PsiAnnotation[] rawAnnotations =
modifierList instanceof GrModifierList ? ((GrModifierList)modifierList).getRawAnnotations() : modifierList.getAnnotations();
for (PsiAnnotation annotation : rawAnnotations) {
final String qname = annotation.getQualifiedName();
if (qname == null || qname.equals(GroovyCommonClassNames.GROOVY_TRANSFORM_ANNOTATION_COLLECTOR)) continue;
final GrAnnotationNameValuePair[] attributes = annotation.getParameterList().getAttributes();
for (GrAnnotationNameValuePair pair : attributes) {
Map<String, GrAnnotationNameValuePair> map = annotations.get(qname);
final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
for (PsiNameValuePair pair : attributes) {
Map<String, PsiNameValuePair> map = annotations.get(qname);
if (map == null) {
map = ContainerUtil.newHashMap();
annotations.put(qname, map);
@@ -142,14 +154,14 @@ public class GrAnnotationCollector {
map.put(pair.getName() != null ? pair.getName() : "value", pair);
}
if (attributes.length == 0 && !annotations.containsKey(qname)) {
annotations.put(qname, ContainerUtil.<String, GrAnnotationNameValuePair>newHashMap());
annotations.put(qname, ContainerUtil.<String, PsiNameValuePair>newHashMap());
}
}
}
private static void collectAliasedAnnotationsFromAnnotationCollectorValueAttribute(@NotNull GrAnnotation annotationCollector,
@NotNull HashMap<String, Map<String, GrAnnotationNameValuePair>> annotations) {
private static void collectAliasedAnnotationsFromAnnotationCollectorValueAttribute(@NotNull PsiAnnotation annotationCollector,
@NotNull HashMap<String, Map<String, PsiNameValuePair>> annotations) {
final PsiAnnotationMemberValue annotationsFromValue = annotationCollector.findAttributeValue("value");
if (annotationsFromValue instanceof GrAnnotationArrayInitializer) {
@@ -157,7 +169,7 @@ public class GrAnnotationCollector {
if (member instanceof GrReferenceExpression) {
final PsiElement resolved = ((GrReferenceExpression)member).resolve();
if (resolved instanceof PsiClass && ((PsiClass)resolved).isAnnotationType()) {
annotations.put(((PsiClass)resolved).getQualifiedName(), ContainerUtil.<String, GrAnnotationNameValuePair>newHashMap());
annotations.put(((PsiClass)resolved).getQualifiedName(), ContainerUtil.<String, PsiNameValuePair>newHashMap());
}
}
}
@@ -165,11 +177,12 @@ public class GrAnnotationCollector {
}
@Nullable
public static GrAnnotation findAnnotationCollector(@Nullable PsiClass clazz) {
if (clazz instanceof GrTypeDefinition) {
final GrModifierList modifierList = ((GrTypeDefinition)clazz).getModifierList();
public static PsiAnnotation findAnnotationCollector(@Nullable PsiClass clazz) {
if (clazz != null) {
final PsiModifierList modifierList = clazz.getModifierList();
if (modifierList != null) {
for (GrAnnotation annotation : modifierList.getRawAnnotations()) {
PsiAnnotation[] annotations = modifierList instanceof GrModifierList ? ((GrModifierList)modifierList).getRawAnnotations() : modifierList.getAnnotations();
for (PsiAnnotation annotation : annotations) {
if (GroovyCommonClassNames.GROOVY_TRANSFORM_ANNOTATION_COLLECTOR.equals(annotation.getQualifiedName())) {
return annotation;
}
@@ -182,7 +195,7 @@ public class GrAnnotationCollector {
@Nullable
public static GrAnnotation findAnnotationCollector(@NotNull GrAnnotation annotation) {
public static PsiAnnotation findAnnotationCollector(@NotNull GrAnnotation annotation) {
final GrCodeReferenceElement ref = annotation.getClassReference();
final PsiElement resolved = ref.resolve();
@@ -22,11 +22,13 @@ import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.light.LightClassReference;
import com.intellij.psi.impl.light.LightElement;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArgumentList;
@@ -139,8 +141,20 @@ public class GrLightAnnotation extends LightElement implements GrAnnotation {
return null;
}
public void addAttribute(GrAnnotationNameValuePair attribute) {
myAnnotationArgList.addAttribute(attribute);
public void addAttribute(PsiNameValuePair attribute) {
if (attribute instanceof GrAnnotationNameValuePair) {
myAnnotationArgList.addAttribute((GrAnnotationNameValuePair)attribute);
}
else {
try {
GrAnnotation annotation =
GroovyPsiElementFactory.getInstance(getProject()).createAnnotationFromText("@Anno(" + attribute.getText() + ")");
myAnnotationArgList.addAttribute(annotation.getParameterList().getAttributes()[0]);
}
catch (IncorrectOperationException e) {
//do nothing
}
}
}
@@ -63,6 +63,7 @@ public final class GroovyCommonClassNames {
@NonNls public static final String GROOVY_LANG_NEWIFY = "groovy.lang.Newify";
@NonNls public static final String GROOVY_LANG_DELEGATES_TO = "groovy.lang.DelegatesTo";
@NonNls public static final String GROOVY_LANG_DELEGATES_TO_TARGET = "groovy.lang.DelegatesTo.Target";
@NonNls public static final String GROOVY_TRANSFORM_COMPILE_DYNAMIC = "groovy.transform.CompileDynamic";
private GroovyCommonClassNames() {
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.groovy.lang.aliasAnnotations
import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection
import org.jetbrains.plugins.groovy.lang.highlighting.GrHighlightingTestBase
/**
@@ -199,4 +200,24 @@ def aaa() {}
def bbb() {}
''')
}
void testCompileDynamic() {
testHighlighting('''\
import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
@CompileStatic
class B {
B() {
println <error>x</error>
}
@CompileDynamic
def foo() {
println <warning>y</warning>
}
}
''', GrUnresolvedAccessInspection)
}
}
@@ -1120,7 +1120,7 @@ print(<error descr="Collection literal contains named and expression arguments a
''')
}
void testDelegatesToApplicability() {
void _testDelegatesToApplicability() {
testHighlighting('''
def with(@DelegatesTo.Target Object target, @DelegatesTo Closure arg) {
arg.delegate = target
@@ -57,7 +57,7 @@ public abstract class TestUtils {
public static final String GROOVY_JAR = "groovy-all.jar";
public static final String GROOVY_JAR_17 = "groovy-all-1.7.jar";
public static final String GROOVY_JAR_18 = "groovy-1.8.0-beta-2.jar";
public static final String GROOVY_JAR_21 = "groovy-all-2.1.0-beta-1.jar";
public static final String GROOVY_JAR_21 = "groovy-all-2.1.3.jar";
public static final String GROOVY_JAR_22 = "groovy-all-2.2.0-beta-1.jar";
public static String getMockJdkHome() {