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
This commit is contained in:
@@ -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) {
|
||||
|
||||
+11
-7
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -88,7 +88,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
protected final JvmFileClassesProvider fileClassesProvider;
|
||||
private final MemberCodegen<?> parentCodegen;
|
||||
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
|
||||
protected final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<ClassDescriptor>();
|
||||
private final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<ClassDescriptor>();
|
||||
|
||||
protected ExpressionCodegen clInit;
|
||||
private NameGenerator inlineNameGenerator;
|
||||
@@ -273,6 +273,18 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
|
||||
// See FileBasedKotlinClass.convertAnnotationVisitor
|
||||
public void addInnerClassInfoFromAnnotation(@NotNull ClassDescriptor classDescriptor) {
|
||||
DeclarationDescriptor current = classDescriptor;
|
||||
while (current != null && !isTopLevelDeclaration(current)) {
|
||||
if (current instanceof ClassDescriptor) {
|
||||
innerClasses.add(((ClassDescriptor) current));
|
||||
}
|
||||
current = current.getContainingDeclaration();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
|
||||
DeclarationDescriptor containing = innerClass.getContainingDeclaration();
|
||||
String outerClassInternalName = null;
|
||||
|
||||
@@ -85,7 +85,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user