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 5b6dc10c4f1..3419eb1a879 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -111,6 +111,7 @@ public interface Errors { // Annotations + DiagnosticFactory0 ANNOTATION_CLASS_CONSTRUCTOR_CALL = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 NOT_AN_ANNOTATION_CLASS = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 ANNOTATION_CLASS_WITH_BODY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INVALID_TYPE_OF_ANNOTATION_MEMBER = DiagnosticFactory0.create(ERROR); 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 403061e7fae..d5162dadaaf 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 @@ -451,6 +451,7 @@ public class DefaultErrorMessages { MAP.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead.", NAME); + MAP.put(ANNOTATION_CLASS_CONSTRUCTOR_CALL, "Annotation class cannot be instantiated"); MAP.put(NOT_AN_ANNOTATION_CLASS, "''{0}'' is not an annotation class", TO_STRING); MAP.put(ANNOTATION_CLASS_WITH_BODY, "Body is not allowed for annotation class"); MAP.put(INVALID_TYPE_OF_ANNOTATION_MEMBER, "Invalid type of annotation member"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index cc20ed001d5..4afc37d39d3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -17,6 +17,8 @@ package org.jetbrains.jet.lang.resolve.calls; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -24,6 +26,7 @@ import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode; @@ -349,6 +352,12 @@ public class CallExpressionResolver { if (functionDescriptor == null) { return JetTypeInfo.create(null, context.dataFlowInfo); } + if (functionDescriptor instanceof ConstructorDescriptor && DescriptorUtils.isAnnotationClass(functionDescriptor.getContainingDeclaration())) { + if (!canInstantiateAnnotationClass(callExpression)) { + context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression)); + } + } + JetType type = functionDescriptor.getReturnType(); return JetTypeInfo.create(type, resolvedCall.getDataFlowInfoForArguments().getResultInfo()); @@ -371,6 +380,20 @@ public class CallExpressionResolver { return JetTypeInfo.create(null, context.dataFlowInfo); } + private static boolean canInstantiateAnnotationClass(@NotNull JetCallExpression expression) { + PsiElement parent = expression.getParent(); + if (parent instanceof JetValueArgument) { + return PsiTreeUtil.getParentOfType(parent, JetAnnotationEntry.class) != null; + } + else if (parent instanceof JetParameter) { + JetClass jetClass = PsiTreeUtil.getParentOfType(parent, JetClass.class); + if (jetClass != null) { + return jetClass.hasModifier(JetTokens.ANNOTATION_KEYWORD); + } + } + return false; + } + private void checkSuper(@NotNull ReceiverValue receiverValue, @NotNull OverloadResolutionResults results, @NotNull BindingTrace trace, @NotNull JetExpression expression) { if (!results.isSingleResult()) return; diff --git a/compiler/testData/codegen/boxWithJava/annotations/javaAnnotationCall.java b/compiler/testData/codegen/boxWithJava/annotations/javaAnnotationCall.java new file mode 100644 index 00000000000..7a6c8fbb6cb --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/annotations/javaAnnotationCall.java @@ -0,0 +1,7 @@ +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@interface JavaAnn { + String value(); +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/annotations/javaAnnotationCall.kt b/compiler/testData/codegen/boxWithJava/annotations/javaAnnotationCall.kt new file mode 100644 index 00000000000..75a38d9a7b2 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/annotations/javaAnnotationCall.kt @@ -0,0 +1,8 @@ +JavaAnn("value") class MyClass + +fun box(): String { + val ann = javaClass().getAnnotation(javaClass()) + if (ann == null) return "fail: cannot find Ann on MyClass}" + if (ann.value() != "value") return "fail: annotation parameter i should be 'value', but was ${ann.value()}" + return "OK" +} diff --git a/compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt b/compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt new file mode 100644 index 00000000000..35ed8d1c673 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt @@ -0,0 +1,35 @@ +annotation class Ann +annotation class Ann1(val a: Int) +annotation class Ann2(val a: Ann1) + +annotation class Ann3(val a: Ann1 = Ann1(1)) + +annotation class Ann4(val value: String) + +Ann2(Ann1(1)) val a = 1 + +Ann2(a = Ann1(1)) val c = 2 + +Ann4("a") class MyClass + +fun foo() { + Ann() + val a = Ann() + + Ann1() + Ann1(1) + bar(Ann()) + bar(a = Ann()) + + val ann = javaClass().getAnnotation(javaClass()) + ann!!.value() +} + +fun bar(a: Ann = Ann()) { + if (a is Ann) {} +} + +fun String.invoke() {} + +// from stdlib +fun javaClass() : Class = null as Class diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 64aaef8b6eb..227a21b6519 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -575,6 +575,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/annotations/BasicAnnotations.kt"); } + @TestMetadata("ConstructorCall.kt") + public void testConstructorCall() throws Exception { + doTest("compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt"); + } + @TestMetadata("Deprecated.kt") public void testDeprecated() throws Exception { doTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 4ea51752097..9036a500041 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -43,6 +43,11 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/boxWithJava/annotations"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("javaAnnotationCall.kt") + public void testJavaAnnotationCall() throws Exception { + doTestWithJava("compiler/testData/codegen/boxWithJava/annotations/javaAnnotationCall.kt"); + } + @TestMetadata("javaNegativePropertyAsAnnotationParameter.kt") public void testJavaNegativePropertyAsAnnotationParameter() throws Exception { doTestWithJava("compiler/testData/codegen/boxWithJava/annotations/javaNegativePropertyAsAnnotationParameter.kt");