From adb0f5eaf9bfa1fa2041f185f4592747b86eea4d Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Mon, 17 Jun 2019 17:16:25 +0300 Subject: [PATCH] [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. --- .../caches/resolve/KotlinCacheServiceImpl.kt | 122 +++++++++++------- .../caches/resolve/util/globalContextUtils.kt | 6 +- 2 files changed, 80 insertions(+), 48 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt index 52459e75faa..4389aa6a515 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KotlinCacheServiceImpl.kt @@ -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.dependencies.ScriptAdditionalIdeaDependenciesProvider 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.util.ProjectRootsUtil 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) -// 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 -// meaning that we can't just change those setting on a per module basis -data class PlatformAnalysisSettings( - val platform: TargetPlatform, val sdk: Sdk?, - val isAdditionalBuiltInFeaturesSupported: Boolean, +/** + * Regulates what sources should be analyzed together. + * + * There are exactly two descendants, which are in string one-to-one correspondence with [ResolutionModeComponent.Mode] pick (meaning + * that after checking value of ResolutionMode, it's safe to downcast settings instance to the respective type): + * - [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 - val isReleaseCoroutines: Boolean, - val isTypeRefinementEnabled: Boolean -) + abstract val isReleaseCoroutines: 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 { override fun getResolutionFacade(elements: List): ResolutionFacade { @@ -112,10 +144,9 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { ): ProjectResolutionFacade { val sdk = dependenciesModuleInfo.sdk val platform = JvmPlatforms.defaultJvmPlatform // TODO: Js scripts? - val settings = PlatformAnalysisSettings( - platform, sdk, true, - LanguageFeature.ReleaseCoroutines.defaultState == LanguageFeature.State.ENABLED, - false // TODO: replace with correct value + val settings = PlatformAnalysisSettings.create( + project, platform, sdk, true, + LanguageFeature.ReleaseCoroutines.defaultState == LanguageFeature.State.ENABLED ) val dependenciesForScriptDependencies = listOf( @@ -133,7 +164,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { getOrBuildGlobalFacade(settings).facadeForSdk } - val globalContext = globalFacade.globalContext.contextWithCompositeExceptionTracker(settings, "facadeForScriptDependencies") + val globalContext = globalFacade.globalContext.contextWithCompositeExceptionTracker(project, "facadeForScriptDependencies") return ProjectResolutionFacade( "facadeForScriptDependencies", resolverForScriptDependenciesName, @@ -152,7 +183,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private inner class GlobalFacade(settings: PlatformAnalysisSettings) { private val sdkContext = GlobalContext(resolverForSdkName) val facadeForSdk = ProjectResolutionFacade( - "facadeForSdk", "$resolverForSdkName ${settings.sdk}", + "facadeForSdk", "$resolverForSdkName with settings=$settings", project, sdkContext, settings, moduleFilter = { it is SdkInfo }, dependencies = listOf( @@ -163,9 +194,9 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { reuseDataFrom = null ) - private val librariesContext = sdkContext.contextWithCompositeExceptionTracker(settings, resolverForLibrariesName) + private val librariesContext = sdkContext.contextWithCompositeExceptionTracker(project, resolverForLibrariesName) val facadeForLibraries = ProjectResolutionFacade( - "facadeForLibraries", "$resolverForLibrariesName for platform ${settings.sdk}", + "facadeForLibraries", "$resolverForLibrariesName with settings=$settings", project, librariesContext, settings, reuseDataFrom = facadeForSdk, 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( - "facadeForModules", "$resolverForModulesName for platform ${settings.platform}", + "facadeForModules", "$resolverForModulesName with settings=$settings", project, modulesContext, settings, reuseDataFrom = facadeForLibraries, moduleFilter = { !it.isLibraryClasses() }, @@ -190,31 +221,18 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { ) } - private fun IdeaModuleInfo.platformSettings(targetPlatform: TargetPlatform) = PlatformAnalysisSettings( - targetPlatform, sdk, - supportsAdditionalBuiltInsMembers(), - isReleaseCoroutines(), - isTypeRefinementEnabled() + private fun IdeaModuleInfo.platformSettings(targetPlatform: TargetPlatform) = PlatformAnalysisSettings.create( + project, targetPlatform, sdk, + supportsAdditionalBuiltInsMembers(project), + isReleaseCoroutines() ) - private fun IdeaModuleInfo.supportsAdditionalBuiltInsMembers(): Boolean { - return IDELanguageSettingsProvider - .getLanguageVersionSettings(this, project) - .supportsFeature(LanguageFeature.AdditionalBuiltInsMembers) - } - private fun IdeaModuleInfo.isReleaseCoroutines(): Boolean { return IDELanguageSettingsProvider .getLanguageVersionSettings(this, project) .supportsFeature(LanguageFeature.ReleaseCoroutines) } - private fun IdeaModuleInfo.isTypeRefinementEnabled(): Boolean { - return IDELanguageSettingsProvider - .getLanguageVersionSettings(this, project) - .isTypeRefinementEnabled() - } - private fun globalFacade(settings: PlatformAnalysisSettings) = getOrBuildGlobalFacade(settings).facadeForModules @@ -225,8 +243,6 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private fun getOrBuildGlobalFacade(settings: PlatformAnalysisSettings) = globalFacadesPerPlatformAndSdk[settings] - private val IdeaModuleInfo.sdk: Sdk? get() = dependencies().firstIsInstanceOrNull()?.sdk - private fun createFacadeForFilesWithSpecialModuleInfo(files: Set): ProjectResolutionFacade { // we assume that all files come from the same module val targetPlatform = files.map { TargetPlatformDetector.getPlatform(it) }.toSet().single() @@ -280,7 +296,8 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { specialModuleInfo is ModuleSourceInfo -> { val dependentModules = specialModuleInfo.getDependentModules() val modulesFacade = globalFacade(settings) - val globalContext = modulesFacade.globalContext.contextWithCompositeExceptionTracker(settings, "facadeForSpecialModuleInfo (ModuleSourceInfo)") + val globalContext = + modulesFacade.globalContext.contextWithCompositeExceptionTracker(project, "facadeForSpecialModuleInfo (ModuleSourceInfo)") makeProjectResolutionFacade( "facadeForSpecialModuleInfo (ModuleSourceInfo)", globalContext, @@ -293,7 +310,10 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { val facadeForScriptDependencies = createFacadeForScriptDependencies( ScriptDependenciesInfo.ForFile(project, specialModuleInfo.scriptFile, specialModuleInfo.scriptDefinition) ) - val globalContext = facadeForScriptDependencies.globalContext.contextWithCompositeExceptionTracker(settings, "facadeForSpecialModuleInfo (ScriptModuleInfo)") + val globalContext = facadeForScriptDependencies.globalContext.contextWithCompositeExceptionTracker( + project, + "facadeForSpecialModuleInfo (ScriptModuleInfo)" + ) makeProjectResolutionFacade( "facadeForSpecialModuleInfo (ScriptModuleInfo)", globalContext, @@ -304,7 +324,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { } specialModuleInfo is ScriptDependenciesInfo -> facadeForScriptDependenciesForProject specialModuleInfo is ScriptDependenciesSourceInfo -> { - val globalContext = facadeForScriptDependenciesForProject.globalContext.contextWithCompositeExceptionTracker(settings, "facadeForSpecialModuleInfo (ScriptDependenciesSourceInfo)") + val globalContext = + facadeForScriptDependenciesForProject.globalContext.contextWithCompositeExceptionTracker( + project, + "facadeForSpecialModuleInfo (ScriptDependenciesSourceInfo)" + ) makeProjectResolutionFacade( "facadeForSpecialModuleInfo (ScriptDependenciesSourceInfo)", globalContext, @@ -317,8 +341,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { specialModuleInfo is LibrarySourceInfo || specialModuleInfo === NotUnderContentRootModuleInfo -> { val librariesFacade = librariesFacade(settings) val debugName = "facadeForSpecialModuleInfo (LibrarySourceInfo or NotUnderContentRootModuleInfo)" - val globalContext = librariesFacade.globalContext.contextWithCompositeExceptionTracker(settings, debugName) - + val globalContext = librariesFacade.globalContext.contextWithCompositeExceptionTracker(project, debugName) makeProjectResolutionFacade( debugName, globalContext, @@ -361,11 +384,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { when (annotated) { is KtFile -> { annotated.fileAnnotationList?.analyze(BodyResolveMode.PARTIAL) - ?: return emptyList() + ?: return emptyList() } is KtModifierListOwner -> { annotated.modifierList?.analyze(BodyResolveMode.PARTIAL) - ?: return emptyList() + ?: return emptyList() } else -> annotated.analyze(BodyResolveMode.PARTIAL) @@ -496,7 +519,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private fun KtCodeFragment.getContextFile(): KtFile? { val contextElement = context ?: return null 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 } @@ -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()?.sdk \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/util/globalContextUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/util/globalContextUtils.kt index 171c0692c30..cf72031daa3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/util/globalContextUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/util/globalContextUtils.kt @@ -5,8 +5,10 @@ package org.jetbrains.kotlin.idea.caches.resolve.util +import com.intellij.openapi.project.Project import org.jetbrains.kotlin.context.GlobalContextImpl 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.LockBasedStorageManager @@ -26,8 +28,8 @@ private fun GlobalContextImpl.contextWithNewLockAndCompositeExceptionTracker(deb ) } -internal fun GlobalContextImpl.contextWithCompositeExceptionTracker(settings: PlatformAnalysisSettings, debugName: String): GlobalContextImpl = - if (settings.isTypeRefinementEnabled) { +internal fun GlobalContextImpl.contextWithCompositeExceptionTracker(project: Project, debugName: String): GlobalContextImpl = + if (project.useCompositeAnalysis) { this.contextWithCompositeExceptionTracker(debugName) } else { this.contextWithNewLockAndCompositeExceptionTracker(debugName)