[Resolve] Introduce CompositeAnalysisSettings

Because we want to support both COMPOSITE and SEPARATE resolution modes
at once, we have to leave 'globalFacadesPerPlatformAndSdk'-map, but in
COMPOSITE mode it should use less parameters for that map, and, in
particular, we shouldn't use Platform and SDK for equality.

This commit introduces separate instance which should be used in
COMPOSITE mode.

COMPOSITE mode itself will be introduced in the following commits.
This commit is contained in:
Dmitry Savvinov
2019-06-17 17:16:25 +03:00
parent 5e95890028
commit adb0f5eaf9
2 changed files with 80 additions and 48 deletions
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTracker import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesModificationTracker
import org.jetbrains.kotlin.idea.core.script.dependencies.ScriptAdditionalIdeaDependenciesProvider import org.jetbrains.kotlin.idea.core.script.dependencies.ScriptAdditionalIdeaDependenciesProvider
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.project.useCompositeAnalysis
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.TargetPlatform
@@ -64,16 +65,47 @@ import org.jetbrains.kotlin.utils.addToStdlib.sumByLong
internal val LOG = Logger.getInstance(KotlinCacheService::class.java) internal val LOG = Logger.getInstance(KotlinCacheService::class.java)
// For every different instance of these settings we must create a different builtIns instance and thus a different moduleDescriptor graph /**
// since in the current implementation types from one module are leaking into other modules' resolution * Regulates what sources should be analyzed together.
// meaning that we can't just change those setting on a per module basis *
data class PlatformAnalysisSettings( * There are exactly two descendants, which are in string one-to-one correspondence with [ResolutionModeComponent.Mode] pick (meaning
val platform: TargetPlatform, val sdk: Sdk?, * that after checking value of ResolutionMode, it's safe to downcast settings instance to the respective type):
val isAdditionalBuiltInFeaturesSupported: Boolean, * - [PlatformAnalysisSettingsImpl] should be used iff we're working under [Mode.SEPARATE], and will create separate
* facade for each platforms, sdk, builtIns settings and other stuff.
* This is the old and stable mode, which should be used by default.
*
* - [CompositeAnalysisSettings] should be used iff we're working under [Mode.COMPOSITE], and will analyze all sources
* together, in one facade.
* This mode is new and experimental, and works only together with TypeRefinement facilities in the compiler's frontend.
* This mode is currently enabled only for HMPP projects
*/
sealed class PlatformAnalysisSettings {
// Effectively unused as a property. Needed only to distinguish different modes when being put in a map // Effectively unused as a property. Needed only to distinguish different modes when being put in a map
val isReleaseCoroutines: Boolean, abstract val isReleaseCoroutines: Boolean
val isTypeRefinementEnabled: Boolean
) companion object {
fun create(
project: Project,
platform: TargetPlatform,
sdk: Sdk?,
isAdditionalBuiltInFeaturesSupported: Boolean,
isReleaseCoroutines: Boolean
) = if (project.useCompositeAnalysis)
CompositeAnalysisSettings(isReleaseCoroutines)
else
PlatformAnalysisSettingsImpl(platform, sdk, isAdditionalBuiltInFeaturesSupported, isReleaseCoroutines)
}
}
data class PlatformAnalysisSettingsImpl(
val platform: TargetPlatform,
val sdk: Sdk?,
val isAdditionalBuiltInFeaturesSupported: Boolean,
override val isReleaseCoroutines: Boolean
) : PlatformAnalysisSettings()
data class CompositeAnalysisSettings(override val isReleaseCoroutines: Boolean) : PlatformAnalysisSettings() {
}
class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
override fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade { override fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade {
@@ -112,10 +144,9 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
): ProjectResolutionFacade { ): ProjectResolutionFacade {
val sdk = dependenciesModuleInfo.sdk val sdk = dependenciesModuleInfo.sdk
val platform = JvmPlatforms.defaultJvmPlatform // TODO: Js scripts? val platform = JvmPlatforms.defaultJvmPlatform // TODO: Js scripts?
val settings = PlatformAnalysisSettings( val settings = PlatformAnalysisSettings.create(
platform, sdk, true, project, platform, sdk, true,
LanguageFeature.ReleaseCoroutines.defaultState == LanguageFeature.State.ENABLED, LanguageFeature.ReleaseCoroutines.defaultState == LanguageFeature.State.ENABLED
false // TODO: replace with correct value
) )
val dependenciesForScriptDependencies = listOf( val dependenciesForScriptDependencies = listOf(
@@ -133,7 +164,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
getOrBuildGlobalFacade(settings).facadeForSdk getOrBuildGlobalFacade(settings).facadeForSdk
} }
val globalContext = globalFacade.globalContext.contextWithCompositeExceptionTracker(settings, "facadeForScriptDependencies") val globalContext = globalFacade.globalContext.contextWithCompositeExceptionTracker(project, "facadeForScriptDependencies")
return ProjectResolutionFacade( return ProjectResolutionFacade(
"facadeForScriptDependencies", "facadeForScriptDependencies",
resolverForScriptDependenciesName, resolverForScriptDependenciesName,
@@ -152,7 +183,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
private inner class GlobalFacade(settings: PlatformAnalysisSettings) { private inner class GlobalFacade(settings: PlatformAnalysisSettings) {
private val sdkContext = GlobalContext(resolverForSdkName) private val sdkContext = GlobalContext(resolverForSdkName)
val facadeForSdk = ProjectResolutionFacade( val facadeForSdk = ProjectResolutionFacade(
"facadeForSdk", "$resolverForSdkName ${settings.sdk}", "facadeForSdk", "$resolverForSdkName with settings=$settings",
project, sdkContext, settings, project, sdkContext, settings,
moduleFilter = { it is SdkInfo }, moduleFilter = { it is SdkInfo },
dependencies = listOf( dependencies = listOf(
@@ -163,9 +194,9 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
reuseDataFrom = null reuseDataFrom = null
) )
private val librariesContext = sdkContext.contextWithCompositeExceptionTracker(settings, resolverForLibrariesName) private val librariesContext = sdkContext.contextWithCompositeExceptionTracker(project, resolverForLibrariesName)
val facadeForLibraries = ProjectResolutionFacade( val facadeForLibraries = ProjectResolutionFacade(
"facadeForLibraries", "$resolverForLibrariesName for platform ${settings.sdk}", "facadeForLibraries", "$resolverForLibrariesName with settings=$settings",
project, librariesContext, settings, project, librariesContext, settings,
reuseDataFrom = facadeForSdk, reuseDataFrom = facadeForSdk,
moduleFilter = { it is LibraryInfo }, moduleFilter = { it is LibraryInfo },
@@ -176,9 +207,9 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
) )
) )
private val modulesContext = librariesContext.contextWithCompositeExceptionTracker(settings, resolverForModulesName) private val modulesContext = librariesContext.contextWithCompositeExceptionTracker(project, resolverForModulesName)
val facadeForModules = ProjectResolutionFacade( val facadeForModules = ProjectResolutionFacade(
"facadeForModules", "$resolverForModulesName for platform ${settings.platform}", "facadeForModules", "$resolverForModulesName with settings=$settings",
project, modulesContext, settings, project, modulesContext, settings,
reuseDataFrom = facadeForLibraries, reuseDataFrom = facadeForLibraries,
moduleFilter = { !it.isLibraryClasses() }, moduleFilter = { !it.isLibraryClasses() },
@@ -190,31 +221,18 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
) )
} }
private fun IdeaModuleInfo.platformSettings(targetPlatform: TargetPlatform) = PlatformAnalysisSettings( private fun IdeaModuleInfo.platformSettings(targetPlatform: TargetPlatform) = PlatformAnalysisSettings.create(
targetPlatform, sdk, project, targetPlatform, sdk,
supportsAdditionalBuiltInsMembers(), supportsAdditionalBuiltInsMembers(project),
isReleaseCoroutines(), isReleaseCoroutines()
isTypeRefinementEnabled()
) )
private fun IdeaModuleInfo.supportsAdditionalBuiltInsMembers(): Boolean {
return IDELanguageSettingsProvider
.getLanguageVersionSettings(this, project)
.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)
}
private fun IdeaModuleInfo.isReleaseCoroutines(): Boolean { private fun IdeaModuleInfo.isReleaseCoroutines(): Boolean {
return IDELanguageSettingsProvider return IDELanguageSettingsProvider
.getLanguageVersionSettings(this, project) .getLanguageVersionSettings(this, project)
.supportsFeature(LanguageFeature.ReleaseCoroutines) .supportsFeature(LanguageFeature.ReleaseCoroutines)
} }
private fun IdeaModuleInfo.isTypeRefinementEnabled(): Boolean {
return IDELanguageSettingsProvider
.getLanguageVersionSettings(this, project)
.isTypeRefinementEnabled()
}
private fun globalFacade(settings: PlatformAnalysisSettings) = private fun globalFacade(settings: PlatformAnalysisSettings) =
getOrBuildGlobalFacade(settings).facadeForModules getOrBuildGlobalFacade(settings).facadeForModules
@@ -225,8 +243,6 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
private fun getOrBuildGlobalFacade(settings: PlatformAnalysisSettings) = private fun getOrBuildGlobalFacade(settings: PlatformAnalysisSettings) =
globalFacadesPerPlatformAndSdk[settings] globalFacadesPerPlatformAndSdk[settings]
private val IdeaModuleInfo.sdk: Sdk? get() = dependencies().firstIsInstanceOrNull<SdkInfo>()?.sdk
private fun createFacadeForFilesWithSpecialModuleInfo(files: Set<KtFile>): ProjectResolutionFacade { private fun createFacadeForFilesWithSpecialModuleInfo(files: Set<KtFile>): ProjectResolutionFacade {
// we assume that all files come from the same module // we assume that all files come from the same module
val targetPlatform = files.map { TargetPlatformDetector.getPlatform(it) }.toSet().single() val targetPlatform = files.map { TargetPlatformDetector.getPlatform(it) }.toSet().single()
@@ -280,7 +296,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
specialModuleInfo is ModuleSourceInfo -> { specialModuleInfo is ModuleSourceInfo -> {
val dependentModules = specialModuleInfo.getDependentModules() val dependentModules = specialModuleInfo.getDependentModules()
val modulesFacade = globalFacade(settings) val modulesFacade = globalFacade(settings)
val globalContext = modulesFacade.globalContext.contextWithCompositeExceptionTracker(settings, "facadeForSpecialModuleInfo (ModuleSourceInfo)") val globalContext =
modulesFacade.globalContext.contextWithCompositeExceptionTracker(project, "facadeForSpecialModuleInfo (ModuleSourceInfo)")
makeProjectResolutionFacade( makeProjectResolutionFacade(
"facadeForSpecialModuleInfo (ModuleSourceInfo)", "facadeForSpecialModuleInfo (ModuleSourceInfo)",
globalContext, globalContext,
@@ -293,7 +310,10 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
val facadeForScriptDependencies = createFacadeForScriptDependencies( val facadeForScriptDependencies = createFacadeForScriptDependencies(
ScriptDependenciesInfo.ForFile(project, specialModuleInfo.scriptFile, specialModuleInfo.scriptDefinition) ScriptDependenciesInfo.ForFile(project, specialModuleInfo.scriptFile, specialModuleInfo.scriptDefinition)
) )
val globalContext = facadeForScriptDependencies.globalContext.contextWithCompositeExceptionTracker(settings, "facadeForSpecialModuleInfo (ScriptModuleInfo)") val globalContext = facadeForScriptDependencies.globalContext.contextWithCompositeExceptionTracker(
project,
"facadeForSpecialModuleInfo (ScriptModuleInfo)"
)
makeProjectResolutionFacade( makeProjectResolutionFacade(
"facadeForSpecialModuleInfo (ScriptModuleInfo)", "facadeForSpecialModuleInfo (ScriptModuleInfo)",
globalContext, globalContext,
@@ -304,7 +324,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
} }
specialModuleInfo is ScriptDependenciesInfo -> facadeForScriptDependenciesForProject specialModuleInfo is ScriptDependenciesInfo -> facadeForScriptDependenciesForProject
specialModuleInfo is ScriptDependenciesSourceInfo -> { specialModuleInfo is ScriptDependenciesSourceInfo -> {
val globalContext = facadeForScriptDependenciesForProject.globalContext.contextWithCompositeExceptionTracker(settings, "facadeForSpecialModuleInfo (ScriptDependenciesSourceInfo)") val globalContext =
facadeForScriptDependenciesForProject.globalContext.contextWithCompositeExceptionTracker(
project,
"facadeForSpecialModuleInfo (ScriptDependenciesSourceInfo)"
)
makeProjectResolutionFacade( makeProjectResolutionFacade(
"facadeForSpecialModuleInfo (ScriptDependenciesSourceInfo)", "facadeForSpecialModuleInfo (ScriptDependenciesSourceInfo)",
globalContext, globalContext,
@@ -317,8 +341,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
specialModuleInfo is LibrarySourceInfo || specialModuleInfo === NotUnderContentRootModuleInfo -> { specialModuleInfo is LibrarySourceInfo || specialModuleInfo === NotUnderContentRootModuleInfo -> {
val librariesFacade = librariesFacade(settings) val librariesFacade = librariesFacade(settings)
val debugName = "facadeForSpecialModuleInfo (LibrarySourceInfo or NotUnderContentRootModuleInfo)" val debugName = "facadeForSpecialModuleInfo (LibrarySourceInfo or NotUnderContentRootModuleInfo)"
val globalContext = librariesFacade.globalContext.contextWithCompositeExceptionTracker(settings, debugName) val globalContext = librariesFacade.globalContext.contextWithCompositeExceptionTracker(project, debugName)
makeProjectResolutionFacade( makeProjectResolutionFacade(
debugName, debugName,
globalContext, globalContext,
@@ -361,11 +384,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
when (annotated) { when (annotated) {
is KtFile -> { is KtFile -> {
annotated.fileAnnotationList?.analyze(BodyResolveMode.PARTIAL) annotated.fileAnnotationList?.analyze(BodyResolveMode.PARTIAL)
?: return emptyList() ?: return emptyList()
} }
is KtModifierListOwner -> { is KtModifierListOwner -> {
annotated.modifierList?.analyze(BodyResolveMode.PARTIAL) annotated.modifierList?.analyze(BodyResolveMode.PARTIAL)
?: return emptyList() ?: return emptyList()
} }
else -> else ->
annotated.analyze(BodyResolveMode.PARTIAL) annotated.analyze(BodyResolveMode.PARTIAL)
@@ -496,7 +519,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
private fun KtCodeFragment.getContextFile(): KtFile? { private fun KtCodeFragment.getContextFile(): KtFile? {
val contextElement = context ?: return null val contextElement = context ?: return null
val contextFile = (contextElement as? KtElement)?.containingKtFile val contextFile = (contextElement as? KtElement)?.containingKtFile
?: throw AssertionError("Analyzing kotlin code fragment of type ${this::class.java} with java context of type ${contextElement::class.java}") ?: throw AssertionError("Analyzing kotlin code fragment of type ${this::class.java} with java context of type ${contextElement::class.java}")
return if (contextFile is KtCodeFragment) contextFile.getContextFile() else contextFile return if (contextFile is KtCodeFragment) contextFile.getContextFile() else contextFile
} }
@@ -505,3 +528,10 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
} }
} }
fun IdeaModuleInfo.supportsAdditionalBuiltInsMembers(project: Project): Boolean {
return IDELanguageSettingsProvider
.getLanguageVersionSettings(this, project)
.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)
}
val IdeaModuleInfo.sdk: Sdk? get() = dependencies().firstIsInstanceOrNull<SdkInfo>()?.sdk
@@ -5,8 +5,10 @@
package org.jetbrains.kotlin.idea.caches.resolve.util package org.jetbrains.kotlin.idea.caches.resolve.util
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings
import org.jetbrains.kotlin.idea.project.useCompositeAnalysis
import org.jetbrains.kotlin.storage.ExceptionTracker import org.jetbrains.kotlin.storage.ExceptionTracker
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
@@ -26,8 +28,8 @@ private fun GlobalContextImpl.contextWithNewLockAndCompositeExceptionTracker(deb
) )
} }
internal fun GlobalContextImpl.contextWithCompositeExceptionTracker(settings: PlatformAnalysisSettings, debugName: String): GlobalContextImpl = internal fun GlobalContextImpl.contextWithCompositeExceptionTracker(project: Project, debugName: String): GlobalContextImpl =
if (settings.isTypeRefinementEnabled) { if (project.useCompositeAnalysis) {
this.contextWithCompositeExceptionTracker(debugName) this.contextWithCompositeExceptionTracker(debugName)
} else { } else {
this.contextWithNewLockAndCompositeExceptionTracker(debugName) this.contextWithNewLockAndCompositeExceptionTracker(debugName)