From 2f64680b630a1ee46f9f4bd43285fbc65c563c77 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 25 Dec 2015 22:44:23 +0300 Subject: [PATCH] Add several subclasses of BinaryVersion To simplify comparison of expected vs actual versions in the future --- .../KotlinSyntheticClassAnnotationTest.java | 4 +-- .../utils/KotlinJavascriptMetadataUtils.kt | 16 ++++++++- .../kotlin/load/java/AbiVersionUtil.java | 2 -- .../jetbrains/kotlin/load/java/JvmAbi.java | 3 +- .../load/java/JvmBytecodeBinaryVersion.kt | 34 ++++++++++++++++++ .../kotlin/load/kotlin/ModuleMapping.kt | 4 +-- ...eadKotlinClassHeaderAnnotationVisitor.java | 5 +-- .../kotlin/builtins/BuiltInsBinaryVersion.kt | 31 ++++++++++++++++ .../builtins/BuiltinsPackageFragment.kt | 4 +-- .../deserialization/BinaryVersion.kt | 35 ++++++++++++++----- .../idea/versions/KotlinAbiVersionIndex.kt | 11 +++--- .../versions/KotlinAbiVersionIndexBase.kt | 7 ++-- .../KotlinJavaScriptAbiVersionIndex.kt | 11 +++--- 13 files changed, 133 insertions(+), 34 deletions(-) create mode 100644 core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmBytecodeBinaryVersion.kt create mode 100644 core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltInsBinaryVersion.kt rename core/{deserialization => util.runtime}/src/org/jetbrains/kotlin/serialization/deserialization/BinaryVersion.kt (57%) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java index e7a3d867c22..729d4f4dfd0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java @@ -22,8 +22,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.load.java.AbiVersionUtil; import org.jetbrains.kotlin.load.java.JvmAbi; +import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion; import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion; import org.jetbrains.kotlin.test.ConfigurationKind; import java.lang.annotation.Annotation; @@ -147,6 +147,6 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { int[] version = (int[]) CodegenTestUtil.getAnnotationAttribute(annotation, VERSION_FIELD_NAME); assertNotNull(version); assertTrue("Annotation " + annotationFqName + " is written with an unsupported format", - AbiVersionUtil.isAbiVersionCompatible(BinaryVersion.create(version))); + AbiVersionUtil.isAbiVersionCompatible(JvmBytecodeBinaryVersion.create(version))); } } diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinJavascriptMetadataUtils.kt b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinJavascriptMetadataUtils.kt index 49490a638fb..a84d2bd796c 100644 --- a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinJavascriptMetadataUtils.kt +++ b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinJavascriptMetadataUtils.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.utils +import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion import java.io.File import javax.xml.bind.DatatypeConverter.parseBase64Binary import javax.xml.bind.DatatypeConverter.printBase64Binary @@ -24,6 +25,19 @@ class KotlinJavascriptMetadata(val abiVersion: Int, val moduleName: String, val val isAbiVersionCompatible: Boolean = KotlinJavascriptMetadataUtils.isAbiVersionCompatible(abiVersion) } +// TODO: move to JS modules +class JsBinaryVersion protected constructor( + major: Int, minor: Int, patch: Int, rest: List +) : BinaryVersion(major, minor, patch, rest) { + companion object { + @JvmField val INVALID_VERSION = JsBinaryVersion.create(IntArray(0)) + + @JvmStatic fun create(version: IntArray) = create(version, ::JsBinaryVersion) + + @JvmStatic fun create(major: Int, minor: Int, patch: Int) = create(major, minor, patch, ::JsBinaryVersion) + } +} + object KotlinJavascriptMetadataUtils { const val JS_EXT: String = ".js" const val META_JS_SUFFIX: String = ".meta.js" @@ -36,7 +50,7 @@ object KotlinJavascriptMetadataUtils { */ private val METADATA_PATTERN = "(?m)\\w+\\.$KOTLIN_JAVASCRIPT_METHOD_NAME\\((\\d+),\\s*(['\"])([^'\"]*)\\2,\\s*(['\"])([^'\"]*)\\4\\)".toPattern() - @JvmField val ABI_VERSION: Int = 3 + @JvmField val ABI_VERSION: Int = JsBinaryVersion.create(0, 3, 0).minor fun replaceSuffix(filePath: String): String = filePath.substringBeforeLast(JS_EXT) + META_JS_SUFFIX diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/AbiVersionUtil.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/AbiVersionUtil.java index a634d60bf6e..da5f289a195 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/AbiVersionUtil.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/AbiVersionUtil.java @@ -20,8 +20,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion; public final class AbiVersionUtil { - public static final BinaryVersion INVALID_VERSION = BinaryVersion.create(new int[0]); - public static boolean isAbiVersionCompatible(@NotNull BinaryVersion actual) { return actual.isCompatibleTo(JvmAbi.VERSION); } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java index 2aa059c82cf..fab76d435bc 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.platform.JavaToKotlinClassMap; -import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion; import org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isClassOrEnumClass; @@ -43,7 +42,7 @@ public final class JvmAbi { * - 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 BinaryVersion VERSION = BinaryVersion.create(1, 0, 2); + public static final JvmBytecodeBinaryVersion VERSION = JvmBytecodeBinaryVersion.create(1, 0, 2); public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls"; public static final String DEFAULT_IMPLS_SUFFIX = "$" + DEFAULT_IMPLS_CLASS_NAME; diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmBytecodeBinaryVersion.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmBytecodeBinaryVersion.kt new file mode 100644 index 00000000000..bfc33bb765b --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmBytecodeBinaryVersion.kt @@ -0,0 +1,34 @@ +/* + * 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.load.java + +import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion + +class JvmBytecodeBinaryVersion protected constructor( + major: Int, minor: Int, patch: Int, rest: List +) : BinaryVersion(major, minor, patch, rest) { + companion object { + @JvmField + val INVALID_VERSION = JvmBytecodeBinaryVersion.create(IntArray(0)) + + @JvmStatic + fun create(version: IntArray) = create(version, ::JvmBytecodeBinaryVersion) + + @JvmStatic + fun create(major: Int, minor: Int, patch: Int) = create(major, minor, patch, ::JvmBytecodeBinaryVersion) + } +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/ModuleMapping.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/ModuleMapping.kt index 29e584d85be..04f8381a9d1 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/ModuleMapping.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/ModuleMapping.kt @@ -17,7 +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.load.java.JvmBytecodeBinaryVersion import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable import java.io.ByteArrayInputStream import java.io.DataInputStream @@ -41,7 +41,7 @@ class ModuleMapping private constructor(val packageFqName2Parts: Map +) : BinaryVersion(major, minor, patch, rest) { + companion object { + @JvmStatic + fun create(version: IntArray) = create(version, ::BuiltInsBinaryVersion) + + @JvmStatic + fun create(major: Int, minor: Int, patch: Int) = create(major, minor, patch, ::BuiltInsBinaryVersion) + } +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltinsPackageFragment.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltinsPackageFragment.kt index a9af714cd6d..9badd81d33d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltinsPackageFragment.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/BuiltinsPackageFragment.kt @@ -37,7 +37,7 @@ class BuiltinsPackageFragment( ) : DeserializedPackageFragment(fqName, storageManager, module, BuiltInsSerializedResourcePaths, loadResource) { val builtinsMessage = loadResource(BuiltInsSerializedResourcePaths.getBuiltInsFilePath(fqName))?.let { stream -> val dataInput = DataInputStream(stream) - val version = BinaryVersion.create((1..dataInput.readInt()).map { dataInput.readInt() }.toIntArray()) + val version = BuiltInsBinaryVersion.create((1..dataInput.readInt()).map { dataInput.readInt() }.toIntArray()) if (!version.isCompatibleTo(BuiltinsPackageFragment.VERSION)) { // TODO: report a proper diagnostic @@ -74,6 +74,6 @@ class BuiltinsPackageFragment( companion object { // Advance this version when the common or builtins-specific binary metadata format is changed - val VERSION = BinaryVersion.create(1, 0, 0) + val VERSION = BuiltInsBinaryVersion.create(1, 0, 0) } } diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/BinaryVersion.kt b/core/util.runtime/src/org/jetbrains/kotlin/serialization/deserialization/BinaryVersion.kt similarity index 57% rename from core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/BinaryVersion.kt rename to core/util.runtime/src/org/jetbrains/kotlin/serialization/deserialization/BinaryVersion.kt index f15c694ede9..225d022f4db 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/BinaryVersion.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/serialization/deserialization/BinaryVersion.kt @@ -16,11 +16,11 @@ package org.jetbrains.kotlin.serialization.deserialization -data class BinaryVersion private constructor( +abstract class BinaryVersion protected constructor( val major: Int, val minor: Int, val patch: Int, - val rest: List = listOf() + val rest: List ) { fun toArray(): IntArray = intArrayOf(major, minor, patch, *rest.toIntArray()) @@ -41,20 +41,37 @@ data class BinaryVersion private constructor( return if (versions.isEmpty()) "unknown" else versions.joinToString(".") } + override fun equals(other: Any?) = + this.javaClass == other?.javaClass && + major == (other as BinaryVersion).major && minor == other.minor && patch == other.patch && rest == other.rest + + override fun hashCode(): Int{ + var result = major + result += 31 * result + minor + result += 31 * result + patch + result += 31 * result + rest.hashCode() + return result + } + 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() + fun create( + version: IntArray, + factory: (major: Int, minor: Int, patch: Int, rest: List) -> T + ): T { + return factory( + version.getOrNull(0) ?: UNKNOWN, + version.getOrNull(1) ?: UNKNOWN, + version.getOrNull(2) ?: UNKNOWN, + if (version.size > 3) version.asList().subList(3, version.size).toList() else emptyList() ) } @JvmStatic - fun create(major: Int, minor: Int, patch: Int) = BinaryVersion(major, minor, patch) + fun create( + major: Int, minor: Int, patch: Int, factory: (major: Int, minor: Int, patch: Int, rest: List) -> T + ): T = factory(major, minor, patch, emptyList()) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinAbiVersionIndex.kt b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinAbiVersionIndex.kt index a85c040a807..2ea1bb1d8cb 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinAbiVersionIndex.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinAbiVersionIndex.kt @@ -21,16 +21,17 @@ import com.intellij.util.indexing.DataIndexer import com.intellij.util.indexing.FileBasedIndex 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.load.java.JvmBytecodeBinaryVersion 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 -object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase(KotlinAbiVersionIndex::class.java) { - +object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase( + KotlinAbiVersionIndex::class.java, { JvmBytecodeBinaryVersion.create(it) } +) { override fun getIndexer() = INDEXER override fun getInputFilter() = FileBasedIndex.InputFilter() { file -> file.fileType == StdFileTypes.CLASS } @@ -60,7 +61,7 @@ object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase( return object : AnnotationVisitor(Opcodes.ASM5) { override fun visit(name: String, value: Any) { if (name == VERSION_FIELD_NAME && value is IntArray) { - version = BinaryVersion.create(value) + version = JvmBytecodeBinaryVersion.create(value) } } } @@ -70,7 +71,7 @@ object KotlinAbiVersionIndex : KotlinAbiVersionIndexBase( if (annotationPresent && version == null) { // No version at all because the class is too old, or version is set to something weird - version = AbiVersionUtil.INVALID_VERSION + version = JvmBytecodeBinaryVersion.INVALID_VERSION } if (version != null) mapOf(version!! to null) else mapOf() diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinAbiVersionIndexBase.kt b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinAbiVersionIndexBase.kt index d8e74a0660f..2b778eed0be 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinAbiVersionIndexBase.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinAbiVersionIndexBase.kt @@ -29,7 +29,10 @@ import java.io.DataOutput /** * Important! This is not a stub-based index. And it has its own version */ -abstract class KotlinAbiVersionIndexBase(private val classOfIndex: Class) : ScalarIndexExtension() { +abstract class KotlinAbiVersionIndexBase( + private val classOfIndex: Class, + private val createBinaryVersion: (IntArray) -> BinaryVersion +) : ScalarIndexExtension() { override fun getName() = ID.create(classOfIndex.canonicalName) @@ -40,7 +43,7 @@ abstract class KotlinAbiVersionIndexBase(private val classOfIndex: Class) override fun read(input: DataInput): BinaryVersion { val size = DataInputOutputUtil.readINT(input) - return BinaryVersion.create((0..size - 1).map { DataInputOutputUtil.readINT(input) }.toIntArray()) + return createBinaryVersion((0..size - 1).map { DataInputOutputUtil.readINT(input) }.toIntArray()) } override fun save(output: DataOutput, value: BinaryVersion) { diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinJavaScriptAbiVersionIndex.kt b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinJavaScriptAbiVersionIndex.kt index 52cdf6c0063..bd53d611c96 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinJavaScriptAbiVersionIndex.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinJavaScriptAbiVersionIndex.kt @@ -21,14 +21,15 @@ 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.JsBinaryVersion import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils import java.util.* -object KotlinJavaScriptAbiVersionIndex : KotlinAbiVersionIndexBase(KotlinJavaScriptAbiVersionIndex::class.java) { - +object KotlinJavaScriptAbiVersionIndex : KotlinAbiVersionIndexBase( + KotlinJavaScriptAbiVersionIndex::class.java, { JsBinaryVersion.create(it) } +) { override fun getIndexer() = INDEXER override fun getInputFilter() = FileBasedIndex.InputFilter() { file -> JavaScript.EXTENSION == file.extension } @@ -46,11 +47,11 @@ object KotlinJavaScriptAbiVersionIndex : KotlinAbiVersionIndexBase