IDEA-58158 (check when annotation parameter value must be .class)

This commit is contained in:
Roman Shevchenko
2012-10-29 14:16:46 +01:00
parent 835cedda09
commit e666bf7998
4 changed files with 35 additions and 12 deletions
@@ -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;
}
@@ -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
@@ -0,0 +1,13 @@
@interface Ann {
Class type();
}
class C {
private static final Class<C> THIS_TYPE = C.class;
@Ann(type = <error descr="Attribute value must be a class literal">THIS_TYPE</error>)
void bad() { }
@Ann(type = C.class)
void good() { }
}
@@ -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); }