diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt index dd79bba7596..033a9e66a82 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt @@ -31,17 +31,32 @@ class KotlinClassHeader( ) { // See kotlin.Metadata enum class Kind(val id: Int) { + UNKNOWN(0), CLASS(1), FILE_FACADE(2), SYNTHETIC_CLASS(3), MULTIFILE_CLASS(4), MULTIFILE_CLASS_PART(5); + + companion object { + private val entryById = values().toMapBy(Kind::id) + + @JvmStatic + fun getById(id: Int) = entryById[id] ?: UNKNOWN + } } enum class SyntheticClassKind(val id: Int) { FUNCTION(1), LOCAL_CLASS(2), INTERFACE_DEFAULT_IMPLS(3); + + companion object { + private val entryById = values().toMapBy(SyntheticClassKind::id) + + @JvmStatic + fun getById(id: Int) = entryById[id] + } } override fun toString() = "$kind " + (if (isLocalClass) "(local) " else "") + "version=$metadataVersion" diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java index ee5fb9ccbda..65ff57b50f6 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java @@ -35,6 +35,8 @@ import static org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.*; import static org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.Kind.*; public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor { + private static final boolean IGNORE_OLD_METADATA = "true".equals(System.getProperty("kotlin.ignore.old.metadata")); + private static final Map HEADER_KINDS = new HashMap(); static { @@ -51,6 +53,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private String[] data = null; private String[] strings = null; private KotlinClassHeader.Kind headerKind = null; + private KotlinClassHeader.SyntheticClassKind syntheticClassKind = null; private boolean isInterfaceDefaultImpls = false; private boolean isLocalClass = false; @@ -73,7 +76,11 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor headerKind, metadataVersion != null ? metadataVersion : JvmMetadataVersion.INVALID_VERSION, bytecodeVersion != null ? bytecodeVersion : JvmBytecodeBinaryVersion.INVALID_VERSION, - data, strings, multifileClassName, isInterfaceDefaultImpls, isLocalClass + data, + strings, + multifileClassName, + isInterfaceDefaultImpls || syntheticClassKind == KotlinClassHeader.SyntheticClassKind.INTERFACE_DEFAULT_IMPLS, + isLocalClass || syntheticClassKind == KotlinClassHeader.SyntheticClassKind.LOCAL_CLASS ); } @@ -87,6 +94,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor @Override public AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId, @NotNull SourceElement source) { FqName fqName = classId.asSingleFqName(); + if (fqName.equals(METADATA)) { + return new KotlinMetadataArgumentVisitor(); + } + + if (IGNORE_OLD_METADATA) return null; + if (KOTLIN_INTERFACE_DEFAULT_IMPLS.equals(fqName)) { isInterfaceDefaultImpls = true; return null; @@ -114,6 +127,89 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor public void visitEnd() { } + private class KotlinMetadataArgumentVisitor implements AnnotationArgumentVisitor { + @Override + public void visit(@Nullable Name name, @Nullable Object value) { + if (name == null) return; + + String string = name.asString(); + if (KIND_FIELD_NAME.equals(string)) { + if (value instanceof Integer) { + headerKind = KotlinClassHeader.Kind.getById((Integer) value); + } + } + else if (METADATA_VERSION_FIELD_NAME.equals(string)) { + if (value instanceof int[]) { + metadataVersion = JvmMetadataVersion.create((int[]) value); + } + } + else if (BYTECODE_VERSION_FIELD_NAME.equals(string)) { + if (value instanceof int[]) { + bytecodeVersion = JvmBytecodeBinaryVersion.create((int[]) value); + } + } + else if (SYNTHETIC_CLASS_KIND_FIELD_NAME.equals(string)) { + if (value instanceof Integer) { + syntheticClassKind = KotlinClassHeader.SyntheticClassKind.getById((Integer) value); + } + } + else if (METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME.equals(string)) { + if (value instanceof String) { + multifileClassName = (String) value; + } + } + } + + @Override + @Nullable + public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) { + String string = name.asString(); + if (METADATA_DATA_FIELD_NAME.equals(string)) { + return dataArrayVisitor(); + } + else if (METADATA_STRINGS_FIELD_NAME.equals(string)) { + return stringsArrayVisitor(); + } + else { + return null; + } + } + + @NotNull + private AnnotationArrayArgumentVisitor dataArrayVisitor() { + return new CollectStringArrayAnnotationVisitor() { + @Override + protected void visitEnd(@NotNull String[] result) { + data = result; + } + }; + } + + @NotNull + private AnnotationArrayArgumentVisitor stringsArrayVisitor() { + return new CollectStringArrayAnnotationVisitor() { + @Override + protected void visitEnd(@NotNull String[] result) { + strings = result; + } + }; + } + + @Override + public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) { + } + + @Nullable + @Override + public AnnotationArgumentVisitor visitAnnotation(@NotNull Name name, @NotNull ClassId classId) { + return null; + } + + @Override + public void visitEnd() { + } + } + private class HeaderAnnotationArgumentVisitor implements AnnotationArgumentVisitor { @Override public void visit(@Nullable Name name, @Nullable Object value) { @@ -183,32 +279,32 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor @Override public void visitEnd() { } + } - private abstract class CollectStringArrayAnnotationVisitor implements AnnotationArrayArgumentVisitor { - private final List strings; + private abstract static class CollectStringArrayAnnotationVisitor implements AnnotationArrayArgumentVisitor { + private final List strings; - public CollectStringArrayAnnotationVisitor() { - this.strings = new ArrayList(); - } - - @Override - public void visit(@Nullable Object value) { - if (value instanceof String) { - strings.add((String) value); - } - } - - @Override - public void visitEnum(@NotNull ClassId enumClassId, @NotNull Name enumEntryName) { - } - - @Override - public void visitEnd() { - //noinspection SSBasedInspection - visitEnd(strings.toArray(new String[strings.size()])); - } - - protected abstract void visitEnd(@NotNull String[] data); + public CollectStringArrayAnnotationVisitor() { + this.strings = new ArrayList(); } + + @Override + public void visit(@Nullable Object value) { + if (value instanceof String) { + strings.add((String) value); + } + } + + @Override + public void visitEnum(@NotNull ClassId enumClassId, @NotNull Name enumEntryName) { + } + + @Override + public void visitEnd() { + //noinspection SSBasedInspection + visitEnd(strings.toArray(new String[strings.size()])); + } + + protected abstract void visitEnd(@NotNull String[] data); } } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/reflectLambda.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/reflectLambda.kt index fb51a9e12db..ee5358af126 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/reflectLambda.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/reflectLambda.kt @@ -14,9 +14,12 @@ * limitations under the License. */ +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") // kotlin.Metadata + package kotlin.reflect.jvm import org.jetbrains.kotlin.load.kotlin.JvmNameResolver +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.deserialization.DeserializationContext import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer @@ -24,7 +27,6 @@ import org.jetbrains.kotlin.serialization.deserialization.TypeTable import org.jetbrains.kotlin.serialization.jvm.BitEncoding import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil -import kotlin.jvm.internal.KotlinFunction import kotlin.reflect.KFunction import kotlin.reflect.jvm.internal.EmptyContainerForLocal import kotlin.reflect.jvm.internal.KFunctionImpl @@ -36,11 +38,11 @@ import kotlin.reflect.jvm.internal.getOrCreateModule * Not all features are currently supported, in particular [KCallable.call] and [KCallable.callBy] will fail at the moment. */ fun Function.reflect(): KFunction? { - val callable = javaClass.getAnnotation(KotlinFunction::class.java) ?: return null - val input = BitEncoding.decodeBytes(callable.data).inputStream() + val annotation = javaClass.getAnnotation(Metadata::class.java) ?: return null + if (annotation.xi != KotlinClassHeader.SyntheticClassKind.FUNCTION.id) return null + val input = BitEncoding.decodeBytes(annotation.d1).inputStream() val nameResolver = JvmNameResolver( - JvmProtoBuf.StringTableTypes.parseDelimitedFrom(input, JvmProtoBufUtil.EXTENSION_REGISTRY), - callable.strings + JvmProtoBuf.StringTableTypes.parseDelimitedFrom(input, JvmProtoBufUtil.EXTENSION_REGISTRY), annotation.d2 ) val proto = ProtoBuf.Function.parseFrom(input, JvmProtoBufUtil.EXTENSION_REGISTRY) val moduleData = javaClass.getOrCreateModule()