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:
Alexander Udalov
2017-04-11 19:25:42 +03:00
parent 722687acd6
commit 7fe9b99087
18 changed files with 202 additions and 73 deletions
@@ -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,