From 276bf950cf893aa806d6cfb3dafa26da996e0543 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 7 Sep 2016 14:21:11 +0300 Subject: [PATCH] Write inner classes for annotation descriptors within the given class file It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations See FileBasedKotlinClass.convertAnnotationVisitor Related tests are already exist in loadJava, but they stopped working after the recent changes: nested classes are not found anymore by name with '$' symbol --- .../kotlin/codegen/AnnotationCodegen.java | 52 ++++++++++++++----- .../DefaultParameterValueSubstitutor.kt | 18 ++++--- .../kotlin/codegen/FunctionCodegen.java | 10 ++-- .../codegen/ImplementationBodyCodegen.java | 10 ++-- .../kotlin/codegen/MemberCodegen.java | 14 ++++- .../kotlin/codegen/PackagePartCodegen.java | 2 +- .../kotlin/codegen/PropertyCodegen.java | 6 +-- 7 files changed, 78 insertions(+), 34 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index 45bdebfb4aa..304fc6126ac 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -67,10 +67,12 @@ public abstract class AnnotationCodegen { private static final AnnotationVisitor NO_ANNOTATION_VISITOR = new AnnotationVisitor(Opcodes.ASM5) {}; + private final MemberCodegen memberCodegen; private final KotlinTypeMapper typeMapper; - private AnnotationCodegen(KotlinTypeMapper mapper) { - typeMapper = mapper; + private AnnotationCodegen(@NotNull MemberCodegen memberCodegen, @NotNull KotlinTypeMapper mapper) { + this.memberCodegen = memberCodegen; + this.typeMapper = mapper; } /** @@ -284,6 +286,11 @@ public abstract class AnnotationCodegen { } String descriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor(); + + if (classifierDescriptor instanceof ClassDescriptor) { + memberCodegen.addInnerClassInfoFromAnnotation(((ClassDescriptor) classifierDescriptor)); + } + AnnotationVisitor annotationVisitor = visitAnnotation(descriptor, rp == RetentionPolicy.RUNTIME); genAnnotationArguments(annotationDescriptor, annotationVisitor); @@ -481,8 +488,12 @@ public abstract class AnnotationCodegen { @NotNull abstract AnnotationVisitor visitAnnotation(String descr, boolean visible); - public static AnnotationCodegen forClass(final ClassVisitor cv, KotlinTypeMapper mapper) { - return new AnnotationCodegen(mapper) { + public static AnnotationCodegen forClass( + final @NotNull ClassVisitor cv, + @NotNull MemberCodegen memberCodegen, + @NotNull KotlinTypeMapper mapper + ) { + return new AnnotationCodegen(memberCodegen, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { @@ -491,8 +502,12 @@ public abstract class AnnotationCodegen { }; } - public static AnnotationCodegen forMethod(final MethodVisitor mv, KotlinTypeMapper mapper) { - return new AnnotationCodegen(mapper) { + public static AnnotationCodegen forMethod( + final @NotNull MethodVisitor mv, + @NotNull MemberCodegen memberCodegen, + @NotNull KotlinTypeMapper mapper + ) { + return new AnnotationCodegen(memberCodegen, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { @@ -501,8 +516,12 @@ public abstract class AnnotationCodegen { }; } - public static AnnotationCodegen forField(final FieldVisitor fv, KotlinTypeMapper mapper) { - return new AnnotationCodegen(mapper) { + public static AnnotationCodegen forField( + final @NotNull FieldVisitor fv, + @NotNull MemberCodegen memberCodegen, + @NotNull KotlinTypeMapper mapper + ) { + return new AnnotationCodegen(memberCodegen, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { @@ -511,8 +530,13 @@ public abstract class AnnotationCodegen { }; } - public static AnnotationCodegen forParameter(final int parameter, final MethodVisitor mv, KotlinTypeMapper mapper) { - return new AnnotationCodegen(mapper) { + public static AnnotationCodegen forParameter( + final int parameter, + final @NotNull MethodVisitor mv, + @NotNull MemberCodegen memberCodegen, + @NotNull KotlinTypeMapper mapper + ) { + return new AnnotationCodegen(memberCodegen, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { @@ -521,8 +545,12 @@ public abstract class AnnotationCodegen { }; } - public static AnnotationCodegen forAnnotationDefaultValue(final MethodVisitor mv, KotlinTypeMapper mapper) { - return new AnnotationCodegen(mapper) { + public static AnnotationCodegen forAnnotationDefaultValue( + final @NotNull MethodVisitor mv, + @NotNull MemberCodegen memberCodegen, + @NotNull KotlinTypeMapper mapper + ) { + return new AnnotationCodegen(memberCodegen, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt index d8b9777ea32..d08dbe01e82 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/DefaultParameterValueSubstitutor.kt @@ -42,12 +42,13 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) { fun generatePrimaryConstructorOverloadsIfNeeded( constructorDescriptor: ConstructorDescriptor, classBuilder: ClassBuilder, + memberCodegen: MemberCodegen<*>, contextKind: OwnerKind, classOrObject: KtClassOrObject ) { val methodElement = classOrObject.getPrimaryConstructor() ?: classOrObject - if (generateOverloadsIfNeeded(methodElement, constructorDescriptor, constructorDescriptor, contextKind, classBuilder)) { + if (generateOverloadsIfNeeded(methodElement, constructorDescriptor, constructorDescriptor, contextKind, classBuilder, memberCodegen)) { return } @@ -55,8 +56,9 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) { return } - generateOverloadWithSubstitutedParameters(constructorDescriptor, constructorDescriptor, classBuilder, methodElement, contextKind, - constructorDescriptor.countDefaultParameters()) + generateOverloadWithSubstitutedParameters( + constructorDescriptor, constructorDescriptor, classBuilder, memberCodegen, methodElement, contextKind, + constructorDescriptor.countDefaultParameters()) } /** @@ -77,7 +79,8 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) { functionDescriptor: FunctionDescriptor, delegateFunctionDescriptor: FunctionDescriptor, contextKind: OwnerKind, - classBuilder: ClassBuilder + classBuilder: ClassBuilder, + memberCodegen: MemberCodegen<*> ): Boolean { if (!functionDescriptor.hasJvmOverloadsAnnotation()) { return false @@ -87,7 +90,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) { for (i in 1..count) { generateOverloadWithSubstitutedParameters( - functionDescriptor, delegateFunctionDescriptor, classBuilder, methodElement, contextKind, i + functionDescriptor, delegateFunctionDescriptor, classBuilder, memberCodegen, methodElement, contextKind, i ) } @@ -112,6 +115,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) { functionDescriptor: FunctionDescriptor, delegateFunctionDescriptor: FunctionDescriptor, classBuilder: ClassBuilder, + memberCodegen: MemberCodegen<*>, methodElement: KtElement?, contextKind: OwnerKind, substituteCount: Int @@ -127,10 +131,10 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) { signature.genericsSignature, FunctionCodegen.getThrownExceptions(functionDescriptor, typeMapper)) - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, signature.returnType) + AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper).genAnnotations(functionDescriptor, signature.returnType) remainingParameters.withIndex().forEach { - val annotationCodegen = AnnotationCodegen.forParameter(it.index, mv, typeMapper) + val annotationCodegen = AnnotationCodegen.forParameter(it.index, mv, memberCodegen, typeMapper) annotationCodegen.genAnnotations(it.value, signature.valueParameters[it.index].asmType) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index ea068617c73..892cada62a8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -138,7 +138,7 @@ public class FunctionCodegen { @NotNull FunctionDescriptor delegateFunctionDescriptor ) { new DefaultParameterValueSubstitutor(state).generateOverloadsIfNeeded( - function, functionDescriptor, delegateFunctionDescriptor, owner.getContextKind(), v + function, functionDescriptor, delegateFunctionDescriptor, owner.getContextKind(), v, memberCodegen ); } @@ -235,7 +235,7 @@ public class FunctionCodegen { Method asmMethod, MethodVisitor mv ) { - AnnotationCodegen annotationCodegen = AnnotationCodegen.forMethod(mv, typeMapper); + AnnotationCodegen annotationCodegen = AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper); if (functionDescriptor instanceof PropertyAccessorDescriptor) { AnnotationUseSiteTarget target = functionDescriptor instanceof PropertySetterDescriptor ? PROPERTY_SETTER : PROPERTY_GETTER; @@ -264,7 +264,7 @@ public class FunctionCodegen { if (kind == JvmMethodParameterKind.VALUE) { ValueParameterDescriptor parameter = iterator.next(); - AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper); + AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, memberCodegen, typeMapper); if (functionDescriptor instanceof PropertySetterDescriptor) { PropertyDescriptor propertyDescriptor = ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty(); @@ -283,7 +283,7 @@ public class FunctionCodegen { ReceiverParameterDescriptor receiver = JvmCodegenUtil.getDirectMember(functionDescriptor).getExtensionReceiverParameter(); if (receiver != null) { - AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper); + AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, memberCodegen, typeMapper); Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(receiver.getType()); annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), RECEIVER); @@ -713,7 +713,7 @@ public class FunctionCodegen { // Only method annotations are copied to the $default method. Parameter annotations are not copied until there are valid use cases; // enum constructors have two additional synthetic parameters which somewhat complicate this task - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, defaultMethod.getReturnType()); + AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper).genAnnotations(functionDescriptor, defaultMethod.getReturnType()); if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { if (this.owner instanceof MultifileClassFacadeContext) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index c1d2ba706ec..bea54cbb5e0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -224,7 +224,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { writeEnclosingMethod(); - AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null); + AnnotationCodegen.forClass(v.getVisitor(), this, typeMapper).genAnnotations(descriptor, null); generateEnumEntries(); } @@ -871,7 +871,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { type.getDescriptor(), typeMapper.mapFieldSignature(property.getType(), property), info.defaultValue); - AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property, type); + AnnotationCodegen.forField(fv, this, typeMapper).genAnnotations(property, type); //This field are always static and final so if it has constant initializer don't do anything in clinit, //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4 @@ -939,7 +939,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { functionCodegen.generateDefaultIfNeeded(constructorContext, constructorDescriptor, OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT, null); - new DefaultParameterValueSubstitutor(state).generatePrimaryConstructorOverloadsIfNeeded(constructorDescriptor, v, kind, myClass); + new DefaultParameterValueSubstitutor(state).generatePrimaryConstructorOverloadsIfNeeded(constructorDescriptor, v, this, kind, myClass); } private void generateSecondaryConstructor(@NotNull final ConstructorDescriptor constructorDescriptor) { @@ -964,7 +964,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { DefaultParameterValueLoader.DEFAULT, null); new DefaultParameterValueSubstitutor(state).generateOverloadsIfNeeded( - constructor, constructorDescriptor, constructorDescriptor, kind, v + constructor, constructorDescriptor, constructorDescriptor, kind, v, this ); } @@ -1545,7 +1545,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { int isDeprecated = KotlinBuiltIns.isDeprecated(descriptor) ? ACC_DEPRECATED : 0; FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(enumEntry, descriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL | isDeprecated, descriptor.getName().asString(), classAsmType.getDescriptor(), null, null); - AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor, null); + AnnotationCodegen.forField(fv, this, typeMapper).genAnnotations(descriptor, null); } initializeEnumConstants(enumEntries); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 7c7f2eb24b0..1026735e729 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -88,7 +88,7 @@ public abstract class MemberCodegen parentCodegen; private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages(); - protected final Collection innerClasses = new LinkedHashSet(); + private final Collection innerClasses = new LinkedHashSet(); protected ExpressionCodegen clInit; private NameGenerator inlineNameGenerator; @@ -273,6 +273,18 @@ public abstract class MemberCodegen { } } Annotated annotatedFile = new AnnotatedSimple(new AnnotationsImpl(fileAnnotationDescriptors)); - AnnotationCodegen.forClass(v.getVisitor(), state.getTypeMapper()).genAnnotations(annotatedFile, null); + AnnotationCodegen.forClass(v.getVisitor(), this, state.getTypeMapper()).genAnnotations(annotatedFile, null); } @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index b8204f63196..46bf31d4e6e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -233,7 +233,7 @@ public class PropertyCodegen { assert state.getClassBuilderMode() != ClassBuilderMode.FULL || constant != null : "Default value for annotation parameter should be compile time value: " + defaultValue.getText(); if (constant != null) { - AnnotationCodegen annotationCodegen = AnnotationCodegen.forAnnotationDefaultValue(mv, typeMapper); + AnnotationCodegen annotationCodegen = AnnotationCodegen.forAnnotationDefaultValue(mv, memberCodegen, typeMapper); annotationCodegen.generateAnnotationDefaultValue(constant, descriptor.getType()); } } @@ -279,7 +279,7 @@ public class PropertyCodegen { Method syntheticMethod = getSyntheticMethodSignature(descriptor); MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), flags, syntheticMethod.getName(), syntheticMethod.getDescriptor(), null, null); - AnnotationCodegen.forMethod(mv, typeMapper) + AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper) .genAnnotations(new AnnotatedSimple(annotations), Type.VOID_TYPE, AnnotationUseSiteTarget.PROPERTY); mv.visitCode(); mv.visitInsn(Opcodes.RETURN); @@ -354,7 +354,7 @@ public class PropertyCodegen { ); Annotated fieldAnnotated = new AnnotatedWithFakeAnnotations(propertyDescriptor, annotations); - AnnotationCodegen.forField(fv, typeMapper).genAnnotations( + AnnotationCodegen.forField(fv, memberCodegen, typeMapper).genAnnotations( fieldAnnotated, type, isDelegate ? AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD : AnnotationUseSiteTarget.FIELD); }