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.Name;
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
@@ -166,10 +167,17 @@ public abstract class AnnotationCodegen {
|
||||
if (isInvisibleFromTheOutside(descriptor)) 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)) {
|
||||
generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
|
||||
}
|
||||
}
|
||||
|
||||
if (unwrapped instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) unwrapped;
|
||||
if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
|
||||
|
||||
@@ -232,7 +232,7 @@ public class FunctionCodegen {
|
||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, CodegenUtilKt.unwrapFrontendVersion(functionDescriptor), asmMethod);
|
||||
}
|
||||
|
||||
generateMethodAnnotations(functionDescriptor, asmMethod, mv);
|
||||
generateMethodAnnotations(functionDescriptor, asmMethod, mv, memberCodegen, typeMapper);
|
||||
|
||||
generateParameterAnnotations(functionDescriptor, mv, jvmSignature);
|
||||
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(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
Method asmMethod,
|
||||
|
||||
@@ -266,15 +266,20 @@ public class PropertyCodegen {
|
||||
@Nullable FunctionDescriptor expectedAnnotationConstructor
|
||||
) {
|
||||
JvmMethodGenericSignature signature = typeMapper.mapAnnotationParameterSignature(descriptor);
|
||||
String name = parameter.getName();
|
||||
if (name == null) return;
|
||||
Method asmMethod = signature.getAsmMethod();
|
||||
MethodVisitor mv = v.newMethod(
|
||||
JvmDeclarationOriginKt.OtherOrigin(parameter, descriptor), ACC_PUBLIC | ACC_ABSTRACT, name,
|
||||
signature.getAsmMethod().getDescriptor(),
|
||||
JvmDeclarationOriginKt.OtherOrigin(parameter, descriptor),
|
||||
ACC_PUBLIC | ACC_ABSTRACT,
|
||||
asmMethod.getName(),
|
||||
asmMethod.getDescriptor(),
|
||||
signature.getGenericsSignature(),
|
||||
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);
|
||||
if (defaultValue != null) {
|
||||
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);
|
||||
}
|
||||
|
||||
@TestMetadata("annotatedAnnotationParameter.kt")
|
||||
public void testAnnotatedAnnotationParameter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotatedEnumEntry.kt")
|
||||
public void testAnnotatedEnumEntry() throws Exception {
|
||||
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);
|
||||
}
|
||||
|
||||
@TestMetadata("annotatedAnnotationParameter.kt")
|
||||
public void testAnnotatedAnnotationParameter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotatedEnumEntry.kt")
|
||||
public void testAnnotatedEnumEntry() throws Exception {
|
||||
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);
|
||||
}
|
||||
|
||||
@TestMetadata("annotatedAnnotationParameter.kt")
|
||||
public void testAnnotatedAnnotationParameter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/annotatedAnnotationParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotatedEnumEntry.kt")
|
||||
public void testAnnotatedEnumEntry() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/annotatedEnumEntry.kt");
|
||||
|
||||
Reference in New Issue
Block a user