[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:
+76
-46
@@ -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
|
||||||
+4
-2
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user