IDE: Don't analyze incompatible KLIBs with components
Issue #KT-36213
This commit is contained in:
+3
-31
@@ -16,8 +16,6 @@ import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters
|
||||
import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters
|
||||
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.metadataVersion
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
@@ -25,6 +23,7 @@ import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.SdkInfo
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.BuiltInsCacheKey
|
||||
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
|
||||
import org.jetbrains.kotlin.idea.klib.getCompatibilityInfo
|
||||
import org.jetbrains.kotlin.idea.util.IJLoggerAdapter
|
||||
import org.jetbrains.kotlin.library.*
|
||||
import org.jetbrains.kotlin.platform.CommonPlatforms
|
||||
@@ -83,50 +82,23 @@ class CommonPlatformKindResolution : IdePlatformKindResolution {
|
||||
// TODO(dsavvinov): unify with NativeLibraryInfo
|
||||
class CommonKlibLibraryInfo(project: Project, library: Library, val libraryRoot: String) : LibraryInfo(project, library) {
|
||||
|
||||
sealed class MetadataInfo {
|
||||
abstract val isCompatible: Boolean
|
||||
|
||||
object Compatible : MetadataInfo() {
|
||||
override val isCompatible get() = true
|
||||
}
|
||||
|
||||
class Incompatible(val isOlder: Boolean) : MetadataInfo() {
|
||||
override val isCompatible get() = false
|
||||
}
|
||||
}
|
||||
|
||||
val commonLibrary = resolveSingleFileKlib(
|
||||
libraryFile = KFile(libraryRoot),
|
||||
logger = LOG,
|
||||
strategy = ToolingSingleFileKlibResolveStrategy
|
||||
)
|
||||
|
||||
val metadataInfo by lazy {
|
||||
val metadataVersion = commonLibrary.safeMetadataVersion
|
||||
when {
|
||||
metadataVersion == null -> MetadataInfo.Incompatible(true) // too old KLIB format, even doesn't have metadata version
|
||||
!metadataVersion.isCompatible() -> MetadataInfo.Incompatible(!metadataVersion.isAtLeast(KlibMetadataVersion.INSTANCE))
|
||||
else -> MetadataInfo.Compatible
|
||||
}
|
||||
}
|
||||
val compatibilityInfo by lazy { commonLibrary.getCompatibilityInfo() }
|
||||
|
||||
override fun getLibraryRoots() = listOf(libraryRoot)
|
||||
|
||||
override val platform: TargetPlatform
|
||||
get() = CommonPlatforms.defaultCommonPlatform
|
||||
|
||||
override fun toString() = "Common" + super.toString()
|
||||
override fun toString() = "CommonKlib" + super.toString()
|
||||
|
||||
companion object {
|
||||
private val LOG = IJLoggerAdapter.getInstance(CommonKlibLibraryInfo::class.java)
|
||||
|
||||
internal val KotlinLibrary.safeMetadataVersion get() = this.readSafe(null) { metadataVersion }
|
||||
|
||||
private fun <T> KotlinLibrary.readSafe(defaultValue: T, action: KotlinLibrary.() -> T) = try {
|
||||
action()
|
||||
} catch (_: IOException) {
|
||||
defaultValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters
|
||||
import org.jetbrains.kotlin.analyzer.common.configureCommonSpecificComponents
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.container.*
|
||||
import org.jetbrains.kotlin.context.ModuleContext
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
@@ -54,7 +53,6 @@ import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
||||
import org.jetbrains.kotlin.serialization.js.createKotlinJavascriptPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer
|
||||
import org.jetbrains.kotlin.serialization.konan.impl.KlibMetadataModuleDescriptorFactoryImpl
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||
|
||||
@@ -132,7 +130,7 @@ class CompositeResolverForModuleFactory(
|
||||
val metadataProvder = container.get<MetadataPackageFragmentProvider>()
|
||||
var klibMetadataProvider: PackageFragmentProvider? = null
|
||||
|
||||
if (moduleInfo is CommonKlibLibraryInfo && moduleInfo.metadataInfo == CommonKlibLibraryInfo.MetadataInfo.Compatible) {
|
||||
if (moduleInfo is CommonKlibLibraryInfo && moduleInfo.compatibilityInfo.isCompatible) {
|
||||
val library = moduleInfo.commonLibrary
|
||||
val languageVersionSettings = container.get<LanguageVersionSettings>()
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.idea.klib
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.metadataVersion
|
||||
import org.jetbrains.kotlin.idea.klib.KlibCompatibilityInfo.*
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
|
||||
/**
|
||||
* Whether a certain KLIB is compatible for the purposes of IDE: indexation, resolve, etc.
|
||||
*/
|
||||
sealed class KlibCompatibilityInfo(val isCompatible: Boolean) {
|
||||
object Compatible : KlibCompatibilityInfo(true)
|
||||
object Pre14Layout : KlibCompatibilityInfo(false)
|
||||
class IncompatibleMetadata(val isOlder: Boolean) : KlibCompatibilityInfo(false)
|
||||
}
|
||||
|
||||
fun KotlinLibrary.getCompatibilityInfo(): KlibCompatibilityInfo {
|
||||
val hasPre14Manifest = readSafe(false) { has_pre_1_4_manifest }
|
||||
if (hasPre14Manifest)
|
||||
return Pre14Layout
|
||||
|
||||
val metadataVersion = readSafe(null) { metadataVersion }
|
||||
return when {
|
||||
metadataVersion == null -> IncompatibleMetadata(true) // too old KLIB format, even doesn't have metadata version
|
||||
!metadataVersion.isCompatible() -> IncompatibleMetadata(!metadataVersion.isAtLeast(KlibMetadataVersion.INSTANCE))
|
||||
else -> Compatible
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.idea.klib
|
||||
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import java.io.IOException
|
||||
|
||||
fun <T> KotlinLibrary.readSafe(defaultValue: T, action: KotlinLibrary.() -> T) = try {
|
||||
action()
|
||||
} catch (_: IOException) {
|
||||
defaultValue
|
||||
}
|
||||
+3
-2
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryNameUtil
|
||||
import org.jetbrains.kotlin.idea.versions.UnsupportedAbiVersionNotificationPanelProvider
|
||||
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
|
||||
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
|
||||
import org.jetbrains.kotlin.idea.klib.KlibCompatibilityInfo.IncompatibleMetadata
|
||||
|
||||
/** TODO: merge [KotlinNativeABICompatibilityChecker] in the future with [UnsupportedAbiVersionNotificationPanelProvider], KT-34525 */
|
||||
class KotlinNativeABICompatibilityChecker(private val project: Project) : ProjectComponent, Disposable {
|
||||
@@ -86,7 +87,7 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec
|
||||
private fun getLibrariesToNotifyAbout(): Map<String, NativeLibraryInfo> {
|
||||
val incompatibleLibraries = getModuleInfosFromIdeaModel(project).asSequence()
|
||||
.filterIsInstance<NativeLibraryInfo>()
|
||||
.filter { !it.metadataInfo.isCompatible }
|
||||
.filter { !it.compatibilityInfo.isCompatible }
|
||||
.associateBy { it.libraryRoot }
|
||||
|
||||
val newEntries = if (cachedIncompatibleLibraries.isNotEmpty())
|
||||
@@ -106,7 +107,7 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec
|
||||
|
||||
val librariesByGroups = HashMap<Pair<LibraryGroup, Boolean>, MutableList<Pair<String, String>>>()
|
||||
librariesToNotify.forEach { (libraryRoot, libraryInfo) ->
|
||||
val isOldMetadata = (libraryInfo.metadataInfo as? NativeLibraryInfo.MetadataInfo.Incompatible)?.isOlder ?: true
|
||||
val isOldMetadata = (libraryInfo.compatibilityInfo as? IncompatibleMetadata)?.isOlder ?: true
|
||||
val (libraryName, libraryGroup) = parseIDELibraryName(libraryInfo)
|
||||
librariesByGroups.computeIfAbsent(libraryGroup to isOldMetadata) { mutableListOf() } += libraryName to libraryRoot
|
||||
}
|
||||
|
||||
+3
-2
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.configuration.klib.KotlinNativeLibraryNameUtil
|
||||
import org.jetbrains.kotlin.idea.versions.UnsupportedAbiVersionNotificationPanelProvider
|
||||
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
|
||||
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
|
||||
import org.jetbrains.kotlin.idea.klib.KlibCompatibilityInfo.IncompatibleMetadata
|
||||
|
||||
/** TODO: merge [KotlinNativeABICompatibilityChecker] in the future with [UnsupportedAbiVersionNotificationPanelProvider], KT-34525 */
|
||||
class KotlinNativeABICompatibilityChecker(private val project: Project) : ProjectComponent, Disposable {
|
||||
@@ -87,7 +88,7 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec
|
||||
private fun getLibrariesToNotifyAbout(): Map<String, NativeLibraryInfo> {
|
||||
val incompatibleLibraries = getModuleInfosFromIdeaModel(project).asSequence()
|
||||
.filterIsInstance<NativeLibraryInfo>()
|
||||
.filter { !it.metadataInfo.isCompatible }
|
||||
.filter { !it.compatibilityInfo.isCompatible }
|
||||
.associateBy { it.libraryRoot }
|
||||
|
||||
val newEntries = if (cachedIncompatibleLibraries.isNotEmpty())
|
||||
@@ -107,7 +108,7 @@ class KotlinNativeABICompatibilityChecker(private val project: Project) : Projec
|
||||
|
||||
val librariesByGroups = HashMap<Pair<LibraryGroup, Boolean>, MutableList<Pair<String, String>>>()
|
||||
librariesToNotify.forEach { (libraryRoot, libraryInfo) ->
|
||||
val isOldMetadata = (libraryInfo.metadataInfo as? NativeLibraryInfo.MetadataInfo.Incompatible)?.isOlder ?: true
|
||||
val isOldMetadata = (libraryInfo.compatibilityInfo as? IncompatibleMetadata)?.isOlder ?: true
|
||||
val (libraryName, libraryGroup) = parseIDELibraryName(libraryInfo)
|
||||
librariesByGroups.computeIfAbsent(libraryGroup to isOldMetadata) { mutableListOf() } += libraryName to libraryRoot
|
||||
}
|
||||
|
||||
+5
-36
@@ -15,8 +15,6 @@ import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters
|
||||
import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.analyzer.getCapability
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.metadataVersion
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
|
||||
@@ -29,9 +27,6 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
|
||||
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
|
||||
import org.jetbrains.kotlin.ide.konan.NativeLibraryInfo.Companion.safeMetadataVersion
|
||||
import org.jetbrains.kotlin.ide.konan.NativeLibraryInfo.MetadataInfo.Compatible
|
||||
import org.jetbrains.kotlin.ide.konan.NativeLibraryInfo.MetadataInfo.Incompatible
|
||||
import org.jetbrains.kotlin.ide.konan.analyzer.NativeResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.SdkInfo
|
||||
@@ -55,7 +50,8 @@ import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||
import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer
|
||||
import org.jetbrains.kotlin.serialization.konan.impl.KlibMetadataModuleDescriptorFactoryImpl
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import java.io.IOException
|
||||
import org.jetbrains.kotlin.idea.klib.getCompatibilityInfo
|
||||
import org.jetbrains.kotlin.idea.klib.readSafe
|
||||
|
||||
private val NativeFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer)
|
||||
|
||||
@@ -64,7 +60,7 @@ fun KotlinLibrary.createPackageFragmentProvider(
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
moduleDescriptor: ModuleDescriptor
|
||||
): PackageFragmentProvider? {
|
||||
if (safeMetadataVersion?.isCompatible() != true) return null
|
||||
if (!getCompatibilityInfo().isCompatible) return null
|
||||
|
||||
val libraryProto = CachingIdeKonanLibraryMetadataLoader.loadModuleHeader(this)
|
||||
|
||||
@@ -177,22 +173,10 @@ private fun createKotlinNativeBuiltIns(moduleInfo: ModuleInfo, projectContext: P
|
||||
private fun ModuleInfo.findNativeStdlib(): NativeLibraryInfo? =
|
||||
dependencies().lazyClosure { it.dependencies() }
|
||||
.filterIsInstance<NativeLibraryInfo>()
|
||||
.firstOrNull { it.isStdlib && it.metadataInfo.isCompatible }
|
||||
.firstOrNull { it.isStdlib && it.compatibilityInfo.isCompatible }
|
||||
|
||||
class NativeLibraryInfo(project: Project, library: Library, val libraryRoot: String) : LibraryInfo(project, library) {
|
||||
|
||||
sealed class MetadataInfo {
|
||||
abstract val isCompatible: Boolean
|
||||
|
||||
object Compatible : MetadataInfo() {
|
||||
override val isCompatible get() = true
|
||||
}
|
||||
|
||||
class Incompatible(val isOlder: Boolean) : MetadataInfo() {
|
||||
override val isCompatible get() = false
|
||||
}
|
||||
}
|
||||
|
||||
private val nativeLibrary = resolveSingleFileKlib(
|
||||
libraryFile = KFile(libraryRoot),
|
||||
logger = LOG,
|
||||
@@ -201,14 +185,7 @@ class NativeLibraryInfo(project: Project, library: Library, val libraryRoot: Str
|
||||
|
||||
val isStdlib get() = libraryRoot.endsWith(KONAN_STDLIB_NAME)
|
||||
|
||||
val metadataInfo by lazy {
|
||||
val metadataVersion = nativeLibrary.safeMetadataVersion
|
||||
when {
|
||||
metadataVersion == null -> Incompatible(true) // too old KLIB format, even doesn't have metadata version
|
||||
!metadataVersion.isCompatible() -> Incompatible(!metadataVersion.isAtLeast(KlibMetadataVersion.INSTANCE))
|
||||
else -> Compatible
|
||||
}
|
||||
}
|
||||
val compatibilityInfo by lazy { nativeLibrary.getCompatibilityInfo() }
|
||||
|
||||
override fun getLibraryRoots() = listOf(libraryRoot)
|
||||
|
||||
@@ -230,13 +207,5 @@ class NativeLibraryInfo(project: Project, library: Library, val libraryRoot: Str
|
||||
private val LOG = IJLoggerAdapter.getInstance(NativeLibraryInfo::class.java)
|
||||
|
||||
val NATIVE_LIBRARY_CAPABILITY = ModuleDescriptor.Capability<KotlinLibrary>("KotlinNativeLibrary")
|
||||
|
||||
internal val KotlinLibrary.safeMetadataVersion get() = this.readSafe(null) { metadataVersion }
|
||||
|
||||
private fun <T> KotlinLibrary.readSafe(defaultValue: T, action: KotlinLibrary.() -> T) = try {
|
||||
action()
|
||||
} catch (_: IOException) {
|
||||
defaultValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user