Improve ABI version from one number to "major.minor.patch"
This commit is contained in:
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
@@ -61,7 +60,6 @@ import java.util.Set;
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean;
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isInterface;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.ABI_VERSION_FIELD_NAME;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
@@ -823,7 +821,7 @@ public class AsmUtil {
|
||||
|
||||
public static void writeKotlinSyntheticClassAnnotation(@NotNull ClassBuilder v, @NotNull KotlinSyntheticClass.Kind kind) {
|
||||
AnnotationVisitor av = v.newAnnotation(Type.getObjectType(KotlinSyntheticClass.CLASS_NAME.getInternalName()).getDescriptor(), true);
|
||||
av.visit(ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
|
||||
JvmCodegenUtil.writeAbiVersion(av);
|
||||
av.visitEnum(
|
||||
JvmAnnotationNames.KIND_FIELD_NAME,
|
||||
Type.getObjectType(KotlinSyntheticClass.KIND_INTERNAL_NAME).getDescriptor(),
|
||||
|
||||
@@ -120,10 +120,13 @@ public class ClassFileFactory implements OutputFileCollection {
|
||||
@Override
|
||||
public byte[] asBytes(ClassBuilderFactory factory) {
|
||||
try {
|
||||
ByteArrayOutputStream moduleMapping = new ByteArrayOutputStream(4*1024);
|
||||
ByteArrayOutputStream moduleMapping = new ByteArrayOutputStream(4096);
|
||||
DataOutputStream dataOutStream = new DataOutputStream(moduleMapping);
|
||||
dataOutStream.writeInt(1);
|
||||
dataOutStream.writeInt(JvmAbi.VERSION);
|
||||
int[] version = JvmAbi.VERSION.toArray();
|
||||
dataOutStream.writeInt(version.length);
|
||||
for (int number : version) {
|
||||
dataOutStream.writeInt(number);
|
||||
}
|
||||
builder.build().writeTo(dataOutStream);
|
||||
dataOutStream.flush();
|
||||
return moduleMapping.toByteArray();
|
||||
|
||||
@@ -237,7 +237,7 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
|
||||
NameResolver nameResolver = new NameResolver(strings.serializeSimpleNames(), strings.serializeQualifiedNames());
|
||||
|
||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CALLABLE), true);
|
||||
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
|
||||
JvmCodegenUtil.writeAbiVersion(av);
|
||||
AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
|
||||
for (String string : BitEncoding.encodeBytes(SerializationUtil.serializeCallableData(nameResolver, callableProto))) {
|
||||
array.visit(null, string);
|
||||
|
||||
@@ -264,7 +264,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
ClassData data = new ClassData(nameResolver, classProto);
|
||||
|
||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true);
|
||||
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
|
||||
JvmCodegenUtil.writeAbiVersion(av);
|
||||
//noinspection ConstantConditions
|
||||
if (kind != null) {
|
||||
av.visitEnum(
|
||||
|
||||
@@ -31,6 +31,8 @@ import org.jetbrains.kotlin.codegen.context.PackageContext;
|
||||
import org.jetbrains.kotlin.codegen.context.RootContext;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment;
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass;
|
||||
@@ -46,6 +48,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -257,4 +260,11 @@ public class JvmCodegenUtil {
|
||||
public static String getMappingFileName(@NotNull String moduleName) {
|
||||
return "META-INF/" + moduleName + "." + ModuleMapping.MAPPING_FILE_EXT;
|
||||
}
|
||||
|
||||
public static void writeAbiVersion(@NotNull AnnotationVisitor av) {
|
||||
av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmAbi.VERSION.toArray());
|
||||
|
||||
// TODO: drop after some time
|
||||
av.visit(JvmAnnotationNames.OLD_ABI_VERSION_FIELD_NAME, JvmAbi.VERSION.getMinor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -184,7 +183,7 @@ public class MultifileClassCodegen(
|
||||
if (files.any { it.isScript }) return
|
||||
|
||||
val av = classBuilder.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS), true)
|
||||
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION)
|
||||
JvmCodegenUtil.writeAbiVersion(av)
|
||||
|
||||
val shortNames = partFqNames.map { it.shortName().asString() }.sorted()
|
||||
val filePartClassNamesArray = av.visitArray(JvmAnnotationNames.FILE_PART_CLASS_NAMES_FIELD_NAME)
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
@@ -36,7 +35,6 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
|
||||
|
||||
public class MultifileClassPartCodegen(
|
||||
v: ClassBuilder,
|
||||
file: JetFile,
|
||||
@@ -60,12 +58,12 @@ public class MultifileClassPartCodegen(
|
||||
override fun generateBody() {
|
||||
for (declaration in element.declarations) {
|
||||
if (declaration is JetNamedFunction || declaration is JetProperty) {
|
||||
genFunctionOrProperty(declaration);
|
||||
genFunctionOrProperty(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
if (state.classBuilderMode == ClassBuilderMode.FULL) {
|
||||
generateInitializers({ createOrGetClInitCodegen(); });
|
||||
generateInitializers { createOrGetClInitCodegen() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +98,7 @@ public class MultifileClassPartCodegen(
|
||||
val data = PackageData(nameResolver, packageProto)
|
||||
|
||||
val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS_PART), true)
|
||||
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION)
|
||||
JvmCodegenUtil.writeAbiVersion(av)
|
||||
av.visit(JvmAnnotationNames.MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassFqName.shortName().asString())
|
||||
val dataArray = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME)
|
||||
for (string in BitEncoding.encodeBytes(SerializationUtil.serializePackageData(data))) {
|
||||
|
||||
@@ -301,7 +301,7 @@ public class PackageCodegen {
|
||||
PackageData data = new PackageData(nameResolver, packageProto);
|
||||
|
||||
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE), true);
|
||||
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
|
||||
JvmCodegenUtil.writeAbiVersion(av);
|
||||
AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
|
||||
for (String string : BitEncoding.encodeBytes(SerializationUtil.serializePackageData(data))) {
|
||||
array.visit(null, string);
|
||||
|
||||
@@ -16,18 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.psi.JetDeclaration;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
@@ -41,12 +37,9 @@ import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.ABI_VERSION_FIELD_NAME;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class PackagePartCodegen extends MemberCodegen<JetFile> {
|
||||
@@ -124,7 +117,7 @@ public class PackagePartCodegen extends MemberCodegen<JetFile> {
|
||||
PackageData data = new PackageData(nameResolver, packageProto);
|
||||
|
||||
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FILE_FACADE), true);
|
||||
av.visit(ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
|
||||
JvmCodegenUtil.writeAbiVersion(av);
|
||||
AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
|
||||
for (String string : BitEncoding.encodeBytes(SerializationUtil.serializePackageData(data))) {
|
||||
array.visit(null, string);
|
||||
|
||||
+4
-3
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.OverrideResolver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
|
||||
import org.jetbrains.kotlin.util.slicedMap.Slices
|
||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice
|
||||
@@ -29,7 +30,7 @@ import org.jetbrains.kotlin.util.slicedMap.WritableSlice
|
||||
public class TraceBasedErrorReporter(private val trace: BindingTrace) : ErrorReporter {
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(javaClass<TraceBasedErrorReporter>())
|
||||
private val LOG = Logger.getInstance(TraceBasedErrorReporter::class.java)
|
||||
|
||||
public val ABI_VERSION_ERRORS: WritableSlice<String, AbiVersionErrorData> = Slices.createCollectiveSlice()
|
||||
// TODO: MutableList is a workaround for KT-5792 Covariant types in Kotlin translated to wildcard types in Java
|
||||
@@ -37,11 +38,11 @@ public class TraceBasedErrorReporter(private val trace: BindingTrace) : ErrorRep
|
||||
}
|
||||
|
||||
public data class AbiVersionErrorData(
|
||||
public val actualVersion: Int,
|
||||
public val actualVersion: BinaryVersion,
|
||||
public val classId: ClassId
|
||||
)
|
||||
|
||||
override fun reportIncompatibleAbiVersion(classId: ClassId, filePath: String, actualVersion: Int) {
|
||||
override fun reportIncompatibleAbiVersion(classId: ClassId, filePath: String, actualVersion: BinaryVersion) {
|
||||
trace.record(ABI_VERSION_ERRORS, filePath, AbiVersionErrorData(actualVersion, classId))
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.psi.stubs.impl.KotlinFileStubImpl;
|
||||
import java.io.IOException;
|
||||
|
||||
public class JetFileElementType extends IStubFileElementType<KotlinFileStub> {
|
||||
public static final int STUB_VERSION = 55;
|
||||
public static final int STUB_VERSION = 56;
|
||||
|
||||
private static final String NAME = "kotlin.FILE";
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
compiler/testData/cli/jvm/wrongAbiVersionLib/bin/ClassWithWrongAbiVersion.class: error: class 'ClassWithWrongAbiVersion' was compiled with an incompatible version of Kotlin. Its ABI version is -1, expected ABI version is $ABI_VERSION$
|
||||
compiler/testData/cli/jvm/wrongAbiVersionLib/bin/wrong/Wrong_packageKt.class: error: class 'wrong/Wrong_packageKt' was compiled with an incompatible version of Kotlin. Its ABI version is -1, expected ABI version is $ABI_VERSION$
|
||||
compiler/testData/cli/jvm/wrongAbiVersionLib/bin/ClassWithWrongAbiVersion.class: error: class 'ClassWithWrongAbiVersion' was compiled with an incompatible version of Kotlin. Its ABI version is unknown, expected ABI version is $ABI_VERSION$
|
||||
compiler/testData/cli/jvm/wrongAbiVersionLib/bin/wrong/Wrong_packageKt.class: error: class 'wrong/Wrong_packageKt' was compiled with an incompatible version of Kotlin. Its ABI version is unknown, expected ABI version is $ABI_VERSION$
|
||||
compiler/testData/cli/jvm/wrongAbiVersion.kt:4:3: error: unresolved reference: bar
|
||||
bar()
|
||||
^
|
||||
|
||||
@@ -71,7 +71,7 @@ public class CliBaseTest {
|
||||
public static String getNormalizedCompilerOutput(@NotNull String pureOutput, @NotNull ExitCode exitCode, @NotNull String testDataDir) {
|
||||
String normalizedOutputWithoutExitCode = pureOutput
|
||||
.replace(new File(testDataDir).getAbsolutePath(), "$TESTDATA_DIR$")
|
||||
.replace("expected ABI version is " + Integer.toString(JvmAbi.VERSION), "expected ABI version is $ABI_VERSION$")
|
||||
.replace("expected ABI version is " + JvmAbi.VERSION, "expected ABI version is $ABI_VERSION$")
|
||||
.replace("\\", "/");
|
||||
|
||||
return removePerfOutput(normalizedOutputWithoutExitCode) + exitCode;
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil;
|
||||
@@ -27,17 +26,18 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass;
|
||||
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;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.ABI_VERSION_FIELD_NAME;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.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.KotlinSyntheticClass.Kind.*;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.VERSION_FIELD_NAME;
|
||||
|
||||
public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
public static final FqName PACKAGE_NAME = new FqName("test");
|
||||
@@ -194,10 +194,10 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
|
||||
Annotation annotation = aClass.getAnnotation(annotationClass);
|
||||
|
||||
Integer version = (Integer) CodegenTestUtil.getAnnotationAttribute(annotation, ABI_VERSION_FIELD_NAME);
|
||||
int[] version = (int[]) CodegenTestUtil.getAnnotationAttribute(annotation, VERSION_FIELD_NAME);
|
||||
assertNotNull(version);
|
||||
assertTrue("Annotation " + annotationFqName + " is written with an unsupported format",
|
||||
AbiVersionUtil.isAbiVersionCompatible(version));
|
||||
AbiVersionUtil.isAbiVersionCompatible(BinaryVersion.create(version)));
|
||||
|
||||
Object actualKind = CodegenTestUtil.getAnnotationAttribute(annotation, KIND_FIELD_NAME);
|
||||
assertNotNull(actualKind);
|
||||
|
||||
@@ -16,11 +16,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.java;
|
||||
|
||||
public final class AbiVersionUtil {
|
||||
public static final int INVALID_VERSION = -1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion;
|
||||
|
||||
public static boolean isAbiVersionCompatible(int abiVersion) {
|
||||
return abiVersion == JvmAbi.VERSION;
|
||||
public final class AbiVersionUtil {
|
||||
public static final BinaryVersion INVALID_VERSION = BinaryVersion.create(new int[0]);
|
||||
|
||||
public static boolean isAbiVersionCompatible(@NotNull BinaryVersion actual) {
|
||||
// TODO: compare versions according to Semantic Versioning
|
||||
return actual.getMajor() == JvmAbi.VERSION.getMajor() &&
|
||||
actual.getMinor() == JvmAbi.VERSION.getMinor();
|
||||
}
|
||||
|
||||
private AbiVersionUtil() {
|
||||
|
||||
@@ -21,13 +21,20 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion;
|
||||
|
||||
public final class JvmAbi {
|
||||
/**
|
||||
* This constant is used to identify binary format (class file) versions
|
||||
* If you change class file metadata format and/or naming conventions, please increase this number
|
||||
* If you change class file metadata format and/or naming conventions, please change this version.
|
||||
* - Major version should be increased only when the new binary format is neither forward- nor backward compatible.
|
||||
* This shouldn't really ever happen at all.
|
||||
* - Minor version should be increased when the new format is backward compatible,
|
||||
* i.e. the new compiler can process old class files, but the old compiler will not be able to process new class files.
|
||||
* - Patch version can be increased freely and is only supposed to be used for debugging. Increase the patch version when you
|
||||
* make a change to the metadata format or the bytecode which is both forward- and backward compatible.
|
||||
*/
|
||||
public static final int VERSION = 24;
|
||||
public static final BinaryVersion VERSION = BinaryVersion.create(0, 24, 0);
|
||||
|
||||
public static final String TRAIT_IMPL_CLASS_NAME = "$TImpl";
|
||||
public static final String TRAIT_IMPL_SUFFIX = "$" + TRAIT_IMPL_CLASS_NAME;
|
||||
|
||||
+3
-1
@@ -38,7 +38,7 @@ public final class JvmAnnotationNames {
|
||||
public static final FqName KOTLIN_SIGNATURE = new FqName("kotlin.jvm.KotlinSignature");
|
||||
public static final FqName OLD_KOTLIN_SIGNATURE = new FqName("jet.runtime.typeinfo.KotlinSignature");
|
||||
|
||||
public static final String ABI_VERSION_FIELD_NAME = "abiVersion";
|
||||
public static final String VERSION_FIELD_NAME = "version";
|
||||
public static final String KIND_FIELD_NAME = "kind";
|
||||
public static final String FILE_PART_CLASS_NAMES_FIELD_NAME = "filePartClassNames";
|
||||
public static final String MULTIFILE_CLASS_NAME_FIELD_NAME = "multifileClassName";
|
||||
@@ -114,6 +114,8 @@ public final class JvmAnnotationNames {
|
||||
@Deprecated
|
||||
public static final FqName OLD_KOTLIN_TRAIT_IMPL = new FqName("jet.KotlinTraitImpl");
|
||||
|
||||
public static final String OLD_ABI_VERSION_FIELD_NAME = "abiVersion";
|
||||
|
||||
// When these annotations appear on a declaration, they are copied to the _type_ of the declaration, becoming type annotations
|
||||
// See also DescriptorRendererOptions#excludedTypeAnnotationClasses
|
||||
public static final Set<FqName> ANNOTATIONS_COPIED_TO_TYPES = KotlinPackage.setOf(
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.load.kotlin
|
||||
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.DataInputStream
|
||||
@@ -28,19 +29,27 @@ public class ModuleMapping private constructor(val packageFqName2Parts: Map<Stri
|
||||
}
|
||||
|
||||
companion object {
|
||||
public val MAPPING_FILE_EXT: String = "kotlin_module";
|
||||
public val MAPPING_FILE_EXT: String = "kotlin_module"
|
||||
|
||||
public val EMPTY: ModuleMapping = ModuleMapping(emptyMap())
|
||||
|
||||
fun create(protoWithAbi: ByteArray? = null): ModuleMapping {
|
||||
if (protoWithAbi == null) {
|
||||
fun create(proto: ByteArray? = null): ModuleMapping {
|
||||
if (proto == null) {
|
||||
return EMPTY
|
||||
}
|
||||
|
||||
val inputStream = DataInputStream(ByteArrayInputStream(protoWithAbi))
|
||||
val intCount = inputStream.readInt()
|
||||
assert(intCount == 1, {"Expected one int value for abi version, but: $intCount"})
|
||||
val abiVersion = Integer.valueOf(inputStream.readInt());
|
||||
val inputStream = DataInputStream(ByteArrayInputStream(proto))
|
||||
val size = inputStream.readInt()
|
||||
|
||||
val abiVersion =
|
||||
if (size == 1) {
|
||||
// TODO: this is a temporary workaround, drop after M13
|
||||
BinaryVersion.create(0, inputStream.readInt(), 0)
|
||||
}
|
||||
else {
|
||||
BinaryVersion.create((0..size - 1).map { inputStream.readInt() }.toIntArray())
|
||||
}
|
||||
|
||||
if (AbiVersionUtil.isAbiVersionCompatible(abiVersion)) {
|
||||
val parseFrom = JvmPackageTable.PackageTable.parseFrom(inputStream)
|
||||
if (parseFrom != null) {
|
||||
@@ -55,6 +64,7 @@ public class ModuleMapping private constructor(val packageFqName2Parts: Map<Stri
|
||||
return ModuleMapping(packageFqNameParts)
|
||||
}
|
||||
}
|
||||
|
||||
return EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -16,13 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.kotlin.header
|
||||
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass
|
||||
|
||||
public class KotlinClassHeader(
|
||||
public val kind: KotlinClassHeader.Kind,
|
||||
public val version: Int,
|
||||
public val version: BinaryVersion,
|
||||
public val annotationData: Array<String>?,
|
||||
public val classKind: KotlinClass.Kind?,
|
||||
public val syntheticClassKind: KotlinSyntheticClass.Kind?,
|
||||
|
||||
+14
-7
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.load.java.AbiVersionUtil;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -59,7 +60,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
OLD_DEPRECATED_ANNOTATIONS_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(OLD_KOTLIN_TRAIT_IMPL), SYNTHETIC_CLASS);
|
||||
}
|
||||
|
||||
private int version = AbiVersionUtil.INVALID_VERSION;
|
||||
private BinaryVersion version = AbiVersionUtil.INVALID_VERSION;
|
||||
private String multifileClassName = null;
|
||||
private String[] filePartClassNames = null;
|
||||
private String[] annotationData = null;
|
||||
@@ -151,12 +152,18 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
|
||||
@Override
|
||||
public void visit(@Nullable Name name, @Nullable Object value) {
|
||||
if (name != null) {
|
||||
if (name.asString().equals(ABI_VERSION_FIELD_NAME)) {
|
||||
version = value instanceof Integer ? (Integer) value : AbiVersionUtil.INVALID_VERSION;
|
||||
}
|
||||
else if (name.asString().equals(MULTIFILE_CLASS_NAME_FIELD_NAME)) {
|
||||
multifileClassName = value instanceof String ? (String) value : null;
|
||||
if (name == null) return;
|
||||
|
||||
String string = name.asString();
|
||||
if (VERSION_FIELD_NAME.equals(string)) {
|
||||
version = value instanceof int[] ? BinaryVersion.create((int[]) value) : AbiVersionUtil.INVALID_VERSION;
|
||||
}
|
||||
else if (MULTIFILE_CLASS_NAME_FIELD_NAME.equals(string)) {
|
||||
multifileClassName = value instanceof String ? (String) value : null;
|
||||
}
|
||||
else if (OLD_ABI_VERSION_FIELD_NAME.equals(string)) {
|
||||
if (version == AbiVersionUtil.INVALID_VERSION && value instanceof Integer && (Integer) value > 0) {
|
||||
version = BinaryVersion.create(0, (Integer) value, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -19,8 +19,8 @@ package org.jetbrains.kotlin.load.java.components
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
|
||||
|
||||
public object RuntimeErrorReporter : ErrorReporter {
|
||||
@@ -29,8 +29,8 @@ public object RuntimeErrorReporter : ErrorReporter {
|
||||
throw IllegalStateException("Incomplete hierarchy for class ${descriptor.getName()}, unresolved classes $unresolvedSuperClasses")
|
||||
}
|
||||
|
||||
override fun reportIncompatibleAbiVersion(classId: ClassId, filePath: String, actualVersion: Int) {
|
||||
throw IllegalStateException("Incompatible ABI version of ${classId}: $actualVersion " +
|
||||
override fun reportIncompatibleAbiVersion(classId: ClassId, filePath: String, actualVersion: BinaryVersion) {
|
||||
throw IllegalStateException("Incompatible ABI version of $classId: $actualVersion " +
|
||||
"(expected version is ${JvmAbi.VERSION})")
|
||||
}
|
||||
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.serialization.deserialization
|
||||
|
||||
data class BinaryVersion private constructor(
|
||||
val major: Int,
|
||||
val minor: Int,
|
||||
val patch: Int,
|
||||
val rest: List<Int> = listOf()
|
||||
) {
|
||||
fun toArray(): IntArray =
|
||||
intArrayOf(major, minor, patch, *rest.toIntArray())
|
||||
|
||||
override fun toString(): String {
|
||||
val versions = toArray().takeWhile { it != UNKNOWN }
|
||||
return if (versions.isEmpty()) "unknown" else versions.joinToString(".")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val UNKNOWN = -1
|
||||
|
||||
@JvmStatic
|
||||
fun create(version: IntArray): BinaryVersion {
|
||||
return BinaryVersion(
|
||||
major = version.getOrNull(0) ?: UNKNOWN,
|
||||
minor = version.getOrNull(1) ?: UNKNOWN,
|
||||
patch = version.getOrNull(2) ?: UNKNOWN,
|
||||
rest = if (version.size() > 3) version.asList().subList(3, version.size()).toList() else listOf()
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun create(major: Int, minor: Int, patch: Int) = BinaryVersion(major, minor, patch)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.name.ClassId;
|
||||
import java.util.List;
|
||||
|
||||
public interface ErrorReporter {
|
||||
void reportIncompatibleAbiVersion(@NotNull ClassId classId, @NotNull String filePath, int actualVersion);
|
||||
void reportIncompatibleAbiVersion(@NotNull ClassId classId, @NotNull String filePath, @NotNull BinaryVersion actualVersion);
|
||||
|
||||
void reportIncompleteHierarchy(@NotNull ClassDescriptor descriptor, @NotNull List<String> unresolvedSuperClasses);
|
||||
|
||||
|
||||
@@ -21,7 +21,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KotlinCallable {
|
||||
@Deprecated
|
||||
int abiVersion();
|
||||
|
||||
int[] version() default {};
|
||||
|
||||
String[] data();
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KotlinClass {
|
||||
@Deprecated
|
||||
int abiVersion();
|
||||
|
||||
int[] version() default {};
|
||||
|
||||
Kind kind() default Kind.CLASS;
|
||||
|
||||
String[] data();
|
||||
|
||||
@@ -21,7 +21,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KotlinFileFacade {
|
||||
@Deprecated
|
||||
int abiVersion();
|
||||
|
||||
int[] version() default {};
|
||||
|
||||
String[] data();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KotlinMultifileClass {
|
||||
@Deprecated
|
||||
int abiVersion();
|
||||
|
||||
int[] version() default {};
|
||||
|
||||
String[] filePartClassNames();
|
||||
}
|
||||
|
||||
@@ -21,8 +21,12 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KotlinMultifileClassPart {
|
||||
@Deprecated
|
||||
int abiVersion();
|
||||
|
||||
int[] version() default {};
|
||||
|
||||
String multifileClassName();
|
||||
|
||||
String[] data();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KotlinPackage {
|
||||
@Deprecated
|
||||
int abiVersion();
|
||||
|
||||
int[] version() default {};
|
||||
|
||||
String[] data();
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface KotlinSyntheticClass {
|
||||
@Deprecated
|
||||
int abiVersion();
|
||||
|
||||
int[] version() default {};
|
||||
|
||||
Kind kind();
|
||||
|
||||
enum Kind {
|
||||
|
||||
@@ -26,15 +26,18 @@ import org.jetbrains.org.objectweb.asm.*
|
||||
* Some additional information is printed to stderr
|
||||
*/
|
||||
|
||||
fun loadAbiVersionOfClass(bytes: ByteArray): Int? {
|
||||
var result: Int? = null
|
||||
fun loadAbiVersionOfClass(bytes: ByteArray): IntArray? {
|
||||
var result: IntArray? = null
|
||||
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.ASM5) {
|
||||
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? {
|
||||
if (desc == "Lkotlin/jvm/internal/KotlinClass;") {
|
||||
return object : AnnotationVisitor(Opcodes.ASM5) {
|
||||
override fun visit(name: String, value: Any) {
|
||||
if (name == "abiVersion") {
|
||||
result = value as Int
|
||||
if (name == "version") {
|
||||
result = value as IntArray
|
||||
}
|
||||
else if (name == "abiVersion") {
|
||||
result = intArrayOf(0, value as Int, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +48,7 @@ fun loadAbiVersionOfClass(bytes: ByteArray): Int? {
|
||||
return result
|
||||
}
|
||||
|
||||
fun loadVersion(library: File): Int {
|
||||
fun loadVersion(library: File): IntArray {
|
||||
val jarFile = JarFile(library)
|
||||
try {
|
||||
for (entry in jarFile.entries()) {
|
||||
@@ -71,8 +74,8 @@ fun main(args: Array<String>) {
|
||||
val library1 = File(args[0])
|
||||
val library2 = File(args[1])
|
||||
|
||||
val v1 = loadVersion(library1)
|
||||
val v2 = loadVersion(library2)
|
||||
val v1 = loadVersion(library1).joinToString(".")
|
||||
val v2 = loadVersion(library2).joinToString(".")
|
||||
|
||||
if (v1 != v2) {
|
||||
System.err.println("ABI versions differ:")
|
||||
|
||||
+5
-4
@@ -16,11 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.decompiler.textBuilder
|
||||
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.name.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter
|
||||
|
||||
class LoggingErrorReporter(private val log: Logger) : ErrorReporter {
|
||||
override fun reportLoadingError(message: String, exception: Exception?) {
|
||||
@@ -35,7 +36,7 @@ class LoggingErrorReporter(private val log: Logger) : ErrorReporter {
|
||||
log.error("Could not infer visibility for $descriptor")
|
||||
}
|
||||
|
||||
override fun reportIncompatibleAbiVersion(classId: ClassId, filePath: String, actualVersion: Int) {
|
||||
override fun reportIncompatibleAbiVersion(classId: ClassId, filePath: String, actualVersion: BinaryVersion) {
|
||||
log.error("Incompatible ABI version for class $classId, actual version: $actualVersion")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,21 +23,23 @@ import com.intellij.util.indexing.FileContent
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.*
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
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
|
||||
|
||||
public object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinAbiVersionIndex>(javaClass<KotlinAbiVersionIndex>()) {
|
||||
public object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinAbiVersionIndex>(KotlinAbiVersionIndex::class.java) {
|
||||
|
||||
override fun getIndexer() = INDEXER
|
||||
|
||||
override fun getInputFilter() = FileBasedIndex.InputFilter() { file -> file.getFileType() == StdFileTypes.CLASS }
|
||||
override fun getInputFilter() = FileBasedIndex.InputFilter() { file -> file.fileType == StdFileTypes.CLASS }
|
||||
|
||||
override fun getVersion() = VERSION
|
||||
|
||||
private val VERSION = 1
|
||||
private val VERSION = 2
|
||||
|
||||
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
|
||||
private val kotlinAnnotationsDesc = setOf(
|
||||
OLD_JET_CLASS_ANNOTATION,
|
||||
OLD_JET_PACKAGE_CLASS_ANNOTATION,
|
||||
@@ -48,12 +50,12 @@ public object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinAbiVersion
|
||||
KOTLIN_FILE_FACADE)
|
||||
.map { asmDescByFqNameWithoutInnerClasses(it) }
|
||||
|
||||
private val INDEXER = DataIndexer<Int, Void, FileContent>() { inputData: FileContent ->
|
||||
var version: Int? = null
|
||||
private val INDEXER = DataIndexer<BinaryVersion, Void, FileContent>() { inputData: FileContent ->
|
||||
var version: BinaryVersion? = null
|
||||
var annotationPresent = false
|
||||
|
||||
tryBlock(inputData) {
|
||||
val classReader = ClassReader(inputData.getContent())
|
||||
val classReader = ClassReader(inputData.content)
|
||||
classReader.accept(object : ClassVisitor(Opcodes.ASM5) {
|
||||
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? {
|
||||
if (!kotlinAnnotationsDesc.contains(desc)) {
|
||||
@@ -62,13 +64,12 @@ public object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinAbiVersion
|
||||
annotationPresent = true
|
||||
return object : AnnotationVisitor(Opcodes.ASM5) {
|
||||
override fun visit(name: String, value: Any) {
|
||||
if (ABI_VERSION_FIELD_NAME == name) {
|
||||
if (value is Int) {
|
||||
version = value
|
||||
when (name) {
|
||||
VERSION_FIELD_NAME -> if (value is IntArray) {
|
||||
version = BinaryVersion.create(value)
|
||||
}
|
||||
else {
|
||||
// Version is set to something weird
|
||||
version = AbiVersionUtil.INVALID_VERSION
|
||||
OLD_ABI_VERSION_FIELD_NAME -> if (version == null && value is Int) {
|
||||
version = BinaryVersion.create(0, value, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,10 +79,10 @@ public object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinAbiVersion
|
||||
}
|
||||
|
||||
if (annotationPresent && version == null) {
|
||||
// No version at all: the class is too old
|
||||
// No version at all because the class is too old, or version is set to something weird
|
||||
version = AbiVersionUtil.INVALID_VERSION
|
||||
}
|
||||
|
||||
if (version != null) mapOf<Int, Void?>(version!! to null) else mapOf()
|
||||
if (version != null) mapOf(version!! to null) else mapOf()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,37 @@ import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.util.indexing.FileContent
|
||||
import com.intellij.util.indexing.ID
|
||||
import com.intellij.util.indexing.ScalarIndexExtension
|
||||
import com.intellij.util.io.ExternalIntegerKeyDescriptor
|
||||
import com.intellij.util.io.DataInputOutputUtil
|
||||
import com.intellij.util.io.KeyDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
|
||||
/**
|
||||
* Important! This is not a stub-based index. And it has its own version
|
||||
*/
|
||||
abstract class KotlinAbiVersionIndexBase<T>(private val classOfIndex: Class<T>) : ScalarIndexExtension<Int>() {
|
||||
abstract class KotlinAbiVersionIndexBase<T>(private val classOfIndex: Class<T>) : ScalarIndexExtension<BinaryVersion>() {
|
||||
|
||||
override fun getName() = ID.create<Int, Void>(classOfIndex.getCanonicalName())
|
||||
override fun getName() = ID.create<BinaryVersion, Void>(classOfIndex.canonicalName)
|
||||
|
||||
override fun getKeyDescriptor() = ExternalIntegerKeyDescriptor()
|
||||
override fun getKeyDescriptor(): KeyDescriptor<BinaryVersion> = object : KeyDescriptor<BinaryVersion> {
|
||||
override fun isEqual(val1: BinaryVersion, val2: BinaryVersion): Boolean = val1 == val2
|
||||
|
||||
override fun getHashCode(value: BinaryVersion): Int = value.hashCode()
|
||||
|
||||
override fun read(input: DataInput): BinaryVersion {
|
||||
val size = DataInputOutputUtil.readINT(input)
|
||||
return BinaryVersion.create((0..size - 1).map { DataInputOutputUtil.readINT(input) }.toIntArray())
|
||||
}
|
||||
|
||||
override fun save(output: DataOutput, value: BinaryVersion) {
|
||||
val array = value.toArray()
|
||||
DataInputOutputUtil.writeINT(output, array.size())
|
||||
for (number in array) {
|
||||
DataInputOutputUtil.writeINT(output, number)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun dependsOnFileContent() = true
|
||||
|
||||
@@ -40,7 +61,7 @@ abstract class KotlinAbiVersionIndexBase<T>(private val classOfIndex: Class<T>)
|
||||
body()
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
LOG.warn("Could not index ABI version for file " + inputData.getFile() + ": " + e.getMessage())
|
||||
LOG.warn("Could not index ABI version for file " + inputData.file + ": " + e.getMessage())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,42 +16,43 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.versions
|
||||
|
||||
import com.google.common.collect.Maps
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.util.indexing.DataIndexer
|
||||
import com.intellij.util.indexing.FileBasedIndex
|
||||
import com.intellij.util.indexing.FileContent
|
||||
import org.jetbrains.kotlin.js.JavaScript
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||
import java.util.ArrayList
|
||||
import java.util.*
|
||||
|
||||
public object KotlinJavaScriptAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinJavaScriptAbiVersionIndex>(javaClass<KotlinJavaScriptAbiVersionIndex>()) {
|
||||
public object KotlinJavaScriptAbiVersionIndex : KotlinAbiVersionIndexBase<KotlinJavaScriptAbiVersionIndex>(KotlinJavaScriptAbiVersionIndex::class.java) {
|
||||
|
||||
override fun getIndexer() = INDEXER
|
||||
|
||||
override fun getInputFilter() = FileBasedIndex.InputFilter() { file -> JavaScript.EXTENSION == file.getExtension() }
|
||||
override fun getInputFilter() = FileBasedIndex.InputFilter() { file -> JavaScript.EXTENSION == file.extension }
|
||||
|
||||
override fun getVersion() = VERSION
|
||||
|
||||
private val VERSION = 1
|
||||
private val VERSION = 2
|
||||
|
||||
private val INDEXER = DataIndexer() { inputData: FileContent ->
|
||||
val result = Maps.newHashMap<Int, Void>()
|
||||
private val INDEXER = DataIndexer { inputData: FileContent ->
|
||||
val result = HashMap<BinaryVersion, Void?>()
|
||||
|
||||
tryBlock(inputData) {
|
||||
val text = VfsUtilCore.loadText(inputData.getFile())
|
||||
val text = VfsUtilCore.loadText(inputData.file)
|
||||
val metadataList = ArrayList<KotlinJavascriptMetadata>()
|
||||
KotlinJavascriptMetadataUtils.parseMetadata(text, metadataList)
|
||||
for (metadata in metadataList) {
|
||||
if (KotlinJavascriptMetadataUtils.isAbiVersionCompatible(metadata.abiVersion)) {
|
||||
result.put(metadata.abiVersion, null)
|
||||
val version = if (KotlinJavascriptMetadataUtils.isAbiVersionCompatible(metadata.abiVersion)) {
|
||||
BinaryVersion.create(0, metadata.abiVersion, 0)
|
||||
}
|
||||
else {
|
||||
// Version is set to something weird
|
||||
result.put(AbiVersionUtil.INVALID_VERSION, null)
|
||||
AbiVersionUtil.INVALID_VERSION
|
||||
}
|
||||
result[version] = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider;
|
||||
import org.jetbrains.kotlin.idea.framework.LibraryPresentationProviderUtil;
|
||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil;
|
||||
import org.jetbrains.kotlin.load.java.AbiVersionUtil;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion;
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils;
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths;
|
||||
import org.jetbrains.kotlin.utils.PathUtil;
|
||||
@@ -76,10 +77,10 @@ public class KotlinRuntimeLibraryUtil {
|
||||
return module != null && ProjectStructureUtil.isJavaKotlinModule(module);
|
||||
}
|
||||
},
|
||||
new Function1<Integer, Boolean>() {
|
||||
new Function1<BinaryVersion, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(Integer abiVersion) {
|
||||
return !AbiVersionUtil.isAbiVersionCompatible(abiVersion);
|
||||
public Boolean invoke(@NotNull BinaryVersion version) {
|
||||
return !AbiVersionUtil.isAbiVersionCompatible(version);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -94,10 +95,11 @@ public class KotlinRuntimeLibraryUtil {
|
||||
return module != null && ProjectStructureUtil.isJsKotlinModule(module);
|
||||
}
|
||||
},
|
||||
new Function1<Integer, Boolean>() {
|
||||
new Function1<BinaryVersion, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(Integer abiVersion) {
|
||||
return !KotlinJavascriptMetadataUtils.isAbiVersionCompatible(abiVersion);
|
||||
public Boolean invoke(@NotNull BinaryVersion version) {
|
||||
// TODO: support major.minor.patch version in JS metadata
|
||||
return !KotlinJavascriptMetadataUtils.isAbiVersionCompatible(version.getMinor());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -328,23 +330,23 @@ public class KotlinRuntimeLibraryUtil {
|
||||
@NotNull
|
||||
private static Collection<VirtualFile> getLibraryRootsWithAbiIncompatibleVersion(
|
||||
@NotNull Project project,
|
||||
@NotNull ScalarIndexExtension<Integer> index,
|
||||
@NotNull ScalarIndexExtension<BinaryVersion> index,
|
||||
@NotNull Function1<Module, Boolean> checkModule,
|
||||
@NotNull Function1<Integer, Boolean> checkAbiVersion
|
||||
@NotNull Function1<BinaryVersion, Boolean> checkVersion
|
||||
) {
|
||||
ID<Integer, Void> id = index.getName();
|
||||
ID<BinaryVersion, Void> id = index.getName();
|
||||
|
||||
Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
|
||||
List<Module> modulesToCheck = KotlinPackage.filter(modules, checkModule);
|
||||
if (modulesToCheck.isEmpty()) return Collections.emptyList();
|
||||
|
||||
Collection<Integer> abiVersions = collectAllKeys(id, modulesToCheck);
|
||||
Set<Integer> badAbiVersions = Sets.newHashSet(KotlinPackage.filter(abiVersions, checkAbiVersion));
|
||||
Collection<BinaryVersion> versions = collectAllKeys(id, modulesToCheck);
|
||||
Set<BinaryVersion> badVersions = Sets.newHashSet(KotlinPackage.filter(versions, checkVersion));
|
||||
Set<VirtualFile> badRoots = Sets.newHashSet();
|
||||
ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(project);
|
||||
|
||||
for (Integer version : badAbiVersions) {
|
||||
for (BinaryVersion version : badVersions) {
|
||||
Collection<VirtualFile> indexedFiles = FileBasedIndex.getInstance().getContainingFiles(
|
||||
id, version, ProjectScope.getLibrariesScope(project));
|
||||
|
||||
@@ -361,12 +363,12 @@ public class KotlinRuntimeLibraryUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<Integer> collectAllKeys(@NotNull ID<Integer, Void> id, @NotNull List<Module> modules) {
|
||||
Set<Integer> allKeys = new HashSet<Integer>();
|
||||
private static <T> Collection<T> collectAllKeys(@NotNull ID<T, Void> id, @NotNull List<Module> modules) {
|
||||
Set<T> allKeys = new HashSet<T>();
|
||||
|
||||
for (Module module : modules) {
|
||||
GlobalSearchScope scope = GlobalSearchScope.moduleWithLibrariesScope(module);
|
||||
FileBasedIndex.getInstance().processAllKeys(id, new CommonProcessors.CollectProcessor<Integer>(allKeys), scope, null);
|
||||
FileBasedIndex.getInstance().processAllKeys(id, new CommonProcessors.CollectProcessor<T>(allKeys), scope, null);
|
||||
}
|
||||
|
||||
return allKeys;
|
||||
|
||||
@@ -68,7 +68,11 @@ class CacheFormatVersion(targetDataRoot: File) {
|
||||
companion object {
|
||||
// Change this when incremental cache format changes
|
||||
private val INCREMENTAL_CACHE_OWN_VERSION = 4
|
||||
private val CACHE_FORMAT_VERSION: Int = INCREMENTAL_CACHE_OWN_VERSION * 1000000 + JvmAbi.VERSION
|
||||
|
||||
private val CACHE_FORMAT_VERSION =
|
||||
INCREMENTAL_CACHE_OWN_VERSION * 1000000 +
|
||||
JvmAbi.VERSION.major * 1000 +
|
||||
JvmAbi.VERSION.minor
|
||||
|
||||
private val NON_INCREMENTAL_MODE_PSEUDO_VERSION = Int.MAX_VALUE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user