[java] PsiClassRefType returns annotations embedded in a ref (IDEA-140234, IDEA-166062)

This commit is contained in:
Roman Shevchenko
2017-04-18 11:40:54 +02:00
parent 184b08380c
commit 311fc75ff8
4 changed files with 58 additions and 8 deletions

View File

@@ -288,6 +288,11 @@ public class AnnotationUtil {
PsiAnnotation annotation = modifierList.findAnnotation(annotationFQN);
if (annotation != null) return true;
PsiType type = null;
if (listOwner instanceof PsiMethod) type = ((PsiMethod)listOwner).getReturnType();
else if (listOwner instanceof PsiVariable) type = ((PsiVariable)listOwner).getType();
if (type != null && type.findAnnotation(annotationFQN) != null) return true;
if (!skipExternal) {
final Project project = listOwner.getProject();
if (ExternalAnnotationsManager.getInstance(project).findExternalAnnotation(listOwner, annotationFQN) != null ||

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -23,10 +23,13 @@ import com.intellij.psi.impl.light.LightClassReference;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashSet;
import java.util.List;
/**
@@ -82,6 +85,34 @@ public class PsiClassReferenceType extends PsiClassType.Stub {
return getReference().getResolveScope();
}
@NotNull
@Override
public PsiAnnotation[] getAnnotations() {
return getAnnotations(true);
}
private PsiAnnotation[] getAnnotations(boolean merge) {
PsiAnnotation[] annotations = super.getAnnotations();
if (merge) {
PsiJavaCodeReferenceElement reference = myReference.compute();
if (reference != null && reference.isValid() && reference.isQualified()) {
PsiAnnotation[] embedded = collectAnnotations(reference);
if (annotations.length > 0 && embedded.length > 0) {
LinkedHashSet<PsiAnnotation> set = ContainerUtil.newLinkedHashSet();
ContainerUtil.addAll(set, annotations);
ContainerUtil.addAll(set, embedded);
annotations = set.toArray(PsiAnnotation.EMPTY_ARRAY);
}
else {
annotations = ArrayUtil.mergeArrays(annotations, embedded);
}
}
}
return annotations;
}
@Override
@NotNull
public LanguageLevel getLanguageLevel() {
@@ -198,7 +229,7 @@ public class PsiClassReferenceType extends PsiClassType.Stub {
public String getPresentableText(boolean annotated) {
String presentableText = PsiNameHelper.getPresentableText(getReference());
PsiAnnotation[] annotations = annotated ? getAnnotations() : PsiAnnotation.EMPTY_ARRAY;
PsiAnnotation[] annotations = annotated ? getAnnotations(false) : PsiAnnotation.EMPTY_ARRAY;
if (annotations.length == 0) return presentableText;
StringBuilder sb = new StringBuilder();
@@ -223,7 +254,7 @@ public class PsiClassReferenceType extends PsiClassType.Stub {
PsiJavaCodeReferenceElement reference = getReference();
if (reference instanceof PsiAnnotatedJavaCodeReferenceElement) {
PsiAnnotatedJavaCodeReferenceElement ref = (PsiAnnotatedJavaCodeReferenceElement)reference;
PsiAnnotation[] annotations = annotated ? getAnnotations() : PsiAnnotation.EMPTY_ARRAY;
PsiAnnotation[] annotations = annotated ? getAnnotations(false) : PsiAnnotation.EMPTY_ARRAY;
return ref.getCanonicalText(annotated, annotations.length == 0 ? null : annotations);
}
return reference.getCanonicalText();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -126,7 +126,7 @@ class Main2 {
}
}
"""
def file = myFixture.addClass("""\
class B implements Main1.I, Main2.I {
<caret>
@@ -171,9 +171,9 @@ class Test implements A {
}
""").containingFile.virtualFile
myFixture.configureFromExistingVirtualFile(file)
invokeAction(true)
myFixture.checkResult """\
package bar;
class Test implements A {
@@ -188,6 +188,9 @@ class Test implements A {
}
void testTypeAnnotationsInImplementedMethod() {
def handler = new OverrideImplementsAnnotationsHandler() { @Override String[] getAnnotations(Project project) { return ["TA"] } }
PlatformTestUtil.registerExtension(OverrideImplementsAnnotationsHandler.EP_NAME, handler, testRootDisposable)
myFixture.addClass """\
import java.lang.annotation.*;
@Target(ElementType.TYPE_USE)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.psi
import com.intellij.codeInsight.AnnotationUtil
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiImmediateClassType
@@ -104,6 +105,16 @@ class AnnotatedTypeTest extends LightCodeInsightFixtureTestCase {
assertAnnotations psi.returnType, "@TA(1)", "@TA(2)"
}
void testIsAnnotated() {
def unqualified = factory.createParameterFromText("@A @TA(1) String p", context)
assert AnnotationUtil.isAnnotated(unqualified, "pkg.A", false)
assert AnnotationUtil.isAnnotated(unqualified, "pkg.TA", false)
def qualified = factory.createParameterFromText("@A java.lang.@TA(1) String p", context)
assert AnnotationUtil.isAnnotated(qualified, "pkg.A", false)
assert AnnotationUtil.isAnnotated(qualified, "pkg.TA", false)
}
private void doTest(String text, String annotated, String canonical) {
assertTypeText(factory.createParameterFromText(text, context).type, annotated, canonical)
}