From 31ad4f8451d8e9da74f21bd19156e9a937872cf1 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Thu, 12 Dec 2013 19:20:03 +0400 Subject: [PATCH] Annotation parameter must be constant --- .../jet/lang/diagnostics/Errors.java | 3 ++ .../rendering/DefaultErrorMessages.java | 3 ++ .../jet/lang/resolve/AnnotationResolver.java | 15 ++++++++ .../jet/lang/resolve/AnnotationUtils.java | 2 +- .../annotationParameterMustBeClassLiteral.kt | 14 ++++++++ .../annotationParameterMustBeConstant.kt | 36 +++++++++++++++++++ .../annotationParameterMustBeEnumConst.kt | 13 +++++++ .../checkers/JetDiagnosticsTestGenerated.java | 15 ++++++++ 8 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeClassLiteral.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeEnumConst.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index db8f325dde8..3a4e11b21d4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -117,6 +117,9 @@ public interface Errors { DiagnosticFactory0 NULLABLE_TYPE_OF_ANNOTATION_MEMBER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 ILLEGAL_ANNOTATION_KEYWORD = DiagnosticFactory0 .create(ERROR, modifierSetPosition(JetTokens.ANNOTATION_KEYWORD)); + DiagnosticFactory0 ANNOTATION_PARAMETER_MUST_BE_CONST = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 ANNOTATION_PARAMETER_MUST_BE_CLASS_LITERAL = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST = DiagnosticFactory0.create(ERROR); // Classes and traits diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index 89c3137068c..403061e7fae 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -456,6 +456,9 @@ public class DefaultErrorMessages { MAP.put(INVALID_TYPE_OF_ANNOTATION_MEMBER, "Invalid type of annotation member"); MAP.put(NULLABLE_TYPE_OF_ANNOTATION_MEMBER, "An annotation parameter cannot be nullable"); MAP.put(ILLEGAL_ANNOTATION_KEYWORD, "''annotation'' keyword is only applicable for class"); + MAP.put(ANNOTATION_PARAMETER_MUST_BE_CONST, "An annotation parameter must be a compile-time constant"); + MAP.put(ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST, "An enum annotation parameter must be a enum constant"); + MAP.put(ANNOTATION_PARAMETER_MUST_BE_CLASS_LITERAL, "An annotation parameter must be a class literal"); MAP.put(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE, "An overriding function is not allowed to specify default values for its parameters"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index a13473922dd..8e246ba8bda 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -255,6 +255,21 @@ public class AnnotationResolver { if (constant != null) { constants.add(constant); } + else { + JetType expressionType = trace.get(BindingContext.EXPRESSION_TYPE, argumentExpression); + if (expressionType != null && expressionType.equals(expectedType)) { + ClassifierDescriptor descriptor = expressionType.getConstructor().getDeclarationDescriptor(); + if (descriptor != null && DescriptorUtils.isEnumClass(descriptor)) { + trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_ENUM_CONST.on(argumentExpression)); + } + else if (descriptor instanceof ClassDescriptor && AnnotationUtils.isJavaLangClass((ClassDescriptor) descriptor)) { + trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_CLASS_LITERAL.on(argumentExpression)); + } + else { + trace.report(Errors.ANNOTATION_PARAMETER_MUST_BE_CONST.on(argumentExpression)); + } + } + } } } return constants; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtils.java index 80013dc570d..baf18799387 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationUtils.java @@ -125,7 +125,7 @@ public class AnnotationUtils { return false; } - private static boolean isJavaLangClass(ClassDescriptor descriptor) { + public static boolean isJavaLangClass(ClassDescriptor descriptor) { return "java.lang.Class".equals(DescriptorUtils.getFQName(descriptor).asString()); } diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeClassLiteral.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeClassLiteral.kt new file mode 100644 index 00000000000..1c043cd0a2e --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeClassLiteral.kt @@ -0,0 +1,14 @@ +annotation class AnnC(val c: Class<*>) + +AnnC(c) +class Test + +AnnC(javaClass()) +class Test2 + +val c: Class<*> = javaClass() + +class A + +// from stdlib +fun javaClass() : Class = null as Class diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant.kt new file mode 100644 index 00000000000..ec35fcd1b5b --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant.kt @@ -0,0 +1,36 @@ +annotation class Ann(val i: Int) +annotation class AnnIA(val ia: IntArray) +annotation class AnnSA(val sa: Array) + +Ann(MyClass().i) +Ann(O.i) +Ann(i) +Ann(i2) +AnnIA(ia) +AnnSA(sa) +class Test { + val i = 1 + Ann(i) val i2 = 1 +} + +var i = 1 +val i2 = foo() + +fun foo(): Int = 1 + +class MyClass { + val i = 1 +} + +object O { + val i = 1 +} + +val ia: IntArray = intArray(1, 2) +val sa: Array = array("a", "b") + +annotation class Ann2 + +// from stdlib +fun array(vararg t : T) : Array = t +fun intArray(vararg content : Int) : IntArray = content diff --git a/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeEnumConst.kt b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeEnumConst.kt new file mode 100644 index 00000000000..ab88f5793da --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeEnumConst.kt @@ -0,0 +1,13 @@ +annotation class AnnE(val i: MyEnum) + +AnnE(e) +class Test + +val e: MyEnum = MyEnum.A + +enum class MyEnum { + A +} + +AnnE(Test()) +class Test2 \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index c331c6b321f..793b56df7e2 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -540,6 +540,21 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/annotations/annotationModifier.kt"); } + @TestMetadata("annotationParameterMustBeClassLiteral.kt") + public void testAnnotationParameterMustBeClassLiteral() throws Exception { + doTest("compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeClassLiteral.kt"); + } + + @TestMetadata("annotationParameterMustBeConstant.kt") + public void testAnnotationParameterMustBeConstant() throws Exception { + doTest("compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeConstant.kt"); + } + + @TestMetadata("annotationParameterMustBeEnumConst.kt") + public void testAnnotationParameterMustBeEnumConst() throws Exception { + doTest("compiler/testData/diagnostics/tests/annotations/annotationParameterMustBeEnumConst.kt"); + } + @TestMetadata("AnnotationsForClasses.kt") public void testAnnotationsForClasses() throws Exception { doTest("compiler/testData/diagnostics/tests/annotations/AnnotationsForClasses.kt");