Serialize descriptors for local/anonymous classes on JVM
Reflection needs this information to work for local classes and anonymous objects
This commit is contained in:
+14
-4
@@ -45,6 +45,19 @@ public final class JvmAnnotationNames {
|
||||
|
||||
public static class KotlinClass {
|
||||
public static final JvmClassName CLASS_NAME = JvmClassName.byInternalName("kotlin/jvm/internal/KotlinClass");
|
||||
public static final ClassId KIND_CLASS_ID =
|
||||
ClassId.topLevel(CLASS_NAME.getFqNameForClassNameWithoutDollars()).createNestedClassId(Name.identifier("Kind"));
|
||||
public static final String KIND_INTERNAL_NAME = JvmClassName.byClassId(KIND_CLASS_ID).getInternalName();
|
||||
|
||||
/**
|
||||
* This enum duplicates {@link kotlin.jvm.internal.KotlinClass.Kind}. Both places should be updated simultaneously.
|
||||
*/
|
||||
public enum Kind {
|
||||
CLASS,
|
||||
LOCAL_CLASS,
|
||||
ANONYMOUS_OBJECT,
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
public static class KotlinSyntheticClass {
|
||||
@@ -54,8 +67,7 @@ public final class JvmAnnotationNames {
|
||||
public static final String KIND_INTERNAL_NAME = JvmClassName.byClassId(KIND_CLASS_ID).getInternalName();
|
||||
|
||||
/**
|
||||
* This enum duplicates {@link kotlin.jvm.internal.KotlinSyntheticClass.Kind}, because this code can't depend on "runtime.jvm".
|
||||
* Both places should be updated simultaneously
|
||||
* This enum duplicates {@link kotlin.jvm.internal.KotlinSyntheticClass.Kind}. Both places should be updated simultaneously.
|
||||
*/
|
||||
public enum Kind {
|
||||
PACKAGE_PART,
|
||||
@@ -66,8 +78,6 @@ public final class JvmAnnotationNames {
|
||||
CALLABLE_REFERENCE_WRAPPER,
|
||||
LOCAL_FUNCTION,
|
||||
ANONYMOUS_FUNCTION,
|
||||
LOCAL_CLASS,
|
||||
ANONYMOUS_OBJECT,
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
+18
-5
@@ -17,22 +17,29 @@
|
||||
package org.jetbrains.kotlin.load.kotlin.header
|
||||
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil
|
||||
|
||||
public class KotlinClassHeader(
|
||||
public val kind: KotlinClassHeader.Kind,
|
||||
public val version: Int,
|
||||
public val annotationData: Array<String>?,
|
||||
public val classKind: KotlinClass.Kind?,
|
||||
public val syntheticClassKind: KotlinSyntheticClass.Kind?
|
||||
) {
|
||||
public val isCompatibleAbiVersion: Boolean get() = AbiVersionUtil.isAbiVersionCompatible(version);
|
||||
|
||||
{
|
||||
assert(!isCompatibleAbiVersion || (annotationData == null) == (kind != Kind.CLASS && kind != Kind.PACKAGE_FACADE)) {
|
||||
"Annotation data should be not null only for CLASS and PACKAGE_FACADE (kind=" + kind + ")"
|
||||
}
|
||||
assert(!isCompatibleAbiVersion || (syntheticClassKind == null) == (kind != Kind.SYNTHETIC_CLASS)) {
|
||||
"Synthetic class kind should be present for SYNTHETIC_CLASS (kind=" + kind + ")"
|
||||
if (isCompatibleAbiVersion) {
|
||||
assert((annotationData == null) == (kind != Kind.CLASS && kind != Kind.PACKAGE_FACADE)) {
|
||||
"Annotation data should be not null only for CLASS and PACKAGE_FACADE (kind=$kind)"
|
||||
}
|
||||
assert((syntheticClassKind == null) == (kind != Kind.SYNTHETIC_CLASS)) {
|
||||
"Synthetic class kind should be present for SYNTHETIC_CLASS (kind=$kind)"
|
||||
}
|
||||
assert((classKind == null) == (kind != Kind.CLASS)) {
|
||||
"Class kind should be present for CLASS (kind=$kind)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +48,12 @@ public class KotlinClassHeader(
|
||||
PACKAGE_FACADE
|
||||
SYNTHETIC_CLASS
|
||||
}
|
||||
|
||||
override fun toString() =
|
||||
"$kind " +
|
||||
(if (classKind != null) "$classKind " else "") +
|
||||
(if (syntheticClassKind != null) "$syntheticClassKind " else "") +
|
||||
"version=$version"
|
||||
}
|
||||
|
||||
public fun KotlinClassHeader.isCompatibleClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.CLASS
|
||||
|
||||
+18
-8
@@ -59,6 +59,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
|
||||
private String[] annotationData = null;
|
||||
private KotlinClassHeader.Kind headerKind = null;
|
||||
private KotlinClass.Kind classKind = null;
|
||||
private KotlinSyntheticClass.Kind syntheticClassKind = null;
|
||||
|
||||
@Nullable
|
||||
@@ -68,7 +69,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
if (!AbiVersionUtil.isAbiVersionCompatible(version)) {
|
||||
return new KotlinClassHeader(headerKind, version, null, syntheticClassKind);
|
||||
return new KotlinClassHeader(headerKind, version, null, classKind, syntheticClassKind);
|
||||
}
|
||||
|
||||
if ((headerKind == CLASS || headerKind == PACKAGE_FACADE) && annotationData == null) {
|
||||
@@ -77,7 +78,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
return null;
|
||||
}
|
||||
|
||||
return new KotlinClassHeader(headerKind, version, annotationData, syntheticClassKind);
|
||||
return new KotlinClassHeader(headerKind, version, annotationData, classKind, syntheticClassKind);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -135,11 +136,6 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
unexpectedEnumArgument(name, enumClassId, enumEntryName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
||||
@@ -203,12 +199,26 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
public ClassHeaderReader() {
|
||||
super(KotlinClass.CLASS_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
if (KotlinClass.KIND_CLASS_ID.equals(enumClassId) && KIND_FIELD_NAME.equals(name.asString())) {
|
||||
classKind = valueOfOrNull(KotlinClass.Kind.class, enumEntryName.asString());
|
||||
if (classKind != null) return;
|
||||
}
|
||||
unexpectedEnumArgument(name, enumClassId, enumEntryName);
|
||||
}
|
||||
}
|
||||
|
||||
private class PackageHeaderReader extends HeaderAnnotationArgumentVisitor {
|
||||
public PackageHeaderReader() {
|
||||
super(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
unexpectedEnumArgument(name, enumClassId, enumEntryName);
|
||||
}
|
||||
}
|
||||
|
||||
private class SyntheticClassHeaderReader extends HeaderAnnotationArgumentVisitor {
|
||||
@@ -218,7 +228,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
if (enumClassId.equals(KotlinSyntheticClass.KIND_CLASS_ID) && name.asString().equals(KIND_FIELD_NAME)) {
|
||||
if (KotlinSyntheticClass.KIND_CLASS_ID.equals(enumClassId) && KIND_FIELD_NAME.equals(name.asString())) {
|
||||
syntheticClassKind = valueOfOrNull(KotlinSyntheticClass.Kind.class, enumEntryName.asString());
|
||||
if (syntheticClassKind != null) return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user