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:
+124
@@ -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 })
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-72
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.caches.resolve
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
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.util.containers.SLRUCache
|
||||
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.caches.resolve.CompositeAnalyzerServices
|
||||
import org.jetbrains.kotlin.caches.resolve.CompositeResolverForModuleFactory
|
||||
import org.jetbrains.kotlin.caches.resolve.resolution
|
||||
import org.jetbrains.kotlin.context.GlobalContextImpl
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.context.withProject
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.project.*
|
||||
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.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.KtFile
|
||||
import org.jetbrains.kotlin.resolve.CompositeBindingContext
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import org.jetbrains.kotlin.platform.DefaultIdeTargetPlatformKindProvider
|
||||
import org.jetbrains.kotlin.platform.toTargetPlatform
|
||||
|
||||
internal class ProjectResolutionFacade(
|
||||
private val debugString: String,
|
||||
@@ -101,7 +82,6 @@ internal class ProjectResolutionFacade(
|
||||
|
||||
private fun computeModuleResolverProvider(): ResolverForProject<IdeaModuleInfo> {
|
||||
val delegateResolverForProject: ResolverForProject<IdeaModuleInfo>
|
||||
val delegateBuiltIns: KotlinBuiltIns?
|
||||
|
||||
if (reuseDataFrom != null) {
|
||||
delegateResolverForProject = reuseDataFrom.cachedResolverForProject
|
||||
@@ -119,61 +99,16 @@ internal class ProjectResolutionFacade(
|
||||
|
||||
val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter)
|
||||
|
||||
val modulesContentFactory = { module: IdeaModuleInfo ->
|
||||
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(
|
||||
val resolverForProject = IdeaResolverForProject(
|
||||
resolverDebugName,
|
||||
projectContext,
|
||||
modulesToCreateResolversFor,
|
||||
modulesContentFactory,
|
||||
moduleLanguageSettingsProvider = IDELanguageSettingsProvider,
|
||||
resolverForModuleFactoryByPlatform = { modulePlatform ->
|
||||
val platform = modulePlatform ?: DefaultIdeTargetPlatformKindProvider.defaultPlatform
|
||||
val parameters = when {
|
||||
platform.isJvm() -> jvmPlatformParameters
|
||||
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
|
||||
syntheticFilesByModule,
|
||||
delegateResolverForProject,
|
||||
builtInsCache,
|
||||
if (invalidateOnOOCB) KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker else null,
|
||||
settings.isReleaseCoroutines,
|
||||
constantSdkDependencyIfAny = if (settings is PlatformAnalysisSettingsImpl) settings.sdk?.let { SdkInfo(project, it) } else null
|
||||
)
|
||||
|
||||
// Fill builtInsCache
|
||||
|
||||
Reference in New Issue
Block a user