IDE: Port JS to use the same KLIB utilities as Native & Common

This commit is contained in:
Dmitriy Dolovov
2020-03-23 20:32:56 +07:00
parent e81479e30b
commit c9245ef497
3 changed files with 27 additions and 80 deletions
@@ -1,30 +0,0 @@
/*
* 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.caches.resolve
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.libraries.Library
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.library.resolveSingleFileKlib
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.js.JsPlatforms
internal class JsKlibLibraryInfo(
project: Project,
library: Library,
private val libraryRoot: String
) : LibraryInfo(project, library) {
val kotlinLibrary = resolveSingleFileKlib(File(libraryRoot))
override fun getLibraryRoots() = listOf(libraryRoot)
override val platform: TargetPlatform
get() = JsPlatforms.defaultJsPlatform
override fun toString() = "JsKlib" + super.toString()
}
@@ -21,19 +21,18 @@ 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.JSLibraryKind
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
import org.jetbrains.kotlin.library.KLIB_MANIFEST_FILE_NAME
import org.jetbrains.kotlin.library.KLIB_PROPERTY_BUILTINS_PLATFORM
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
import org.jetbrains.kotlin.idea.klib.AbstractKlibLibraryInfo
import org.jetbrains.kotlin.idea.klib.isKlibLibraryRootForPlatform
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.resolve.TargetEnvironment
import java.io.IOException
import java.util.*
class JsPlatformKindResolution : IdePlatformKindResolution {
override fun isLibraryFileForPlatform(virtualFile: VirtualFile): Boolean {
return virtualFile.extension == "js" || virtualFile.extension == "kjsm" || virtualFile.isJsKlibRoot
return virtualFile.extension == "js"
|| virtualFile.extension == "kjsm"
|| virtualFile.isKlibLibraryRootForPlatform(JsPlatforms.defaultJsPlatform)
}
override val libraryKind: PersistentLibraryKind<*>?
@@ -56,7 +55,9 @@ class JsPlatformKindResolution : IdePlatformKindResolution {
): ResolverForModuleFactory = JsResolverForModuleFactory(environment)
override fun createLibraryInfo(project: Project, library: Library): List<LibraryInfo> {
val klibFiles = library.getFiles(OrderRootType.CLASSES).filter { it.isJsKlibRoot }
val klibFiles = library.getFiles(OrderRootType.CLASSES).filter {
it.isKlibLibraryRootForPlatform(JsPlatforms.defaultJsPlatform)
}
return if (klibFiles.isNotEmpty()) {
klibFiles.mapNotNull {
@@ -70,28 +71,7 @@ class JsPlatformKindResolution : IdePlatformKindResolution {
}
}
// TODO unify the solution between Native and Common
private val VirtualFile.isJsKlibRoot: Boolean
get() {
// The virtual file for a library packed in a ZIP file will have path like "/some/path/to/the/file.klib!/",
// and therefore will be recognized by VFS as a directory (isDirectory == true).
// So, first, let's check the extension.
val extension = extension
if (!extension.isNullOrEmpty() && extension != KLIB_FILE_EXTENSION) return false
fun checkComponent(componentFile: VirtualFile): Boolean {
val manifestFile = componentFile.findChild(KLIB_MANIFEST_FILE_NAME)?.takeIf { !it.isDirectory } ?: return false
val manifestProperties = try {
manifestFile.inputStream.use { Properties().apply { load(it) } }
} catch (_: IOException) {
return false
}
return manifestProperties.getProperty(KLIB_PROPERTY_BUILTINS_PLATFORM) == BuiltInsPlatform.JS.name
}
// run check for library root too
// this is necessary to recognize old style KLIBs that do not have components, and report tem to user appropriately
return checkComponent(this) || children?.any(::checkComponent) == true
}
class JsKlibLibraryInfo(project: Project, library: Library, libraryRoot: String) : AbstractKlibLibraryInfo(project, library, libraryRoot) {
override val platform: TargetPlatform
get() = JsPlatforms.defaultJsPlatform
}
@@ -15,13 +15,11 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.frontend.di.createContainerForLazyResolve
import org.jetbrains.kotlin.idea.klib.getCompatibilityInfo
import org.jetbrains.kotlin.idea.klib.createKlibPackageFragmentProvider
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
import org.jetbrains.kotlin.konan.util.KlibMetadataFactories
import org.jetbrains.kotlin.library.metadata.parseModuleHeader
import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
@@ -79,10 +77,14 @@ internal fun <M : ModuleInfo> createPackageFragmentProvider(
moduleDescriptor: ModuleDescriptorImpl
): List<PackageFragmentProvider> = when (moduleInfo) {
is JsKlibLibraryInfo -> {
val library = moduleInfo.kotlinLibrary
if (moduleInfo.compatibilityInfo.isCompatible) {
val library = moduleInfo.resolvedKotlinLibrary
val languageVersionSettings = container.get<LanguageVersionSettings>()
if (library.getCompatibilityInfo().isCompatible) {
val metadataFactories = KlibMetadataFactories({ DefaultBuiltIns.Instance }, DynamicTypeDeserializer)
val metadataFactories = KlibMetadataFactories(
{ DefaultBuiltIns.Instance },
DynamicTypeDeserializer
)
val klibMetadataModuleDescriptorFactory = KlibMetadataModuleDescriptorFactoryImpl(
metadataFactories.DefaultDescriptorFactory,
@@ -91,19 +93,14 @@ internal fun <M : ModuleInfo> createPackageFragmentProvider(
metadataFactories.platformDependentTypeTransformer
)
val packageFragmentNames = parseModuleHeader(library.moduleHeaderData).packageFragmentNameList
val klibBasedPackageFragmentProvider = klibMetadataModuleDescriptorFactory.createPackageFragmentProvider(
library,
packageAccessHandler = null,
packageFragmentNames = packageFragmentNames,
storageManager = moduleContext.storageManager,
moduleDescriptor = moduleDescriptor,
configuration = CompilerDeserializationConfiguration(container.get()),
compositePackageFragmentAddend = null
val klibBasedPackageFragmentProvider = library.createKlibPackageFragmentProvider(
moduleContext.storageManager,
klibMetadataModuleDescriptorFactory,
languageVersionSettings,
moduleDescriptor
)
listOf(klibBasedPackageFragmentProvider)
listOfNotNull(klibBasedPackageFragmentProvider)
} else {
emptyList()
}