diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java index 52eff0173a0..8894592e28b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClassFileFactory.java @@ -21,6 +21,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.io.DataOutputStream; import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,6 +29,7 @@ import org.jetbrains.annotations.TestOnly; import org.jetbrains.kotlin.backend.common.output.OutputFile; import org.jetbrains.kotlin.backend.common.output.OutputFileCollection; import org.jetbrains.kotlin.codegen.state.GenerationState; +import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; import org.jetbrains.kotlin.load.kotlin.PackageParts; import org.jetbrains.kotlin.name.FqName; @@ -114,8 +116,12 @@ public class ClassFileFactory implements OutputFileCollection { @Override public byte[] asBytes(ClassBuilderFactory factory) { try { - ByteArrayOutputStream moduleMapping = new ByteArrayOutputStream(1024); - builder.build().writeTo(moduleMapping); + ByteArrayOutputStream moduleMapping = new ByteArrayOutputStream(4*1024); + DataOutputStream dataOutStream = new DataOutputStream(moduleMapping); + dataOutStream.writeInt(1); + dataOutStream.writeInt(JvmAbi.VERSION); + builder.build().writeTo(dataOutStream); + dataOutStream.flush(); return moduleMapping.toByteArray(); } catch (UnsupportedEncodingException e) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/classFileUtils.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/classFileUtils.kt index 9ed21a31ff7..1553f76fe11 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/classFileUtils.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/classFileUtils.kt @@ -38,7 +38,7 @@ private fun List.addCompiledParts(state: GenerationState): List() }.map { - ModuleMapping(it.contentsToByteArray()) + ModuleMapping.create(it.contentsToByteArray()) } return mappings.map { it.findPackageParts(packageFqName) }.filterNotNull().flatMap { it.parts }.distinct() diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt index 16f72d22fa5..e8fb04d3dd2 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackageFragmentProvider.kt @@ -101,7 +101,7 @@ public class IncrementalPackageFragmentProvider( JetScope.Empty } else { - val moduleMapping = incrementalCache.getModuleMappingData()?.let { ModuleMapping(it) } + val moduleMapping = incrementalCache.getModuleMappingData()?.let { ModuleMapping.create(it) } val actualPackagePartFiles = moduleMapping?.findPackageParts(fqName.asString())?.let { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackagePartProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackagePartProvider.kt index 41df41bd8a7..aa2b2fc9c0e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackagePartProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/incremental/IncrementalPackagePartProvider.kt @@ -29,7 +29,7 @@ internal class IncrementalPackagePartProvider private constructor( incrementalCaches: List, storageManager: StorageManager ) : PackagePartProvider { - private val moduleMappings = storageManager.createLazyValue { incrementalCaches.map { ModuleMapping(it.getModuleMappingData()) } } + private val moduleMappings = storageManager.createLazyValue { incrementalCaches.map { ModuleMapping.create(it.getModuleMappingData()) } } private val fqNamesToIgnore = incrementalCaches.flatMap { IncrementalPackageFragmentProvider.fqNamesToLoad(it.getObsoletePackageParts(), sourceFiles).map { it.asString() } } diff --git a/compiler/testData/cli/jvm/wrongAbiVersionLib/bin/META-INF/main.kotlin_module b/compiler/testData/cli/jvm/wrongAbiVersionLib/bin/META-INF/main.kotlin_module index fb10a661736..f64daa520df 100644 Binary files a/compiler/testData/cli/jvm/wrongAbiVersionLib/bin/META-INF/main.kotlin_module and b/compiler/testData/cli/jvm/wrongAbiVersionLib/bin/META-INF/main.kotlin_module differ 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 a9c96fe8550..4d6bda68b46 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 @@ -16,27 +16,12 @@ package org.jetbrains.kotlin.load.kotlin +import org.jetbrains.kotlin.load.java.AbiVersionUtil import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable -import java.io.Writer +import java.io.ByteArrayInputStream +import java.io.DataInputStream -public class ModuleMapping(proto: ByteArray? = null) { - - val packageFqName2Parts = hashMapOf() - - init { - if (proto != null) { - val parseFrom: JvmPackageTable.PackageTable? = JvmPackageTable.PackageTable.parseFrom(proto) - if (parseFrom != null) { - parseFrom.packagePartsList.map { - val packageParts = PackageParts(it.packageFqName) - packageFqName2Parts.put(it.packageFqName, packageParts) - it.classNameList.map { - packageParts.parts.add(it) - } - } - } - } - } +public class ModuleMapping private constructor(val packageFqName2Parts: Map) { fun findPackageParts(packageFqName: String): PackageParts? { return packageFqName2Parts[packageFqName] @@ -44,6 +29,34 @@ public class ModuleMapping(proto: ByteArray? = null) { companion object { public val MAPPING_FILE_EXT: String = "kotlin_module"; + + public val EMPTY: ModuleMapping = ModuleMapping(emptyMap()) + + fun create(protoWithAbi: ByteArray? = null): ModuleMapping { + if (protoWithAbi == 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()); + if (AbiVersionUtil.isAbiVersionCompatible(abiVersion)) { + val parseFrom = JvmPackageTable.PackageTable.parseFrom(inputStream) + if (parseFrom != null) { + val packageFqNameParts = hashMapOf() + parseFrom.packagePartsList.forEach { + val packageParts = PackageParts(it.packageFqName) + packageFqNameParts.put(it.packageFqName, packageParts) + it.classNameList.forEach { + packageParts.parts.add(it) + } + } + return ModuleMapping(packageFqNameParts) + } + } + return EMPTY + } } } @@ -58,7 +71,7 @@ public class PackageParts(val packageFqName: String) { packageFqName.hashCode() * 31 + parts.hashCode() companion object { - @jvmStatic public fun PackageParts.serialize(builder : JvmPackageTable.PackageTable.Builder) { + @jvmStatic public fun PackageParts.serialize(builder: JvmPackageTable.PackageTable.Builder) { if (this.parts.isNotEmpty()) { val packageParts = JvmPackageTable.PackageParts.newBuilder() packageParts.setPackageFqName(this.packageFqName) diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackagePartProvider.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackagePartProvider.kt index 23824d7e207..6f97a51f912 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackagePartProvider.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/RuntimePackagePartProvider.kt @@ -27,13 +27,13 @@ class RuntimePackagePartProvider(val classLoader : ClassLoader) : PackagePartPro fun registerModule(moduleName: String) { module2Mapping.putIfAbsent(moduleName, lazy { - val resourceAsStream: InputStream = classLoader.getResourceAsStream("META-INF/$moduleName.${ModuleMapping.MAPPING_FILE_EXT}") ?: return@lazy ModuleMapping() + val resourceAsStream: InputStream = classLoader.getResourceAsStream("META-INF/$moduleName.${ModuleMapping.MAPPING_FILE_EXT}") ?: return@lazy ModuleMapping.create() try { - return@lazy ModuleMapping(resourceAsStream.readBytes()) + return@lazy ModuleMapping.create(resourceAsStream.readBytes()) } catch (e: Exception) { - return@lazy ModuleMapping() + return@lazy ModuleMapping.create() } }) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/moduleMappingIndexes.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/moduleMappingIndexes.kt index cd0022a1186..988c99998a7 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/moduleMappingIndexes.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/moduleMappingIndexes.kt @@ -78,9 +78,9 @@ public object KotlinModuleMappingIndex : FileBasedIndexExtension { return object : DataIndexer { - override fun map(inputData: FileContent): MutableMap { + override fun map(inputData: FileContent): Map { val content = inputData.getContent() - val moduleMapping = ModuleMapping(content) + val moduleMapping = ModuleMapping.create(content) return moduleMapping.packageFqName2Parts } }