KTIJ-664 [SealedClassInheritorsProvider]: IDE-specific implementation

This commit is contained in:
Andrei Klunnyi
2020-12-10 15:09:16 +01:00
parent f02b73103b
commit 3af0257b38
17 changed files with 181 additions and 24 deletions
@@ -56,7 +56,8 @@ class CompositeResolverForModuleFactory(
moduleContext: ModuleContext,
moduleContent: ModuleContent<M>,
resolverForProject: ResolverForProject<M>,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
sealedInheritorsProvider: SealedClassInheritorsProvider
): ResolverForModule {
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
val project = moduleContext.project
@@ -178,7 +179,7 @@ class CompositeResolverForModuleFactory(
}
// Called by all normal containers set-ups
configureModule(moduleContext, targetPlatform, analyzerServices, trace, languageVersionSettings)
configureModule(moduleContext, targetPlatform, analyzerServices, trace, languageVersionSettings,)
configureStandardResolveComponents()
useInstance(moduleContentScope)
useInstance(declarationProviderFactory)
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
import org.jetbrains.kotlin.platform.idePlatformKind
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider
import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
@@ -38,7 +39,8 @@ class JsResolverForModuleFactory(
moduleContext: ModuleContext,
moduleContent: ModuleContent<M>,
resolverForProject: ResolverForProject<M>,
languageVersionSettings: LanguageVersionSettings
languageVersionSettings: LanguageVersionSettings,
sealedInheritorsProvider: SealedClassInheritorsProvider
): ResolverForModule {
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
val project = moduleContext.project
@@ -24,6 +24,7 @@ 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.compiler.IdeSealedClassInheritorsProvider
import org.jetbrains.kotlin.idea.project.findAnalyzerServices
import org.jetbrains.kotlin.idea.project.useCompositeAnalysis
import org.jetbrains.kotlin.load.java.structure.JavaClass
@@ -83,7 +84,8 @@ class IdeaResolverForProject(
projectContext.withModule(descriptor),
moduleContent,
this,
languageVersionSettings
languageVersionSettings,
sealedInheritorsProvider = IdeSealedClassInheritorsProvider
)
}
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2020 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.compiler
import com.intellij.psi.*
import com.intellij.psi.search.*
import com.intellij.psi.search.searches.ClassInheritorsSearch
import com.intellij.psi.search.searches.ClassInheritorsSearch.SearchParameters
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.containingPackage
import org.jetbrains.kotlin.idea.caches.resolve.util.javaResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.util.resolveToDescriptor
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider
object IdeSealedClassInheritorsProvider : SealedClassInheritorsProvider() {
override fun computeSealedSubclasses(
sealedClass: ClassDescriptor,
allowSealedInheritorsInDifferentFilesOfSamePackage: Boolean
): Collection<ClassDescriptor> {
val sealedKtClass = sealedClass.findPsi() as? KtClass ?: return emptyList()
val searchScope: SearchScope = if (allowSealedInheritorsInDifferentFilesOfSamePackage) {
val module = sealedKtClass.module ?: return emptyList()
val moduleSourceScope = GlobalSearchScope.moduleScope(module)
val containingPackage = sealedClass.containingPackage() ?: return emptyList()
val psiPackage = JavaDirectoryService.getInstance().getPackage(sealedKtClass.containingFile.containingDirectory)
?: JavaPsiFacade.getInstance(sealedKtClass.project).findPackage(containingPackage.asString())
?: return emptyList()
val packageScope = PackageScope(psiPackage, false, false)
moduleSourceScope.intersectWith(packageScope)
} else {
GlobalSearchScope.fileScope(sealedKtClass.containingFile) // Kotlin version prior to 1.5
}
val lightClass = sealedKtClass.toLightClass() ?: return emptyList()
val searchParameters = SearchParameters(lightClass, searchScope, false, true, false)
return ClassInheritorsSearch.search(searchParameters)
.map mapper@{
val resolutionFacade = it.javaResolutionFacade() ?: return@mapper null
it.resolveToDescriptor(resolutionFacade)
}.filterNotNull()
.sortedBy(ClassDescriptor::getName) // order needs to be stable (at least for tests)
}
}