From 9b5d3d5be928e0d755c430861ba0b97dbe168019 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 5 Jul 2013 15:14:56 +0400 Subject: [PATCH] IDEA-80399 inject language into variables declared without types --- .../intelliLang/util/AnnotationUtilEx.java | 17 +++++++++++ .../groovy/GrConcatenationInjector.java | 29 ++++++++++++++----- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/AnnotationUtilEx.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/AnnotationUtilEx.java index ac270a37b760..2397b47701e5 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/AnnotationUtilEx.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/AnnotationUtilEx.java @@ -195,6 +195,23 @@ public class AnnotationUtilEx { boolean inHierarchy) { if (!PsiUtilEx.isLanguageAnnotationTarget(owner)) return PsiAnnotation.EMPTY_ARRAY; + return getAnnotationsFromImpl(owner, annotationName, allowIndirect, inHierarchy); + } + + + /** + * The parameter allowIndirect determines if the method should look for indirect annotations, i.e. + * annotations which have themselves been annotated by the supplied annotation name. Currently, this only allows + * one level of indirection and returns an array of [base-annotation, indirect annotation] + *

+ * The annotationName parameter is a pair of the target annotation class' fully qualified name as a + * String and as a Set. This is done for performance reasons because the Set is required by the + * {@link com.intellij.codeInsight.AnnotationUtil} utility class and allows to avoid unecessary object constructions. + */ + + public static PsiAnnotation[] getAnnotationsFromImpl(PsiModifierListOwner owner, + Pair> annotationName, + boolean allowIndirect, boolean inHierarchy) { final PsiAnnotation directAnnotation = inHierarchy? AnnotationUtil.findAnnotationInHierarchy(owner, annotationName.second) : AnnotationUtil.findAnnotation(owner, annotationName.second); diff --git a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationInjector.java b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationInjector.java index 41d97a5bfe84..b83f706e9796 100644 --- a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationInjector.java +++ b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationInjector.java @@ -27,6 +27,7 @@ import org.intellij.plugins.intelliLang.inject.InjectedLanguage; import org.intellij.plugins.intelliLang.inject.InjectorUtils; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.intellij.plugins.intelliLang.util.AnnotationUtilEx; +import org.intellij.plugins.intelliLang.util.PsiUtilEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -36,6 +37,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; import java.util.Collections; @@ -52,21 +54,18 @@ public class GrConcatenationInjector implements MultiHostInjector { assert context instanceof GrLiteral; final GrLiteral literal = (GrLiteral)context; - if (!(literal instanceof PsiLanguageInjectionHost)) return; - final PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)literal; - final PsiElement parent = literal.getParent(); if (parent instanceof GrAssignmentExpression && ((GrAssignmentExpression)parent).getRValue() == literal) { final GrExpression lvalue = ((GrAssignmentExpression)parent).getLValue(); if (lvalue instanceof GrReferenceExpression) { final PsiElement resolved = ((GrReferenceExpression)lvalue).resolve(); if (resolved instanceof PsiModifierListOwner) { - processAnnotations(registrar, host, (PsiModifierListOwner)resolved); + processAnnotations(registrar, literal, (PsiModifierListOwner)resolved); } } } else if (parent instanceof GrVariable) { - processAnnotations(registrar, host, ((GrVariable)parent)); + processAnnotations(registrar, literal, ((GrVariable)parent)); } else if (parent instanceof GrArgumentList) { final PsiElement pparent = parent.getParent(); @@ -80,7 +79,7 @@ public class GrConcatenationInjector implements MultiHostInjector { if (map != null) { final Pair pair = map.get(literal); - processAnnotations(registrar, host, pair.first); + processAnnotations(registrar, literal, pair.first); } } } @@ -93,7 +92,7 @@ public class GrConcatenationInjector implements MultiHostInjector { final Pair> pair = Configuration.getInstance().getAdvancedConfiguration().getLanguageAnnotationPair(); - final PsiAnnotation[] annotations = AnnotationUtilEx.getAnnotationFrom(annotationOwner, pair, true); + final PsiAnnotation[] annotations = getAnnotationFrom(annotationOwner, pair, true, true); if (annotations.length > 0) { final String id = AnnotationUtilEx.calcAnnotationValue(annotations, "value"); final String prefix = AnnotationUtilEx.calcAnnotationValue(annotations, "prefix"); @@ -115,6 +114,22 @@ public class GrConcatenationInjector implements MultiHostInjector { } } + @NotNull + public static PsiAnnotation[] getAnnotationFrom(PsiModifierListOwner owner, + Pair> annotationName, + boolean allowIndirect, + boolean inHierarchy) { + if (!isLanguageAnnotationTargetGroovy(owner)) return PsiAnnotation.EMPTY_ARRAY; + + return AnnotationUtilEx.getAnnotationsFromImpl(owner, annotationName, allowIndirect, inHierarchy); + } + + private static boolean isLanguageAnnotationTargetGroovy(PsiModifierListOwner owner) { + return owner instanceof GrMethod && ((GrMethod)owner).getReturnTypeElementGroovy() == null || + owner instanceof GrVariable && ((GrVariable)owner).getTypeElementGroovy() == null || + PsiUtilEx.isLanguageAnnotationTarget(owner); + } + @NotNull @Override public List> elementsToInjectIn() {