diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index acd4192cb0c..a8d4376eda4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -247,10 +247,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { @Override protected void generateKotlinAnnotation() { - if (!isTopLevelOrInnerClass(descriptor)) { - v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_LOCAL_CLASS), true).visitEnd(); - } - final DescriptorSerializer serializer = DescriptorSerializer.create(descriptor, new JvmSerializerExtension(v.getSerializationBindings(), state)); @@ -260,9 +256,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { @Override public Unit invoke(AnnotationVisitor av) { writeAnnotationData(av, serializer, classProto, false); - if (!isTopLevelOrInnerClass(descriptor)) { - av.visit(JvmAnnotationNames.SYNTHETIC_CLASS_KIND_FIELD_NAME, KotlinClassHeader.SyntheticClassKind.LOCAL_CLASS.getId()); - } return Unit.INSTANCE; } }); diff --git a/compiler/testData/codegen/bytecodeListing/annotations/literals.txt b/compiler/testData/codegen/bytecodeListing/annotations/literals.txt index f9eef08db63..bc0b7e59e72 100644 --- a/compiler/testData/codegen/bytecodeListing/annotations/literals.txt +++ b/compiler/testData/codegen/bytecodeListing/annotations/literals.txt @@ -41,7 +41,6 @@ final class LiteralsKt$foo$2 { public synthetic method invoke(): java.lang.Object } -@kotlin.jvm.internal.KotlinLocalClass @kotlin.Metadata @kotlin.jvm.internal.KotlinClass public final class LiteralsKt$foo$3 { diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/DelegatedProperty.kt b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/DelegatedProperty.kt index 0662beba560..282ab61f3b2 100644 --- a/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/DelegatedProperty.kt +++ b/compiler/testData/loadJava/compiledKotlin/annotations/packageMembers/DelegatedProperty.kt @@ -1,3 +1,6 @@ +// SKIP_IN_RUNTIME_TEST because the anonymous object has no container and thus a non-local ClassId +// TODO: unskip + package test import kotlin.reflect.KProperty diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt b/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt index 0e41230165b..87c7b8242b9 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt +++ b/compiler/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass +import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.InTextDirectivesUtils @@ -55,7 +56,7 @@ object InlineTestUtil { private fun obtainInlineInfo(files: Iterable): InlineInfo { val inlineMethods = HashSet() - val classHeaders = hashMapOf() + val binaryClasses = hashMapOf() for (file in files) { val bytes = file.asByteArray() @@ -76,10 +77,10 @@ object InlineTestUtil { } cr.accept(classVisitor, 0) - classHeaders.put(classVisitor.className, getClassHeader(file)) + binaryClasses.put(classVisitor.className, loadBinaryClass(file)) } - return InlineInfo(inlineMethods, classHeaders) + return InlineInfo(inlineMethods, binaryClasses) } private fun checkInlineMethodNotInvoked(files: Iterable, inlinedMethods: Set): List { @@ -127,7 +128,7 @@ object InlineTestUtil { val inlinedMethods = inlineInfo.inlineMethods val notInlinedParameters = ArrayList() for (file in files) { - if (!isClassOrPackagePartKind(getClassHeader(file))) continue + if (!isClassOrPackagePartKind(loadBinaryClass(file))) continue ClassReader(file.asByteArray()).accept(object : ClassVisitorWithName() { override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { @@ -167,15 +168,15 @@ object InlineTestUtil { if (classInternalName.startsWith("kotlin/jvm/internal/")) return true - return isClassOrPackagePartKind(inlineInfo.classHeaders[classInternalName]!!) + return isClassOrPackagePartKind(inlineInfo.binaryClasses[classInternalName]!!) } - private fun isClassOrPackagePartKind(header: KotlinClassHeader): Boolean { - return header.kind == KotlinClassHeader.Kind.CLASS && !header.isLocalClass + private fun isClassOrPackagePartKind(klass: KotlinJvmBinaryClass): Boolean { + return klass.classHeader.kind == KotlinClassHeader.Kind.CLASS && !klass.classId.isLocal } - private fun getClassHeader(file: OutputFile): KotlinClassHeader { - return FileBasedKotlinClass.create(file.asByteArray()) { + private fun loadBinaryClass(file: OutputFile): KotlinJvmBinaryClass { + val klass = FileBasedKotlinClass.create(file.asByteArray()) { className, classHeader, innerClasses -> object : FileBasedKotlinClass(className, classHeader, innerClasses) { override fun getLocation(): String = throw UnsupportedOperationException() @@ -184,10 +185,11 @@ object InlineTestUtil { override fun equals(other: Any?): Boolean = throw UnsupportedOperationException() override fun toString(): String = throw UnsupportedOperationException() } - }!!.classHeader + }!! + return klass } - private class InlineInfo(val inlineMethods: Set, val classHeaders: Map) + private class InlineInfo(val inlineMethods: Set, val binaryClasses: Map) private data class NotInlinedCall(val fromCall: MethodInfo, val inlineMethod: MethodInfo) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt index 7eaea8a4b33..b06b98c5449 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.jvm.runtime import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAllTo -import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.GenerationUtils import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime import org.jetbrains.kotlin.descriptors.* @@ -26,8 +25,6 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.jvm.compiler.ExpectedLoadErrorsUtil import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil import org.jetbrains.kotlin.load.java.ANNOTATIONS_COPIED_TO_TYPES -import org.jetbrains.kotlin.load.java.JvmAnnotationNames -import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_LOCAL_CLASS import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.structure.reflect.classId import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader @@ -51,10 +48,6 @@ import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.Configuratio import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.sure -import org.jetbrains.org.objectweb.asm.AnnotationVisitor -import org.jetbrains.org.objectweb.asm.ClassReader -import org.jetbrains.org.objectweb.asm.ClassVisitor -import org.jetbrains.org.objectweb.asm.Opcodes import java.io.File import java.net.URLClassLoader import java.util.* @@ -168,7 +161,7 @@ abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() { packageScopes.add(packageView.memberScope) } } - else if (header == null || (header.kind == KotlinClassHeader.Kind.CLASS && !classFile.isLocalClass())) { + else if (header == null || header.kind == KotlinClassHeader.Kind.CLASS) { // Either a normal Kotlin class or a Java class val classId = klass.classId if (!classId.isLocal) { @@ -185,21 +178,6 @@ abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() { return SyntheticPackageViewForTest(module, packageScopes, classes) } - private fun File.isLocalClass(): Boolean { - var result = false - - ClassReader(inputStream()).accept(object : ClassVisitor(Opcodes.ASM5) { - override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? { - if (desc == AsmUtil.asmDescByFqNameWithoutInnerClasses(KOTLIN_LOCAL_CLASS)) { - result = true - } - return super.visitAnnotation(desc, visible) - } - }, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES) - - return result - } - private fun adaptJavaSource(text: String): String { val typeAnnotations = arrayOf("NotNull", "Nullable", "ReadOnly", "Mutable") return typeAnnotations.fold(text) { text, annotation -> text.replace("@$annotation", "") }.replace( 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 c2c5d413a4c..f435249ca61 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 @@ -35,7 +35,6 @@ public final class JvmAnnotationNames { public static final FqName KOTLIN_MULTIFILE_CLASS_PART = new FqName("kotlin.jvm.internal.KotlinMultifileClassPart"); public static final FqName KOTLIN_SYNTHETIC_CLASS = new FqName("kotlin.jvm.internal.KotlinSyntheticClass"); public static final FqName KOTLIN_FUNCTION = new FqName("kotlin.jvm.internal.KotlinFunction"); - public static final FqName KOTLIN_LOCAL_CLASS = new FqName("kotlin.jvm.internal.KotlinLocalClass"); public static final String VERSION_FIELD_NAME = "version"; public static final String METADATA_VERSION_FIELD_NAME = "mv"; @@ -72,7 +71,7 @@ public final class JvmAnnotationNames { private static final Set NULLABILITY_ANNOTATIONS = new HashSet(); private static final Set SPECIAL_META_ANNOTATIONS = new HashSet(); static { - for (FqName fqName : Arrays.asList(METADATA, KOTLIN_CLASS, KOTLIN_SYNTHETIC_CLASS, KOTLIN_LOCAL_CLASS)) { + for (FqName fqName : Arrays.asList(METADATA, KOTLIN_CLASS, KOTLIN_SYNTHETIC_CLASS)) { SPECIAL_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 25a96b12798..1b97a3097cd 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 @@ -25,8 +25,7 @@ class KotlinClassHeader( val bytecodeVersion: JvmBytecodeBinaryVersion, val data: Array?, val strings: Array?, - val multifileClassName: String?, - val isLocalClass: Boolean + val multifileClassName: String? ) { // See kotlin.Metadata enum class Kind(val id: Int) { @@ -47,15 +46,7 @@ class KotlinClassHeader( enum class SyntheticClassKind(val id: Int) { FUNCTION(1), - LOCAL_CLASS(2); - - 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" + override fun toString() = "$kind 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 a9b7a4f48ea..4aeace97e7a 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 @@ -53,8 +53,6 @@ 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 isLocalClass = false; @Nullable public KotlinClassHeader createHeader() { @@ -77,8 +75,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor bytecodeVersion != null ? bytecodeVersion : JvmBytecodeBinaryVersion.INVALID_VERSION, data, strings, - multifileClassName, - isLocalClass || syntheticClassKind == KotlinClassHeader.SyntheticClassKind.LOCAL_CLASS + multifileClassName ); } @@ -98,11 +95,6 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor if (IGNORE_OLD_METADATA) return null; - if (KOTLIN_LOCAL_CLASS.equals(fqName)) { - isLocalClass = true; - return null; - } - if (headerKind != null) { // Ignore all Kotlin annotations except the first found return null; @@ -142,11 +134,6 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor bytecodeVersion = new JvmBytecodeBinaryVersion((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; diff --git a/core/runtime.jvm/src/kotlin/Metadata.kt b/core/runtime.jvm/src/kotlin/Metadata.kt index 4ac2655e205..f20245b183e 100644 --- a/core/runtime.jvm/src/kotlin/Metadata.kt +++ b/core/runtime.jvm/src/kotlin/Metadata.kt @@ -60,7 +60,6 @@ internal annotation class Metadata( * An extra integer. For a synthetic class, the specific kind of this class which is one of the following: * * 1 Anonymous class for a lambda or a function reference - * 2 Local class or anonymous object literal * * A value other than this (e.g. 0) or a missing value means this is a synthetic class of some other sort. * This kind has no effect on the compiler because it doesn't read synthetic class metadata. It may be used in IDEs and tools. diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt index ea03a102c60..500083d9746 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt @@ -69,11 +69,12 @@ fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean { if (ClassFileViewProvider.isInnerClass(file)) { return true } - val header = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file)?.classHeader ?: return false + + val (header, classId) = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file) ?: return false + if (classId.isLocal) return true return header.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS || - header.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART || - header.isLocalClass + header.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART } fun findMultifileClassParts(file: VirtualFile, classId: ClassId, header: KotlinClassHeader): List { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt index 17de4a48eb1..0554f10f37e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt @@ -81,7 +81,7 @@ open class KotlinClsStubBuilder : ClsStubBuilder() { } return when (header.kind) { KotlinClassHeader.Kind.CLASS -> { - if (header.isLocalClass) return null + if (classId.isLocal) return null val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData, strings) val context = components.createContext(nameResolver, packageFqName, TypeTable(classProto.typeTable)) 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 9119403245e..e0654682ace 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt @@ -22,19 +22,20 @@ import org.jetbrains.kotlin.idea.caches.IDEKotlinBinaryClassCache import org.jetbrains.kotlin.idea.decompiler.navigation.NavigateToDecompiledLibraryTest import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader +import org.jetbrains.kotlin.name.ClassId import org.junit.Assert abstract class AbstractInternalCompiledClassesTest : KotlinLightCodeInsightFixtureTestCase() { - private fun isFileWithHeader(predicate: (KotlinClassHeader) -> Boolean) : VirtualFile.() -> Boolean = { - val header = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(this)?.classHeader - header != null && predicate(header) + private fun isFileWithHeader(predicate: (KotlinClassHeader, ClassId) -> Boolean) : VirtualFile.() -> Boolean = { + val info = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(this) + info != null && predicate(info.classHeader, info.classId) } protected fun isSyntheticClass(): VirtualFile.() -> Boolean = - isFileWithHeader { it.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS } + isFileWithHeader { header, classId -> header.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS } protected fun doTestNoPsiFilesAreBuiltForLocalClass(): Unit = - doTestNoPsiFilesAreBuiltFor("local", isFileWithHeader { it.isLocalClass }) + doTestNoPsiFilesAreBuiltFor("local", isFileWithHeader { header, classId -> classId.isLocal }) protected fun doTestNoPsiFilesAreBuiltForSyntheticClasses(): Unit = doTestNoPsiFilesAreBuiltFor("synthetic", isSyntheticClass()) 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 57192fdf139..6e1aa6b5f28 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt @@ -143,11 +143,11 @@ open class IncrementalCacheImpl( sourceToClassesMap.add(it, className) } - val header = kotlinClass.classHeader - if (header.isLocalClass) { + if (kotlinClass.classId.isLocal) { return CompilationResult.NO_CHANGES } + val header = kotlinClass.classHeader val changesInfo = when (header.kind) { KotlinClassHeader.Kind.FILE_FACADE -> { assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" }