Support different target platforms for modules in AnalyzerFacade
Instead of reusing the same AnalyzerFacade that is used for resolution of a module to resolve its dependencies, analyze each dependency module/library with a facade depending on its target platform. Introduce and use CommonLibraryDetectionUtil in addition to KotlinJavaScriptLibraryDetectionUtil, to detect common libraries (with .kotlin_metadata files). Note that before multi-platform projects, this was not needed because there were only two platforms (JVM and JS), and JVM module had only JVM modules/libraries as dependencies, JS module had only JS modules/libraries as dependencies. Now, for example, a JVM module can have a common module/library as a dependency, and it would be incorrect to analyze that dependency with JvmAnalyzerFacade because that facade does not know anything about .kotlin_metadata files. The changes in Dsl.kt and KotlinCacheServiceImpl.kt are needed because PsiElement.getJavaDescriptorResolver, called from some IDE code, started to fail on a common module, because the container for a common module does not have the JavaDescriptorResolver
This commit is contained in:
@@ -34,9 +34,12 @@ inline fun <reified T : Any> ComponentProvider.get(): T {
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : Any> ComponentProvider.tryGetService(request: Class<T>): T? {
|
||||
return resolve(request)?.getValue() as T?
|
||||
}
|
||||
|
||||
fun <T : Any> ComponentProvider.getService(request: Class<T>): T {
|
||||
val valueDescriptor = resolve(request) ?: throw IllegalArgumentException("Unresolved service: $request")
|
||||
return valueDescriptor.getValue() as T
|
||||
return tryGetService(request) ?: throw IllegalArgumentException("Unresolved service: $request")
|
||||
}
|
||||
|
||||
fun StorageComponentContainer.useInstance(instance: Any) {
|
||||
|
||||
@@ -157,66 +157,71 @@ interface ModuleInfo {
|
||||
}
|
||||
|
||||
abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
||||
fun <M : ModuleInfo> setupResolverForProject(
|
||||
debugName: String,
|
||||
projectContext: ProjectContext,
|
||||
modules: Collection<M>,
|
||||
modulesContent: (M) -> ModuleContent,
|
||||
platformParameters: P,
|
||||
targetEnvironment: TargetEnvironment = CompilerEnvironment,
|
||||
builtIns: (M) -> KotlinBuiltIns = { DefaultBuiltIns.Instance },
|
||||
delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
|
||||
packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty },
|
||||
firstDependency: M? = null,
|
||||
modulePlatforms: (M) -> MultiTargetPlatform?
|
||||
): ResolverForProject<M> {
|
||||
val storageManager = projectContext.storageManager
|
||||
companion object {
|
||||
fun <P : PlatformAnalysisParameters, M : ModuleInfo> setupResolverForProject(
|
||||
debugName: String,
|
||||
projectContext: ProjectContext,
|
||||
modules: Collection<M>,
|
||||
analyzerFacade: (M) -> AnalyzerFacade<P>,
|
||||
modulesContent: (M) -> ModuleContent,
|
||||
platformParameters: P,
|
||||
targetEnvironment: TargetEnvironment = CompilerEnvironment,
|
||||
builtIns: (M) -> KotlinBuiltIns = { DefaultBuiltIns.Instance },
|
||||
delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
|
||||
packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty },
|
||||
firstDependency: M? = null,
|
||||
modulePlatforms: (M) -> MultiTargetPlatform?
|
||||
): ResolverForProject<M> {
|
||||
val storageManager = projectContext.storageManager
|
||||
|
||||
val resolverForProject = ResolverForProjectImpl(debugName, modules.keysToMap { module ->
|
||||
ModuleDescriptorImpl(module.name, storageManager, builtIns(module), modulePlatforms(module), module.capabilities)
|
||||
}, delegateResolver)
|
||||
val resolverForProject = ResolverForProjectImpl(debugName, modules.keysToMap { module ->
|
||||
ModuleDescriptorImpl(module.name, storageManager, builtIns(module), modulePlatforms(module), module.capabilities)
|
||||
}, delegateResolver)
|
||||
|
||||
for (module in modules) {
|
||||
resolverForProject.descriptorForModule(module).setDependencies(LazyModuleDependencies(
|
||||
storageManager,
|
||||
computeDependencies = {
|
||||
val orderedDependencies = listOfNotNull(firstDependency) + module.dependencies()
|
||||
val dependenciesDescriptors = orderedDependencies.mapTo(ArrayList<ModuleDescriptorImpl>()) { dependencyInfo ->
|
||||
resolverForProject.descriptorForModule(dependencyInfo as M)
|
||||
for (module in modules) {
|
||||
resolverForProject.descriptorForModule(module).setDependencies(LazyModuleDependencies(
|
||||
storageManager,
|
||||
computeDependencies = {
|
||||
val orderedDependencies = listOfNotNull(firstDependency) + module.dependencies()
|
||||
val dependenciesDescriptors = orderedDependencies.mapTo(ArrayList<ModuleDescriptorImpl>()) { dependencyInfo ->
|
||||
resolverForProject.descriptorForModule(dependencyInfo as M)
|
||||
}
|
||||
module.dependencyOnBuiltIns().adjustDependencies(
|
||||
resolverForProject.descriptorForModule(module).builtIns.builtInsModule, dependenciesDescriptors)
|
||||
dependenciesDescriptors
|
||||
},
|
||||
computeModulesWhoseInternalsAreVisible = {
|
||||
module.modulesWhoseInternalsAreVisible().mapTo(LinkedHashSet()) {
|
||||
resolverForProject.descriptorForModule(it as M)
|
||||
}
|
||||
},
|
||||
computeImplementingModules = {
|
||||
if (modulePlatforms(module) != MultiTargetPlatform.Common) emptySet()
|
||||
else modules
|
||||
.filter { modulePlatforms(it) != MultiTargetPlatform.Common && module in it.dependencies() }
|
||||
.mapTo(mutableSetOf(), resolverForProject::descriptorForModule)
|
||||
}
|
||||
module.dependencyOnBuiltIns().adjustDependencies(
|
||||
resolverForProject.descriptorForModule(module).builtIns.builtInsModule, dependenciesDescriptors)
|
||||
dependenciesDescriptors
|
||||
},
|
||||
computeModulesWhoseInternalsAreVisible = {
|
||||
module.modulesWhoseInternalsAreVisible().mapTo(LinkedHashSet()) { resolverForProject.descriptorForModule(it as M) }
|
||||
},
|
||||
computeImplementingModules = {
|
||||
if (modulePlatforms(module) != MultiTargetPlatform.Common) emptySet()
|
||||
else modules
|
||||
.filter { modulePlatforms(it) != MultiTargetPlatform.Common && module in it.dependencies() }
|
||||
.mapTo(mutableSetOf(), resolverForProject::descriptorForModule)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
for (module in modules) {
|
||||
val descriptor = resolverForProject.descriptorForModule(module)
|
||||
val computeResolverForModule = storageManager.createLazyValue {
|
||||
val content = modulesContent(module)
|
||||
createResolverForModule(
|
||||
module, descriptor, projectContext.withModule(descriptor), modulesContent(module),
|
||||
platformParameters, targetEnvironment, resolverForProject,
|
||||
packagePartProviderFactory(module, content)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
descriptor.initialize(DelegatingPackageFragmentProvider { computeResolverForModule().packageFragmentProvider })
|
||||
resolverForProject.resolverByModuleDescriptor[descriptor] = computeResolverForModule
|
||||
}
|
||||
for (module in modules) {
|
||||
val descriptor = resolverForProject.descriptorForModule(module)
|
||||
val computeResolverForModule = storageManager.createLazyValue {
|
||||
val content = modulesContent(module)
|
||||
analyzerFacade(module).createResolverForModule(
|
||||
module, descriptor, projectContext.withModule(descriptor), modulesContent(module),
|
||||
platformParameters, targetEnvironment, resolverForProject,
|
||||
packagePartProviderFactory(module, content)
|
||||
)
|
||||
}
|
||||
|
||||
return resolverForProject
|
||||
descriptor.initialize(DelegatingPackageFragmentProvider { computeResolverForModule().packageFragmentProvider })
|
||||
resolverForProject.resolverByModuleDescriptor[descriptor] = computeResolverForModule
|
||||
}
|
||||
|
||||
return resolverForProject
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun <M : ModuleInfo> createResolverForModule(
|
||||
|
||||
@@ -72,7 +72,7 @@ object DefaultAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters>() {
|
||||
val project = files.firstOrNull()?.project ?: throw AssertionError("No files to analyze")
|
||||
val resolver = setupResolverForProject(
|
||||
"sources for metadata serializer",
|
||||
ProjectContext(project), listOf(moduleInfo),
|
||||
ProjectContext(project), listOf(moduleInfo), { DefaultAnalyzerFacade },
|
||||
{ ModuleContent(files, GlobalSearchScope.allScope(project)) },
|
||||
object : PlatformAnalysisParameters {},
|
||||
packagePartProviderFactory = packagePartProviderFactory,
|
||||
|
||||
+5
@@ -61,6 +61,11 @@ public class ForTestCompileRuntime {
|
||||
return assertExists(new File("dist/kotlinc/lib/kotlin-runtime-sources.jar"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static File stdlibCommonForTests() {
|
||||
return assertExists(new File("dist/common/kotlin-stdlib-common.jar"));
|
||||
}
|
||||
|
||||
// TODO: Do not use these classes, remove them after stdlib tests are merged in the same build as the compiler
|
||||
@NotNull
|
||||
@Deprecated
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.lazy
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analyzer.AnalyzerFacade
|
||||
import org.jetbrains.kotlin.analyzer.ModuleContent
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.container.get
|
||||
@@ -35,9 +36,9 @@ fun createResolveSessionForFiles(
|
||||
): ResolveSession {
|
||||
val projectContext = ProjectContext(project)
|
||||
val testModule = TestModule(addBuiltIns)
|
||||
val resolverForProject = JvmAnalyzerFacade.setupResolverForProject(
|
||||
val resolverForProject = AnalyzerFacade.setupResolverForProject(
|
||||
"test",
|
||||
projectContext, listOf(testModule),
|
||||
projectContext, listOf(testModule), { JvmAnalyzerFacade },
|
||||
{ ModuleContent(syntheticFiles, GlobalSearchScope.allScope(project)) },
|
||||
JvmPlatformParameters { testModule },
|
||||
modulePlatforms = { MultiTargetPlatform.Specific("JVM") }
|
||||
|
||||
+3
-2
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.jvm.compiler
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analyzer.AnalyzerFacade
|
||||
import org.jetbrains.kotlin.analyzer.ModuleContent
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.analyzer.ResolverForProject
|
||||
@@ -65,9 +66,9 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() {
|
||||
val modules = setupModules(environment, moduleDirs)
|
||||
val projectContext = ProjectContext(environment.project)
|
||||
val builtIns = JvmBuiltIns(projectContext.storageManager)
|
||||
val resolverForProject = JvmAnalyzerFacade.setupResolverForProject(
|
||||
val resolverForProject = AnalyzerFacade.setupResolverForProject(
|
||||
"test",
|
||||
projectContext, modules,
|
||||
projectContext, modules, { JvmAnalyzerFacade },
|
||||
{ module -> ModuleContent(module.kotlinFiles, module.javaFilesScope) },
|
||||
JvmPlatformParameters {
|
||||
javaClass ->
|
||||
|
||||
Reference in New Issue
Block a user