Introduce AbstractResolverForProject

Previously, ResolverForProjectImpl had multiple callbacks in
constructor. Some of those callbacks were used only to overcome module
visibility and provide an ability to inject IDE-specific logic into
compiler (ResolverForProject is in the 'compiler'-module)

This commit introduces abstract class which implements
environment-independent logic (previously, this logic had been stored in
ResolverForProjectImpl) with several abstract met hods (previously,
callbacks). Then, we provide few concrete implementations of
AbstractResolverForProject with clear semantics:

- IdeaResolverForProject: resolver used in IDE, where we have indices,
  oracles, multiple modules, etc.
- ResolverForSingleModuleProject: resolver for project with only one
  module, commonly used for CLI compiler/tests
- one anonymous implementation for MultimoduleTests

This refactoring achieves several things:
- now it is easier to see what kinds of ResolverForProject you might see
  in some particular environment (previously, one had to inspect all
  call-sites of constructor)
- we can easily add IDE-specific logic in IdeaResolverForProject without
  adding noisy callbacks (which most probably wouldn't have any other
  non-trivial implementations)
This commit is contained in:
Dmitry Savvinov
2019-09-23 18:44:58 +03:00
parent 48719c4050
commit bfacc1a3c5
8 changed files with 253 additions and 162 deletions
@@ -124,35 +124,22 @@ class CommonResolverForModuleFactory(
else languageVersionSettings.getFeatureSupport(feature) else languageVersionSettings.getFeatureSupport(feature)
} }
val resolverForModuleFactory = CommonResolverForModuleFactory(
CommonAnalysisParameters(metadataPartProviderFactory),
CompilerEnvironment,
CommonPlatforms.defaultCommonPlatform,
shouldCheckExpectActual = false
)
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val resolver = ResolverForProjectImpl( val resolver = ResolverForSingleModuleProject(
"sources for metadata serializer", "sources for metadata serializer",
ProjectContext(project, "metadata serializer"), ProjectContext(project, "metadata serializer"),
listOf(moduleInfo), moduleInfo,
invalidateOnOOCB = false, resolverForModuleFactory,
modulesContent = { ModuleContent(it, files, GlobalSearchScope.allScope(project)) }, GlobalSearchScope.allScope(project),
moduleLanguageSettingsProvider = object : LanguageSettingsProvider { languageVersionSettings = multiplatformLanguageSettings,
override fun getLanguageVersionSettings( syntheticFiles = files
moduleInfo: ModuleInfo,
project: Project,
isReleaseCoroutines: Boolean?
) = multiplatformLanguageSettings
override fun getTargetPlatform(
moduleInfo: ModuleInfo,
project: Project
) = TargetPlatformVersion.NoVersion
},
resolverForModuleFactoryByPlatform = {
CommonResolverForModuleFactory(
CommonAnalysisParameters(metadataPartProviderFactory),
CompilerEnvironment,
CommonPlatforms.defaultCommonPlatform,
shouldCheckExpectActual = false
)
},
builtInsProvider = { DefaultBuiltIns.Instance },
sdkDependency = { null }
) )
val moduleDescriptor = resolver.descriptorForModule(moduleInfo) val moduleDescriptor = resolver.descriptorForModule(moduleInfo)
@@ -54,7 +54,6 @@ abstract class ResolverForProject<M : ModuleInfo> {
abstract val name: String abstract val name: String
abstract val allModules: Collection<M> abstract val allModules: Collection<M>
abstract val builtInsProvider: (M) -> KotlinBuiltIns
override fun toString() = name override fun toString() = name
@@ -79,7 +78,6 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo)) override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo))
override val allModules: Collection<M> = listOf() override val allModules: Collection<M> = listOf()
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos") override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos")
override val builtInsProvider: (M) -> KotlinBuiltIns = { DefaultBuiltIns.Instance }
} }
data class ModuleContent<out M : ModuleInfo>( data class ModuleContent<out M : ModuleInfo>(
@@ -128,7 +126,7 @@ class LazyModuleDependencies<M : ModuleInfo>(
storageManager: StorageManager, storageManager: StorageManager,
private val module: M, private val module: M,
firstDependency: M? = null, firstDependency: M? = null,
private val resolverForProject: ResolverForProjectImpl<M> private val resolverForProject: AbstractResolverForProject<M>
) : ModuleDependencies { ) : ModuleDependencies {
private val dependencies = storageManager.createLazyValue { private val dependencies = storageManager.createLazyValue {
val moduleDescriptor = resolverForProject.descriptorForModule(module) val moduleDescriptor = resolverForProject.descriptorForModule(module)
@@ -16,20 +16,15 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtFile
class ResolverForProjectImpl<M : ModuleInfo>( abstract class AbstractResolverForProject<M : ModuleInfo>(
private val debugName: String, private val debugName: String,
private val projectContext: ProjectContext, protected val projectContext: ProjectContext,
modules: Collection<M>, modules: Collection<M>,
private val modulesContent: (M) -> ModuleContent<M>, private val fallbackModificationTracker: ModificationTracker? = null,
private val moduleLanguageSettingsProvider: LanguageSettingsProvider,
private val resolverForModuleFactoryByPlatform: (TargetPlatform?) -> ResolverForModuleFactory,
private val invalidateOnOOCB: Boolean,
override val builtInsProvider: (M) -> KotlinBuiltIns,
private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(), private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
private val sdkDependency: (M) -> M?, private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory
private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory,
private val isReleaseCoroutines: Boolean? = null
) : ResolverForProject<M>() { ) : ResolverForProject<M>() {
private class ModuleData( private class ModuleData(
@@ -58,6 +53,11 @@ class ResolverForProjectImpl<M : ModuleInfo>(
assert(moduleInfoToResolvableInfo.values.toSet() == modules.toSet()) assert(moduleInfoToResolvableInfo.values.toSet() == modules.toSet())
} }
abstract fun sdkDependency(module: M): M?
abstract fun modulesContent(module: M): ModuleContent<M>
abstract fun builtInsForModule(module: M): KotlinBuiltIns
abstract fun createResolverForModule(descriptor: ModuleDescriptor, moduleInfo: M): ResolverForModule
override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? { override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? {
if (!isCorrectModuleInfo(moduleInfo)) { if (!isCorrectModuleInfo(moduleInfo)) {
return null return null
@@ -108,25 +108,9 @@ class ResolverForProjectImpl<M : ModuleInfo>(
resolverByModuleDescriptor.getOrPut(descriptor) { resolverByModuleDescriptor.getOrPut(descriptor) {
checkModuleIsCorrect(module) checkModuleIsCorrect(module)
ResolverForModuleComputationTracker.getInstance(projectContext.project) ResolverForModuleComputationTracker.getInstance(projectContext.project)?.onResolverComputed(module)
?.onResolverComputed(module)
val moduleContent = modulesContent(module) createResolverForModule(descriptor, module)
val languageVersionSettings =
moduleLanguageSettingsProvider.getLanguageVersionSettings(module, projectContext.project, isReleaseCoroutines)
// FIXME(dsavvinov): make sure that module.platform returns platform with the same JvmTarget as this one
val targetPlatformVersion = moduleLanguageSettingsProvider.getTargetPlatform(module, projectContext.project)
val resolverForModuleFactory = resolverForModuleFactoryByPlatform(module.platform)
resolverForModuleFactory.createResolverForModule(
descriptor as ModuleDescriptorImpl,
projectContext.withModule(descriptor),
moduleContent,
this@ResolverForProjectImpl,
languageVersionSettings
)
} }
} }
} }
@@ -153,7 +137,7 @@ class ResolverForProjectImpl<M : ModuleInfo>(
private fun doGetDescriptorForModule(module: M): ModuleDescriptorImpl { private fun doGetDescriptorForModule(module: M): ModuleDescriptorImpl {
val moduleFromThisResolver = moduleInfoToResolvableInfo[module] val moduleFromThisResolver = moduleInfoToResolvableInfo[module]
?: return delegateResolver.descriptorForModule(module) as ModuleDescriptorImpl ?: return delegateResolver.descriptorForModule(module) as ModuleDescriptorImpl
return projectContext.storageManager.compute { return projectContext.storageManager.compute {
var moduleData = descriptorByModule.getOrPut(moduleFromThisResolver) { var moduleData = descriptorByModule.getOrPut(moduleFromThisResolver) {
@@ -183,24 +167,20 @@ class ResolverForProjectImpl<M : ModuleInfo>(
val moduleDescriptor = ModuleDescriptorImpl( val moduleDescriptor = ModuleDescriptorImpl(
module.name, module.name,
projectContext.storageManager, projectContext.storageManager,
builtInsProvider(module), builtInsForModule(module),
module.platform, module.platform,
module.capabilities, module.capabilities,
module.stableName module.stableName
) )
moduleInfoByDescriptor[moduleDescriptor] = module moduleInfoByDescriptor[moduleDescriptor] = module
setupModuleDescriptor(module, moduleDescriptor) setupModuleDescriptor(module, moduleDescriptor)
val modificationTracker = (module as? TrackableModuleInfo)?.createModificationTracker() ?: if (invalidateOnOOCB) { val modificationTracker = (module as? TrackableModuleInfo)?.createModificationTracker() ?: fallbackModificationTracker
KotlinModificationTrackerService.getInstance(projectContext.project).outOfBlockModificationTracker
} else {
null
}
return ModuleData(moduleDescriptor, modificationTracker) return ModuleData(moduleDescriptor, modificationTracker)
} }
} }
private class DelegatingPackageFragmentProvider<M : ModuleInfo>( private class DelegatingPackageFragmentProvider<M : ModuleInfo>(
private val resolverForProject: ResolverForProjectImpl<M>, private val resolverForProject: AbstractResolverForProject<M>,
private val module: ModuleDescriptor, private val module: ModuleDescriptor,
moduleContent: ModuleContent<M>, moduleContent: ModuleContent<M>,
private val packageOracle: PackageOracle private val packageOracle: PackageOracle
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2019 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.analyzer
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.psi.KtFile
class ResolverForSingleModuleProject<M : ModuleInfo>(
debugName: String,
projectContext: ProjectContext,
module: M,
private val resolverForModuleFactory: ResolverForModuleFactory,
private val searchScope: GlobalSearchScope,
private val builtIns: KotlinBuiltIns = DefaultBuiltIns.Instance,
private val languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
private val syntheticFiles: Collection<KtFile> = emptyList(),
private val sdkDependency: M? = null
) : AbstractResolverForProject<M>(
debugName,
projectContext,
listOf(module),
null,
EmptyResolverForProject(),
PackageOracleFactory.OptimisticFactory
) {
override fun sdkDependency(module: M): M? = sdkDependency
override fun modulesContent(module: M): ModuleContent<M> = ModuleContent(module, syntheticFiles, searchScope)
override fun builtInsForModule(module: M): KotlinBuiltIns = builtIns
override fun createResolverForModule(descriptor: ModuleDescriptor, moduleInfo: M): ResolverForModule =
resolverForModuleFactory.createResolverForModule(
descriptor as ModuleDescriptorImpl,
projectContext.withModule(descriptor),
modulesContent(moduleInfo),
this,
languageVersionSettings
)
}
@@ -46,18 +46,16 @@ fun createResolveSessionForFiles(
packagePartProviderFactory = { PackagePartProvider.Empty }, packagePartProviderFactory = { PackagePartProvider.Empty },
moduleByJavaClass = { testModule } moduleByJavaClass = { testModule }
) )
val resolverForProject = ResolverForProjectImpl(
val resolverForProject = ResolverForSingleModuleProject(
"test", "test",
projectContext, listOf(testModule), projectContext,
{ ModuleContent(it, syntheticFiles, GlobalSearchScope.allScope(project)) }, testModule,
invalidateOnOOCB = false, JvmResolverForModuleFactory(platformParameters, CompilerEnvironment, JvmPlatforms.defaultJvmPlatform),
moduleLanguageSettingsProvider = LanguageSettingsProvider.Default, GlobalSearchScope.allScope(project),
resolverForModuleFactoryByPlatform = { syntheticFiles = syntheticFiles
JvmResolverForModuleFactory(platformParameters, CompilerEnvironment, JvmPlatforms.defaultJvmPlatform)
},
builtInsProvider = { DefaultBuiltIns.Instance },
sdkDependency = { null }
) )
return resolverForProject.resolverForModule(testModule).componentProvider.get<ResolveSession>() return resolverForProject.resolverForModule(testModule).componentProvider.get<ResolveSession>()
} }
@@ -28,9 +28,12 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -87,24 +90,39 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() {
modules.first { it._name == moduleName } modules.first { it._name == moduleName }
} }
) )
val resolverForProject = ResolverForProjectImpl(
val resolverForProject = object : AbstractResolverForProject<TestModule>(
"test", "test",
projectContext, modules, projectContext,
invalidateOnOOCB = false, modules
modulesContent = { module -> ModuleContent(module, module.kotlinFiles, module.javaFilesScope) }, ) {
moduleLanguageSettingsProvider = LanguageSettingsProvider.Default, override fun sdkDependency(module: TestModule): TestModule? = null
resolverForModuleFactoryByPlatform = {
JvmResolverForModuleFactory(platformParameters, CompilerEnvironment, JvmPlatforms.defaultJvmPlatform) override fun modulesContent(module: TestModule): ModuleContent<TestModule> =
}, ModuleContent(module, module.kotlinFiles, module.javaFilesScope)
sdkDependency = { null },
builtInsProvider = { builtIns } override fun builtInsForModule(module: TestModule): KotlinBuiltIns = builtIns
)
override fun createResolverForModule(descriptor: ModuleDescriptor, moduleInfo: TestModule): ResolverForModule =
JvmResolverForModuleFactory(
platformParameters,
CompilerEnvironment,
JvmPlatforms.defaultJvmPlatform
).createResolverForModule(
descriptor as ModuleDescriptorImpl,
projectContext.withModule(descriptor),
modulesContent(moduleInfo),
this,
LanguageVersionSettingsImpl.DEFAULT
)
}
builtIns.initialize( builtIns.initialize(
resolverForProject.descriptorForModule(resolverForProject.allModules.first()), resolverForProject.descriptorForModule(resolverForProject.allModules.first()),
resolverForProject.resolverForModule(resolverForProject.allModules.first()) resolverForProject.resolverForModule(resolverForProject.allModules.first())
.componentProvider.get<LanguageVersionSettings>() .componentProvider.get<LanguageVersionSettings>()
.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) .supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)
)
performChecks(resolverForProject, modules) performChecks(resolverForProject, modules)
} }
@@ -0,0 +1,124 @@
/*
* Copyright 2010-2019 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.caches.resolve
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.util.ModificationTracker
import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
import org.jetbrains.kotlin.caches.resolve.CompositeAnalyzerServices
import org.jetbrains.kotlin.caches.resolve.CompositeResolverForModuleFactory
import org.jetbrains.kotlin.caches.resolve.resolution
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
import org.jetbrains.kotlin.idea.caches.project.findSdkAcrossDependencies
import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
import org.jetbrains.kotlin.idea.caches.project.getPlatformModuleInfo
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.idea.project.IdeaEnvironment
import org.jetbrains.kotlin.idea.project.findAnalyzerServices
import org.jetbrains.kotlin.idea.project.useCompositeAnalysis
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.platform.idePlatformKind
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.platform.toTargetPlatform
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
class IdeaResolverForProject(
debugName: String,
projectContext: ProjectContext,
private val modules: Collection<IdeaModuleInfo>,
private val syntheticFilesByModule: Map<IdeaModuleInfo, Collection<KtFile>>,
delegateResolver: ResolverForProject<IdeaModuleInfo>,
private val builtInsCache: BuiltInsCache,
fallbackModificationTracker: ModificationTracker? = null,
private val isReleaseCoroutines: Boolean? = null,
// TODO(dsavvinov): this is needed only for non-composite analysis, extract separate resolver implementation instead
private val constantSdkDependencyIfAny: IdeaModuleInfo? = null
) : AbstractResolverForProject<IdeaModuleInfo>(
debugName,
projectContext,
modules,
fallbackModificationTracker,
delegateResolver,
ServiceManager.getService(projectContext.project, IdePackageOracleFactory::class.java)
) {
override fun sdkDependency(module: IdeaModuleInfo): IdeaModuleInfo? {
if (projectContext.project.useCompositeAnalysis) {
require(constantSdkDependencyIfAny == null) { "Shouldn't pass SDK dependency manually for composite analysis mode" }
}
return constantSdkDependencyIfAny ?: module.findSdkAcrossDependencies()
}
override fun modulesContent(module: IdeaModuleInfo): ModuleContent<IdeaModuleInfo> =
ModuleContent(module, syntheticFilesByModule[module] ?: emptyList(), module.contentScope())
override fun builtInsForModule(module: IdeaModuleInfo): KotlinBuiltIns {
require(module in modules)
val key = module.platform.idePlatformKind.resolution.getKeyForBuiltIns(module)
return builtInsCache.getOrPut(key) { throw IllegalStateException("Can't find builtIns by key $key for module $module") }
}
override fun createResolverForModule(descriptor: ModuleDescriptor, moduleInfo: IdeaModuleInfo): ResolverForModule {
val moduleContent = ModuleContent(moduleInfo, syntheticFilesByModule[moduleInfo] ?: listOf(), moduleInfo.contentScope())
val languageVersionSettings =
IDELanguageSettingsProvider.getLanguageVersionSettings(moduleInfo, projectContext.project, isReleaseCoroutines)
val resolverForModuleFactory = getResolverForModuleFactory(moduleInfo)
return resolverForModuleFactory.createResolverForModule(
descriptor as ModuleDescriptorImpl,
projectContext.withModule(descriptor),
moduleContent,
this,
languageVersionSettings
)
}
private fun getResolverForModuleFactory(moduleInfo: IdeaModuleInfo): ResolverForModuleFactory {
val platform = moduleInfo.platform
val jvmPlatformParameters = JvmPlatformParameters(
packagePartProviderFactory = { IDEPackagePartProvider(it.moduleContentScope) },
moduleByJavaClass = { javaClass: JavaClass ->
val psiClass = (javaClass as JavaClassImpl).psi
psiClass.getPlatformModuleInfo(JvmPlatforms.unspecifiedJvmPlatform)?.platformModule ?: psiClass.getNullableModuleInfo()
}
)
val commonPlatformParameters = CommonAnalysisParameters(
metadataPartProviderFactory = { IDEPackagePartProvider(it.moduleContentScope) }
)
return if (!projectContext.project.useCompositeAnalysis) {
val parameters = when {
platform.isJvm() -> jvmPlatformParameters
platform.isCommon() -> commonPlatformParameters
else -> PlatformAnalysisParameters.Empty
}
platform.idePlatformKind.resolution.createResolverForModuleFactory(parameters, IdeaEnvironment, platform)
} else {
CompositeResolverForModuleFactory(
commonPlatformParameters,
jvmPlatformParameters,
platform,
CompositeAnalyzerServices(platform.componentPlatforms.map { it.toTargetPlatform().findAnalyzerServices })
)
}
}
}
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.idea.caches.resolve package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValueProvider
@@ -24,36 +23,18 @@ import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker import com.intellij.psi.util.PsiModificationTracker
import com.intellij.util.containers.SLRUCache import com.intellij.util.containers.SLRUCache
import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
import org.jetbrains.kotlin.caches.resolve.CompositeAnalyzerServices
import org.jetbrains.kotlin.caches.resolve.CompositeResolverForModuleFactory
import org.jetbrains.kotlin.caches.resolve.resolution import org.jetbrains.kotlin.caches.resolve.resolution
import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.context.withProject import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.caches.project.* import org.jetbrains.kotlin.idea.caches.project.*
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.idea.project.IdeaEnvironment
import org.jetbrains.kotlin.idea.project.findAnalyzerServices
import org.jetbrains.kotlin.idea.project.useCompositeAnalysis
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.platform.idePlatformKind import org.jetbrains.kotlin.platform.idePlatformKind
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompositeBindingContext import org.jetbrains.kotlin.resolve.CompositeBindingContext
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.kotlin.platform.DefaultIdeTargetPlatformKindProvider
import org.jetbrains.kotlin.platform.toTargetPlatform
internal class ProjectResolutionFacade( internal class ProjectResolutionFacade(
private val debugString: String, private val debugString: String,
@@ -101,7 +82,6 @@ internal class ProjectResolutionFacade(
private fun computeModuleResolverProvider(): ResolverForProject<IdeaModuleInfo> { private fun computeModuleResolverProvider(): ResolverForProject<IdeaModuleInfo> {
val delegateResolverForProject: ResolverForProject<IdeaModuleInfo> val delegateResolverForProject: ResolverForProject<IdeaModuleInfo>
val delegateBuiltIns: KotlinBuiltIns?
if (reuseDataFrom != null) { if (reuseDataFrom != null) {
delegateResolverForProject = reuseDataFrom.cachedResolverForProject delegateResolverForProject = reuseDataFrom.cachedResolverForProject
@@ -119,61 +99,16 @@ internal class ProjectResolutionFacade(
val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter) val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter)
val modulesContentFactory = { module: IdeaModuleInfo -> val resolverForProject = IdeaResolverForProject(
ModuleContent(module, syntheticFilesByModule[module] ?: listOf(), module.contentScope())
}
val jvmPlatformParameters = JvmPlatformParameters(
packagePartProviderFactory = { IDEPackagePartProvider(it.moduleContentScope) },
moduleByJavaClass = { javaClass: JavaClass ->
val psiClass = (javaClass as JavaClassImpl).psi
psiClass.getPlatformModuleInfo(JvmPlatforms.unspecifiedJvmPlatform)?.platformModule ?: psiClass.getNullableModuleInfo()
}
)
val commonPlatformParameters = CommonAnalysisParameters(
metadataPartProviderFactory = { IDEPackagePartProvider(it.moduleContentScope) }
)
val resolverForProject = ResolverForProjectImpl(
resolverDebugName, resolverDebugName,
projectContext, projectContext,
modulesToCreateResolversFor, modulesToCreateResolversFor,
modulesContentFactory, syntheticFilesByModule,
moduleLanguageSettingsProvider = IDELanguageSettingsProvider, delegateResolverForProject,
resolverForModuleFactoryByPlatform = { modulePlatform -> builtInsCache,
val platform = modulePlatform ?: DefaultIdeTargetPlatformKindProvider.defaultPlatform if (invalidateOnOOCB) KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker else null,
val parameters = when { settings.isReleaseCoroutines,
platform.isJvm() -> jvmPlatformParameters constantSdkDependencyIfAny = if (settings is PlatformAnalysisSettingsImpl) settings.sdk?.let { SdkInfo(project, it) } else null
platform.isCommon() -> commonPlatformParameters
else -> PlatformAnalysisParameters.Empty
}
if (!project.useCompositeAnalysis)
platform.idePlatformKind.resolution.createResolverForModuleFactory(parameters, IdeaEnvironment, platform)
else
CompositeResolverForModuleFactory(
commonPlatformParameters,
jvmPlatformParameters,
modulePlatform!!,
CompositeAnalyzerServices(modulePlatform.componentPlatforms.map { it.toTargetPlatform().findAnalyzerServices })
)
},
builtInsProvider = { module ->
require(module in modulesToCreateResolversFor)
val key = module.platform.idePlatformKind.resolution.getKeyForBuiltIns(module)
builtInsCache.getOrPut(key) { throw IllegalStateException("Can't find builtIns by key $key for module $module") }
},
delegateResolver = delegateResolverForProject,
sdkDependency = { module ->
if (settings is PlatformAnalysisSettingsImpl)
settings.sdk?.let { SdkInfo(project, it) }
else
module.findSdkAcrossDependencies()
},
packageOracleFactory = ServiceManager.getService(project, IdePackageOracleFactory::class.java),
invalidateOnOOCB = invalidateOnOOCB,
isReleaseCoroutines = settings.isReleaseCoroutines
) )
// Fill builtInsCache // Fill builtInsCache