diff --git a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/ClsClassFinder.kt b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/ClsClassFinder.kt index 4a61f451848..66614583369 100644 --- a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/ClsClassFinder.kt +++ b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/ClsClassFinder.kt @@ -11,6 +11,7 @@ import com.intellij.psi.ClassFileViewProvider import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.findKotlinClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -20,7 +21,10 @@ object ClsClassFinder { val partsFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName) return partNames.mapNotNull { - partsFinder.findKotlinClass(ClassId(packageFqName, Name.identifier(it.substringAfterLast('/')))) + partsFinder.findKotlinClass( + ClassId(packageFqName, Name.identifier(it.substringAfterLast('/'))), + JvmMetadataVersion.INSTANCE + ) } } diff --git a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/ClsKotlinBinaryClassCache.kt b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/ClsKotlinBinaryClassCache.kt index f8e0bcf26cd..a87c6502bf9 100644 --- a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/ClsKotlinBinaryClassCache.kt +++ b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/ClsKotlinBinaryClassCache.kt @@ -45,7 +45,7 @@ class ClsKotlinBinaryClassCache { getKotlinBinaryFromCache(file)?.let { return it.isKotlinBinary } - return kotlinJvmBinaryClass(file, fileContent) != null + return kotlinJvmBinaryClass(file, fileContent, JvmMetadataVersion.INSTANCE) != null } fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? { @@ -54,16 +54,19 @@ class ClsKotlinBinaryClassCache { return null } - return kotlinJvmBinaryClass(file, fileContent) + return kotlinJvmBinaryClass(file, fileContent, cached?.headerData?.metadataVersion ?: JvmMetadataVersion.INSTANCE) } private fun kotlinJvmBinaryClass( file: VirtualFile, - fileContent: ByteArray? + fileContent: ByteArray?, + jvmMetadataVersion: JvmMetadataVersion ): KotlinJvmBinaryClass? { if (ModelBranch.getFileBranch(file) != null) return null val classFileContent = try { - KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file, fileContent) + KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent( + file, jvmMetadataVersion, fileContent = fileContent + ) } catch (e: Exception) { if (e is ControlFlowException) throw e return null @@ -94,7 +97,7 @@ class ClsKotlinBinaryClassCache { } } - val kotlinBinaryClass = kotlinJvmBinaryClass(file, fileContent) ?: return null + val kotlinBinaryClass = kotlinJvmBinaryClass(file, fileContent, JvmMetadataVersion.INSTANCE) ?: return null return createHeaderInfo(kotlinBinaryClass) } diff --git a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/DirectoryBasedClassFinder.kt b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/DirectoryBasedClassFinder.kt index 028a883de4f..ce4f60dc4d6 100644 --- a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/DirectoryBasedClassFinder.kt +++ b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/DirectoryBasedClassFinder.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.classId import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder.Result.KotlinClass +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import java.io.InputStream @@ -18,15 +19,16 @@ class DirectoryBasedClassFinder( val packageDirectory: VirtualFile, val directoryPackageFqName: FqName ) : KotlinClassFinder { - override fun findKotlinClassOrContent(javaClass: JavaClass): KotlinClassFinder.Result? = findKotlinClassOrContent(javaClass.classId!!) + override fun findKotlinClassOrContent(javaClass: JavaClass, jvmMetadataVersion: JvmMetadataVersion): KotlinClassFinder.Result? = + findKotlinClassOrContent(javaClass.classId!!, jvmMetadataVersion) - override fun findKotlinClassOrContent(classId: ClassId): KotlinClassFinder.Result? { + override fun findKotlinClassOrContent(classId: ClassId, jvmMetadataVersion: JvmMetadataVersion): KotlinClassFinder.Result? { if (classId.packageFqName != directoryPackageFqName) { return null } val targetName = classId.relativeClassName.pathSegments().joinToString("$", postfix = ".class") val virtualFile = packageDirectory.findChild(targetName) - if (virtualFile != null && isKotlinWithCompatibleAbiVersion(virtualFile)) { + if (virtualFile != null && isKotlinWithCompatibleAbiVersion(virtualFile, jvmMetadataVersion)) { return ClsKotlinBinaryClassCache.getInstance().getKotlinBinaryClass(virtualFile)?.let(::KotlinClass) } return null @@ -45,12 +47,12 @@ class DirectoryBasedClassFinder( /** * Checks if this file is a compiled Kotlin class file ABI-compatible with the current plugin */ -private fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean { +private fun isKotlinWithCompatibleAbiVersion(file: VirtualFile, jvmMetadataVersion: JvmMetadataVersion): Boolean { val clsKotlinBinaryClassCache = ClsKotlinBinaryClassCache.getInstance() if (!clsKotlinBinaryClassCache.isKotlinJvmCompiledFile(file)) return false val kotlinClass = clsKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file) - return kotlinClass != null && kotlinClass.metadataVersion.isCompatible() + return kotlinClass != null && kotlinClass.metadataVersion.isCompatible(jvmMetadataVersion) } diff --git a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/DirectoryBasedDataFinder.kt b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/DirectoryBasedDataFinder.kt index f4f697d5c82..46836869023 100644 --- a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/DirectoryBasedDataFinder.kt +++ b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/DirectoryBasedDataFinder.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.decompiler.stub.file import com.intellij.openapi.diagnostic.Logger import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement import org.jetbrains.kotlin.load.kotlin.findKotlinClass +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.serialization.deserialization.ClassData @@ -15,10 +16,11 @@ import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder class DirectoryBasedDataFinder( val classFinder: DirectoryBasedClassFinder, - val log: Logger + val log: Logger, + private val jvmMetadataVersion: JvmMetadataVersion ) : ClassDataFinder { override fun findClassData(classId: ClassId): ClassData? { - val binaryClass = classFinder.findKotlinClass(classId) ?: return null + val binaryClass = classFinder.findKotlinClass(classId, jvmMetadataVersion) ?: return null val classHeader = binaryClass.classHeader val data = classHeader.data if (data == null) { diff --git a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/KotlinClsStubBuilder.kt b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/KotlinClsStubBuilder.kt index b715c17470c..eeddedaacc8 100644 --- a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/KotlinClsStubBuilder.kt +++ b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/KotlinClsStubBuilder.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.Flags import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.TypeTable +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -32,7 +33,6 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.KClassValue import org.jetbrains.kotlin.serialization.deserialization.getClassId import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.storage.StorageManager open class KotlinClsStubBuilder : ClsStubBuilder() { override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + KotlinStubVersions.CLASSFILE_STUB_VERSION @@ -60,11 +60,11 @@ open class KotlinClsStubBuilder : ClsStubBuilder() { val classId = kotlinClass.classId val packageFqName = header.packageName?.let { FqName(it) } ?: classId.packageFqName - if (!header.metadataVersion.isCompatible()) { + if (!header.metadataVersion.isCompatibleWithCurrentCompilerVersion()) { return createIncompatibleAbiVersionFileStub() } - val components = createStubBuilderComponents(file, packageFqName, fileContent) + val components = createStubBuilderComponents(file, packageFqName, fileContent, header.metadataVersion) if (header.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS) { val partFiles = ClsClassFinder.findMultifileClassParts(file, classId, header.multifilePartNames) return createMultifileClassStub(header, partFiles, classId.asSingleFqName(), components) @@ -105,10 +105,15 @@ open class KotlinClsStubBuilder : ClsStubBuilder() { } } - private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName, fileContent: ByteArray): ClsStubBuilderComponents { + private fun createStubBuilderComponents( + file: VirtualFile, + packageFqName: FqName, + fileContent: ByteArray, + jvmMetadataVersion: JvmMetadataVersion + ): ClsStubBuilderComponents { val classFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName) - val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG) - val annotationLoader = AnnotationLoaderForClassFileStubBuilder(classFinder, file, fileContent) + val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG, jvmMetadataVersion) + val annotationLoader = AnnotationLoaderForClassFileStubBuilder(classFinder, file, fileContent, jvmMetadataVersion) return ClsStubBuilderComponents(classDataFinder, annotationLoader, file) } @@ -127,7 +132,8 @@ open class KotlinClsStubBuilder : ClsStubBuilder() { private class AnnotationLoaderForClassFileStubBuilder( kotlinClassFinder: KotlinClassFinder, private val cachedFile: VirtualFile, - private val cachedFileContent: ByteArray + private val cachedFileContent: ByteArray, + override val jvmMetadataVersion: JvmMetadataVersion ) : AbstractBinaryClassAnnotationLoader(kotlinClassFinder) { private val storage = diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/DeserializerForClassfileDecompiler.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/DeserializerForClassfileDecompiler.kt index 1fbdd92962a..629bd393100 100644 --- a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/DeserializerForClassfileDecompiler.kt +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/DeserializerForClassfileDecompiler.kt @@ -16,10 +16,8 @@ import org.jetbrains.kotlin.contracts.ContractDeserializerImpl import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.NotFoundClasses import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.load.kotlin.BinaryClassAnnotationAndConstantLoaderImpl -import org.jetbrains.kotlin.load.kotlin.JavaFlexibleTypeDeserializer -import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource -import org.jetbrains.kotlin.load.kotlin.findKotlinClass +import org.jetbrains.kotlin.load.kotlin.* +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -33,12 +31,13 @@ fun DeserializerForClassfileDecompiler(classFile: VirtualFile): DeserializerForC ClsKotlinBinaryClassCache.getInstance().getKotlinBinaryClassHeaderData(classFile) ?: error("Decompiled data factory shouldn't be called on an unsupported file: $classFile") val packageFqName = kotlinClassHeaderInfo.classId.packageFqName - return DeserializerForClassfileDecompiler(classFile.parent!!, packageFqName) + return DeserializerForClassfileDecompiler(classFile.parent!!, packageFqName, kotlinClassHeaderInfo.metadataVersion) } class DeserializerForClassfileDecompiler( packageDirectory: VirtualFile, - directoryPackageFqName: FqName + directoryPackageFqName: FqName, + private val jvmMetadataVersion: JvmMetadataVersion ) : DeserializerForDecompilerBase(directoryPackageFqName) { override val builtIns: KotlinBuiltIns get() = DefaultBuiltIns.Instance @@ -47,10 +46,11 @@ class DeserializerForClassfileDecompiler( override val deserializationComponents: DeserializationComponents init { - val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG) + val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG, jvmMetadataVersion) val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor) - val annotationAndConstantLoader = - BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, storageManager, classFinder) + val annotationAndConstantLoader = createBinaryClassAnnotationAndConstantLoader( + moduleDescriptor, notFoundClasses, storageManager, classFinder, jvmMetadataVersion + ) val configuration = object : DeserializationConfiguration { override val readDeserializedContracts: Boolean = true @@ -72,7 +72,7 @@ class DeserializerForClassfileDecompiler( assert(packageFqName == directoryPackageFqName) { "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), jvmMetadataVersion) val header = binaryClassForPackageClass?.classHeader val annotationData = header?.data val strings = header?.strings diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/buildDecompiledTextForClassFile.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/buildDecompiledTextForClassFile.kt index 26888c1976f..0489a81082d 100644 --- a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/buildDecompiledTextForClassFile.kt +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/buildDecompiledTextForClassFile.kt @@ -27,7 +27,7 @@ fun buildDecompiledTextForClassFile( val classId = classHeader.classId - if (!classHeader.metadataVersion.isCompatible()) { + if (!classHeader.metadataVersion.isCompatibleWithCurrentCompilerVersion()) { return createIncompatibleAbiVersionDecompiledText(JvmMetadataVersion.INSTANCE, classHeader.metadataVersion) } diff --git a/build-common/src/org/jetbrains/kotlin/build/generatedFiles.kt b/build-common/src/org/jetbrains/kotlin/build/generatedFiles.kt index d488c45ae40..f713452c4e3 100644 --- a/build-common/src/org/jetbrains/kotlin/build/generatedFiles.kt +++ b/build-common/src/org/jetbrains/kotlin/build/generatedFiles.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.build import org.jetbrains.kotlin.incremental.LocalFileKotlinClass +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping import org.jetbrains.kotlin.utils.sure import java.io.File @@ -32,9 +33,10 @@ open class GeneratedFile( class GeneratedJvmClass( sourceFiles: Collection, - outputFile: File + outputFile: File, + jvmMetadataVersionFromLanguageVersion: JvmMetadataVersion ) : GeneratedFile(sourceFiles, outputFile) { - val outputClass = LocalFileKotlinClass.create(outputFile).sure { + val outputClass = LocalFileKotlinClass.create(outputFile, jvmMetadataVersionFromLanguageVersion).sure { "Couldn't load KotlinClass from $outputFile; it may happen because class doesn't have valid Kotlin annotations" } } diff --git a/build-common/src/org/jetbrains/kotlin/compilerRunner/SimpleOutputItem.kt b/build-common/src/org/jetbrains/kotlin/compilerRunner/SimpleOutputItem.kt index 55102f2b56d..ff9927179c3 100644 --- a/build-common/src/org/jetbrains/kotlin/compilerRunner/SimpleOutputItem.kt +++ b/build-common/src/org/jetbrains/kotlin/compilerRunner/SimpleOutputItem.kt @@ -18,15 +18,16 @@ package org.jetbrains.kotlin.compilerRunner import org.jetbrains.kotlin.build.GeneratedFile import org.jetbrains.kotlin.build.GeneratedJvmClass +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import java.io.File data class SimpleOutputItem(val sourceFiles: Collection, val outputFile: File) { override fun toString(): String = - "$sourceFiles->$outputFile" + "$sourceFiles->$outputFile" } -fun SimpleOutputItem.toGeneratedFile(): GeneratedFile = - when { - outputFile.name.endsWith(".class") -> GeneratedJvmClass(sourceFiles, outputFile) - else -> GeneratedFile(sourceFiles, outputFile) - } \ No newline at end of file +fun SimpleOutputItem.toGeneratedFile(jvmMetadataVersionFromLanguageVersion: JvmMetadataVersion): GeneratedFile = + when { + outputFile.name.endsWith(".class") -> GeneratedJvmClass(sourceFiles, outputFile, jvmMetadataVersionFromLanguageVersion) + else -> GeneratedFile(sourceFiles, outputFile) + } \ No newline at end of file diff --git a/build-common/src/org/jetbrains/kotlin/incremental/LocalFileKotlinClass.kt b/build-common/src/org/jetbrains/kotlin/incremental/LocalFileKotlinClass.kt index 5b6732a6ac2..f8ad71189da 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/LocalFileKotlinClass.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/LocalFileKotlinClass.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.incremental import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.resolve.jvm.JvmClassName import java.io.File @@ -32,10 +33,12 @@ class LocalFileKotlinClass private constructor( ) : FileBasedKotlinClass(className, classVersion, classHeader, innerClasses) { companion object { - fun create(file: File): LocalFileKotlinClass? { + fun create(file: File, jvmMetadataVersionFromLanguageVersion: JvmMetadataVersion): LocalFileKotlinClass? { val fileContents = file.readBytes() - return FileBasedKotlinClass.create(fileContents) { - className, classVersion, classHeader, innerClasses -> + return FileBasedKotlinClass.create( + fileContents, + jvmMetadataVersionFromLanguageVersion + ) { className, classVersion, classHeader, innerClasses -> LocalFileKotlinClass(file, fileContents, className, classVersion, classHeader, innerClasses) } } diff --git a/build-common/test/org/jetbrains/kotlin/incremental/testingUtils/classFilesComparison.kt b/build-common/test/org/jetbrains/kotlin/incremental/testingUtils/classFilesComparison.kt index d10b89f3cec..054e4a6e6d5 100644 --- a/build-common/test/org/jetbrains/kotlin/incremental/testingUtils/classFilesComparison.kt +++ b/build-common/test/org/jetbrains/kotlin/incremental/testingUtils/classFilesComparison.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.metadata.DebugProtoBuf import org.jetbrains.kotlin.metadata.js.DebugJsProtoBuf import org.jetbrains.kotlin.metadata.jvm.DebugJvmProtoBuf import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.protobuf.ExtensionRegistry import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil @@ -151,8 +152,8 @@ private fun classFileToString(classFile: File): String { val traceVisitor = TraceClassVisitor(PrintWriter(out)) ClassReader(classFile.readBytes()).accept(traceVisitor, 0) - val classHeader = LocalFileKotlinClass.create(classFile)?.classHeader ?: return "" - if (!classHeader.metadataVersion.isCompatible()) { + val classHeader = LocalFileKotlinClass.create(classFile, JvmMetadataVersion.INSTANCE)?.classHeader ?: return "" + if (!classHeader.metadataVersion.isCompatibleWithCurrentCompilerVersion()) { error("Incompatible class ($classHeader): $classFile") } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index c0cafab50cc..9455e1f64cb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable import org.jetbrains.kotlin.protobuf.MessageLite import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN +import org.jetbrains.kotlin.utils.toMetadataVersion import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.commons.Method import org.jetbrains.org.objectweb.asm.tree.* @@ -122,7 +123,7 @@ class AnonymousObjectTransformer( override fun visitEnd() {} }, ClassReader.SKIP_FRAMES) - val header = metadataReader.createHeader() + val header = metadataReader.createHeader(inliningContext.state.languageVersionSettings.languageVersion.toMetadataVersion()) assert(isSameModule || (header != null && isPublicAbi(header))) { "Trying to inline an anonymous object which is not part of the public ABI: ${oldObjectType.className}" } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt index c894cfabec8..3f2b881f327 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -43,6 +43,7 @@ import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.diagnostics.OnDemandSuppressCache import org.jetbrains.kotlin.resolve.jvm.JvmClassName +import org.jetbrains.kotlin.resolve.jvm.JvmCompilerDeserializationConfiguration import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.* import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration @@ -184,7 +185,7 @@ class GenerationState private constructor( val packagesWithObsoleteParts: Set val obsoleteMultifileClasses: List val deserializationConfiguration: DeserializationConfiguration = - CompilerDeserializationConfiguration(languageVersionSettings) + JvmCompilerDeserializationConfiguration(languageVersionSettings) val deprecationProvider = DeprecationResolver( LockBasedStorageManager.NO_LOCKS, languageVersionSettings, JavaDeprecationSettings diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmPackagePartProvider.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmPackagePartProvider.kt index dfa5d15c826..de246874e6f 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmPackagePartProvider.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmPackagePartProvider.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.load.kotlin.loadModuleMapping import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration +import org.jetbrains.kotlin.resolve.jvm.JvmCompilerDeserializationConfiguration import java.io.ByteArrayOutputStream import java.io.EOFException import java.io.PrintStream @@ -38,7 +39,7 @@ class JvmPackagePartProvider( languageVersionSettings: LanguageVersionSettings, private val scope: GlobalSearchScope ) : JvmPackagePartProviderBase() { - override val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings) + override val deserializationConfiguration = JvmCompilerDeserializationConfiguration(languageVersionSettings) override val loadedModules: MutableList> = SmartList() diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataKlibSerializer.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataKlibSerializer.kt index 6e96d370b8d..abe934f492f 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataKlibSerializer.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/metadata/K2MetadataKlibSerializer.kt @@ -33,8 +33,8 @@ import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.CommonPlatforms import org.jetbrains.kotlin.platform.TargetPlatform -import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices +import org.jetbrains.kotlin.resolve.jvm.JvmCompilerDeserializationConfiguration import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.utils.keysToMap @@ -232,7 +232,7 @@ private class KlibMetadataDependencyContainer( packageFragmentNames = packageFragmentNames, storageManager = LockBasedStorageManager("KlibMetadataPackageFragmentProvider"), moduleDescriptor = libraryModuleDescriptor, - configuration = CompilerDeserializationConfiguration(languageVersionSettings), + configuration = JvmCompilerDeserializationConfiguration(languageVersionSettings), compositePackageFragmentAddend = null, lookupTracker = LookupTracker.DO_NOTHING ).also { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt index 29b6d894eca..0090ffd0e8d 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.java.createConstantOrError +import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredPropertySymbols @@ -29,6 +30,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue +import org.jetbrains.kotlin.utils.toMetadataVersion internal class AnnotationsLoader(private val session: FirSession, private val kotlinClassFinder: KotlinClassFinder) { private fun loadAnnotation( @@ -190,7 +192,7 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko classId.shortClassName.asString() != JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME ) return false - val klass = kotlinClassFinder.findKotlinClass(classId) + val klass = kotlinClassFinder.findKotlinClass(classId, session.languageVersionSettings.languageVersion.toMetadataVersion()) return klass != null && SpecialJvmAnnotations.isAnnotatedWithContainerMetaAnnotation(klass) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt index 953c7884245..719b53b1caa 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation +import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.kotlin.* import org.jetbrains.kotlin.metadata.ProtoBuf @@ -24,6 +25,7 @@ import org.jetbrains.kotlin.protobuf.MessageLite import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.utils.addToStdlib.runIf +import org.jetbrains.kotlin.utils.toMetadataVersion class JvmBinaryAnnotationDeserializer( val session: FirSession, @@ -37,8 +39,9 @@ class JvmBinaryAnnotationDeserializer( private val annotationInfoForDefaultImpls by lazy(LazyThreadSafetyMode.PUBLICATION) { val defaultImplsClassId = kotlinBinaryClass.classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME)) - val (defaultImplsClass, defaultImplsByteContent) = kotlinClassFinder.findKotlinClassOrContent(defaultImplsClassId) as? KotlinClassFinder.Result.KotlinClass - ?: return@lazy null + val (defaultImplsClass, defaultImplsByteContent) = kotlinClassFinder.findKotlinClassOrContent( + defaultImplsClassId, session.languageVersionSettings.languageVersion.toMetadataVersion() + ) as? KotlinClassFinder.Result.KotlinClass ?: return@lazy null session.loadMemberAnnotations(defaultImplsClass, defaultImplsByteContent, kotlinClassFinder) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmClassFileBasedSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmClassFileBasedSymbolProvider.kt index cbc347d6017..a06a3ed1806 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmClassFileBasedSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmClassFileBasedSymbolProvider.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.deserialization.* import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.java.FirJavaFacade import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass +import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.load.kotlin.* @@ -29,6 +30,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol +import org.jetbrains.kotlin.utils.toMetadataVersion import java.nio.file.Path import java.nio.file.Paths @@ -60,12 +62,16 @@ class JvmClassFileBasedSymbolProvider( if (partName in kotlinBuiltins) return@mapNotNull null val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars) if (!javaFacade.hasTopLevelClassOf(classId)) return@mapNotNull null - val (kotlinJvmBinaryClass, byteContent) = - kotlinClassFinder.findKotlinClassOrContent(classId) as? KotlinClassFinder.Result.KotlinClass ?: return@mapNotNull null + val jvmMetadataVersion = session.languageVersionSettings.languageVersion.toMetadataVersion() + val (kotlinJvmBinaryClass, byteContent) = kotlinClassFinder.findKotlinClassOrContent( + classId, jvmMetadataVersion + ) as? KotlinClassFinder.Result.KotlinClass ?: return@mapNotNull null val facadeName = kotlinJvmBinaryClass.classHeader.multifileClassName?.takeIf { it.isNotEmpty() } val facadeFqName = facadeName?.let { JvmClassName.byInternalName(it).fqNameForTopLevelClassMaybeWithDollars } - val facadeBinaryClass = facadeFqName?.let { kotlinClassFinder.findKotlinClass(ClassId.topLevel(it)) } + val facadeBinaryClass = facadeFqName?.let { + kotlinClassFinder.findKotlinClass(ClassId.topLevel(it), jvmMetadataVersion) + } val moduleData = moduleDataProvider.getModuleData(kotlinJvmBinaryClass.containingLibrary.toPath()) ?: return@mapNotNull null @@ -94,8 +100,11 @@ class JvmClassFileBasedSymbolProvider( private val KotlinJvmBinaryClass.incompatibility: IncompatibleVersionErrorData? get() { // TODO: skipMetadataVersionCheck - if (classHeader.metadataVersion.isCompatible()) return null - return IncompatibleVersionErrorData(classHeader.metadataVersion, JvmMetadataVersion.INSTANCE, location, classId) + val expectedMetadataVersion = session.languageVersionSettings.languageVersion.toMetadataVersion() + if (classHeader.metadataVersion.isCompatible(expectedMetadataVersion)) return null + return IncompatibleVersionErrorData( + classHeader.metadataVersion, maxOf(expectedMetadataVersion, JvmMetadataVersion.INSTANCE.next()), location, classId + ) } private val KotlinJvmBinaryClass.isPreReleaseInvisible: Boolean @@ -105,7 +114,9 @@ class JvmClassFileBasedSymbolProvider( // Kotlin classes are annotated Java classes, so this check also looks for them. if (!javaFacade.hasTopLevelClassOf(classId)) return null - val result = kotlinClassFinder.findKotlinClassOrContent(classId) + val result = kotlinClassFinder.findKotlinClassOrContent( + classId, session.languageVersionSettings.languageVersion.toMetadataVersion() + ) if (result !is KotlinClassFinder.Result.KotlinClass) { if (parentContext != null || (classId.isNestedClass && getClass(classId.outermostClassId)?.fir !is FirJavaClass)) { // Nested class of Kotlin class should have been a Kotlin class. diff --git a/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/FileBasedKotlinClass.java b/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/FileBasedKotlinClass.java index 5d223877927..6947b241729 100644 --- a/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/FileBasedKotlinClass.java +++ b/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/FileBasedKotlinClass.java @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap; import org.jetbrains.kotlin.descriptors.SourceElement; import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader; import org.jetbrains.kotlin.load.kotlin.header.ReadKotlinClassHeaderAnnotationVisitor; +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; @@ -76,6 +77,7 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass { @Nullable public static T create( @NotNull byte[] fileContents, + @NotNull JvmMetadataVersion jvmMetadataVersionFromLanguageVersion, @NotNull Function4 factory ) { ReadKotlinClassHeaderAnnotationVisitor readHeaderVisitor = new ReadKotlinClassHeaderAnnotationVisitor(); @@ -108,7 +110,7 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass { String className = classNameRef.get(); if (className == null) return null; - KotlinClassHeader header = readHeaderVisitor.createHeader(); + KotlinClassHeader header = readHeaderVisitor.createHeader(jvmMetadataVersionFromLanguageVersion); if (header == null) return null; ClassId id = resolveNameByInternalName(className, innerClasses); diff --git a/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt b/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt index b1b4d835478..20a8e335dac 100644 --- a/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt +++ b/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinBinaryClassCache.kt @@ -12,7 +12,7 @@ import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.util.Computable import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiJavaModule -import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import java.lang.ref.WeakReference import java.util.concurrent.CopyOnWriteArrayList @@ -59,8 +59,19 @@ class KotlinBinaryClassCache : Disposable { } companion object { + @Deprecated( + "Please pass jvmMetadataVersion explicitly", + ReplaceWith( + "getKotlinBinaryClassOrClassFileContent(file, JvmMetadataVersion.INSTANCE, fileContent = fileContent)", + "org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion" + ) + ) fun getKotlinBinaryClassOrClassFileContent( - file: VirtualFile, fileContent: ByteArray? = null + file: VirtualFile, fileContent: ByteArray? + ) = getKotlinBinaryClassOrClassFileContent(file, jvmMetadataVersion = JvmMetadataVersion.INSTANCE, fileContent = fileContent) + + fun getKotlinBinaryClassOrClassFileContent( + file: VirtualFile, jvmMetadataVersion: JvmMetadataVersion, fileContent: ByteArray? = null ): KotlinClassFinder.Result? { if (file.extension != JavaClassFileType.INSTANCE.defaultExtension && file.fileType !== JavaClassFileType.INSTANCE @@ -76,7 +87,7 @@ class KotlinBinaryClassCache : Disposable { } val aClass = ApplicationManager.getApplication().runReadAction(Computable { - VirtualFileKotlinClass.create(file, fileContent) + VirtualFileKotlinClass.create(file, jvmMetadataVersion, fileContent) }) return requestCache.cache(file, aClass) diff --git a/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/VirtualFileKotlinClass.kt b/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/VirtualFileKotlinClass.kt index 5c568fb885f..0dc778e6f6f 100644 --- a/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/VirtualFileKotlinClass.kt +++ b/compiler/frontend.common.jvm/src/org/jetbrains/kotlin/load/kotlin/VirtualFileKotlinClass.kt @@ -11,6 +11,7 @@ import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder.Result.KotlinClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.util.PerformanceCounter import java.io.FileNotFoundException @@ -46,14 +47,14 @@ class VirtualFileKotlinClass private constructor( private val LOG = Logger.getInstance(VirtualFileKotlinClass::class.java) private val perfCounter = PerformanceCounter.create("Binary class from Kotlin file") - internal fun create(file: VirtualFile, fileContent: ByteArray?): KotlinClassFinder.Result? { + internal fun create(file: VirtualFile, jvmMetadataVersion: JvmMetadataVersion, fileContent: ByteArray?): KotlinClassFinder.Result? { return perfCounter.time { assert(file.extension == JavaClassFileType.INSTANCE.defaultExtension || file.fileType == JavaClassFileType.INSTANCE) { "Trying to read binary data from a non-class file $file" } try { val byteContent = fileContent ?: file.contentsToByteArray(false) if (byteContent.isNotEmpty()) { - val kotlinJvmBinaryClass = create(byteContent) { name, classVersion, header, innerClasses -> + val kotlinJvmBinaryClass = create(byteContent, jvmMetadataVersion) { name, classVersion, header, innerClasses -> VirtualFileKotlinClass(file, name, classVersion, header, innerClasses) } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/VirtualFileFinder.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/VirtualFileFinder.kt index ab276d14006..4a3b893967f 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/VirtualFileFinder.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/VirtualFileFinder.kt @@ -21,9 +21,9 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.utils.sure @@ -32,12 +32,12 @@ abstract class VirtualFileFinder : KotlinClassFinder { abstract fun findSourceOrBinaryVirtualFile(classId: ClassId): VirtualFile? - override fun findKotlinClassOrContent(classId: ClassId): KotlinClassFinder.Result? { + override fun findKotlinClassOrContent(classId: ClassId, jvmMetadataVersion: JvmMetadataVersion): KotlinClassFinder.Result? { val file = findVirtualFileWithHeader(classId) ?: return null - return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file) + return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file, jvmMetadataVersion) } - override fun findKotlinClassOrContent(javaClass: JavaClass): KotlinClassFinder.Result? { + override fun findKotlinClassOrContent(javaClass: JavaClass, jvmMetadataVersion: JvmMetadataVersion): KotlinClassFinder.Result? { var file = (javaClass as? VirtualFileBoundJavaClass)?.virtualFile ?: return null if (javaClass.outerClass != null) { @@ -46,7 +46,7 @@ abstract class VirtualFileFinder : KotlinClassFinder { file = file.parent!!.findChild(classFileName(javaClass) + ".class").sure { "Virtual file not found for $javaClass" } } - return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file) + return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file, jvmMetadataVersion) } private fun classFileName(jClass: JavaClass): String { 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 5d376c769ee..606c2be21c4 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 @@ -39,6 +39,7 @@ import org.jetbrains.kotlin.serialization.deserialization.DeserializationCompone import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault import org.jetbrains.kotlin.utils.keysToMap class IncrementalPackageFragmentProvider( @@ -94,7 +95,10 @@ class IncrementalPackageFragmentProvider( val partName = JvmClassName.byInternalName(internalName) val jvmBinaryClass = - kotlinClassFinder.findKotlinClass(ClassId.topLevel(partName.fqNameForTopLevelClassMaybeWithDollars)) + kotlinClassFinder.findKotlinClass( + ClassId.topLevel(partName.fqNameForTopLevelClassMaybeWithDollars), + deserializationComponents.configuration.jvmMetadataVersionOrDefault() + ) val metadataVersion = jvmBinaryClass?.classHeader?.metadataVersion diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmCompilerDeserializationConfiguration.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmCompilerDeserializationConfiguration.kt new file mode 100644 index 00000000000..774d80a308c --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/JvmCompilerDeserializationConfiguration.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.jvm + +import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion +import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration +import org.jetbrains.kotlin.utils.toMetadataVersion + +class JvmCompilerDeserializationConfiguration( + languageVersionSettings: LanguageVersionSettings +) : CompilerDeserializationConfiguration(languageVersionSettings) { + override val binaryVersion: JvmMetadataVersion + get() = languageVersionSettings.languageVersion.toMetadataVersion() +} \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/OptionalAnnotationPackageFragmentProvider.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/OptionalAnnotationPackageFragmentProvider.kt index ba2f3821cb5..0b814b104e6 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/OptionalAnnotationPackageFragmentProvider.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/OptionalAnnotationPackageFragmentProvider.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration +import org.jetbrains.kotlin.resolve.jvm.JvmCompilerDeserializationConfiguration import org.jetbrains.kotlin.resolve.sam.SamConversionResolver import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -49,7 +49,7 @@ class OptionalAnnotationPackageFragmentProvider( val classDataFinder = OptionalAnnotationClassDataFinder(optionalAnnotationClasses) val components = storageManager.createLazyValue { DeserializationComponents( - storageManager, module, CompilerDeserializationConfiguration(languageVersionSettings), + storageManager, module, JvmCompilerDeserializationConfiguration(languageVersionSettings), classDataFinder, AnnotationAndConstantLoaderImpl(module, notFoundClasses, serializerProtocol), this, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompilerDeserializationConfiguration.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompilerDeserializationConfiguration.kt index 08ed503963a..e15d1afb274 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompilerDeserializationConfiguration.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompilerDeserializationConfiguration.kt @@ -5,24 +5,26 @@ package org.jetbrains.kotlin.resolve -import org.jetbrains.kotlin.config.AnalysisFlags -import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration -class CompilerDeserializationConfiguration(languageVersionSettings: LanguageVersionSettings) : DeserializationConfiguration { - override val skipMetadataVersionCheck = languageVersionSettings.getFlag(AnalysisFlags.skipMetadataVersionCheck) +open class CompilerDeserializationConfiguration( + protected val languageVersionSettings: LanguageVersionSettings +) : DeserializationConfiguration { - override val skipPrereleaseCheck = languageVersionSettings.getFlag(AnalysisFlags.skipPrereleaseCheck) + final override val skipMetadataVersionCheck = languageVersionSettings.getFlag(AnalysisFlags.skipMetadataVersionCheck) - override val reportErrorsOnPreReleaseDependencies = + final override val skipPrereleaseCheck = languageVersionSettings.getFlag(AnalysisFlags.skipPrereleaseCheck) + + final override val reportErrorsOnPreReleaseDependencies = !skipPrereleaseCheck && !languageVersionSettings.isPreRelease() - override val allowUnstableDependencies = languageVersionSettings.getFlag(AnalysisFlags.allowUnstableDependencies) + final override val allowUnstableDependencies = languageVersionSettings.getFlag(AnalysisFlags.allowUnstableDependencies) - override val typeAliasesAllowed = languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases) + final override val typeAliasesAllowed = languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases) - override val isJvmPackageNameSupported = languageVersionSettings.supportsFeature(LanguageFeature.JvmPackageName) + final override val isJvmPackageNameSupported = languageVersionSettings.supportsFeature(LanguageFeature.JvmPackageName) - override val readDeserializedContracts: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.ReadDeserializedContracts) + final override val readDeserializedContracts: Boolean = + languageVersionSettings.supportsFeature(LanguageFeature.ReadDeserializedContracts) } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt index 69e83c97238..d1fa057606b 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt @@ -32,8 +32,8 @@ import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.compilerRunner.MessageCollectorToOutputItemsCollectorAdapter import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl -import org.jetbrains.kotlin.compilerRunner.SimpleOutputItem import org.jetbrains.kotlin.compilerRunner.toGeneratedFile +import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.LookupTracker @@ -41,9 +41,11 @@ import org.jetbrains.kotlin.incremental.parsing.classesFqNames import org.jetbrains.kotlin.incremental.util.BufferingMessageCollector import org.jetbrains.kotlin.incremental.util.ExceptionLocation import org.jetbrains.kotlin.incremental.util.reportException +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.progress.CompilationCanceledStatus import org.jetbrains.kotlin.util.removeSuffixIfPresent +import org.jetbrains.kotlin.utils.toMetadataVersion import java.io.File abstract class IncrementalCompilerRunner< @@ -411,6 +413,10 @@ abstract class IncrementalCompilerRunner< var exitCode = ExitCode.OK + // TODO: ideally we should read arguments not here but at earlier stages + val jvmMetadataVersionFromLanguageVersion = + LanguageVersion.fromVersionString(args.languageVersion)?.toMetadataVersion() ?: JvmMetadataVersion.INSTANCE + while (dirtySources.any() || runWithNoDirtyKotlinSources(caches)) { val complementaryFiles = caches.platformCache.getComplementaryFilesRecursive(dirtySources) dirtySources.addAll(complementaryFiles) @@ -447,8 +453,9 @@ abstract class IncrementalCompilerRunner< val text = allDirtySources.joinToString(separator = System.getProperty("line.separator")) { it.normalize().absolutePath } dirtySourcesSinceLastTimeFile.writeText(text) - - val generatedFiles = outputItemsCollector.outputs.map(SimpleOutputItem::toGeneratedFile) + val generatedFiles = outputItemsCollector.outputs.map { + it.toGeneratedFile(jvmMetadataVersionFromLanguageVersion) + } if (compilationMode is CompilationMode.Incremental) { // todo: feels dirty, can this be refactored? val dirtySourcesSet = dirtySources.toHashSet() diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt index 822396f93d2..40c5b791b59 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt @@ -40,6 +40,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.configureJdkClasspathRoots import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.IncrementalCompilation +import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotDisabled import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.IncrementalRun.NoChanges @@ -85,8 +86,9 @@ fun makeIncrementally( val buildReporter = BuildReporter(icReporter = reporter, buildMetricsReporter = DoNothingBuildMetricsReporter) withIC(args) { + val useK2 = args.useK2 || LanguageVersion.fromVersionString(args.languageVersion)?.usesK2 == true val compiler = - if (args.useK2 && args.useFirIC && args.useFirLT /* TODO: move LT check into runner */ ) + if (useK2 && args.useFirIC && args.useFirLT /* TODO: move LT check into runner */) IncrementalFirJvmCompilerRunner( cachesDir, buildReporter, @@ -101,7 +103,7 @@ fun makeIncrementally( cachesDir, buildReporter, // Use precise setting in case of non-Gradle build - usePreciseJavaTracking = !args.useK2, // TODO: add fir-based java classes tracker when available and set this to true + usePreciseJavaTracking = !useK2, // TODO: add fir-based java classes tracker when available and set this to true buildHistoryFile = buildHistoryFile, outputDirs = null, modulesApiHistory = EmptyModulesApiHistory, diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfo.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfo.kt index 41403653717..218be6b6797 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfo.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfo.kt @@ -107,5 +107,5 @@ private class KotlinClassHeaderClassVisitor : ClassVisitor(Opcodes.API_VERSION) ) } - fun getKotlinClassHeader(): KotlinClassHeader? = kotlinClassHeaderAnnotationVisitor.createHeader() + fun getKotlinClassHeader(): KotlinClassHeader? = kotlinClassHeaderAnnotationVisitor.createHeaderWithDefaultMetadataVersion() } diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirICLightTreeJvmCompilerRunnerTest.kt b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirICLightTreeJvmCompilerRunnerTest.kt index 08f5b2cd3aa..484b82eb1fc 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirICLightTreeJvmCompilerRunnerTest.kt +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirICLightTreeJvmCompilerRunnerTest.kt @@ -13,6 +13,7 @@ abstract class AbstractIncrementalFirICLightTreeJvmCompilerRunnerTest : Abstract override fun createCompilerArguments(destinationDir: File, testDir: File): K2JVMCompilerArguments = super.createCompilerArguments(destinationDir, testDir).apply { useK2 = true + languageVersion = "2.0" useIR = true useFirIC = true useFirLT = true diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirJvmCompilerRunnerTest.kt b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirJvmCompilerRunnerTest.kt index 04d8fa18568..09aa2e40b6b 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirJvmCompilerRunnerTest.kt +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirJvmCompilerRunnerTest.kt @@ -24,6 +24,7 @@ abstract class AbstractIncrementalFirJvmCompilerRunnerTest : AbstractIncremental override fun createCompilerArguments(destinationDir: File, testDir: File): K2JVMCompilerArguments = super.createCompilerArguments(destinationDir, testDir).apply { useK2 = true + languageVersion = "2.0" useIR = true } diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirLightTreeJvmCompilerRunnerTest.kt b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirLightTreeJvmCompilerRunnerTest.kt index cbed336c9d9..799f19d707c 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirLightTreeJvmCompilerRunnerTest.kt +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/AbstractIncrementalFirLightTreeJvmCompilerRunnerTest.kt @@ -13,6 +13,7 @@ abstract class AbstractIncrementalFirLightTreeJvmCompilerRunnerTest : AbstractIn override fun createCompilerArguments(destinationDir: File, testDir: File): K2JVMCompilerArguments = super.createCompilerArguments(destinationDir, testDir).apply { useK2 = true + languageVersion = "2.0" useIR = true useFirIC = false useFirLT = true diff --git a/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt index c8df70c3a30..3282e80af21 100644 --- a/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt +++ b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMemberSignature +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.tree.MethodNode @@ -213,7 +214,9 @@ object InlineTestUtil { } private fun loadBinaryClass(file: OutputFile): KotlinJvmBinaryClass = - FileBasedKotlinClass.create(file.asByteArray()) { className, classVersion, classHeader, innerClasses -> + FileBasedKotlinClass.create( + file.asByteArray(), JvmMetadataVersion.INSTANCE + ) { className, classVersion, classHeader, innerClasses -> object : FileBasedKotlinClass(className, classVersion, classHeader, innerClasses) { override val location: String get() = throw UnsupportedOperationException() diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFirUsingFlag/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFirUsingFlag/library/a.kt new file mode 100644 index 00000000000..71e3e5d293d --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFirUsingFlag/library/a.kt @@ -0,0 +1,5 @@ +package lib + +class Box(val value: String) + +inline fun get(block: () -> T): T = block() diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFirUsingFlag/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFirUsingFlag/output.txt new file mode 100644 index 00000000000..63445d07c89 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFirUsingFlag/output.txt @@ -0,0 +1,2 @@ +warning: compiler flag -Xuse-k2 is deprecated, please use -language-version 2.0 instead +OK diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFirUsingFlag/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFirUsingFlag/source.kt new file mode 100644 index 00000000000..ffadd735100 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFirUsingFlag/source.kt @@ -0,0 +1,5 @@ +import lib.* + +fun main() { + get { Box("OK").value } +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/JvmModuleProtoBufTest.kt b/compiler/tests/org/jetbrains/kotlin/codegen/JvmModuleProtoBufTest.kt index 3be50f4eb8d..be4deadbc3a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/JvmModuleProtoBufTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/codegen/JvmModuleProtoBufTest.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.load.kotlin.loadModuleMapping import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping -import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration +import org.jetbrains.kotlin.resolve.jvm.JvmCompilerDeserializationConfiguration import org.jetbrains.kotlin.test.CompilerTestUtil import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase @@ -51,7 +51,7 @@ class JvmModuleProtoBufTest : KtUsefulTestCase() { val mapping = ModuleMapping.loadModuleMapping( File(tmpdir, "META-INF/$moduleName.${ModuleMapping.MAPPING_FILE_EXT}").readBytes(), "test", - CompilerDeserializationConfiguration(LanguageVersionSettingsImpl(loadWith, ApiVersion.createByLanguageVersion(loadWith))), + JvmCompilerDeserializationConfiguration(LanguageVersionSettingsImpl(loadWith, ApiVersion.createByLanguageVersion(loadWith))), ::error ) val result = buildString { diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java index 6c0798324e0..7549996f311 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/KotlinSyntheticClassAnnotationTest.java @@ -143,7 +143,7 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { int[] version = (int[]) CodegenTestUtil.getAnnotationAttribute(annotation, METADATA_VERSION_FIELD_NAME); assertNotNull(version); assertTrue("Annotation " + annotationFqName + " is written with an unsupported format", - new JvmMetadataVersion(version).isCompatible()); + new JvmMetadataVersion(version).isCompatibleWithCurrentCompilerVersion()); } @NotNull diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index e7828794652..2dc03d6de7e 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.MockLibraryUtil import org.jetbrains.kotlin.test.TestJdkKind import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparatorAdaptor.validateAndCompareDescriptorWithFile +import org.jetbrains.kotlin.utils.toMetadataVersion import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.tree.ClassNode import java.io.ByteArrayInputStream @@ -388,7 +389,7 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration } fun testStrictMetadataVersionSemanticsOldVersion() { - val nextMetadataVersion = JvmMetadataVersion(JvmMetadataVersion.INSTANCE.major, JvmMetadataVersion.INSTANCE.minor + 1, 0) + val nextMetadataVersion = JvmMetadataVersion.INSTANCE.next() val library = compileLibrary( "library", additionalOptions = listOf("-Xgenerate-strict-metadata-version", "-Xmetadata-version=$nextMetadataVersion") ) @@ -409,7 +410,7 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration val expectedMajor = if (languageVersion.usesK2) 2 else 1 val expectedMinor = if (languageVersion < LanguageVersion.KOTLIN_1_4) 1 else languageVersion.minor - val topLevelClass = LocalFileKotlinClass.create(File(tmpdir.absolutePath, "Foo.class"))!! + val topLevelClass = LocalFileKotlinClass.create(File(tmpdir.absolutePath, "Foo.class"), languageVersion.toMetadataVersion())!! val classVersion = topLevelClass.classHeader.metadataVersion assertEquals("Actual version: $classVersion", expectedMajor, classVersion.major) assertEquals("Actual version: $classVersion", expectedMinor, classVersion.minor) @@ -641,6 +642,11 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration } } + fun testFirAgainstFirUsingFlag() { + val library = compileLibrary("library", additionalOptions = listOf("-language-version", "2.0")) + compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xuse-k2")) + } + fun testFirAgainstFir() { val library = compileLibrary("library", additionalOptions = listOf("-language-version", "2.0")) compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-language-version", "2.0")) @@ -691,6 +697,8 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration } fun testOldJvmAgainstFirWithStableAbi() { + // TODO: looks like now it's not possible to compile library with version 2.0 to be able to compile against it without additional flags + // Should we delete this test? val library = compileLibrary("library", additionalOptions = listOf("-language-version", "2.0", "-Xabi-stability=stable")) compileKotlin("source.kt", tmpdir, listOf(library)) } diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/KotlinClassFinderTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/KotlinClassFinderTest.kt index 11b45706bbe..88bc75034d5 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/KotlinClassFinderTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/KotlinClassFinderTest.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder import org.jetbrains.kotlin.load.kotlin.findKotlinClass +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.KotlinTestUtils @@ -49,7 +50,7 @@ class KotlinClassFinderTest : KotlinTestWithEnvironmentManagement() { fun testNestedClass() { val tmpdir = KotlinTestUtils.tmpDirForTest(this) KotlinTestUtils.compileKotlinWithJava( - listOf(), listOf(File("compiler/testData/kotlinClassFinder/nestedClass.kt")), tmpdir, testRootDisposable, null + listOf(), listOf(File("compiler/testData/kotlinClassFinder/nestedClass.kt")), tmpdir, testRootDisposable, null ) val environment = createEnvironment(tmpdir) @@ -60,7 +61,9 @@ class KotlinClassFinderTest : KotlinTestWithEnvironmentManagement() { assertNotNull(psiClass, "Psi class not found for $className") assertTrue(psiClass !is KtLightClass, "Kotlin light classes are not not expected") - val binaryClass = VirtualFileFinder.SERVICE.getInstance(project).findKotlinClass(JavaClassImpl(psiClass)) + val binaryClass = VirtualFileFinder.SERVICE.getInstance(project).findKotlinClass( + JavaClassImpl(psiClass), JvmMetadataVersion.INSTANCE + ) assertNotNull(binaryClass, "No binary class for $className") assertEquals("test/A.B.C", binaryClass.classId.toString()) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/KotlinJavacBasedClassFinderTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/KotlinJavacBasedClassFinderTest.kt index f81fb3ba4ba..dd4110a1d9e 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/KotlinJavacBasedClassFinderTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/KotlinJavacBasedClassFinderTest.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.javac.JavacWrapper import org.jetbrains.kotlin.javac.components.JavacBasedClassFinder import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder import org.jetbrains.kotlin.load.kotlin.findKotlinClass +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil @@ -66,7 +67,7 @@ class KotlinJavacBasedClassFinderTest : KotlinTestWithEnvironmentManagement() { val found = classFinder.findClass(classId) assertNotNull(found, "Class not found for $className") - val binaryClass = VirtualFileFinder.SERVICE.getInstance(project).findKotlinClass(found) + val binaryClass = VirtualFileFinder.SERVICE.getInstance(project).findKotlinClass(found, JvmMetadataVersion.INSTANCE) assertNotNull(binaryClass, "No binary class for $className") assertEquals("test/A.B.C", binaryClass.classId.toString()) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageFragment.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageFragment.kt index dc8c45ec080..4039d96e164 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageFragment.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageFragment.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.storage.getValue +import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault class LazyJavaPackageFragment( outerContext: LazyJavaResolverContext, @@ -39,10 +40,13 @@ class LazyJavaPackageFragment( ) : PackageFragmentDescriptorImpl(outerContext.module, jPackage.fqName) { private val c = outerContext.childForClassOrPackage(this) + private val jvmMetadataVersion = + outerContext.components.deserializedDescriptorResolver.components.configuration.jvmMetadataVersionOrDefault() + internal val binaryClasses by c.storageManager.createLazyValue { c.components.packagePartProvider.findPackageParts(fqName.asString()).mapNotNull { partName -> val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars) - c.components.kotlinClassFinder.findKotlinClass(classId)?.let { partName to it } + c.components.kotlinClassFinder.findKotlinClass(classId, jvmMetadataVersion)?.let { partName to it } }.toMap() } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt index b8287f4df28..4efe3d6d295 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaPackageScope.kt @@ -30,12 +30,14 @@ import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.findKotlinClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.storage.NullableLazyValue import org.jetbrains.kotlin.utils.alwaysTrue +import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault import java.util.* class LazyJavaPackageScope( @@ -49,6 +51,10 @@ class LazyJavaPackageScope( c.components.finder.knownClassNamesInPackage(ownerDescriptor.fqName) } + private val jvmMetadataVersion: JvmMetadataVersion + get() = c.components.deserializedDescriptorResolver.components.configuration.jvmMetadataVersionOrDefault() + + private val classes = c.storageManager.createMemoizedFunctionWithNullableValues classByRequest@{ request -> val requestClassId = ClassId(ownerDescriptor.fqName, request.name) @@ -56,9 +62,9 @@ class LazyJavaPackageScope( val kotlinClassOrClassFileContent = // These branches should be semantically equal, but the first one could be faster if (request.javaClass != null) - c.components.kotlinClassFinder.findKotlinClassOrContent(request.javaClass) + c.components.kotlinClassFinder.findKotlinClassOrContent(request.javaClass, jvmMetadataVersion) else - c.components.kotlinClassFinder.findKotlinClassOrContent(requestClassId) + c.components.kotlinClassFinder.findKotlinClassOrContent(requestClassId, jvmMetadataVersion) val kotlinBinaryClass = kotlinClassOrClassFileContent?.toKotlinJvmBinaryClass() @@ -84,8 +90,8 @@ class LazyJavaPackageScope( "Couldn't find kotlin binary class for light class created by kotlin binary file\n" + "JavaClass: $javaClass\n" + "ClassId: $requestClassId\n" + - "findKotlinClass(JavaClass) = ${c.components.kotlinClassFinder.findKotlinClass(javaClass)}\n" + - "findKotlinClass(ClassId) = ${c.components.kotlinClassFinder.findKotlinClass(requestClassId)}\n" + "findKotlinClass(JavaClass) = ${c.components.kotlinClassFinder.findKotlinClass(javaClass, jvmMetadataVersion)}\n" + + "findKotlinClass(ClassId) = ${c.components.kotlinClassFinder.findKotlinClass(requestClassId, jvmMetadataVersion)}\n" ) } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt index 02e13c390cd..7cea5104f2c 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.NameResolver +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -33,6 +34,8 @@ class BinaryClassAnnotationAndConstantLoaderImpl( ) { private val annotationDeserializer = AnnotationDeserializer(module, notFoundClasses) + override var jvmMetadataVersion: JvmMetadataVersion = JvmMetadataVersion.INSTANCE + override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor = annotationDeserializer.deserializeAnnotation(proto, nameResolver) @@ -224,3 +227,18 @@ class BinaryClassAnnotationAndConstantLoaderImpl( return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses) } } + +// Note: this function is needed because we cannot pass JvmMetadataVersion +// directly to the BinaryClassAnnotationAndConstantLoaderImpl constructor. +// This constructor is used by dependency injection. +fun createBinaryClassAnnotationAndConstantLoader( + module: ModuleDescriptor, + notFoundClasses: NotFoundClasses, + storageManager: StorageManager, + kotlinClassFinder: KotlinClassFinder, + jvmMetadataVersion: JvmMetadataVersion +): BinaryClassAnnotationAndConstantLoaderImpl = BinaryClassAnnotationAndConstantLoaderImpl( + module, notFoundClasses, storageManager, kotlinClassFinder +).apply { + this.jvmMetadataVersion = jvmMetadataVersion +} diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt index e504f8c50fd..d67c1776124 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializationComponentsForJava.kt @@ -40,6 +40,7 @@ import org.jetbrains.kotlin.load.java.sources.JavaSourceElementFactory import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.typeEnhancement.JavaTypeEnhancement import org.jetbrains.kotlin.load.java.typeEnhancement.SignatureEnhancement +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -122,7 +123,7 @@ class DeserializationComponentsForJava( val deserializationComponentsForJava = makeDeserializationComponentsForJava( module, storageManager, notFoundClasses, lazyJavaPackageFragmentProvider, - kotlinClassFinder, deserializedDescriptorResolver, errorReporter + kotlinClassFinder, deserializedDescriptorResolver, errorReporter, JvmMetadataVersion.INSTANCE ) deserializedDescriptorResolver.setComponents(deserializationComponentsForJava) @@ -183,11 +184,12 @@ fun makeDeserializationComponentsForJava( lazyJavaPackageFragmentProvider: LazyJavaPackageFragmentProvider, reflectKotlinClassFinder: KotlinClassFinder, deserializedDescriptorResolver: DeserializedDescriptorResolver, - errorReporter: ErrorReporter + errorReporter: ErrorReporter, + jvmMetadataVersion: JvmMetadataVersion ): DeserializationComponentsForJava { val javaClassDataFinder = JavaClassDataFinder(reflectKotlinClassFinder, deserializedDescriptorResolver) - val binaryClassAnnotationAndConstantLoader = BinaryClassAnnotationAndConstantLoaderImpl( - module, notFoundClasses, storageManager, reflectKotlinClassFinder + val binaryClassAnnotationAndConstantLoader = createBinaryClassAnnotationAndConstantLoader( + module, notFoundClasses, storageManager, reflectKotlinClassFinder, jvmMetadataVersion ) return DeserializationComponentsForJava( storageManager, module, DeserializationConfiguration.Default, javaClassDataFinder, diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt index 92cddcb35af..a9acbaa0cbf 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt @@ -28,11 +28,14 @@ import org.jetbrains.kotlin.serialization.deserialization.DeserializationCompone import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope +import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault import javax.inject.Inject class DeserializedDescriptorResolver { lateinit var components: DeserializationComponents + private val ownMetadataVersion: JvmMetadataVersion get() = components.configuration.jvmMetadataVersionOrDefault() + // component dependency cycle @Inject fun setComponents(components: DeserializationComponentsForJava) { @@ -80,8 +83,10 @@ class DeserializedDescriptorResolver { private val KotlinJvmBinaryClass.incompatibility: IncompatibleVersionErrorData? get() { - if (skipMetadataVersionCheck || classHeader.metadataVersion.isCompatible()) return null - return IncompatibleVersionErrorData(classHeader.metadataVersion, JvmMetadataVersion.INSTANCE, location, classId) + if (skipMetadataVersionCheck || classHeader.metadataVersion.isCompatible(ownMetadataVersion)) return null + return IncompatibleVersionErrorData( + classHeader.metadataVersion, maxOf(ownMetadataVersion.prev(), JvmMetadataVersion.INSTANCE), location, classId + ) } /** @@ -120,7 +125,7 @@ class DeserializedDescriptorResolver { throw IllegalStateException("Could not read data from ${klass.location}", e) } } catch (e: Throwable) { - if (skipMetadataVersionCheck || klass.classHeader.metadataVersion.isCompatible()) { + if (skipMetadataVersionCheck || klass.classHeader.metadataVersion.isCompatible(ownMetadataVersion)) { throw e } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt index 2b963c95b68..09cca102c5c 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/JavaClassDataFinder.kt @@ -19,13 +19,16 @@ package org.jetbrains.kotlin.load.kotlin import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.serialization.deserialization.ClassData import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder +import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault class JavaClassDataFinder( internal val kotlinClassFinder: KotlinClassFinder, private val deserializedDescriptorResolver: DeserializedDescriptorResolver ) : ClassDataFinder { override fun findClassData(classId: ClassId): ClassData? { - val kotlinClass = kotlinClassFinder.findKotlinClass(classId) ?: return null + val kotlinClass = kotlinClassFinder.findKotlinClass( + classId, deserializedDescriptorResolver.components.configuration.jvmMetadataVersionOrDefault() + ) ?: return null assert(kotlinClass.classId == classId) { "Class with incorrect id found: expected $classId, actual ${kotlinClass.classId}" } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/ModuleMappingUtil.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/ModuleMappingUtil.kt index 191ea2c0bfe..3ee62701a50 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/ModuleMappingUtil.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/ModuleMappingUtil.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.load.kotlin import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration +import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault fun ModuleMapping.Companion.loadModuleMapping( bytes: ByteArray?, @@ -20,5 +21,6 @@ fun ModuleMapping.Companion.loadModuleMapping( debugName, configuration.skipMetadataVersionCheck, configuration.isJvmPackageNameSupported, + configuration.jvmMetadataVersionOrDefault(), reportIncompatibleVersionError ) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java index c8aee757989..5a5cf0131ba 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java @@ -61,7 +61,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor private String[] serializedIrFields = null; @Nullable - public KotlinClassHeader createHeader() { + public KotlinClassHeader createHeaderWithDefaultMetadataVersion() { + return createHeader(JvmMetadataVersion.INSTANCE); + } + + @Nullable + public KotlinClassHeader createHeader(JvmMetadataVersion metadataVersionFromLanguageVersion) { if (headerKind == null || metadataVersionArray == null) { return null; } @@ -69,7 +74,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor JvmMetadataVersion metadataVersion = new JvmMetadataVersion(metadataVersionArray, (extraInt & JvmAnnotationNames.METADATA_STRICT_VERSION_SEMANTICS_FLAG) != 0); - if (!metadataVersion.isCompatible()) { + if (!metadataVersion.isCompatible(metadataVersionFromLanguageVersion)) { incompatibleData = data; data = null; } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/utils/deserializationHelpers.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/utils/deserializationHelpers.kt new file mode 100644 index 00000000000..2f83a2b2d1e --- /dev/null +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/utils/deserializationHelpers.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.utils + +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion +import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration + +fun DeserializationConfiguration.jvmMetadataVersionOrDefault(): JvmMetadataVersion = + binaryVersion as? JvmMetadataVersion ?: JvmMetadataVersion.INSTANCE \ No newline at end of file diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/PackagePartScopeCache.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/PackagePartScopeCache.kt index 4c3d7f4412b..b0ad87d7244 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/PackagePartScopeCache.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/PackagePartScopeCache.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.utils.jvmMetadataVersionOrDefault import java.util.concurrent.ConcurrentHashMap class PackagePartScopeCache(private val resolver: DeserializedDescriptorResolver, private val kotlinClassFinder: ReflectKotlinClassFinder) { @@ -25,7 +26,7 @@ class PackagePartScopeCache(private val resolver: DeserializedDescriptorResolver if (fileClass.classHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS) fileClass.classHeader.multifilePartNames.mapNotNull { partName -> val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars) - kotlinClassFinder.findKotlinClass(classId) + kotlinClassFinder.findKotlinClass(classId, resolver.components.configuration.jvmMetadataVersionOrDefault()) } else listOf(fileClass) diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/ReflectKotlinClass.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/ReflectKotlinClass.kt index 41e246c4318..10b87618006 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/ReflectKotlinClass.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/ReflectKotlinClass.kt @@ -54,7 +54,7 @@ class ReflectKotlinClass private constructor( fun create(klass: Class<*>): ReflectKotlinClass? { val headerReader = ReadKotlinClassHeaderAnnotationVisitor() ReflectClassStructure.loadClassAnnotations(klass, headerReader) - return ReflectKotlinClass(klass, headerReader.createHeader() ?: return null) + return ReflectKotlinClass(klass, headerReader.createHeaderWithDefaultMetadataVersion() ?: return null) } } diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/ReflectKotlinClassFinder.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/ReflectKotlinClassFinder.kt index 674a9f64999..3f273db94f6 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/ReflectKotlinClassFinder.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/components/ReflectKotlinClassFinder.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder.Result.KotlinClass +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol @@ -33,9 +34,10 @@ class ReflectKotlinClassFinder(private val classLoader: ClassLoader) : KotlinCla return classLoader.tryLoadClass(fqName)?.let { ReflectKotlinClass.create(it) }?.let(::KotlinClass) } - override fun findKotlinClassOrContent(classId: ClassId) = findKotlinClass(classId.toRuntimeFqName()) + override fun findKotlinClassOrContent(classId: ClassId, jvmMetadataVersion: JvmMetadataVersion) = + findKotlinClass(classId.toRuntimeFqName()) - override fun findKotlinClassOrContent(javaClass: JavaClass): KotlinClassFinder.Result? { + override fun findKotlinClassOrContent(javaClass: JavaClass, jvmMetadataVersion: JvmMetadataVersion): KotlinClassFinder.Result? { // TODO: go through javaClass's class loader return findKotlinClass(javaClass.fqName?.asString() ?: return null) } diff --git a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationLoader.kt b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationLoader.kt index 24f634abeca..e455d3b3d65 100644 --- a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationLoader.kt +++ b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationLoader.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.metadata.deserialization.* import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf.propertySignature import org.jetbrains.kotlin.metadata.jvm.deserialization.ClassMapperLite +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -25,6 +26,8 @@ import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer abstract class AbstractBinaryClassAnnotationLoader>( protected val kotlinClassFinder: KotlinClassFinder ) : AnnotationLoader { + abstract val jvmMetadataVersion: JvmMetadataVersion + protected abstract fun getAnnotationsContainer(binaryClass: KotlinJvmBinaryClass): S protected abstract fun loadAnnotation( @@ -220,7 +223,8 @@ abstract class AbstractBinaryClassAnnotationLoader M - major == INSTANCE.major && minor <= INSTANCE.minor + 1 || - major == 2 && INSTANCE.major == 1 && minor == 9 || - major < INSTANCE.major - } + if (major == 1 && minor == 0) return false + // The same for 0.* + if (major == 0) return false + // Otherwise we just compare with the given limitVersion + return this <= limitVersion + } + + fun next(): JvmMetadataVersion { + if (minor < 9 || major > 1) return JvmMetadataVersion(major, minor + 1, 0) + return JvmMetadataVersion(2, 0, 0) + } + + fun prev(): JvmMetadataVersion { + if (minor > 0) return JvmMetadataVersion(major, minor - 1, 0) + return JvmMetadataVersion(major - 1, 9, 0) + } companion object { @JvmField val INSTANCE = JvmMetadataVersion(1, 8, 0) + private val INSTANCE_NEXT = INSTANCE.next() + @JvmField val INVALID_VERSION = JvmMetadataVersion() } diff --git a/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/ModuleMapping.kt b/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/ModuleMapping.kt index 5d8de440f1f..43258009c81 100644 --- a/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/ModuleMapping.kt +++ b/core/metadata.jvm/src/org/jetbrains/kotlin/metadata/jvm/deserialization/ModuleMapping.kt @@ -53,6 +53,7 @@ class ModuleMapping private constructor( debugName: String, skipMetadataVersionCheck: Boolean, isJvmPackageNameSupported: Boolean, + metadataVersionFromLanguageVersion: JvmMetadataVersion, reportIncompatibleVersionError: (JvmMetadataVersion) -> Unit, ): ModuleMapping { if (bytes == null) { @@ -63,7 +64,7 @@ class ModuleMapping private constructor( val versionNumber = readVersionNumber(stream) ?: return CORRUPTED val preVersion = JvmMetadataVersion(*versionNumber) - if (!skipMetadataVersionCheck && !preVersion.isCompatible()) { + if (!skipMetadataVersionCheck && !preVersion.isCompatible(metadataVersionFromLanguageVersion)) { reportIncompatibleVersionError(preVersion) return EMPTY } @@ -72,7 +73,7 @@ class ModuleMapping private constructor( val flags = if (isKotlin1Dot4OrLater(preVersion)) stream.readInt() else 0 val version = JvmMetadataVersion(versionNumber, (flags and STRICT_METADATA_VERSION_SEMANTICS_FLAG) != 0) - if (!skipMetadataVersionCheck && !version.isCompatible()) { + if (!skipMetadataVersionCheck && !version.isCompatible(metadataVersionFromLanguageVersion)) { reportIncompatibleVersionError(version) return EMPTY } diff --git a/core/metadata/src/org/jetbrains/kotlin/metadata/deserialization/BinaryVersion.kt b/core/metadata/src/org/jetbrains/kotlin/metadata/deserialization/BinaryVersion.kt index 1106ff859b9..e2ad65fddc3 100644 --- a/core/metadata/src/org/jetbrains/kotlin/metadata/deserialization/BinaryVersion.kt +++ b/core/metadata/src/org/jetbrains/kotlin/metadata/deserialization/BinaryVersion.kt @@ -14,7 +14,7 @@ package org.jetbrains.kotlin.metadata.deserialization * - 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 binaries which is both forward- and backward compatible. */ -abstract class BinaryVersion(private vararg val numbers: Int) { +abstract class BinaryVersion(private vararg val numbers: Int) : Comparable { val major: Int = numbers.getOrNull(0) ?: UNKNOWN val minor: Int = numbers.getOrNull(1) ?: UNKNOWN val patch: Int = numbers.getOrNull(2) ?: UNKNOWN @@ -87,6 +87,18 @@ abstract class BinaryVersion(private vararg val numbers: Int) { return result } + override fun compareTo(other: BinaryVersion): Int { + return when { + major > other.major -> 1 + major < other.major -> -1 + minor > other.minor -> 1 + minor < other.minor -> -1 + patch > other.patch -> 1 + patch < other.patch -> -1 + else -> 0 + } + } + companion object { const val MAX_LENGTH = 1024 private const val UNKNOWN = -1 diff --git a/jps/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/incremental/AbstractJvmProtoComparisonTest.kt b/jps/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/incremental/AbstractJvmProtoComparisonTest.kt index 3e0be6a8cf2..e075a91b6f1 100644 --- a/jps/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/incremental/AbstractJvmProtoComparisonTest.kt +++ b/jps/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/incremental/AbstractJvmProtoComparisonTest.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.incremental.storage.ProtoMapValue import org.jetbrains.kotlin.incremental.toProtoData import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.metadata.jvm.deserialization.BitEncoding +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.test.MockLibraryUtil import java.io.File @@ -31,12 +32,12 @@ abstract class AbstractJvmProtoComparisonTest : AbstractProtoComparisonTest ([B)V + public fun ([BLkotlinx/metadata/internal/metadata/jvm/deserialization/JvmMetadataVersion;)V public final fun accept (Lkotlinx/metadata/jvm/KmModuleVisitor;)V public final fun getBytes ()[B public static final fun read ([B)Lkotlinx/metadata/jvm/KotlinModuleMetadata; diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt index 6bd65c7842c..26b81bb2fe3 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinClassMetadata.kt @@ -445,7 +445,7 @@ sealed class KotlinClassMetadata(val annotationData: Metadata) { if (!JvmMetadataVersion( annotationData.metadataVersion, (annotationData.extraInt and (1 shl 3)/* see JvmAnnotationNames.METADATA_STRICT_VERSION_SEMANTICS_FLAG */) != 0 - ).isCompatible() + ).isCompatibleWithCurrentCompilerVersion() ) return null return try { diff --git a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt index 70c97fb3f30..bcf5bd011b9 100644 --- a/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt +++ b/libraries/kotlinx-metadata/jvm/src/kotlinx/metadata/jvm/KotlinModuleMetadata.kt @@ -25,9 +25,13 @@ import org.jetbrains.kotlin.metadata.jvm.deserialization.serializeToByteArray * * @property bytes the byte array representing the contents of a `.kotlin_module` file */ -class KotlinModuleMetadata(@Suppress("CanBeParameter", "MemberVisibilityCanBePrivate") val bytes: ByteArray) { - @get:IgnoreInApiDump internal val data: ModuleMapping = ModuleMapping.loadModuleMapping( - bytes, javaClass.name, skipMetadataVersionCheck = false, isJvmPackageNameSupported = true +class KotlinModuleMetadata(@Suppress("MemberVisibilityCanBePrivate") val bytes: ByteArray, jvmMetadataVersion: JvmMetadataVersion) { + @get:IgnoreInApiDump + internal val data: ModuleMapping = ModuleMapping.loadModuleMapping( + bytes, javaClass.name, + skipMetadataVersionCheck = false, + isJvmPackageNameSupported = true, + metadataVersionFromLanguageVersion = jvmMetadataVersion ) { // TODO: report incorrect versions of modules } @@ -86,7 +90,7 @@ class KotlinModuleMetadata(@Suppress("CanBeParameter", "MemberVisibilityCanBePri */ @Deprecated("Writer API is deprecated as excessive and cumbersome. Please use KotlinModuleMetadata.write(kmModule, metadataVersion)") fun write(metadataVersion: IntArray = COMPATIBLE_METADATA_VERSION): KotlinModuleMetadata = - KotlinModuleMetadata(b.build().serializeToByteArray(JvmMetadataVersion(*metadataVersion), 0)) + KotlinModuleMetadata(b.build().serializeToByteArray(JvmMetadataVersion(*metadataVersion), 0), jvmMetadataVersion) } /** @@ -125,7 +129,7 @@ class KotlinModuleMetadata(@Suppress("CanBeParameter", "MemberVisibilityCanBePri @JvmStatic fun read(bytes: ByteArray): KotlinModuleMetadata? { try { - val result = KotlinModuleMetadata(bytes) + val result = KotlinModuleMetadata(bytes, JvmMetadataVersion.INSTANCE) if (result.data == ModuleMapping.EMPTY) return null if (result.data == ModuleMapping.CORRUPTED) { diff --git a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiAnalysisHandlerExtension.kt b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiAnalysisHandlerExtension.kt index 9450979783c..5d365d53163 100644 --- a/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiAnalysisHandlerExtension.kt +++ b/plugins/jvm-abi-gen/src/org/jetbrains/kotlin/jvm/abi/JvmAbiAnalysisHandlerExtension.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.compilerRunner.OutputItemsCollector import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.incremental.isClassFile @@ -37,6 +38,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension +import org.jetbrains.kotlin.utils.toMetadataVersion import org.jetbrains.org.objectweb.asm.ClassReader import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.ClassWriter @@ -124,7 +126,7 @@ class JvmAbiAnalysisHandlerExtension( for (output in outputs) { if (!output.file.isClassFile()) continue - val classData = output.classData() ?: continue + val classData = output.classData(compilerConfiguration) ?: continue val header = classData.classHeader val isNeededForAbi = when (header.kind) { KotlinClassHeader.Kind.CLASS -> { @@ -198,11 +200,13 @@ class JvmAbiAnalysisHandlerExtension( // null bytes means that file should not be written private var bytes: ByteArray? ) { - fun classData(): ClassData? = + fun classData(compilerConfiguration: CompilerConfiguration): ClassData? = when { bytes == null -> null !file.isClassFile() -> null - else -> FileBasedKotlinClass.create(bytes!!) { classId, classVersion, classHeader, _ -> + else -> FileBasedKotlinClass.create( + bytes!!, compilerConfiguration.languageVersionSettings.languageVersion.toMetadataVersion() + ) { classId, classVersion, classHeader, _ -> ClassData(classId, classVersion, classHeader) } } diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/PackageFragmentFromClassLoaderProvider.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/PackageFragmentFromClassLoaderProvider.kt index cc2551d4183..187ffcd7b71 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/PackageFragmentFromClassLoaderProvider.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/PackageFragmentFromClassLoaderProvider.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.utils.toMetadataVersion import kotlin.script.experimental.api.ScriptCompilationConfiguration import kotlin.script.experimental.jvm.ClassLoaderByConfiguration @@ -45,10 +46,11 @@ class PackageFragmentFromClassLoaderProviderExtension( val deserializedDescriptorResolver = DeserializedDescriptorResolver() val singleModuleClassResolver = SingleModuleClassResolver() val notFoundClasses = NotFoundClasses(storageManager, module) + val languageVersionSettings = compilerConfiguration.languageVersionSettings val packagePartProvider = PackagePartFromClassLoaderProvider( classLoader, - compilerConfiguration.languageVersionSettings, + languageVersionSettings, compilerConfiguration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]!! ) @@ -63,7 +65,8 @@ class PackageFragmentFromClassLoaderProviderExtension( val deserializationComponentsForJava = makeDeserializationComponentsForJava( module, storageManager, notFoundClasses, lazyJavaPackageFragmentProvider, - reflectKotlinClassFinder, deserializedDescriptorResolver, RuntimeErrorReporter + reflectKotlinClassFinder, deserializedDescriptorResolver, RuntimeErrorReporter, + languageVersionSettings.languageVersion.toMetadataVersion() ) deserializedDescriptorResolver.setComponents(deserializationComponentsForJava) diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/PackagePartFromClassLoaderProvider.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/PackagePartFromClassLoaderProvider.kt index 75ccd4447c4..bab265dc081 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/PackagePartFromClassLoaderProvider.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/PackagePartFromClassLoaderProvider.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.tryLoadModuleMapping import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.load.kotlin.JvmPackagePartProviderBase import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping -import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration +import org.jetbrains.kotlin.resolve.jvm.JvmCompilerDeserializationConfiguration import kotlin.script.experimental.jvm.util.forAllMatchingFiles class PackagePartFromClassLoaderProvider( @@ -19,7 +19,7 @@ class PackagePartFromClassLoaderProvider( languageVersionSettings: LanguageVersionSettings, messageCollector: MessageCollector ) : JvmPackagePartProviderBase() { - override val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings) + override val deserializationConfiguration = JvmCompilerDeserializationConfiguration(languageVersionSettings) override val loadedModules: MutableList> = SmartList()