Introduce infrastructure to separate string table from metadata on JVM
Nothing especially helpful happens here, this is only a big refactoring introducing a separate string array for the string table, which is currently always empty, but will contain actual strings soon
This commit is contained in:
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPackage;
|
import org.jetbrains.kotlin.resolve.jvm.JvmPackage;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||||
|
import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
|
||||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
import org.jetbrains.kotlin.types.TypesPackage;
|
import org.jetbrains.kotlin.types.TypesPackage;
|
||||||
@@ -841,6 +842,18 @@ public class AsmUtil {
|
|||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void writeAnnotationData(@NotNull AnnotationVisitor av, @NotNull byte[] bytes) {
|
||||||
|
JvmCodegenUtil.writeAbiVersion(av);
|
||||||
|
AnnotationVisitor data = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
|
||||||
|
for (String string : BitEncoding.encodeBytes(bytes)) {
|
||||||
|
data.visit(null, string);
|
||||||
|
}
|
||||||
|
data.visitEnd();
|
||||||
|
AnnotationVisitor strings = av.visitArray(JvmAnnotationNames.STRINGS_FIELD_NAME);
|
||||||
|
// TODO: write the actual string table
|
||||||
|
strings.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String asmDescByFqNameWithoutInnerClasses(@NotNull FqName fqName) {
|
public static String asmDescByFqNameWithoutInnerClasses(@NotNull FqName fqName) {
|
||||||
return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor();
|
return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor();
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
||||||
import org.jetbrains.kotlin.serialization.ProtoBuf;
|
import org.jetbrains.kotlin.serialization.ProtoBuf;
|
||||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
|
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||||
import org.jetbrains.kotlin.utils.UtilsPackage;
|
import org.jetbrains.kotlin.utils.UtilsPackage;
|
||||||
@@ -231,12 +230,7 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
|
|||||||
ProtoBuf.Callable callableProto = serializer.callableProto(funDescriptor).build();
|
ProtoBuf.Callable callableProto = serializer.callableProto(funDescriptor).build();
|
||||||
|
|
||||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CALLABLE), true);
|
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CALLABLE), true);
|
||||||
JvmCodegenUtil.writeAbiVersion(av);
|
writeAnnotationData(av, serializer.serialize(callableProto));
|
||||||
AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
|
|
||||||
for (String string : BitEncoding.encodeBytes(serializer.serialize(callableProto))) {
|
|
||||||
array.visit(null, string);
|
|
||||||
}
|
|
||||||
array.visitEnd();
|
|
||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
|
||||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
||||||
import org.jetbrains.kotlin.serialization.ProtoBuf;
|
import org.jetbrains.kotlin.serialization.ProtoBuf;
|
||||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
|
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.org.objectweb.asm.*;
|
import org.jetbrains.org.objectweb.asm.*;
|
||||||
@@ -254,7 +253,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
ProtoBuf.Class classProto = serializer.classProto(descriptor).build();
|
ProtoBuf.Class classProto = serializer.classProto(descriptor).build();
|
||||||
|
|
||||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true);
|
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true);
|
||||||
JvmCodegenUtil.writeAbiVersion(av);
|
writeAnnotationData(av, serializer.serialize(classProto));
|
||||||
if (kind != null) {
|
if (kind != null) {
|
||||||
av.visitEnum(
|
av.visitEnum(
|
||||||
JvmAnnotationNames.KIND_FIELD_NAME,
|
JvmAnnotationNames.KIND_FIELD_NAME,
|
||||||
@@ -262,11 +261,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
kind.toString()
|
kind.toString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
|
|
||||||
for (String string : BitEncoding.encodeBytes(serializer.serialize(classProto))) {
|
|
||||||
array.visit(null, string);
|
|
||||||
}
|
|
||||||
array.visitEnd();
|
|
||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.psi.JetNamedFunction
|
|||||||
import org.jetbrains.kotlin.psi.JetProperty
|
import org.jetbrains.kotlin.psi.JetProperty
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
|
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -96,13 +95,8 @@ public class MultifileClassPartCodegen(
|
|||||||
if (packageProto.memberCount == 0) return
|
if (packageProto.memberCount == 0) return
|
||||||
|
|
||||||
val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS_PART), true)
|
val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS_PART), true)
|
||||||
JvmCodegenUtil.writeAbiVersion(av)
|
AsmUtil.writeAnnotationData(av, serializer.serialize(packageProto))
|
||||||
av.visit(JvmAnnotationNames.MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassFqName.shortName().asString())
|
av.visit(JvmAnnotationNames.MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassFqName.shortName().asString())
|
||||||
val dataArray = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME)
|
|
||||||
for (string in BitEncoding.encodeBytes(serializer.serialize(packageProto))) {
|
|
||||||
dataArray.visit(null, string)
|
|
||||||
}
|
|
||||||
dataArray.visitEnd()
|
|
||||||
av.visitEnd()
|
av.visitEnd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ import org.jetbrains.kotlin.serialization.ProtoBuf;
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor;
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor;
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor;
|
||||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
|
|
||||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
@@ -291,12 +290,7 @@ public class PackageCodegen {
|
|||||||
ProtoBuf.Package packageProto = serializer.packageProtoWithoutDescriptors().build();
|
ProtoBuf.Package packageProto = serializer.packageProtoWithoutDescriptors().build();
|
||||||
|
|
||||||
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE), true);
|
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE), true);
|
||||||
JvmCodegenUtil.writeAbiVersion(av);
|
AsmUtil.writeAnnotationData(av, serializer.serialize(packageProto));
|
||||||
AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
|
|
||||||
for (String string : BitEncoding.encodeBytes(serializer.serialize(packageProto))) {
|
|
||||||
array.visit(null, string);
|
|
||||||
}
|
|
||||||
array.visitEnd();
|
|
||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.psi.*;
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
import org.jetbrains.kotlin.serialization.DescriptorSerializer;
|
||||||
import org.jetbrains.kotlin.serialization.ProtoBuf;
|
import org.jetbrains.kotlin.serialization.ProtoBuf;
|
||||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding;
|
|
||||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
|
|
||||||
@@ -41,6 +40,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
|
import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
|
||||||
|
import static org.jetbrains.kotlin.codegen.AsmUtil.writeAnnotationData;
|
||||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
public class PackagePartCodegen extends MemberCodegen<JetFile> {
|
public class PackagePartCodegen extends MemberCodegen<JetFile> {
|
||||||
@@ -128,12 +128,7 @@ public class PackagePartCodegen extends MemberCodegen<JetFile> {
|
|||||||
if (packageProto.getMemberCount() == 0) return;
|
if (packageProto.getMemberCount() == 0) return;
|
||||||
|
|
||||||
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FILE_FACADE), true);
|
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FILE_FACADE), true);
|
||||||
JvmCodegenUtil.writeAbiVersion(av);
|
writeAnnotationData(av, serializer.serialize(packageProto));
|
||||||
AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
|
|
||||||
for (String string : BitEncoding.encodeBytes(serializer.serialize(packageProto))) {
|
|
||||||
array.visit(null, string);
|
|
||||||
}
|
|
||||||
array.visitEnd();
|
|
||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-7
@@ -117,17 +117,20 @@ public class IncrementalPackageFragmentProvider(
|
|||||||
allParts.filterNot { it in obsoletePackageParts }
|
allParts.filterNot { it in obsoletePackageParts }
|
||||||
} ?: emptyList<String>()
|
} ?: emptyList<String>()
|
||||||
|
|
||||||
val dataOfPackageParts = actualPackagePartFiles.map { incrementalCache.getPackagePartData(it) }.filterNotNull()
|
val scopes = actualPackagePartFiles
|
||||||
|
.map {
|
||||||
|
incrementalCache.getPackagePartData(it)
|
||||||
|
}
|
||||||
|
.filterNotNull()
|
||||||
|
.map {
|
||||||
|
IncrementalPackageScope(JvmProtoBufUtil.readPackageDataFrom(it.data, it.strings))
|
||||||
|
}
|
||||||
|
|
||||||
if (dataOfPackageParts.isEmpty()) {
|
if (scopes.isEmpty()) {
|
||||||
JetScope.Empty
|
JetScope.Empty
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val scopes = dataOfPackageParts.map { IncrementalPackageScope(JvmProtoBufUtil.readPackageDataFrom(it)) }
|
ChainedScope(this, "Member scope for incremental compilation: union of package parts data", *scopes.toTypedArray())
|
||||||
ChainedScope(this,
|
|
||||||
"Member scope for incremental compilation: union of package parts data",
|
|
||||||
*scopes.toTypedArray<JetScope>()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -16,10 +16,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.load.kotlin.incremental.components
|
package org.jetbrains.kotlin.load.kotlin.incremental.components
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class JvmPackagePartProto(val data: ByteArray, val strings: Array<String>) : Serializable
|
||||||
|
|
||||||
public interface IncrementalCache {
|
public interface IncrementalCache {
|
||||||
public fun getObsoletePackageParts(): Collection<String>
|
public fun getObsoletePackageParts(): Collection<String>
|
||||||
|
|
||||||
public fun getPackagePartData(fqName: String): ByteArray?
|
public fun getPackagePartData(fqName: String): JvmPackagePartProto?
|
||||||
|
|
||||||
public fun getModuleMappingData(): ByteArray?
|
public fun getModuleMappingData(): ByteArray?
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -17,12 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.rmi.kotlinr
|
package org.jetbrains.kotlin.rmi.kotlinr
|
||||||
|
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
|
||||||
import org.jetbrains.kotlin.rmi.CompileService
|
import org.jetbrains.kotlin.rmi.CompileService
|
||||||
import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface
|
import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface
|
||||||
import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT
|
import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT
|
||||||
import java.rmi.server.UnicastRemoteObject
|
import java.rmi.server.UnicastRemoteObject
|
||||||
|
|
||||||
|
|
||||||
public class RemoteIncrementalCacheServer(val cache: IncrementalCache, port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteIncrementalCache {
|
public class RemoteIncrementalCacheServer(val cache: IncrementalCache, port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteIncrementalCache {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -31,7 +31,7 @@ public class RemoteIncrementalCacheServer(val cache: IncrementalCache, port: Int
|
|||||||
|
|
||||||
override fun getObsoletePackageParts(): Collection<String> = cache.getObsoletePackageParts()
|
override fun getObsoletePackageParts(): Collection<String> = cache.getObsoletePackageParts()
|
||||||
|
|
||||||
override fun getPackagePartData(fqName: String): ByteArray? = cache.getPackagePartData(fqName)
|
override fun getPackagePartData(fqName: String): JvmPackagePartProto? = cache.getPackagePartData(fqName)
|
||||||
|
|
||||||
override fun getModuleMappingData(): ByteArray? = cache.getModuleMappingData()
|
override fun getModuleMappingData(): ByteArray? = cache.getModuleMappingData()
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.rmi
|
package org.jetbrains.kotlin.rmi
|
||||||
|
|
||||||
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
import org.jetbrains.kotlin.incremental.components.ScopeKind
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
|
||||||
import org.jetbrains.kotlin.modules.TargetId
|
import org.jetbrains.kotlin.modules.TargetId
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.rmi.Remote
|
import java.rmi.Remote
|
||||||
@@ -34,7 +35,7 @@ public interface CompileService : Remote {
|
|||||||
public fun getObsoletePackageParts(): Collection<String>
|
public fun getObsoletePackageParts(): Collection<String>
|
||||||
|
|
||||||
@Throws(RemoteException::class)
|
@Throws(RemoteException::class)
|
||||||
public fun getPackagePartData(fqName: String): ByteArray?
|
public fun getPackagePartData(fqName: String): JvmPackagePartProto?
|
||||||
|
|
||||||
@Throws(RemoteException::class)
|
@Throws(RemoteException::class)
|
||||||
public fun getModuleMappingData(): ByteArray?
|
public fun getModuleMappingData(): ByteArray?
|
||||||
|
|||||||
+2
-1
@@ -17,12 +17,13 @@
|
|||||||
package org.jetbrains.kotlin.rmi.service
|
package org.jetbrains.kotlin.rmi.service
|
||||||
|
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
|
||||||
import org.jetbrains.kotlin.rmi.CompileService
|
import org.jetbrains.kotlin.rmi.CompileService
|
||||||
|
|
||||||
public class RemoteIncrementalCacheClient(val cache: CompileService.RemoteIncrementalCache): IncrementalCache {
|
public class RemoteIncrementalCacheClient(val cache: CompileService.RemoteIncrementalCache): IncrementalCache {
|
||||||
override fun getObsoletePackageParts(): Collection<String> = cache.getObsoletePackageParts()
|
override fun getObsoletePackageParts(): Collection<String> = cache.getObsoletePackageParts()
|
||||||
|
|
||||||
override fun getPackagePartData(fqName: String): ByteArray? = cache.getPackagePartData(fqName)
|
override fun getPackagePartData(fqName: String): JvmPackagePartProto? = cache.getPackagePartData(fqName)
|
||||||
|
|
||||||
override fun getModuleMappingData(): ByteArray? = cache.getModuleMappingData()
|
override fun getModuleMappingData(): ByteArray? = cache.getModuleMappingData()
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,9 @@ public class KotlinClassAnnotationTest extends CodegenTestCase {
|
|||||||
|
|
||||||
String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinClass, "data");
|
String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinClass, "data");
|
||||||
assertNotNull(data);
|
assertNotNull(data);
|
||||||
ClassData classData = JvmProtoBufUtil.readClassDataFrom(data);
|
String[] strings = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinClass, "strings");
|
||||||
|
assertNotNull(strings);
|
||||||
|
ClassData classData = JvmProtoBufUtil.readClassDataFrom(data, strings);
|
||||||
|
|
||||||
Set<String> callableNames = collectCallableNames(classData.getClassProto().getMemberList(), classData.getNameResolver());
|
Set<String> callableNames = collectCallableNames(classData.getClassProto().getMemberList(), classData.getNameResolver());
|
||||||
assertSameElements(Arrays.asList("foo", "bar"), callableNames);
|
assertSameElements(Arrays.asList("foo", "bar"), callableNames);
|
||||||
|
|||||||
@@ -60,7 +60,9 @@ public class KotlinPackageAnnotationTest extends CodegenTestCase {
|
|||||||
|
|
||||||
String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "data");
|
String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "data");
|
||||||
assertNotNull(data);
|
assertNotNull(data);
|
||||||
PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data);
|
String[] strings = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "strings");
|
||||||
|
assertNotNull(strings);
|
||||||
|
PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data, strings);
|
||||||
|
|
||||||
Set<String> callableNames = collectCallableNames(packageData.getPackageProto().getMemberList(), packageData.getNameResolver());
|
Set<String> callableNames = collectCallableNames(packageData.getPackageProto().getMemberList(), packageData.getNameResolver());
|
||||||
assertEmpty(callableNames);
|
assertEmpty(callableNames);
|
||||||
@@ -84,7 +86,9 @@ public class KotlinPackageAnnotationTest extends CodegenTestCase {
|
|||||||
|
|
||||||
String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "data");
|
String[] data = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "data");
|
||||||
assertNotNull(data);
|
assertNotNull(data);
|
||||||
PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data);
|
String[] strings = (String[]) CodegenTestUtil.getAnnotationAttribute(kotlinPackage, "strings");
|
||||||
|
assertNotNull(strings);
|
||||||
|
PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data, strings);
|
||||||
|
|
||||||
Set<String> callableNames = collectCallableNames(packageData.getPackageProto().getMemberList(), packageData.getNameResolver());
|
Set<String> callableNames = collectCallableNames(packageData.getPackageProto().getMemberList(), packageData.getNameResolver());
|
||||||
assertSameElements(callableNames, Arrays.asList("foo", "bar"));
|
assertSameElements(callableNames, Arrays.asList("foo", "bar"));
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public final class JvmAnnotationNames {
|
|||||||
public static final String FILE_PART_CLASS_NAMES_FIELD_NAME = "filePartClassNames";
|
public static final String FILE_PART_CLASS_NAMES_FIELD_NAME = "filePartClassNames";
|
||||||
public static final String MULTIFILE_CLASS_NAME_FIELD_NAME = "multifileClassName";
|
public static final String MULTIFILE_CLASS_NAME_FIELD_NAME = "multifileClassName";
|
||||||
public static final String DATA_FIELD_NAME = "data";
|
public static final String DATA_FIELD_NAME = "data";
|
||||||
|
public static final String STRINGS_FIELD_NAME = "strings";
|
||||||
public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value");
|
public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value");
|
||||||
public static final Name TARGET_ANNOTATION_MEMBER_NAME = Name.identifier("allowedTargets");
|
public static final Name TARGET_ANNOTATION_MEMBER_NAME = Name.identifier("allowedTargets");
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -61,7 +61,9 @@ public final class DeserializedDescriptorResolver {
|
|||||||
public ClassDescriptor resolveClass(@NotNull KotlinJvmBinaryClass kotlinClass) {
|
public ClassDescriptor resolveClass(@NotNull KotlinJvmBinaryClass kotlinClass) {
|
||||||
String[] data = readData(kotlinClass, KOTLIN_CLASS);
|
String[] data = readData(kotlinClass, KOTLIN_CLASS);
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
ClassData classData = JvmProtoBufUtil.readClassDataFrom(data);
|
String[] strings = kotlinClass.getClassHeader().getStrings();
|
||||||
|
assert strings != null : "String table not found in " + kotlinClass;
|
||||||
|
ClassData classData = JvmProtoBufUtil.readClassDataFrom(data, strings);
|
||||||
KotlinJvmBinarySourceElement sourceElement = new KotlinJvmBinarySourceElement(kotlinClass);
|
KotlinJvmBinarySourceElement sourceElement = new KotlinJvmBinarySourceElement(kotlinClass);
|
||||||
return components.getClassDeserializer().deserializeClass(
|
return components.getClassDeserializer().deserializeClass(
|
||||||
kotlinClass.getClassId(),
|
kotlinClass.getClassId(),
|
||||||
@@ -75,13 +77,15 @@ public final class DeserializedDescriptorResolver {
|
|||||||
public JetScope createKotlinPackagePartScope(@NotNull PackageFragmentDescriptor descriptor, @NotNull KotlinJvmBinaryClass kotlinClass) {
|
public JetScope createKotlinPackagePartScope(@NotNull PackageFragmentDescriptor descriptor, @NotNull KotlinJvmBinaryClass kotlinClass) {
|
||||||
String[] data = readData(kotlinClass, KOTLIN_FILE_FACADE_OR_MULTIFILE_CLASS_PART);
|
String[] data = readData(kotlinClass, KOTLIN_FILE_FACADE_OR_MULTIFILE_CLASS_PART);
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
//all classes are included in java scope
|
String[] strings = kotlinClass.getClassHeader().getStrings();
|
||||||
PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data);
|
assert strings != null : "String table not found in " + kotlinClass;
|
||||||
|
PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data, strings);
|
||||||
return new DeserializedPackageMemberScope(
|
return new DeserializedPackageMemberScope(
|
||||||
descriptor, packageData.getPackageProto(), packageData.getNameResolver(), components,
|
descriptor, packageData.getPackageProto(), packageData.getNameResolver(), components,
|
||||||
new Function0<Collection<Name>>() {
|
new Function0<Collection<Name>>() {
|
||||||
@Override
|
@Override
|
||||||
public Collection<Name> invoke() {
|
public Collection<Name> invoke() {
|
||||||
|
// All classes are included into Java scope
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -27,11 +27,12 @@ public class JavaClassDataFinder(
|
|||||||
) : ClassDataFinder {
|
) : ClassDataFinder {
|
||||||
override fun findClassData(classId: ClassId): ClassDataWithSource? {
|
override fun findClassData(classId: ClassId): ClassDataWithSource? {
|
||||||
val kotlinJvmBinaryClass = kotlinClassFinder.findKotlinClass(classId) ?: return null
|
val kotlinJvmBinaryClass = kotlinClassFinder.findKotlinClass(classId) ?: return null
|
||||||
assert(kotlinJvmBinaryClass.getClassId() == classId) {
|
assert(kotlinJvmBinaryClass.classId == classId) {
|
||||||
"Class with incorrect id found: expected $classId, actual ${kotlinJvmBinaryClass.getClassId()}"
|
"Class with incorrect id found: expected $classId, actual ${kotlinJvmBinaryClass.classId}"
|
||||||
}
|
}
|
||||||
val data = deserializedDescriptorResolver.readData(kotlinJvmBinaryClass, DeserializedDescriptorResolver.KOTLIN_CLASS) ?: return null
|
val data = deserializedDescriptorResolver.readData(kotlinJvmBinaryClass, DeserializedDescriptorResolver.KOTLIN_CLASS) ?: return null
|
||||||
val classData = JvmProtoBufUtil.readClassDataFrom(data)
|
val strings = kotlinJvmBinaryClass.classHeader.strings ?: error("String table not found in $kotlinJvmBinaryClass")
|
||||||
|
val classData = JvmProtoBufUtil.readClassDataFrom(data, strings)
|
||||||
return ClassDataWithSource(classData, KotlinJvmBinarySourceElement(kotlinJvmBinaryClass))
|
return ClassDataWithSource(classData, KotlinJvmBinarySourceElement(kotlinJvmBinaryClass))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -25,6 +25,7 @@ public class KotlinClassHeader(
|
|||||||
public val kind: KotlinClassHeader.Kind,
|
public val kind: KotlinClassHeader.Kind,
|
||||||
public val version: BinaryVersion,
|
public val version: BinaryVersion,
|
||||||
public val annotationData: Array<String>?,
|
public val annotationData: Array<String>?,
|
||||||
|
public val strings: Array<String>?,
|
||||||
public val classKind: KotlinClass.Kind?,
|
public val classKind: KotlinClass.Kind?,
|
||||||
public val syntheticClassKind: KotlinSyntheticClass.Kind?,
|
public val syntheticClassKind: KotlinSyntheticClass.Kind?,
|
||||||
public val filePartClassNames: Array<String>?,
|
public val filePartClassNames: Array<String>?,
|
||||||
|
|||||||
+33
-16
@@ -64,6 +64,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
private String multifileClassName = null;
|
private String multifileClassName = null;
|
||||||
private String[] filePartClassNames = null;
|
private String[] filePartClassNames = null;
|
||||||
private String[] annotationData = null;
|
private String[] annotationData = null;
|
||||||
|
private String[] strings = null;
|
||||||
private KotlinClassHeader.Kind headerKind = null;
|
private KotlinClassHeader.Kind headerKind = null;
|
||||||
private KotlinClass.Kind classKind = null;
|
private KotlinClass.Kind classKind = null;
|
||||||
private KotlinSyntheticClass.Kind syntheticClassKind = null;
|
private KotlinSyntheticClass.Kind syntheticClassKind = null;
|
||||||
@@ -80,7 +81,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!AbiVersionUtil.isAbiVersionCompatible(version)) {
|
if (!AbiVersionUtil.isAbiVersionCompatible(version)) {
|
||||||
return new KotlinClassHeader(headerKind, version, null, classKind, syntheticClassKind, null, null);
|
return new KotlinClassHeader(headerKind, version, null, strings, classKind, syntheticClassKind, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldHaveData() && annotationData == null) {
|
if (shouldHaveData() && annotationData == null) {
|
||||||
@@ -89,7 +90,9 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new KotlinClassHeader(headerKind, version, annotationData, classKind, syntheticClassKind, filePartClassNames, multifileClassName);
|
return new KotlinClassHeader(
|
||||||
|
headerKind, version, annotationData, strings, classKind, syntheticClassKind, filePartClassNames, multifileClassName
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldHaveData() {
|
private boolean shouldHaveData() {
|
||||||
@@ -171,10 +174,14 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
||||||
if (name.asString().equals(DATA_FIELD_NAME)) {
|
String string = name.asString();
|
||||||
|
if (DATA_FIELD_NAME.equals(string)) {
|
||||||
return dataArrayVisitor();
|
return dataArrayVisitor();
|
||||||
}
|
}
|
||||||
else if (name.asString().equals(FILE_PART_CLASS_NAMES_FIELD_NAME)) {
|
else if (STRINGS_FIELD_NAME.equals(string)) {
|
||||||
|
return stringsArrayVisitor();
|
||||||
|
}
|
||||||
|
else if (FILE_PART_CLASS_NAMES_FIELD_NAME.equals(string)) {
|
||||||
return filePartClassNamesVisitor();
|
return filePartClassNamesVisitor();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -186,12 +193,32 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
private AnnotationArrayArgumentVisitor filePartClassNamesVisitor() {
|
private AnnotationArrayArgumentVisitor filePartClassNamesVisitor() {
|
||||||
return new CollectStringArrayAnnotationVisitor() {
|
return new CollectStringArrayAnnotationVisitor() {
|
||||||
@Override
|
@Override
|
||||||
protected void visitEnd(String[] data) {
|
protected void visitEnd(@NotNull String[] data) {
|
||||||
filePartClassNames = data;
|
filePartClassNames = data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private AnnotationArrayArgumentVisitor dataArrayVisitor() {
|
||||||
|
return new CollectStringArrayAnnotationVisitor() {
|
||||||
|
@Override
|
||||||
|
protected void visitEnd(@NotNull String[] data) {
|
||||||
|
annotationData = data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private AnnotationArrayArgumentVisitor stringsArrayVisitor() {
|
||||||
|
return new CollectStringArrayAnnotationVisitor() {
|
||||||
|
@Override
|
||||||
|
protected void visitEnd(@NotNull String[] data) {
|
||||||
|
strings = data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||||
}
|
}
|
||||||
@@ -202,16 +229,6 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private AnnotationArrayArgumentVisitor dataArrayVisitor() {
|
|
||||||
return new CollectStringArrayAnnotationVisitor() {
|
|
||||||
@Override
|
|
||||||
protected void visitEnd(String[] data) {
|
|
||||||
annotationData = data;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitEnd() {
|
public void visitEnd() {
|
||||||
}
|
}
|
||||||
@@ -240,7 +257,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
visitEnd(strings.toArray(new String[strings.size()]));
|
visitEnd(strings.toArray(new String[strings.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void visitEnd(String[] data);
|
protected abstract void visitEnd(@NotNull String[] data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -31,11 +31,11 @@ public object JvmProtoBufUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun readClassDataFrom(data: Array<String>): ClassData =
|
public fun readClassDataFrom(data: Array<String>, strings: Array<String>): ClassData =
|
||||||
readClassDataFrom(BitEncoding.decodeBytes(data))
|
readClassDataFrom(BitEncoding.decodeBytes(data), strings)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun readClassDataFrom(bytes: ByteArray): ClassData {
|
public fun readClassDataFrom(bytes: ByteArray, strings: Array<String>): ClassData {
|
||||||
val input = ByteArrayInputStream(bytes)
|
val input = ByteArrayInputStream(bytes)
|
||||||
val nameResolver = NameResolverImpl.read(input)
|
val nameResolver = NameResolverImpl.read(input)
|
||||||
val classProto = ProtoBuf.Class.parseFrom(input, EXTENSION_REGISTRY)
|
val classProto = ProtoBuf.Class.parseFrom(input, EXTENSION_REGISTRY)
|
||||||
@@ -43,11 +43,11 @@ public object JvmProtoBufUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun readPackageDataFrom(data: Array<String>): PackageData =
|
public fun readPackageDataFrom(data: Array<String>, strings: Array<String>): PackageData =
|
||||||
readPackageDataFrom(BitEncoding.decodeBytes(data))
|
readPackageDataFrom(BitEncoding.decodeBytes(data), strings)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun readPackageDataFrom(bytes: ByteArray): PackageData {
|
public fun readPackageDataFrom(bytes: ByteArray, strings: Array<String>): PackageData {
|
||||||
val input = ByteArrayInputStream(bytes)
|
val input = ByteArrayInputStream(bytes)
|
||||||
val nameResolver = NameResolverImpl.read(input)
|
val nameResolver = NameResolverImpl.read(input)
|
||||||
val packageProto = ProtoBuf.Package.parseFrom(input, EXTENSION_REGISTRY)
|
val packageProto = ProtoBuf.Package.parseFrom(input, EXTENSION_REGISTRY)
|
||||||
|
|||||||
@@ -30,4 +30,6 @@ public @interface KotlinCallable {
|
|||||||
int[] version() default {};
|
int[] version() default {};
|
||||||
|
|
||||||
String[] data();
|
String[] data();
|
||||||
|
|
||||||
|
String[] strings();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ public @interface KotlinClass {
|
|||||||
|
|
||||||
String[] data();
|
String[] data();
|
||||||
|
|
||||||
|
String[] strings();
|
||||||
|
|
||||||
enum Kind {
|
enum Kind {
|
||||||
CLASS,
|
CLASS,
|
||||||
|
|
||||||
|
|||||||
@@ -30,4 +30,6 @@ public @interface KotlinFileFacade {
|
|||||||
int[] version() default {};
|
int[] version() default {};
|
||||||
|
|
||||||
String[] data();
|
String[] data();
|
||||||
|
|
||||||
|
String[] strings();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,4 +30,6 @@ public @interface KotlinMultifileClass {
|
|||||||
int[] version() default {};
|
int[] version() default {};
|
||||||
|
|
||||||
String[] filePartClassNames();
|
String[] filePartClassNames();
|
||||||
|
|
||||||
|
String[] strings();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,4 +32,6 @@ public @interface KotlinMultifileClassPart {
|
|||||||
String multifileClassName();
|
String multifileClassName();
|
||||||
|
|
||||||
String[] data();
|
String[] data();
|
||||||
|
|
||||||
|
String[] strings();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,4 +30,6 @@ public @interface KotlinPackage {
|
|||||||
int[] version() default {};
|
int[] version() default {};
|
||||||
|
|
||||||
String[] data();
|
String[] data();
|
||||||
|
|
||||||
|
String[] strings();
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-3
@@ -70,20 +70,25 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
|
|||||||
LOG.error("Corrupted kotlin header for file ${file.getName()}")
|
LOG.error("Corrupted kotlin header for file ${file.getName()}")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
val strings = header.strings
|
||||||
|
if (strings == null) {
|
||||||
|
LOG.error("String table not found in file ${file.getName()}")
|
||||||
|
return null
|
||||||
|
}
|
||||||
return when {
|
return when {
|
||||||
header.isCompatiblePackageFacadeKind() -> {
|
header.isCompatiblePackageFacadeKind() -> {
|
||||||
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData)
|
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings)
|
||||||
val context = components.createContext(nameResolver, packageFqName)
|
val context = components.createContext(nameResolver, packageFqName)
|
||||||
createPackageFacadeStub(packageProto, packageFqName, context)
|
createPackageFacadeStub(packageProto, packageFqName, context)
|
||||||
}
|
}
|
||||||
header.isCompatibleClassKind() -> {
|
header.isCompatibleClassKind() -> {
|
||||||
if (header.classKind != JvmAnnotationNames.KotlinClass.Kind.CLASS) return null
|
if (header.classKind != JvmAnnotationNames.KotlinClass.Kind.CLASS) return null
|
||||||
val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData)
|
val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData, strings)
|
||||||
val context = components.createContext(nameResolver, packageFqName)
|
val context = components.createContext(nameResolver, packageFqName)
|
||||||
createTopLevelClassStub(classId, classProto, context)
|
createTopLevelClassStub(classId, classProto, context)
|
||||||
}
|
}
|
||||||
header.isCompatibleFileFacadeKind() -> {
|
header.isCompatibleFileFacadeKind() -> {
|
||||||
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData)
|
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings)
|
||||||
val context = components.createContext(nameResolver, packageFqName)
|
val context = components.createContext(nameResolver, packageFqName)
|
||||||
createFileFacadeStub(packageProto, classId.asSingleFqName(), context)
|
createFileFacadeStub(packageProto, classId.asSingleFqName(), context)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.idea.stubindex.KotlinFileStubForIde
|
|||||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -87,7 +86,7 @@ fun createMultifileClassStub(
|
|||||||
val multifileClassContainer = ProtoContainer(null, packageFqName)
|
val multifileClassContainer = ProtoContainer(null, packageFqName)
|
||||||
for (partFile in partFiles) {
|
for (partFile in partFiles) {
|
||||||
val partHeader = partFile.classHeader
|
val partHeader = partFile.classHeader
|
||||||
val partData = JvmProtoBufUtil.readPackageDataFrom(partHeader.annotationData!!)
|
val partData = JvmProtoBufUtil.readPackageDataFrom(partHeader.annotationData!!, partHeader.strings!!)
|
||||||
val partContext = components.createContext(partData.nameResolver, packageFqName)
|
val partContext = components.createContext(partData.nameResolver, packageFqName)
|
||||||
for (partMember in partData.packageProto.memberList) {
|
for (partMember in partData.packageProto.memberList) {
|
||||||
createCallableStub(fileStub, partMember, partContext, multifileClassContainer)
|
createCallableStub(fileStub, partMember, partContext, multifileClassContainer)
|
||||||
|
|||||||
+6
-4
@@ -62,12 +62,14 @@ public class DeserializerForDecompiler(
|
|||||||
"Was called for $facadeFqName; only members of $directoryPackageFqName package are expected."
|
"Was called for $facadeFqName; only members of $directoryPackageFqName package are expected."
|
||||||
}
|
}
|
||||||
val binaryClassForPackageClass = classFinder.findKotlinClass(ClassId.topLevel(facadeFqName))
|
val binaryClassForPackageClass = classFinder.findKotlinClass(ClassId.topLevel(facadeFqName))
|
||||||
val annotationData = binaryClassForPackageClass?.classHeader?.annotationData
|
val header = binaryClassForPackageClass?.classHeader
|
||||||
if (annotationData == null) {
|
val annotationData = header?.annotationData
|
||||||
LOG.error("Could not read annotation data for $facadeFqName from ${binaryClassForPackageClass?.classId}")
|
val strings = header?.strings
|
||||||
|
if (annotationData == null || strings == null) {
|
||||||
|
LOG.error("Could not read annotation data for $facadeFqName from ${binaryClassForPackageClass?.getClassId()}")
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData)
|
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings)
|
||||||
val membersScope = DeserializedPackageMemberScope(
|
val membersScope = DeserializedPackageMemberScope(
|
||||||
createDummyPackageFragment(packageFqName), packageProto, nameResolver, deserializationComponents
|
createDummyPackageFragment(packageFqName), packageProto, nameResolver, deserializationComponents
|
||||||
) { emptyList() }
|
) { emptyList() }
|
||||||
|
|||||||
+9
-4
@@ -73,14 +73,19 @@ class DirectoryBasedDataFinder(
|
|||||||
) : ClassDataFinder {
|
) : ClassDataFinder {
|
||||||
override fun findClassData(classId: ClassId): ClassDataWithSource? {
|
override fun findClassData(classId: ClassId): ClassDataWithSource? {
|
||||||
val binaryClass = classFinder.findKotlinClass(classId) ?: return null
|
val binaryClass = classFinder.findKotlinClass(classId) ?: return null
|
||||||
val data = binaryClass.getClassHeader().annotationData
|
val classHeader = binaryClass.classHeader
|
||||||
|
val data = classHeader.annotationData
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
log.error("Annotation data missing for ${binaryClass.getClassId()}")
|
log.error("Annotation data missing for ${binaryClass.classId}")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val strings = classHeader.strings
|
||||||
|
if (strings == null) {
|
||||||
|
log.error("String table not found in class ${binaryClass.classId}")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val classData = JvmProtoBufUtil.readClassDataFrom(data)
|
return ClassDataWithSource(JvmProtoBufUtil.readClassDataFrom(data, strings))
|
||||||
return ClassDataWithSource(classData)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
|
|||||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
|
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
|
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName.byInternalName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName.byInternalName
|
||||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
|
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
|
||||||
@@ -167,7 +168,7 @@ public class IncrementalCacheImpl(
|
|||||||
|
|
||||||
public fun saveModuleMappingToCache(sourceFiles: Collection<File>, file: File): ChangesInfo {
|
public fun saveModuleMappingToCache(sourceFiles: Collection<File>, file: File): ChangesInfo {
|
||||||
val jvmClassName = JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)
|
val jvmClassName = JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)
|
||||||
protoMap.process(jvmClassName, file.readBytes(), isPackage = false, checkChangesIsOpenPart = false)
|
protoMap.process(jvmClassName, file.readBytes(), emptyArray<String>(), isPackage = false, checkChangesIsOpenPart = false)
|
||||||
dirtyOutputClassesMap.notDirty(MODULE_MAPPING_FILE_NAME)
|
dirtyOutputClassesMap.notDirty(MODULE_MAPPING_FILE_NAME)
|
||||||
sourceFiles.forEach { sourceToClassesMap.add(it, jvmClassName) }
|
sourceFiles.forEach { sourceToClassesMap.add(it, jvmClassName) }
|
||||||
return ChangesInfo.NO_CHANGES
|
return ChangesInfo.NO_CHANGES
|
||||||
@@ -249,8 +250,10 @@ public class IncrementalCacheImpl(
|
|||||||
return obsoletePackageParts
|
return obsoletePackageParts
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPackagePartData(fqName: String): ByteArray? {
|
override fun getPackagePartData(fqName: String): JvmPackagePartProto? {
|
||||||
return protoMap[JvmClassName.byInternalName(fqName)]?.bytes
|
return protoMap[JvmClassName.byInternalName(fqName)]?.let { value ->
|
||||||
|
JvmPackagePartProto(value.bytes, value.strings)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getModuleMappingData(): ByteArray? {
|
override fun getModuleMappingData(): ByteArray? {
|
||||||
@@ -275,19 +278,24 @@ public class IncrementalCacheImpl(
|
|||||||
public fun process(kotlinClass: LocalFileKotlinClass, isPackage: Boolean, checkChangesIsOpenPart: Boolean = true): ChangesInfo {
|
public fun process(kotlinClass: LocalFileKotlinClass, isPackage: Boolean, checkChangesIsOpenPart: Boolean = true): ChangesInfo {
|
||||||
val header = kotlinClass.classHeader
|
val header = kotlinClass.classHeader
|
||||||
val bytes = BitEncoding.decodeBytes(header.annotationData!!)
|
val bytes = BitEncoding.decodeBytes(header.annotationData!!)
|
||||||
return put(kotlinClass.className, bytes, isPackage, checkChangesIsOpenPart)
|
return put(kotlinClass.className, bytes, header.strings!!, isPackage, checkChangesIsOpenPart)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun process(className: JvmClassName, data: ByteArray, isPackage: Boolean, checkChangesIsOpenPart: Boolean): ChangesInfo {
|
public fun process(className: JvmClassName, data: ByteArray, strings: Array<String>, isPackage: Boolean, checkChangesIsOpenPart: Boolean): ChangesInfo {
|
||||||
return put(className, data, isPackage, checkChangesIsOpenPart)
|
return put(className, data, strings, isPackage, checkChangesIsOpenPart)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun put(className: JvmClassName, bytes: ByteArray, isPackage: Boolean, checkChangesIsOpenPart: Boolean): ChangesInfo {
|
private fun put(
|
||||||
|
className: JvmClassName, bytes: ByteArray, strings: Array<String>, isPackage: Boolean, checkChangesIsOpenPart: Boolean
|
||||||
|
): ChangesInfo {
|
||||||
val key = className.internalName
|
val key = className.internalName
|
||||||
val oldData = storage[key]
|
val oldData = storage[key]
|
||||||
val data = ProtoMapValue(isPackage, bytes)
|
val data = ProtoMapValue(isPackage, bytes, strings)
|
||||||
|
|
||||||
if (oldData == null || !Arrays.equals(bytes, oldData.bytes) || isPackage != oldData.isPackageFacade) {
|
if (oldData == null ||
|
||||||
|
!Arrays.equals(bytes, oldData.bytes) ||
|
||||||
|
!Arrays.equals(strings, oldData.strings) ||
|
||||||
|
isPackage != oldData.isPackageFacade) {
|
||||||
storage[key] = data
|
storage[key] = data
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -757,14 +765,19 @@ private object ProtoMapValueExternalizer : DataExternalizer<ProtoMapValue> {
|
|||||||
out.writeBoolean(value.isPackageFacade)
|
out.writeBoolean(value.isPackageFacade)
|
||||||
out.writeInt(value.bytes.size())
|
out.writeInt(value.bytes.size())
|
||||||
out.write(value.bytes)
|
out.write(value.bytes)
|
||||||
|
out.writeInt(value.strings.size())
|
||||||
|
for (string in value.strings) {
|
||||||
|
out.writeUTF(string)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun read(`in`: DataInput): ProtoMapValue {
|
override fun read(`in`: DataInput): ProtoMapValue {
|
||||||
val isPackageFacade = `in`.readBoolean()
|
val isPackageFacade = `in`.readBoolean()
|
||||||
val length = `in`.readInt()
|
val bytesLength = `in`.readInt()
|
||||||
val buf = ByteArray(length)
|
val bytes = ByteArray(bytesLength)
|
||||||
`in`.readFully(buf)
|
`in`.readFully(bytes, 0, bytesLength)
|
||||||
return ProtoMapValue(isPackageFacade, buf)
|
val stringsLength = `in`.readInt()
|
||||||
|
val strings = Array<String>(stringsLength) { `in`.readUTF() }
|
||||||
|
return ProtoMapValue(isPackageFacade, bytes, strings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public sealed class DifferenceKind() {
|
|||||||
public class MEMBERS(val names: Collection<String>): DifferenceKind()
|
public class MEMBERS(val names: Collection<String>): DifferenceKind()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ProtoMapValue(val isPackageFacade: Boolean, val bytes: ByteArray)
|
data class ProtoMapValue(val isPackageFacade: Boolean, val bytes: ByteArray, val strings: Array<String>)
|
||||||
|
|
||||||
public fun difference(oldData: ProtoMapValue, newData: ProtoMapValue): DifferenceKind {
|
public fun difference(oldData: ProtoMapValue, newData: ProtoMapValue): DifferenceKind {
|
||||||
if (oldData.isPackageFacade != newData.isPackageFacade) return DifferenceKind.CLASS_SIGNATURE
|
if (oldData.isPackageFacade != newData.isPackageFacade) return DifferenceKind.CLASS_SIGNATURE
|
||||||
@@ -127,8 +127,8 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val oldClassData = JvmProtoBufUtil.readClassDataFrom(oldData.bytes)
|
val oldClassData = JvmProtoBufUtil.readClassDataFrom(oldData.bytes, oldData.strings)
|
||||||
val newClassData = JvmProtoBufUtil.readClassDataFrom(newData.bytes)
|
val newClassData = JvmProtoBufUtil.readClassDataFrom(newData.bytes, newData.strings)
|
||||||
|
|
||||||
val oldProto = oldClassData.classProto
|
val oldProto = oldClassData.classProto
|
||||||
val newProto = newClassData.classProto
|
val newProto = newClassData.classProto
|
||||||
@@ -217,8 +217,8 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class DifferenceCalculatorForPackageFacade(oldData: ProtoMapValue, newData: ProtoMapValue) : DifferenceCalculator() {
|
private class DifferenceCalculatorForPackageFacade(oldData: ProtoMapValue, newData: ProtoMapValue) : DifferenceCalculator() {
|
||||||
val oldPackageData = JvmProtoBufUtil.readPackageDataFrom(oldData.bytes)
|
val oldPackageData = JvmProtoBufUtil.readPackageDataFrom(oldData.bytes, oldData.strings)
|
||||||
val newPackageData = JvmProtoBufUtil.readPackageDataFrom(newData.bytes)
|
val newPackageData = JvmProtoBufUtil.readPackageDataFrom(newData.bytes, newData.strings)
|
||||||
|
|
||||||
val oldProto = oldPackageData.packageProto
|
val oldProto = oldPackageData.packageProto
|
||||||
val newProto = newPackageData.packageProto
|
val newProto = newPackageData.packageProto
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.test.JetTestUtils
|
|||||||
import org.jetbrains.kotlin.test.MockLibraryUtil
|
import org.jetbrains.kotlin.test.MockLibraryUtil
|
||||||
import org.jetbrains.kotlin.utils.Printer
|
import org.jetbrains.kotlin.utils.Printer
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
public abstract class AbstractProtoComparisonTest : UsefulTestCase() {
|
public abstract class AbstractProtoComparisonTest : UsefulTestCase() {
|
||||||
|
|
||||||
@@ -85,8 +84,14 @@ public abstract class AbstractProtoComparisonTest : UsefulTestCase() {
|
|||||||
val oldProtoBytes = BitEncoding.decodeBytes(oldClassHeader.annotationData!!)
|
val oldProtoBytes = BitEncoding.decodeBytes(oldClassHeader.annotationData!!)
|
||||||
val newProtoBytes = BitEncoding.decodeBytes(newClassHeader.annotationData!!)
|
val newProtoBytes = BitEncoding.decodeBytes(newClassHeader.annotationData!!)
|
||||||
|
|
||||||
val oldProto = ProtoMapValue(oldClassHeader.isCompatiblePackageFacadeKind() || oldClassHeader.isCompatibleFileFacadeKind(), oldProtoBytes)
|
val oldProto = ProtoMapValue(
|
||||||
val newProto = ProtoMapValue(newClassHeader.isCompatiblePackageFacadeKind() || newClassHeader.isCompatibleFileFacadeKind(), newProtoBytes)
|
oldClassHeader.isCompatiblePackageFacadeKind() || oldClassHeader.isCompatibleFileFacadeKind(),
|
||||||
|
oldProtoBytes, oldClassHeader.strings!!
|
||||||
|
)
|
||||||
|
val newProto = ProtoMapValue(
|
||||||
|
newClassHeader.isCompatiblePackageFacadeKind() || newClassHeader.isCompatibleFileFacadeKind(),
|
||||||
|
newProtoBytes, newClassHeader.strings!!
|
||||||
|
)
|
||||||
|
|
||||||
val diff = when {
|
val diff = when {
|
||||||
newClassHeader.isCompatiblePackageFacadeKind(), newClassHeader.isCompatibleClassKind(), newClassHeader.isCompatibleFileFacadeKind() ->
|
newClassHeader.isCompatiblePackageFacadeKind(), newClassHeader.isCompatibleClassKind(), newClassHeader.isCompatibleFileFacadeKind() ->
|
||||||
|
|||||||
Reference in New Issue
Block a user