diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java index e6781ce9ed50..4c70eeffdf63 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -658,7 +658,16 @@ public class PsiImplUtil { findApplicableTarget((PsiAnnotation)element, TargetType.TYPE_USE) == TargetType.TYPE_USE; } - @Nullable + public static void collectTypeUseAnnotations(@NotNull PsiModifierList modifierList, @NotNull List annotations) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (isTypeAnnotation(annotation)) { + annotations.add(annotation); + } + } + } + + /** @deprecated use {@link #collectTypeUseAnnotations(PsiModifierList, List)} (to be removed in IDEA 16) */ + @SuppressWarnings("unused") public static List getTypeUseAnnotations(@NotNull PsiModifierList modifierList) { SmartList result = null; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 7b8c2632dd70..29305d4d75e6 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -592,10 +592,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme if (!isQualified()) { PsiModifierList modifierList = PsiImplUtil.findNeighbourModifierList(this); if (modifierList != null) { - List typeAnnotations = PsiImplUtil.getTypeUseAnnotations(modifierList); - if (typeAnnotations != null && !typeAnnotations.isEmpty()) { - annotations.addAll(typeAnnotations); - } + PsiImplUtil.collectTypeUseAnnotations(modifierList, annotations); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java index fae8063dbe7e..8df615aa7c91 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java @@ -37,6 +37,8 @@ import org.jetbrains.annotations.Nullable; import java.util.List; public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeElement { + private static final Class[] INTERMEDIATES = {PsiComment.class, PsiWhiteSpace.class, PsiAnnotation.class, PsiTypeParameterList.class}; + @SuppressWarnings({"UnusedDeclaration"}) public PsiTypeElementImpl() { this(JavaElementType.TYPE); @@ -69,7 +71,7 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl } private PsiType calculateType() { - final PsiType inferredType = PsiAugmentProvider.getInferredType(this); + PsiType inferredType = PsiAugmentProvider.getInferredType(this); if (inferredType != null) { return inferredType; } @@ -153,16 +155,13 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl return type == null ? PsiType.NULL : type; } - private void addTypeUseAnnotations(List list) { + private void addTypeUseAnnotations(List annotations) { PsiElement parent = this; while (parent instanceof PsiTypeElement) { - PsiElement left = PsiTreeUtil.skipSiblingsBackward(parent, PsiComment.class, PsiWhiteSpace.class, PsiAnnotation.class); + PsiElement left = PsiTreeUtil.skipSiblingsBackward(parent, INTERMEDIATES); if (left instanceof PsiModifierList) { - List annotations = PsiImplUtil.getTypeUseAnnotations((PsiModifierList)left); - if (annotations != null && !annotations.isEmpty()) { - list.addAll(annotations); - } + PsiImplUtil.collectTypeUseAnnotations((PsiModifierList)left, annotations); break; } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy index 98d166167804..bb2e2ba20a0b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy @@ -40,8 +40,8 @@ class AnnotatedTypeTest extends LightCodeInsightFixtureTestCase { class I { } } - class E1 extends Exception { } - class E2 extends Exception { }""".stripIndent()) + @SuppressWarnings("ExceptionClassNameDoesntEndWithException") class E1 extends Exception { } + @SuppressWarnings("ExceptionClassNameDoesntEndWithException") class E2 extends Exception { }""".stripIndent()) } public void testPrimitiveArrayType() { @@ -78,20 +78,32 @@ class AnnotatedTypeTest extends LightCodeInsightFixtureTestCase { public void testDisjunctionType() { def psi = factory.createStatementFromText("try { } catch (@A @TA(1) E1 | @TA(2) E2 e) { }", context) as PsiTryStatement - assertTypeText(psi.catchBlockParameters[0].type, "pkg.@pkg.TA(1) E1 | pkg.@pkg.TA(2) E2", "pkg.E1 | pkg.E2") + assertTypeText psi.catchBlockParameters[0].type, "pkg.@pkg.TA(1) E1 | pkg.@pkg.TA(2) E2", "pkg.E1 | pkg.E2" } public void testDiamondType() { def psi = factory.createStatementFromText("Class<@TA String> cs = new Class<>()", context) as PsiDeclarationStatement def var = psi.declaredElements[0] as PsiVariable - assertTypeText(var.initializer.type, "java.lang.Class", "java.lang.Class") + assertTypeText var.initializer.type, "java.lang.Class", "java.lang.Class" } public void testImmediateClassType() { def aClass = myFixture.javaFacade.findClass(CommonClassNames.JAVA_LANG_OBJECT) def annotations = factory.createParameterFromText("@TA int x", context).modifierList.annotations def type = new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY, LanguageLevel.JDK_1_8, annotations) - assertTypeText(type, "java.lang.@pkg.TA Object", CommonClassNames.JAVA_LANG_OBJECT) + assertTypeText type, "java.lang.@pkg.TA Object", CommonClassNames.JAVA_LANG_OBJECT + } + + public void testFieldType() { + def psi = factory.createFieldFromText("@A @TA(1) String f;", context) + assertTypeText psi.type, "java.lang.@pkg.TA(1) String", "java.lang.String" + assertAnnotations psi.type, "@TA(1)" + } + + public void testMethodReturnType() { + def psi = factory.createMethodFromText("@A @TA(1) String m() { return null; }", context) + assertTypeText psi.returnType, "java.lang.@pkg.TA(1) String", "java.lang.String" + assertAnnotations psi.returnType, "@TA(1)" } private void doTest(String text, String annotated, String canonical) { @@ -102,4 +114,8 @@ class AnnotatedTypeTest extends LightCodeInsightFixtureTestCase { assert type.getCanonicalText(true) == annotated assert type.getCanonicalText(false) == canonical } + + private static void assertAnnotations(PsiType type, String... annotations) { + assert type.annotations.collect { it.text } == annotations.toList() + } } \ No newline at end of file