Drop isLocalClass, do not write KotlinLocalClass

This commit is contained in:
Alexander Udalov
2016-01-18 02:23:53 +03:00
parent e17cd12c3c
commit aef6d49b48
13 changed files with 34 additions and 81 deletions
@@ -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;
}
});
@@ -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 {
@@ -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
@@ -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<OutputFile>): InlineInfo {
val inlineMethods = HashSet<MethodInfo>()
val classHeaders = hashMapOf<String, KotlinClassHeader>()
val binaryClasses = hashMapOf<String, KotlinJvmBinaryClass>()
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<OutputFile>, inlinedMethods: Set<MethodInfo>): List<NotInlinedCall> {
@@ -127,7 +128,7 @@ object InlineTestUtil {
val inlinedMethods = inlineInfo.inlineMethods
val notInlinedParameters = ArrayList<NotInlinedParameter>()
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<String>?): 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<MethodInfo>, val classHeaders: Map<String, KotlinClassHeader>)
private class InlineInfo(val inlineMethods: Set<MethodInfo>, val binaryClasses: Map<String, KotlinJvmBinaryClass>)
private data class NotInlinedCall(val fromCall: MethodInfo, val inlineMethod: MethodInfo)
@@ -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(
@@ -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<JvmClassName> NULLABILITY_ANNOTATIONS = new HashSet<JvmClassName>();
private static final Set<JvmClassName> SPECIAL_META_ANNOTATIONS = new HashSet<JvmClassName>();
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));
}
@@ -25,8 +25,7 @@ class KotlinClassHeader(
val bytecodeVersion: JvmBytecodeBinaryVersion,
val data: Array<String>?,
val strings: Array<String>?,
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"
}
@@ -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;
-1
View File
@@ -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.
@@ -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<KotlinJvmBinaryClass> {
@@ -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)
@@ -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())
@@ -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" }