From e666bf7998d5049c6d98583c2b137f3c576bf7a9 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 29 Oct 2012 14:16:46 +0100 Subject: [PATCH] IDEA-58158 (check when annotation parameter value must be .class) --- .../analysis/AnnotationsHighlightUtil.java | 32 ++++++++++++------- .../src/messages/JavaErrorMessages.properties | 1 + .../annotations/incompatibleType5.java | 13 ++++++++ .../daemon/AnnotationsHighlightingTest.java | 1 + 4 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/incompatibleType5.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index 862f6aa45171..1c06d18dc6d4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -70,6 +70,7 @@ public class AnnotationsHighlightUtil { } else { PsiType returnType = method.getReturnType(); + assert returnType != null : method; PsiAnnotationMemberValue value = pair.getValue(); HighlightInfo info = checkMemberValueType(value, returnType); if (info != null) return info; @@ -84,11 +85,10 @@ public class AnnotationsHighlightUtil { PsiNameValuePair[] attributes = annotation.getAttributes(); for (PsiNameValuePair attribute : attributes) { if (attribute == pair) break; - if (Comparing.equal(attribute.getName(), pair.getName())) { + String name = pair.getName(); + if (Comparing.equal(attribute.getName(), name)) { String description = JavaErrorMessages.message("annotation.duplicate.attribute", - pair.getName() == null - ? PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME - : pair.getName()); + name == null ? PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME : name); return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, pair, description); } } @@ -101,28 +101,35 @@ public class AnnotationsHighlightUtil { } @Nullable - public static HighlightInfo checkMemberValueType(PsiAnnotationMemberValue value, PsiType expectedType) { + public static HighlightInfo checkMemberValueType(@Nullable PsiAnnotationMemberValue value, PsiType expectedType) { if (value == null) return null; + + if (expectedType instanceof PsiClassType && expectedType.equalsToText(CommonClassNames.JAVA_LANG_CLASS)) { + if (!(value instanceof PsiClassObjectAccessExpression)) { + String description = JavaErrorMessages.message("annotation.non.class.literal.attribute.value"); + return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, value, description); + } + } + if (value instanceof PsiAnnotation) { PsiJavaCodeReferenceElement nameRef = ((PsiAnnotation)value).getNameReferenceElement(); if (nameRef == null) return null; + if (expectedType instanceof PsiClassType) { PsiClass aClass = ((PsiClassType)expectedType).resolve(); - if (nameRef.isReferenceTo(aClass)) return null; + if (aClass != null && nameRef.isReferenceTo(aClass)) return null; } if (expectedType instanceof PsiArrayType) { PsiType componentType = ((PsiArrayType)expectedType).getComponentType(); if (componentType instanceof PsiClassType) { PsiClass aClass = ((PsiClassType)componentType).resolve(); - if (nameRef.isReferenceTo(aClass)) return null; + if (aClass != null && nameRef.isReferenceTo(aClass)) return null; } } String description = JavaErrorMessages.message("annotation.incompatible.types", - formatReference(nameRef), - HighlightUtil.formatType(expectedType)); - + formatReference(nameRef), HighlightUtil.formatType(expectedType)); return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, value, description); } else if (value instanceof PsiArrayInitializerMemberValue) { @@ -134,7 +141,8 @@ public class AnnotationsHighlightUtil { PsiExpression expr = (PsiExpression)value; PsiType type = expr.getType(); if (type != null && TypeConversionUtil.areTypesAssignmentCompatible(expectedType, expr) || - expectedType instanceof PsiArrayType && TypeConversionUtil.areTypesAssignmentCompatible(((PsiArrayType)expectedType).getComponentType(), expr)) { + expectedType instanceof PsiArrayType && + TypeConversionUtil.areTypesAssignmentCompatible(((PsiArrayType)expectedType).getComponentType(), expr)) { return null; } @@ -143,7 +151,7 @@ public class AnnotationsHighlightUtil { return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, value, description); } - LOG.error("Unknown annotation member value: "+value); + LOG.error("Unknown annotation member value: " + value); return null; } diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index 588603458c1d..df767bd2e85a 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -9,6 +9,7 @@ annotation.duplicate.attribute=Duplicate attribute ''{0}'' annotation.missing.attribute={0} missing though required annotation.not.applicable=''@{0}'' not applicable to {1} annotation.non.constant.attribute.value=Attribute value must be constant +annotation.non.class.literal.attribute.value=Attribute value must be a class literal annotation.invalid.annotation.member.type=Invalid type for annotation member annotation.cyclic.element.type=Cyclic annotation element type annotation.annotation.type.expected=Annotation type expected diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/incompatibleType5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/incompatibleType5.java new file mode 100644 index 000000000000..33967c52b44c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/incompatibleType5.java @@ -0,0 +1,13 @@ +@interface Ann { + Class type(); +} + +class C { + private static final Class THIS_TYPE = C.class; + + @Ann(type = THIS_TYPE) + void bad() { } + + @Ann(type = C.class) + void good() { } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java index d129080054fc..189cd8f775ad 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java @@ -35,6 +35,7 @@ public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIncompatibleType2() { doTest(false); } public void testIncompatibleType3() { doTest(false); } public void testIncompatibleType4() { doTest(false); } + public void testIncompatibleType5() { doTest(false); } public void testMissingAttribute() { doTest(false); } public void testDuplicateAnnotation() { doTest(false); } public void testNonConstantInitializer() { doTest(false); }