diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt index 1e07157dc1f..9067ec4f15e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AbstractResolverForProject.kt @@ -12,8 +12,6 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.RESOLUTION_ANCHOR_PROVIDER_CAPABILITY -import org.jetbrains.kotlin.resolve.ResolutionAnchorProvider import org.jetbrains.kotlin.utils.checkWithAttachment abstract class AbstractResolverForProject( @@ -22,8 +20,7 @@ abstract class AbstractResolverForProject( modules: Collection, protected val fallbackModificationTracker: ModificationTracker? = null, private val delegateResolver: ResolverForProject = EmptyResolverForProject(), - private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory, - protected val resolutionAnchorProvider: ResolutionAnchorProvider = ResolutionAnchorProvider.Default, + private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory ) : ResolverForProject() { protected class ModuleData( @@ -196,13 +193,15 @@ abstract class AbstractResolverForProject( return moduleData } + protected open fun getAdditionalCapabilities(): Map, Any?> = emptyMap() + private fun createModuleDescriptor(module: M): ModuleData { val moduleDescriptor = ModuleDescriptorImpl( module.name, projectContext.storageManager, builtInsForModule(module), module.platform, - module.capabilities + listOf(RESOLUTION_ANCHOR_PROVIDER_CAPABILITY to resolutionAnchorProvider), + module.capabilities + getAdditionalCapabilities(), module.stableName, ) moduleInfoByDescriptor[moduleDescriptor] = module diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/ResolutionAnchorProvider.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/ResolutionAnchorProvider.kt index 0d628410af8..45ec3c898c5 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/ResolutionAnchorProvider.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/ResolutionAnchorProvider.kt @@ -9,13 +9,7 @@ import org.jetbrains.kotlin.descriptors.ModuleCapability import org.jetbrains.kotlin.descriptors.ModuleDescriptor interface ResolutionAnchorProvider { - fun getResolutionAnchor(moduleDescriptor: ModuleDescriptor): ModuleDescriptor? = null - - companion object { - val Default: ResolutionAnchorProvider = object : ResolutionAnchorProvider { - override fun getResolutionAnchor(moduleDescriptor: ModuleDescriptor): ModuleDescriptor? = null - } - } + fun getResolutionAnchor(moduleDescriptor: ModuleDescriptor): ModuleDescriptor? } val RESOLUTION_ANCHOR_PROVIDER_CAPABILITY = ModuleCapability("ResolutionAnchorProvider") diff --git a/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/KotlinCacheService.kt b/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/KotlinCacheService.kt index 2e34d91ed1b..09d791d4efe 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/KotlinCacheService.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/KotlinCacheService.kt @@ -21,8 +21,8 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiFile import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.idea.resolve.ResolutionFacade -import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache interface KotlinCacheService { @@ -36,4 +36,6 @@ interface KotlinCacheService { fun getSuppressionCache(): KotlinSuppressCache fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? + + fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, settings: PlatformAnalysisSettings): ResolutionFacade? } \ No newline at end of file diff --git a/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/PlatformAnalysisSettings.kt b/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/PlatformAnalysisSettings.kt new file mode 100644 index 00000000000..e4a1dc19707 --- /dev/null +++ b/idea/ide-common/src/org/jetbrains/kotlin/caches/resolve/PlatformAnalysisSettings.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2021 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.caches.resolve + +/** + * Regulates which sources should be analyzed together. + * + * There are exactly two descendants, which are in strong one-to-one correspondence with [ResolutionModeComponent.Mode] (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 + */ +interface PlatformAnalysisSettings \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaResolverForProject.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaResolverForProject.kt index a9e07b5b3d4..265c9f7a28b 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaResolverForProject.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IdeaResolverForProject.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.idea.caches.resolve import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.util.ModificationTracker import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters @@ -14,6 +13,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.caches.resolve.* import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.context.withModule +import org.jetbrains.kotlin.descriptors.ModuleCapability import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.idea.caches.project.* @@ -32,6 +32,7 @@ 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.KtFile +import org.jetbrains.kotlin.resolve.RESOLUTION_ANCHOR_PROVIDER_CAPABILITY import org.jetbrains.kotlin.resolve.ResolutionAnchorProvider import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters @@ -42,20 +43,34 @@ class IdeaResolverForProject( private val syntheticFilesByModule: Map>, delegateResolver: ResolverForProject, fallbackModificationTracker: ModificationTracker? = null, - // TODO(dsavvinov): this is needed only for non-composite analysis, extract separate resolver implementation instead - private val constantSdkDependencyIfAny: SdkInfo? = null + private val settings: PlatformAnalysisSettings ) : AbstractResolverForProject( debugName, projectContext, modules, fallbackModificationTracker, delegateResolver, - ServiceManager.getService(projectContext.project, IdePackageOracleFactory::class.java), - ServiceManager.getService(projectContext.project, ResolutionAnchorProvider::class.java) + ServiceManager.getService(projectContext.project, IdePackageOracleFactory::class.java) ) { + + companion object { + val PLATFORM_ANALYSIS_SETTINGS = ModuleCapability("PlatformAnalysisSettings") + } + + private val resolutionAnchorProvider = ServiceManager.getService(projectContext.project, ResolutionAnchorProvider::class.java) + + private val constantSdkDependencyIfAny: SdkInfo? = + if (settings is PlatformAnalysisSettingsImpl) settings.sdk?.let { SdkInfo(projectContext.project, it) } else null + private val builtInsCache: BuiltInsCache = (delegateResolver as? IdeaResolverForProject)?.builtInsCache ?: BuiltInsCache(projectContext, this) + override fun getAdditionalCapabilities(): Map, Any?> { + return super.getAdditionalCapabilities() + + (PLATFORM_ANALYSIS_SETTINGS to settings) + + (RESOLUTION_ANCHOR_PROVIDER_CAPABILITY to resolutionAnchorProvider) + } + override fun sdkDependency(module: IdeaModuleInfo): SdkInfo? { if (projectContext.project.useCompositeAnalysis) { require(constantSdkDependencyIfAny == null) { "Shouldn't pass SDK dependency manually for composite analysis mode" } 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 ca4cf51cfab..5c9576558f1 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 @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForSdk import org.jetbrains.kotlin.analyzer.ResolverForProject.Companion.resolverForSpecialInfoName import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.caches.resolve.KotlinCacheService +import org.jetbrains.kotlin.caches.resolve.PlatformAnalysisSettings import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.context.GlobalContext import org.jetbrains.kotlin.context.GlobalContextImpl @@ -66,41 +67,24 @@ import org.jetbrains.kotlin.utils.addToStdlib.sumByLong internal val LOG = Logger.getInstance(KotlinCacheService::class.java) -/** - * Regulates which sources should be analyzed together. - * - * There are exactly two descendants, which are in strong one-to-one correspondence with [ResolutionModeComponent.Mode] (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 { - companion object { - fun create( - project: Project, - platform: TargetPlatform, - sdk: Sdk?, - isAdditionalBuiltInFeaturesSupported: Boolean - ) = if (project.useCompositeAnalysis) - CompositeAnalysisSettings - else - PlatformAnalysisSettingsImpl(platform, sdk, isAdditionalBuiltInFeaturesSupported) - } -} - data class PlatformAnalysisSettingsImpl( val platform: TargetPlatform, val sdk: Sdk?, val isAdditionalBuiltInFeaturesSupported: Boolean, -) : PlatformAnalysisSettings() +) : PlatformAnalysisSettings + +object CompositeAnalysisSettings : PlatformAnalysisSettings + +fun createPlatformAnalysisSettings( + project: Project, + platform: TargetPlatform, + sdk: Sdk?, + isAdditionalBuiltInFeaturesSupported: Boolean +) = if (project.useCompositeAnalysis) + CompositeAnalysisSettings +else + PlatformAnalysisSettingsImpl(platform, sdk, isAdditionalBuiltInFeaturesSupported) -object CompositeAnalysisSettings : PlatformAnalysisSettings() class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { override fun getResolutionFacade(elements: List): ResolutionFacade { @@ -144,7 +128,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { ): ProjectResolutionFacade { val sdk = dependenciesModuleInfo.sdk val platform = JvmPlatforms.defaultJvmPlatform // TODO: Js scripts? - val settings = PlatformAnalysisSettings.create(project, platform, sdk, true) + val settings = createPlatformAnalysisSettings(project, platform, sdk, true) val dependenciesForScriptDependencies = listOf( LibraryModificationTracker.getInstance(project), @@ -217,7 +201,7 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { ) } - private fun IdeaModuleInfo.platformSettings(targetPlatform: TargetPlatform) = PlatformAnalysisSettings.create( + private fun IdeaModuleInfo.platformSettings(targetPlatform: TargetPlatform) = createPlatformAnalysisSettings( this@KotlinCacheServiceImpl.project, targetPlatform, sdk, supportsAdditionalBuiltInsMembers(this@KotlinCacheServiceImpl.project) ) @@ -469,6 +453,13 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { private fun getResolutionFacadeByModuleInfo(moduleInfo: IdeaModuleInfo, platform: TargetPlatform): ResolutionFacade { val settings = moduleInfo.platformSettings(platform) + return getResolutionFacadeByModuleInfoAndSettings(moduleInfo, settings) + } + + private fun getResolutionFacadeByModuleInfoAndSettings( + moduleInfo: IdeaModuleInfo, + settings: PlatformAnalysisSettings + ): ResolutionFacade { val projectFacade = when (moduleInfo) { is ScriptDependenciesInfo.ForProject, is ScriptDependenciesSourceInfo.ForProject -> facadeForScriptDependenciesForProject @@ -481,6 +472,11 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService { override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? = (moduleInfo as? IdeaModuleInfo)?.let { getResolutionFacadeByModuleInfo(it, platform) } + override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, settings: PlatformAnalysisSettings): ResolutionFacade? { + val ideaModuleInfo = moduleInfo as? IdeaModuleInfo ?: return null + return getResolutionFacadeByModuleInfoAndSettings(ideaModuleInfo, settings) + } + private fun Collection.filterNotInProjectSource(moduleInfo: IdeaModuleInfo): Set { return mapNotNull { if (it is KtCodeFragment) it.getContextFile() else it diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt index 416bd50016b..50750a43a97 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/ProjectResolutionFacade.kt @@ -14,6 +14,7 @@ import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager import com.intellij.util.containers.SLRUCache import org.jetbrains.kotlin.analyzer.* +import org.jetbrains.kotlin.caches.resolve.PlatformAnalysisSettings import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.withProject import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -116,17 +117,15 @@ internal class ProjectResolutionFacade( val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter) - val resolverForProject = IdeaResolverForProject( + return IdeaResolverForProject( resolverDebugName, globalContext.withProject(project), modulesToCreateResolversFor, syntheticFilesByModule, delegateResolverForProject, if (invalidateOnOOCB) KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker else null, - constantSdkDependencyIfAny = if (settings is PlatformAnalysisSettingsImpl) settings.sdk?.let { SdkInfo(project, it) } else null + settings ) - - return resolverForProject } internal fun resolverForModuleInfo(moduleInfo: IdeaModuleInfo) = cachedResolverForProject.resolverForModule(moduleInfo) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/compiler/IdeSealedClassInheritorsProvider.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/compiler/IdeSealedClassInheritorsProvider.kt index 493726659fd..9760f4f9240 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/compiler/IdeSealedClassInheritorsProvider.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/compiler/IdeSealedClassInheritorsProvider.kt @@ -6,20 +6,27 @@ package org.jetbrains.kotlin.idea.compiler import com.intellij.openapi.module.Module -import com.intellij.psi.* -import com.intellij.psi.search.* +import com.intellij.openapi.project.Project +import com.intellij.psi.JavaDirectoryService +import com.intellij.psi.PsiPackage +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.PackageScope +import com.intellij.psi.search.SearchScope import com.intellij.psi.search.searches.ClassInheritorsSearch import com.intellij.psi.search.searches.ClassInheritorsSearch.SearchParameters +import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.moduleInfo import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.containingPackage import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors -import org.jetbrains.kotlin.idea.caches.resolve.util.javaResolutionFacade +import org.jetbrains.kotlin.idea.caches.resolve.IdeaResolverForProject.Companion.PLATFORM_ANALYSIS_SETTINGS import org.jetbrains.kotlin.idea.caches.resolve.util.resolveToDescriptor +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.psi.KtClass @@ -36,6 +43,9 @@ object IdeSealedClassInheritorsProvider : SealedClassInheritorsProvider() { ): Collection { val sealedKtClass = sealedClass.findPsi() as? KtClass ?: return emptyList() + val project = sealedKtClass.project + val moduleDescriptor = sealedClass.module + val searchScope: SearchScope = if (allowSealedInheritorsInDifferentFilesOfSamePackage) { val module = sealedKtClass.module ?: return emptyList() @@ -46,7 +56,7 @@ object IdeSealedClassInheritorsProvider : SealedClassInheritorsProvider() { val mppAwareSearchScope = GlobalSearchScope.union(modulesScope) val containingPackage = sealedClass.containingPackage() ?: return emptyList() - val psiPackage = KotlinJavaPsiFacade.getInstance(sealedKtClass.project) + val psiPackage = KotlinJavaPsiFacade.getInstance(project) .findPackage(containingPackage.asString(), GlobalSearchScope.moduleScope(module)) ?: getPackageViaDirectoryService(sealedKtClass) ?: return emptyList() @@ -57,15 +67,14 @@ object IdeSealedClassInheritorsProvider : SealedClassInheritorsProvider() { GlobalSearchScope.fileScope(sealedKtClass.containingFile) // Kotlin version prior to 1.5 } - val kotlinAsJavaSupport = KotlinAsJavaSupport.getInstance(sealedKtClass.project) + val kotlinAsJavaSupport = KotlinAsJavaSupport.getInstance(project) val lightClass = sealedKtClass.toLightClass() ?: kotlinAsJavaSupport.getFakeLightClass(sealedKtClass) val searchParameters = SearchParameters(lightClass, searchScope, false, true, false) + val resolutionFacade = getResolutionFacade(moduleDescriptor, project) ?: return emptyList() + return ClassInheritorsSearch.search(searchParameters) - .map mapper@{ - val resolutionFacade = it.javaResolutionFacade() ?: return@mapper null - it.resolveToDescriptor(resolutionFacade) - }.filterNotNull() + .mapNotNull { it.resolveToDescriptor(resolutionFacade) } .sortedBy(ClassDescriptor::getName) // order needs to be stable (at least for tests) } @@ -78,4 +87,10 @@ object IdeSealedClassInheritorsProvider : SealedClassInheritorsProvider() { val directory = ktClass.containingFile.containingDirectory ?: return null return JavaDirectoryService.getInstance().getPackage(directory) } +} + +private fun getResolutionFacade(moduleDescriptor: ModuleDescriptor, project: Project): ResolutionFacade? { + val analysisSettings = moduleDescriptor.getCapability(PLATFORM_ANALYSIS_SETTINGS) ?: return null + val moduleInfo = moduleDescriptor.getCapability(ModuleInfo.Capability) ?: return null + return KotlinCacheService.getInstance(project).getResolutionFacadeByModuleInfo(moduleInfo, analysisSettings) } \ No newline at end of file