Prohibit instantiation of annotation classes
#KT-3465 Fixed
This commit is contained in:
@@ -111,6 +111,7 @@ public interface Errors {
|
||||
|
||||
// Annotations
|
||||
|
||||
DiagnosticFactory0<JetCallExpression> ANNOTATION_CLASS_CONSTRUCTOR_CALL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<JetAnnotationEntry, String> NOT_AN_ANNOTATION_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> ANNOTATION_CLASS_WITH_BODY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetTypeReference> INVALID_TYPE_OF_ANNOTATION_MEMBER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
+1
@@ -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");
|
||||
|
||||
+23
@@ -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<? extends CallableDescriptor> results,
|
||||
@NotNull BindingTrace trace, @NotNull JetExpression expression) {
|
||||
if (!results.isSingleResult()) return;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface JavaAnn {
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
JavaAnn("value") class MyClass
|
||||
|
||||
fun box(): String {
|
||||
val ann = javaClass<MyClass>().getAnnotation(javaClass<JavaAnn>())
|
||||
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"
|
||||
}
|
||||
@@ -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() {
|
||||
<!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>
|
||||
val <!UNUSED_VARIABLE!>a<!> = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>
|
||||
|
||||
<!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann1(<!NO_VALUE_FOR_PARAMETER!>)<!><!>
|
||||
<!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann1(1)<!>
|
||||
bar(<!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>)
|
||||
bar(a = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>)
|
||||
|
||||
val ann = javaClass<MyClass>().getAnnotation(javaClass<Ann4>())
|
||||
ann!!.value()
|
||||
}
|
||||
|
||||
fun bar(a: Ann = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>Ann()<!>) {
|
||||
if (a is Ann) {}
|
||||
}
|
||||
|
||||
fun String.invoke() {}
|
||||
|
||||
// from stdlib
|
||||
fun <T> javaClass() : Class<T> = null <!CAST_NEVER_SUCCEEDS!>as<!> Class<T>
|
||||
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user