diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 8106ba43850..89662512950 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -43,7 +43,6 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.java.JvmAnnotationNames; -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass; import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqNameUnsafe; @@ -256,17 +255,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { protected void generateKotlinAnnotation() { if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; - KotlinClass.Kind kind; - if (isAnonymousObject(descriptor)) { - kind = KotlinClass.Kind.ANONYMOUS_OBJECT; - } - else if (isTopLevelOrInnerClass(descriptor)) { - // Default value is Kind.CLASS - kind = null; - } - else { - // LOCAL_CLASS is also written to inner classes of local classes - kind = KotlinClass.Kind.LOCAL_CLASS; + if (!isTopLevelOrInnerClass(descriptor)) { + AnnotationVisitor av = v.getVisitor().visitAnnotation( + asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_LOCAL_CLASS), true + ); + av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmAbi.VERSION.toArray()); + av.visitEnd(); } DescriptorSerializer serializer = @@ -276,13 +270,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true); writeAnnotationData(av, serializer, classProto); - if (kind != null) { - av.visitEnum( - JvmAnnotationNames.KIND_FIELD_NAME, - Type.getObjectType(KotlinClass.KIND_INTERNAL_NAME).getDescriptor(), - kind.toString() - ); - } av.visitEnd(); } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/FileBasedKotlinClass.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/FileBasedKotlinClass.java index 67a9529da12..f59d77e8bf6 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/FileBasedKotlinClass.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/FileBasedKotlinClass.java @@ -270,9 +270,6 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass { if (name.equals(JvmAnnotationNames.KotlinSyntheticClass.KIND_INTERNAL_NAME)) { return JvmAnnotationNames.KotlinSyntheticClass.KIND_CLASS_ID; } - else if (name.equals(JvmAnnotationNames.KotlinClass.KIND_INTERNAL_NAME)) { - return JvmAnnotationNames.KotlinClass.KIND_CLASS_ID; - } List classes = new ArrayList(1); boolean local = false; diff --git a/compiler/testData/codegen/bytecodeListing/annotations/literals.txt b/compiler/testData/codegen/bytecodeListing/annotations/literals.txt index 7ceb93edb71..6666962805c 100644 --- a/compiler/testData/codegen/bytecodeListing/annotations/literals.txt +++ b/compiler/testData/codegen/bytecodeListing/annotations/literals.txt @@ -20,7 +20,7 @@ method (p0: int): void } -@kotlin.jvm.internal.KotlinClass LiteralsKt$foo$3 { +@kotlin.jvm.internal.KotlinLocalClass @kotlin.jvm.internal.KotlinClass LiteralsKt$foo$3 { inner class LiteralsKt$foo$3 field $kotlinClass: kotlin.reflect.KClass method (): void diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt b/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt index 3c09b0e4d37..ccb23e253a0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt +++ b/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt @@ -185,7 +185,7 @@ public object InlineTestUtil { } private fun isClassOrPackagePartKind(header: KotlinClassHeader): Boolean { - return header.classKind == JvmAnnotationNames.KotlinClass.Kind.CLASS || header.isInterfaceDefaultImpls + return (header.kind == KotlinClassHeader.Kind.CLASS && !header.isLocalClass) || header.isInterfaceDefaultImpls } private fun getClassHeader(file: OutputFile): KotlinClassHeader { diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java index c02e8d2ff2a..9ec16af4125 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java @@ -19,14 +19,12 @@ package org.jetbrains.kotlin.codegen; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.load.java.AbiVersionUtil; import org.jetbrains.kotlin.load.java.JvmAbi; -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass; +import org.jetbrains.kotlin.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass; import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.resolve.jvm.JvmClassName; import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion; import org.jetbrains.kotlin.test.ConfigurationKind; @@ -34,9 +32,6 @@ import java.lang.annotation.Annotation; import java.util.Collection; import java.util.List; -import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KIND_FIELD_NAME; -import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.ANONYMOUS_OBJECT; -import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.LOCAL_CLASS; import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.VERSION_FIELD_NAME; public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { @@ -93,8 +88,7 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { public void testLocalClass() { doTestKotlinClass( "fun foo() { class Local }", - "Local", - LOCAL_CLASS + "Local" ); } @@ -108,24 +102,21 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { public void testLocalTraitInterface() { doTestKotlinClass( "fun foo() { interface Local { fun bar() = 42 } }", - "Local.class", - LOCAL_CLASS + "Local.class" ); } public void testInnerClassOfLocalClass() { doTestKotlinClass( "fun foo() { class Local { inner class Inner } }", - "Inner", - LOCAL_CLASS + "Inner" ); } public void testAnonymousObject() { doTestKotlinClass( "val o = object {}", - "$1", - ANONYMOUS_OBJECT + "$1" ); } @@ -138,22 +129,17 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { } private void doTestKotlinSyntheticClass(@NotNull String code, @NotNull String classFilePart) { - doTest(code, classFilePart, KotlinSyntheticClass.CLASS_NAME, null); + doTest(code, classFilePart, KotlinSyntheticClass.CLASS_NAME.getFqNameForClassNameWithoutDollars()); } - private void doTestKotlinClass( - @NotNull String code, - @NotNull String classFilePart, - @NotNull KotlinClass.Kind expectedKind - ) { - doTest(code, classFilePart, KotlinClass.CLASS_NAME, expectedKind.toString()); + private void doTestKotlinClass(@NotNull String code, @NotNull String classFilePart) { + doTest(code, classFilePart, JvmAnnotationNames.KOTLIN_CLASS, JvmAnnotationNames.KOTLIN_LOCAL_CLASS); } private void doTest( @NotNull String code, @NotNull final String classFilePart, - @NotNull JvmClassName annotationName, - @Nullable String expectedKind + @NotNull FqName... annotationFqNames ) { loadText("package " + PACKAGE_NAME + "\n\n" + code); List output = generateClassesInFile().asList(); @@ -169,14 +155,12 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { String path = files.iterator().next().getRelativePath(); String fqName = path.substring(0, path.length() - ".class".length()).replace('/', '.'); Class aClass = generateClass(fqName); - assertAnnotatedWithKind(aClass, annotationName.getFqNameForClassNameWithoutDollars().asString(), expectedKind); + for (FqName annotationFqName : annotationFqNames) { + assertAnnotatedWith(aClass, annotationFqName.asString()); + } } - private void assertAnnotatedWithKind( - @NotNull Class aClass, - @NotNull String annotationFqName, - @Nullable String expectedKind - ) { + private void assertAnnotatedWith(@NotNull Class aClass, @NotNull String annotationFqName) { Class annotationClass = loadAnnotationClassQuietly(annotationFqName); assertTrue("No annotation " + annotationFqName + " found in " + aClass, aClass.isAnnotationPresent(annotationClass)); @@ -186,9 +170,5 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { assertNotNull(version); assertTrue("Annotation " + annotationFqName + " is written with an unsupported format", AbiVersionUtil.isAbiVersionCompatible(BinaryVersion.create(version))); - - Object actualKind = CodegenTestUtil.getAnnotationAttribute(annotation, KIND_FIELD_NAME); - assertNotNull(actualKind); - assertEquals("Annotation " + annotationFqName + " has the wrong kind", expectedKind, actualKind.toString()); } } diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt index 44836798c97..21dc941dda8 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt @@ -150,11 +150,10 @@ public abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdi val packageView = module.getPackage(LoadDescriptorUtil.TEST_PACKAGE_FQNAME) packageScopes.add(packageView.memberScope) } - else if (header == null || - (header.kind == KotlinClassHeader.Kind.CLASS && header.classKind == JvmAnnotationNames.KotlinClass.Kind.CLASS)) { + else if (header == null || (header.kind == KotlinClassHeader.Kind.CLASS && !header.isLocalClass)) { // Either a normal Kotlin class or a Java class val classId = klass.classId - if (!classId.isLocal()) { + if (!classId.isLocal) { val classDescriptor = module.findClassAcrossModuleDependencies(classId).sure { "Couldn't resolve class $className" } if (DescriptorUtils.isTopLevelDeclaration(classDescriptor)) { classes.add(classDescriptor) diff --git a/compiler/tests/org/jetbrains/kotlin/serialization/AbstractLocalClassProtoTest.kt b/compiler/tests/org/jetbrains/kotlin/serialization/AbstractLocalClassProtoTest.kt index fbd1246cba2..f1899b6a4fc 100644 --- a/compiler/tests/org/jetbrains/kotlin/serialization/AbstractLocalClassProtoTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/serialization/AbstractLocalClassProtoTest.kt @@ -76,17 +76,13 @@ public abstract class AbstractLocalClassProtoTest : TestCaseWithTmpdir() { ) } + @Suppress("UNCHECKED_CAST") private fun assertHasAnnotationData(clazz: Class<*>) { - @Suppress("UNCHECKED_CAST") - val annotation = clazz.getAnnotation( + checkNotNull(clazz.getAnnotation( clazz.classLoader.loadClass(JvmAnnotationNames.KOTLIN_CLASS.asString()) as Class - ) - assert(annotation != null) { "KotlinClass annotation is not found for class $clazz" } - - val kindMethod = annotation.annotationType().getDeclaredMethod("kind") - val kind = kindMethod(annotation) - assert(kind.toString() != JvmAnnotationNames.KotlinClass.Kind.CLASS.toString()) { - "'kind' should not be CLASS: $clazz (was $kind)" - } + )) { "KotlinClass annotation is not found for class $clazz" } + checkNotNull(clazz.getAnnotation( + clazz.classLoader.loadClass(JvmAnnotationNames.KOTLIN_LOCAL_CLASS.asString()) as Class + )) { "KotlinLocalClass annotation is not found for class $clazz" } } } 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 c690ccb0d14..4c28d1f5332 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 @@ -28,13 +28,14 @@ import java.util.HashSet; import java.util.Set; public final class JvmAnnotationNames { - public static final FqName KOTLIN_CLASS = KotlinClass.CLASS_NAME.getFqNameForClassNameWithoutDollars(); + public static final FqName KOTLIN_CLASS = new FqName("kotlin.jvm.internal.KotlinClass"); public static final FqName KOTLIN_PACKAGE = new FqName("kotlin.jvm.internal.KotlinPackage"); public static final FqName KOTLIN_FILE_FACADE = new FqName("kotlin.jvm.internal.KotlinFileFacade"); public static final FqName KOTLIN_MULTIFILE_CLASS = new FqName("kotlin.jvm.internal.KotlinMultifileClass"); public static final FqName KOTLIN_MULTIFILE_CLASS_PART = new FqName("kotlin.jvm.internal.KotlinMultifileClassPart"); public static final FqName KOTLIN_CALLABLE = new FqName("kotlin.jvm.internal.KotlinCallable"); public static final FqName KOTLIN_INTERFACE_DEFAULT_IMPLS = new FqName("kotlin.jvm.internal.KotlinInterfaceDefaultImpls"); + public static final FqName KOTLIN_LOCAL_CLASS = new FqName("kotlin.jvm.internal.KotlinLocalClass"); public static final FqName JAVA_LANG_DEPRECATED = new FqName("java.lang.Deprecated"); @@ -68,23 +69,6 @@ public final class JvmAnnotationNames { public static final FqName ENHANCED_NULLABILITY_ANNOTATION = new FqName("kotlin.jvm.internal.EnhancedNullability"); public static final FqName ENHANCED_MUTABILITY_ANNOTATION = new FqName("kotlin.jvm.internal.EnhancedMutability"); - 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 { public static final JvmClassName CLASS_NAME = JvmClassName.byInternalName("kotlin/jvm/internal/KotlinSyntheticClass"); public static final ClassId KIND_CLASS_ID = @@ -125,6 +109,7 @@ public final class JvmAnnotationNames { } SPECIAL_ANNOTATIONS.add(KotlinSyntheticClass.CLASS_NAME); SPECIAL_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_INTERFACE_DEFAULT_IMPLS)); + SPECIAL_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_LOCAL_CLASS)); for (FqName fqName : Arrays.asList(JETBRAINS_NOT_NULL_ANNOTATION, JETBRAINS_NULLABLE_ANNOTATION)) { NULLABILITY_ANNOTATIONS.add(JvmClassName.byFqNameWithoutInnerClasses(fqName)); 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 f12bc55a7a6..dadad589ede 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 @@ -17,24 +17,22 @@ package org.jetbrains.kotlin.load.kotlin.header import org.jetbrains.kotlin.load.java.AbiVersionUtil -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion -public class KotlinClassHeader( - public val kind: KotlinClassHeader.Kind, - public val version: BinaryVersion, - public val annotationData: Array?, - public val strings: Array?, - public val classKind: KotlinClass.Kind?, - public val syntheticClassKind: String?, - public val filePartClassNames: Array?, - public val multifileClassName: String?, - public val isInterfaceDefaultImpls: Boolean +class KotlinClassHeader( + val kind: KotlinClassHeader.Kind, + val version: BinaryVersion, + val annotationData: Array?, + val strings: Array?, + val syntheticClassKind: String?, + val filePartClassNames: Array?, + val multifileClassName: String?, + val isInterfaceDefaultImpls: Boolean, + val isLocalClass: Boolean ) { - public val isCompatibleAbiVersion: Boolean get() = AbiVersionUtil.isAbiVersionCompatible(version) + val isCompatibleAbiVersion: Boolean get() = AbiVersionUtil.isAbiVersionCompatible(version) - public enum class Kind { + enum class Kind { CLASS, PACKAGE_FACADE, FILE_FACADE, @@ -45,13 +43,13 @@ public class KotlinClassHeader( override fun toString() = "$kind " + - (if (classKind != null) "$classKind " else "") + + (if (isLocalClass) "(local) " else "") + (if (syntheticClassKind != null) "$syntheticClassKind " else "") + "version=$version" } -public fun KotlinClassHeader.isCompatibleClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.CLASS -public fun KotlinClassHeader.isCompatiblePackageFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.PACKAGE_FACADE -public fun KotlinClassHeader.isCompatibleFileFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.FILE_FACADE -public fun KotlinClassHeader.isCompatibleMultifileClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS -public fun KotlinClassHeader.isCompatibleMultifileClassPartKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART +fun KotlinClassHeader.isCompatibleClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.CLASS +fun KotlinClassHeader.isCompatiblePackageFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.PACKAGE_FACADE +fun KotlinClassHeader.isCompatibleFileFacadeKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.FILE_FACADE +fun KotlinClassHeader.isCompatibleMultifileClassKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS +fun KotlinClassHeader.isCompatibleMultifileClassPartKind(): Boolean = isCompatibleAbiVersion && kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART 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 ecbb2d71eff..384d96eafee 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 @@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.SourceElement; import org.jetbrains.kotlin.load.java.AbiVersionUtil; import org.jetbrains.kotlin.name.ClassId; +import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.jvm.JvmClassName; import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion; @@ -39,7 +40,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private static final Map OLD_DEPRECATED_ANNOTATIONS_KINDS = new HashMap(); static { - HEADER_KINDS.put(KotlinClass.CLASS_NAME, CLASS); + HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_CLASS), CLASS); HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE), PACKAGE_FACADE); HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_FILE_FACADE), FILE_FACADE); HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_MULTIFILE_CLASS), MULTIFILE_CLASS); @@ -66,9 +67,9 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private String[] annotationData = null; private String[] strings = null; private KotlinClassHeader.Kind headerKind = null; - private KotlinClass.Kind classKind = null; private String syntheticClassKind = null; private boolean isInterfaceDefaultImpls = false; + private boolean isLocalClass = false; @Nullable public KotlinClassHeader createHeader() { @@ -76,11 +77,6 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor return null; } - if (headerKind == CLASS && classKind == null) { - // Default class kind is Kind.CLASS - classKind = KotlinClass.Kind.CLASS; - } - if (!AbiVersionUtil.isAbiVersionCompatible(version)) { annotationData = null; } @@ -91,8 +87,8 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor } return new KotlinClassHeader( - headerKind, version, annotationData, strings, classKind, syntheticClassKind, filePartClassNames, multifileClassName, - isInterfaceDefaultImpls + headerKind, version, annotationData, strings, syntheticClassKind, filePartClassNames, multifileClassName, + isInterfaceDefaultImpls, isLocalClass ); } @@ -106,10 +102,15 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor @Nullable @Override public AnnotationArgumentVisitor visitAnnotation(@NotNull ClassId classId, @NotNull SourceElement source) { - if (KOTLIN_INTERFACE_DEFAULT_IMPLS.equals(classId.asSingleFqName())) { + FqName fqName = classId.asSingleFqName(); + if (KOTLIN_INTERFACE_DEFAULT_IMPLS.equals(fqName)) { isInterfaceDefaultImpls = true; return null; } + else if (KOTLIN_LOCAL_CLASS.equals(fqName)) { + isLocalClass = true; + return null; + } if (headerKind != null) { // Ignore all Kotlin annotations except the first found @@ -269,14 +270,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private class ClassHeaderReader extends HeaderAnnotationArgumentVisitor { 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()); - } + super(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_CLASS)); } } @@ -316,16 +310,4 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor } } } - - // 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; - } - } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinClass.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinClass.java index 77270d3e02b..b54eaa1db15 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinClass.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinClass.java @@ -29,12 +29,14 @@ public @interface KotlinClass { int[] version() default {}; - Kind kind() default Kind.CLASS; - String[] data(); String[] strings(); + @Deprecated + Kind kind() default Kind.CLASS; + + @Deprecated enum Kind { CLASS, diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinLocalClass.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinLocalClass.java new file mode 100644 index 00000000000..8086c610a9f --- /dev/null +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinLocalClass.java @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.jvm.internal; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface KotlinLocalClass { + int[] version() default {}; +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/DecompiledUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/DecompiledUtils.kt index 091bf3d5230..ef6644f7dae 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/DecompiledUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/DecompiledUtils.kt @@ -21,7 +21,6 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.ClassFileViewProvider import org.jetbrains.kotlin.idea.caches.JarUserDataManager import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedClassFinder -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader @@ -71,9 +70,8 @@ public fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean { val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.classHeader ?: return false return header.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS || - (header.kind == KotlinClassHeader.Kind.CLASS && header.classKind != null && header.classKind != KotlinClass.Kind.CLASS) || header.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART || - header.syntheticClassKind == "PACKAGE_PART" + header.isLocalClass || header.syntheticClassKind == "PACKAGE_PART" } public fun isKotlinJavaScriptInternalCompiledFile(file: VirtualFile): Boolean = diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinClsStubBuilder.kt index 997e8179139..fc5cb8d7fd7 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinClsStubBuilder.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.idea.decompiler.isKotlinInternalCompiledFile import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedClassFinder import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedDataFinder import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter -import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind @@ -82,7 +81,7 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() { createPackageFacadeStub(packageProto, packageFqName, context) } header.isCompatibleClassKind() -> { - if (header.classKind != JvmAnnotationNames.KotlinClass.Kind.CLASS) return null + if (header.isLocalClass) return null val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData, strings) val context = components.createContext(nameResolver, packageFqName) createTopLevelClassStub(classId, classProto, context) diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt b/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt index 974a0a30eaa..ffae3ec46d1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt @@ -20,7 +20,6 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager import org.jetbrains.kotlin.idea.decompiler.navigation.NavigateToDecompiledLibraryTest import org.jetbrains.kotlin.idea.test.JetLightCodeInsightFixtureTestCase -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.junit.Assert @@ -34,11 +33,8 @@ public abstract class AbstractInternalCompiledClassesTest : JetLightCodeInsightF protected fun isSyntheticClass(): VirtualFile.() -> Boolean = isFileWithHeader { it.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS } - private fun isClassOfKind(kind: KotlinClass.Kind): VirtualFile.() -> Boolean = - isFileWithHeader { it.classKind == kind } - - protected fun doTestNoPsiFilesAreBuiltForLocalClass(kind: KotlinClass.Kind): Unit = - doTestNoPsiFilesAreBuiltFor(kind.name(), isClassOfKind(kind)) + protected fun doTestNoPsiFilesAreBuiltForLocalClass(): Unit = + doTestNoPsiFilesAreBuiltFor("local", isFileWithHeader { it.isLocalClass }) protected fun doTestNoPsiFilesAreBuiltForSyntheticClasses(): Unit = doTestNoPsiFilesAreBuiltFor("synthetic", isSyntheticClass()) diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/InternalCompiledClassesTest.kt b/idea/tests/org/jetbrains/kotlin/idea/decompiler/InternalCompiledClassesTest.kt index 37b930949c5..5c372773f05 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/InternalCompiledClassesTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/InternalCompiledClassesTest.kt @@ -20,17 +20,13 @@ import com.intellij.psi.ClassFileViewProvider import com.intellij.testFramework.LightProjectDescriptor import org.jetbrains.kotlin.idea.test.JdkAndMockLibraryProjectDescriptor import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.ANONYMOUS_OBJECT -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.LOCAL_CLASS public class InternalCompiledClassesTest : AbstractInternalCompiledClassesTest() { private val TEST_DATA_PATH = PluginTestCaseBase.getTestDataPathBase() + "/decompiler/internalClasses" fun testSyntheticClassesAreInvisible() = doTestNoPsiFilesAreBuiltForSyntheticClasses() - fun testLocalClassIsInvisible() = doTestNoPsiFilesAreBuiltForLocalClass(LOCAL_CLASS) - - fun testAnonymousObjectIsInvisible() = doTestNoPsiFilesAreBuiltForLocalClass(ANONYMOUS_OBJECT) + fun testLocalClassesAreInvisible() = doTestNoPsiFilesAreBuiltForLocalClass() fun testInnerClassIsInvisible() = doTestNoPsiFilesAreBuiltFor("inner or nested class") { ClassFileViewProvider.isInnerClass(this) diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt index 6a1573694f0..093349ccec1 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt @@ -31,7 +31,6 @@ import org.jetbrains.kotlin.jps.build.GeneratedJvmClass import org.jetbrains.kotlin.jps.build.KotlinBuilder import org.jetbrains.kotlin.jps.incremental.storage.BasicMap import org.jetbrains.kotlin.jps.incremental.storage.BasicStringMap -import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.ModuleMapping import org.jetbrains.kotlin.load.kotlin.PackageClassUtils @@ -216,10 +215,11 @@ public class IncrementalCacheImpl( constantsMap.process(kotlinClass) + inlineFunctionsMap.process(kotlinClass) } - header.isCompatibleClassKind() && JvmAnnotationNames.KotlinClass.Kind.CLASS == header.classKind -> + header.isCompatibleClassKind() && !header.isLocalClass -> { protoMap.process(kotlinClass, isPackage = false) + constantsMap.process(kotlinClass) + inlineFunctionsMap.process(kotlinClass) + } else -> ChangesInfo.NO_CHANGES }