Generate get-targeted annotations on annotation constructor parameters
This change would also make NotNull annotations to be generated on non-primitive annotation methods, but we skip this deliberately because annotation methods never return null on JVM anyway #KT-25287 Fixed
This commit is contained in:
committed by
Ilya Gorbunov
parent
9df949c039
commit
dc1f4c7d5b
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
|||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.resolve.AnnotationChecker;
|
import org.jetbrains.kotlin.resolve.AnnotationChecker;
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
|
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
|
||||||
import org.jetbrains.kotlin.resolve.constants.*;
|
import org.jetbrains.kotlin.resolve.constants.*;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
@@ -166,10 +167,17 @@ public abstract class AnnotationCodegen {
|
|||||||
if (isInvisibleFromTheOutside(descriptor)) return;
|
if (isInvisibleFromTheOutside(descriptor)) return;
|
||||||
if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return;
|
if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return;
|
||||||
|
|
||||||
|
// No need to annotate annotation methods since they're always non-null
|
||||||
|
if (descriptor instanceof PropertyGetterDescriptor &&
|
||||||
|
DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (returnType != null && !AsmUtil.isPrimitive(returnType)) {
|
if (returnType != null && !AsmUtil.isPrimitive(returnType)) {
|
||||||
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
|
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unwrapped instanceof ClassDescriptor) {
|
if (unwrapped instanceof ClassDescriptor) {
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) unwrapped;
|
ClassDescriptor classDescriptor = (ClassDescriptor) unwrapped;
|
||||||
if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
|
if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ public class FunctionCodegen {
|
|||||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, CodegenUtilKt.unwrapFrontendVersion(functionDescriptor), asmMethod);
|
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, CodegenUtilKt.unwrapFrontendVersion(functionDescriptor), asmMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateMethodAnnotations(functionDescriptor, asmMethod, mv);
|
generateMethodAnnotations(functionDescriptor, asmMethod, mv, memberCodegen, typeMapper);
|
||||||
|
|
||||||
generateParameterAnnotations(functionDescriptor, mv, jvmSignature);
|
generateParameterAnnotations(functionDescriptor, mv, jvmSignature);
|
||||||
GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, jvmSignature, state, (flags & ACC_SYNTHETIC) != 0);
|
GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, jvmSignature, state, (flags & ACC_SYNTHETIC) != 0);
|
||||||
@@ -474,14 +474,6 @@ public class FunctionCodegen {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateMethodAnnotations(
|
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
|
||||||
Method asmMethod,
|
|
||||||
MethodVisitor mv
|
|
||||||
) {
|
|
||||||
generateMethodAnnotations(functionDescriptor, asmMethod, mv, memberCodegen, typeMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void generateMethodAnnotations(
|
public static void generateMethodAnnotations(
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor functionDescriptor,
|
||||||
Method asmMethod,
|
Method asmMethod,
|
||||||
|
|||||||
@@ -266,15 +266,20 @@ public class PropertyCodegen {
|
|||||||
@Nullable FunctionDescriptor expectedAnnotationConstructor
|
@Nullable FunctionDescriptor expectedAnnotationConstructor
|
||||||
) {
|
) {
|
||||||
JvmMethodGenericSignature signature = typeMapper.mapAnnotationParameterSignature(descriptor);
|
JvmMethodGenericSignature signature = typeMapper.mapAnnotationParameterSignature(descriptor);
|
||||||
String name = parameter.getName();
|
Method asmMethod = signature.getAsmMethod();
|
||||||
if (name == null) return;
|
|
||||||
MethodVisitor mv = v.newMethod(
|
MethodVisitor mv = v.newMethod(
|
||||||
JvmDeclarationOriginKt.OtherOrigin(parameter, descriptor), ACC_PUBLIC | ACC_ABSTRACT, name,
|
JvmDeclarationOriginKt.OtherOrigin(parameter, descriptor),
|
||||||
signature.getAsmMethod().getDescriptor(),
|
ACC_PUBLIC | ACC_ABSTRACT,
|
||||||
|
asmMethod.getName(),
|
||||||
|
asmMethod.getDescriptor(),
|
||||||
signature.getGenericsSignature(),
|
signature.getGenericsSignature(),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
PropertyGetterDescriptor getter = descriptor.getGetter();
|
||||||
|
assert getter != null : "Annotation property should have a getter: " + descriptor;
|
||||||
|
FunctionCodegen.generateMethodAnnotations(getter, asmMethod, mv, memberCodegen, typeMapper);
|
||||||
|
|
||||||
KtExpression defaultValue = loadAnnotationArgumentDefaultValue(parameter, descriptor, expectedAnnotationConstructor);
|
KtExpression defaultValue = loadAnnotationArgumentDefaultValue(parameter, descriptor, expectedAnnotationConstructor);
|
||||||
if (defaultValue != null) {
|
if (defaultValue != null) {
|
||||||
ConstantValue<?> constant = ExpressionCodegen.getCompileTimeConstant(
|
ConstantValue<?> constant = ExpressionCodegen.getCompileTimeConstant(
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
annotation class Name(val value: String)
|
||||||
|
|
||||||
|
annotation class Anno(
|
||||||
|
@get:Name("O") val o: String,
|
||||||
|
@get:Name("K") val k: String
|
||||||
|
)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val ms = Anno::class.java.declaredMethods
|
||||||
|
|
||||||
|
return (ms.single { it.name == "o" }.annotations.single() as Name).value +
|
||||||
|
(ms.single { it.name == "k" }.annotations.single() as Name).value
|
||||||
|
}
|
||||||
+5
@@ -41,6 +41,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotatedAnnotationParameter.kt")
|
||||||
|
public void testAnnotatedAnnotationParameter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("annotatedEnumEntry.kt")
|
@TestMetadata("annotatedEnumEntry.kt")
|
||||||
public void testAnnotatedEnumEntry() throws Exception {
|
public void testAnnotatedEnumEntry() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt");
|
runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt");
|
||||||
|
|||||||
+5
@@ -46,6 +46,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotatedAnnotationParameter.kt")
|
||||||
|
public void testAnnotatedAnnotationParameter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("annotatedEnumEntry.kt")
|
@TestMetadata("annotatedEnumEntry.kt")
|
||||||
public void testAnnotatedEnumEntry() throws Exception {
|
public void testAnnotatedEnumEntry() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt");
|
runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt");
|
||||||
|
|||||||
+5
@@ -41,6 +41,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("annotatedAnnotationParameter.kt")
|
||||||
|
public void testAnnotatedAnnotationParameter() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("annotatedEnumEntry.kt")
|
@TestMetadata("annotatedEnumEntry.kt")
|
||||||
public void testAnnotatedEnumEntry() throws Exception {
|
public void testAnnotatedEnumEntry() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt");
|
runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user