diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index fe314cddc18..fc6ef94e8ff 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.load.java.JavaVisibilities; import org.jetbrains.kotlin.load.java.JvmAbi; +import org.jetbrains.kotlin.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.resolve.DescriptorUtils; @@ -821,9 +822,11 @@ public class AsmUtil { public static void writeKotlinSyntheticClassAnnotation(@NotNull ClassBuilder v, @NotNull KotlinSyntheticClass.Kind kind) { AnnotationVisitor av = v.newAnnotation(Type.getObjectType(KotlinSyntheticClass.CLASS_NAME.getInternalName()).getDescriptor(), true); av.visit(ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); - av.visitEnum(KotlinSyntheticClass.KIND_FIELD_NAME.asString(), - Type.getObjectType(KotlinSyntheticClass.KIND_INTERNAL_NAME).getDescriptor(), - kind.toString()); + av.visitEnum( + JvmAnnotationNames.KIND_FIELD_NAME, + Type.getObjectType(KotlinSyntheticClass.KIND_INTERNAL_NAME).getDescriptor(), + kind.toString() + ); av.visitEnd(); } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java index 03d8376524b..c9c94811458 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java @@ -29,8 +29,7 @@ import java.lang.annotation.Annotation; import java.util.Collection; import java.util.List; -import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.ABI_VERSION_FIELD_NAME; -import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass; +import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.*; import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass.Kind.*; public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { @@ -147,7 +146,7 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { assertNotNull(version); assertTrue("KotlinSyntheticClass annotation is written with an unsupported format", AbiVersionUtil.isAbiVersionCompatible(version)); - Object actualKind = CodegenTestUtil.getAnnotationAttribute(annotation, KotlinSyntheticClass.KIND_FIELD_NAME.asString()); + Object actualKind = CodegenTestUtil.getAnnotationAttribute(annotation, KIND_FIELD_NAME); assertNotNull(actualKind); assertEquals("KotlinSyntheticClass annotation has the wrong kind", expectedKind.toString(), actualKind.toString()); } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java index d1fe4ad456f..623d4a13534 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.load.java; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; @@ -28,13 +27,14 @@ import java.util.HashSet; import java.util.Set; public final class JvmAnnotationNames { - public static final FqName KOTLIN_CLASS = new FqName("kotlin.jvm.internal.KotlinClass"); + public static final FqName KOTLIN_CLASS = KotlinClass.CLASS_NAME.getFqNameForClassNameWithoutDollars(); public static final FqName KOTLIN_PACKAGE = new FqName("kotlin.jvm.internal.KotlinPackage"); public static final FqName KOTLIN_SIGNATURE = new FqName("kotlin.jvm.KotlinSignature"); public static final FqName OLD_KOTLIN_SIGNATURE = new FqName("jet.runtime.typeinfo.KotlinSignature"); public static final String ABI_VERSION_FIELD_NAME = "abiVersion"; + public static final String KIND_FIELD_NAME = "kind"; public static final String DATA_FIELD_NAME = "data"; public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value"); @@ -43,14 +43,16 @@ public final class JvmAnnotationNames { public static final FqName JETBRAINS_MUTABLE_ANNOTATION = new FqName("org.jetbrains.annotations.Mutable"); public static final FqName JETBRAINS_READONLY_ANNOTATION = new FqName("org.jetbrains.annotations.ReadOnly"); + public static class KotlinClass { + public static final JvmClassName CLASS_NAME = JvmClassName.byInternalName("kotlin/jvm/internal/KotlinClass"); + } + public static class KotlinSyntheticClass { public static final JvmClassName CLASS_NAME = JvmClassName.byInternalName("kotlin/jvm/internal/KotlinSyntheticClass"); 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(); - public static final Name KIND_FIELD_NAME = Name.identifier("kind"); - /** * This enum duplicates {@link kotlin.jvm.internal.KotlinSyntheticClass.Kind}, because this code can't depend on "runtime.jvm". * Both places should be updated simultaneously @@ -67,19 +69,6 @@ public final class JvmAnnotationNames { LOCAL_CLASS, ANONYMOUS_OBJECT, ; - - @Nullable - public static Kind valueOfOrNull(@NotNull String name) { - try { - return valueOf(name); - } - catch (IllegalArgumentException e) { - return null; - } - } - } - - private KotlinSyntheticClass() { } } 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 1d5837c6089..e9a34e935c4 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 @@ -19,11 +19,14 @@ package org.jetbrains.kotlin.load.kotlin.header; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.load.java.AbiVersionUtil; -import org.jetbrains.kotlin.resolve.jvm.JvmClassName; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.resolve.jvm.JvmClassName; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import static org.jetbrains.kotlin.load.java.AbiVersionUtil.isAbiVersionCompatible; import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.*; @@ -36,7 +39,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private int version = AbiVersionUtil.INVALID_VERSION; static { - HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_CLASS), CLASS); + HEADER_KINDS.put(KotlinClass.CLASS_NAME, CLASS); HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE), PACKAGE_FACADE); HEADER_KINDS.put(KotlinSyntheticClass.CLASS_NAME, SYNTHETIC_CLASS); @@ -183,10 +186,8 @@ 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.equals(KotlinSyntheticClass.KIND_FIELD_NAME)) { - // Don't call KotlinSyntheticClass.Kind.valueOf() here, because it will throw an exception if there's no such value, - // but we don't want to fail if we're loading the header with an _incompatible_ ABI version - syntheticClassKind = KotlinSyntheticClass.Kind.valueOfOrNull(enumEntryName.asString()); + if (enumClassId.equals(KotlinSyntheticClass.KIND_CLASS_ID) && name.asString().equals(KIND_FIELD_NAME)) { + syntheticClassKind = valueOfOrNull(KotlinSyntheticClass.Kind.class, enumEntryName.asString()); if (syntheticClassKind != null) return; } if (isAbiVersionCompatible(version)) { @@ -223,4 +224,16 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor } return null; } + + // This function is needed here because Enum.valueOf() throws exception if there's no such value, + // but we don't want to fail if we're loading the header with an _incompatible_ ABI version + @Nullable + private static > E valueOfOrNull(@NotNull Class enumClass, @NotNull String entry) { + try { + return Enum.valueOf(enumClass, entry); + } + catch (IllegalArgumentException e) { + return null; + } + } }