KTIJ-664 [SealedClassInheritorsProvider]: IDE-specific implementation
This commit is contained in:
@@ -41,10 +41,8 @@ import org.jetbrains.kotlin.load.kotlin.DeserializationComponentsForJava
|
|||||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
|
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitsExtensionsResolutionFilter
|
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitsExtensionsResolutionFilter
|
||||||
import org.jetbrains.kotlin.resolve.createContainer
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmDiagnosticComponents
|
import org.jetbrains.kotlin.resolve.jvm.JvmDiagnosticComponents
|
||||||
import org.jetbrains.kotlin.resolve.jvm.multiplatform.OptionalAnnotationPackageFragmentProvider
|
import org.jetbrains.kotlin.resolve.jvm.multiplatform.OptionalAnnotationPackageFragmentProvider
|
||||||
@@ -68,8 +66,12 @@ fun createContainerForLazyResolveWithJava(
|
|||||||
configureJavaClassFinder: (StorageComponentContainer.() -> Unit)? = null,
|
configureJavaClassFinder: (StorageComponentContainer.() -> Unit)? = null,
|
||||||
javaClassTracker: JavaClassesTracker? = null,
|
javaClassTracker: JavaClassesTracker? = null,
|
||||||
implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter? = null,
|
implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter? = null,
|
||||||
|
sealedInheritorsProvider: SealedClassInheritorsProvider = CliSealedClassInheritorsProvider
|
||||||
): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatformAnalyzerServices) {
|
): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatformAnalyzerServices) {
|
||||||
configureModule(moduleContext, jvmPlatform, JvmPlatformAnalyzerServices, bindingTrace, languageVersionSettings)
|
configureModule(
|
||||||
|
moduleContext, jvmPlatform, JvmPlatformAnalyzerServices, bindingTrace, languageVersionSettings,
|
||||||
|
sealedInheritorsProvider
|
||||||
|
)
|
||||||
|
|
||||||
configureIncrementalCompilation(lookupTracker, expectActualTracker)
|
configureIncrementalCompilation(lookupTracker, expectActualTracker)
|
||||||
configureStandardResolveComponents()
|
configureStandardResolveComponents()
|
||||||
|
|||||||
+4
-1
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
|||||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||||
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
|
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
|
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider
|
||||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||||
@@ -54,7 +55,8 @@ class JvmResolverForModuleFactory(
|
|||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
moduleContent: ModuleContent<M>,
|
moduleContent: ModuleContent<M>,
|
||||||
resolverForProject: ResolverForProject<M>,
|
resolverForProject: ResolverForProject<M>,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
sealedInheritorsProvider: SealedClassInheritorsProvider
|
||||||
): ResolverForModule {
|
): ResolverForModule {
|
||||||
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
||||||
val project = moduleContext.project
|
val project = moduleContext.project
|
||||||
@@ -108,6 +110,7 @@ class JvmResolverForModuleFactory(
|
|||||||
ExpectActualTracker.DoNothing,
|
ExpectActualTracker.DoNothing,
|
||||||
packagePartProvider,
|
packagePartProvider,
|
||||||
languageVersionSettings,
|
languageVersionSettings,
|
||||||
|
sealedInheritorsProvider = sealedInheritorsProvider,
|
||||||
useBuiltInsProvider = false // TODO: load built-ins from module dependencies in IDE
|
useBuiltInsProvider = false // TODO: load built-ins from module dependencies in IDE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatformVersion
|
import org.jetbrains.kotlin.platform.TargetPlatformVersion
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider
|
||||||
|
import org.jetbrains.kotlin.resolve.CliSealedClassInheritorsProvider
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.storage.getValue
|
import org.jetbrains.kotlin.storage.getValue
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -119,7 +121,8 @@ abstract class ResolverForModuleFactory {
|
|||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
moduleContent: ModuleContent<M>,
|
moduleContent: ModuleContent<M>,
|
||||||
resolverForProject: ResolverForProject<M>,
|
resolverForProject: ResolverForProject<M>,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
sealedInheritorsProvider: SealedClassInheritorsProvider = CliSealedClassInheritorsProvider
|
||||||
): ResolverForModule
|
): ResolverForModule
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -85,7 +85,8 @@ class CommonResolverForModuleFactory(
|
|||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
moduleContent: ModuleContent<M>,
|
moduleContent: ModuleContent<M>,
|
||||||
resolverForProject: ResolverForProject<M>,
|
resolverForProject: ResolverForProject<M>,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
sealedInheritorsProvider: SealedClassInheritorsProvider
|
||||||
): ResolverForModule {
|
): ResolverForModule {
|
||||||
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
||||||
val project = moduleContext.project
|
val project = moduleContext.project
|
||||||
|
|||||||
@@ -51,8 +51,10 @@ fun StorageComponentContainer.configureModule(
|
|||||||
platform: TargetPlatform,
|
platform: TargetPlatform,
|
||||||
analyzerServices: PlatformDependentAnalyzerServices,
|
analyzerServices: PlatformDependentAnalyzerServices,
|
||||||
trace: BindingTrace,
|
trace: BindingTrace,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
sealedProvider: SealedClassInheritorsProvider = CliSealedClassInheritorsProvider
|
||||||
) {
|
) {
|
||||||
|
useInstance(sealedProvider)
|
||||||
useInstance(moduleContext)
|
useInstance(moduleContext)
|
||||||
useInstance(moduleContext.module)
|
useInstance(moduleContext.module)
|
||||||
useInstance(moduleContext.project)
|
useInstance(moduleContext.project)
|
||||||
@@ -103,7 +105,6 @@ private fun StorageComponentContainer.configurePlatformIndependentComponents() {
|
|||||||
useImpl<ClassicTypeSystemContextForCS>()
|
useImpl<ClassicTypeSystemContextForCS>()
|
||||||
useImpl<ClassicConstraintSystemUtilContext>()
|
useImpl<ClassicConstraintSystemUtilContext>()
|
||||||
useInstance(ProgressManagerBasedCancellationChecker)
|
useInstance(ProgressManagerBasedCancellationChecker)
|
||||||
useInstance(SealedClassInheritorsProviderImpl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,17 +18,17 @@ abstract class SealedClassInheritorsProvider {
|
|||||||
*/
|
*/
|
||||||
abstract fun computeSealedSubclasses(
|
abstract fun computeSealedSubclasses(
|
||||||
sealedClass: ClassDescriptor,
|
sealedClass: ClassDescriptor,
|
||||||
freedomForSealedInterfacesSupported: Boolean
|
allowSealedInheritorsInDifferentFilesOfSamePackage: Boolean
|
||||||
): Collection<ClassDescriptor>
|
): Collection<ClassDescriptor>
|
||||||
}
|
}
|
||||||
|
|
||||||
object SealedClassInheritorsProviderImpl : SealedClassInheritorsProvider() {
|
object CliSealedClassInheritorsProvider : SealedClassInheritorsProvider() {
|
||||||
// Note this is a generic and slow implementation which would work almost for any subclass of ClassDescriptor.
|
// Note this is a generic and slow implementation which would work almost for any subclass of ClassDescriptor.
|
||||||
// Please avoid using it in new code.
|
// Please avoid using it in new code.
|
||||||
// TODO: do something more clever instead at call sites of this function
|
// TODO: do something more clever instead at call sites of this function
|
||||||
override fun computeSealedSubclasses(
|
override fun computeSealedSubclasses(
|
||||||
sealedClass: ClassDescriptor,
|
sealedClass: ClassDescriptor,
|
||||||
freedomForSealedInterfacesSupported: Boolean
|
allowSealedInheritorsInDifferentFilesOfSamePackage: Boolean
|
||||||
): Collection<ClassDescriptor> {
|
): Collection<ClassDescriptor> {
|
||||||
if (sealedClass.modality != Modality.SEALED) return emptyList()
|
if (sealedClass.modality != Modality.SEALED) return emptyList()
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ object SealedClassInheritorsProviderImpl : SealedClassInheritorsProvider() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val container = if (!freedomForSealedInterfacesSupported) {
|
val container = if (!allowSealedInheritorsInDifferentFilesOfSamePackage) {
|
||||||
sealedClass.containingDeclaration
|
sealedClass.containingDeclaration
|
||||||
} else {
|
} else {
|
||||||
sealedClass.parents.firstOrNull { it is PackageFragmentDescriptor }
|
sealedClass.parents.firstOrNull { it is PackageFragmentDescriptor }
|
||||||
@@ -56,7 +56,7 @@ object SealedClassInheritorsProviderImpl : SealedClassInheritorsProvider() {
|
|||||||
if (container is PackageFragmentDescriptor) {
|
if (container is PackageFragmentDescriptor) {
|
||||||
collectSubclasses(
|
collectSubclasses(
|
||||||
container.getMemberScope(),
|
container.getMemberScope(),
|
||||||
collectNested = freedomForSealedInterfacesSupported
|
collectNested = allowSealedInheritorsInDifferentFilesOfSamePackage
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
collectSubclasses(sealedClass.unsubstitutedInnerClassesScope, collectNested = true)
|
collectSubclasses(sealedClass.unsubstitutedInnerClassesScope, collectNested = true)
|
||||||
|
|||||||
+2
-2
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||||
import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy
|
import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProviderImpl
|
import org.jetbrains.kotlin.resolve.CliSealedClassInheritorsProvider
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
@@ -165,7 +165,7 @@ class DeserializedClassDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is needed because classes compiled with Kotlin 1.0 did not contain the sealed_subclass_fq_name field
|
// This is needed because classes compiled with Kotlin 1.0 did not contain the sealed_subclass_fq_name field
|
||||||
return SealedClassInheritorsProviderImpl.computeSealedSubclasses(this, freedomForSealedInterfacesSupported = false)
|
return CliSealedClassInheritorsProvider.computeSealedSubclasses(this, allowSealedInheritorsInDifferentFilesOfSamePackage = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSealedSubclasses() = sealedSubclasses()
|
override fun getSealedSubclasses() = sealedSubclasses()
|
||||||
|
|||||||
+3
-2
@@ -56,7 +56,8 @@ class CompositeResolverForModuleFactory(
|
|||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
moduleContent: ModuleContent<M>,
|
moduleContent: ModuleContent<M>,
|
||||||
resolverForProject: ResolverForProject<M>,
|
resolverForProject: ResolverForProject<M>,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
sealedInheritorsProvider: SealedClassInheritorsProvider
|
||||||
): ResolverForModule {
|
): ResolverForModule {
|
||||||
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
||||||
val project = moduleContext.project
|
val project = moduleContext.project
|
||||||
@@ -178,7 +179,7 @@ class CompositeResolverForModuleFactory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called by all normal containers set-ups
|
// Called by all normal containers set-ups
|
||||||
configureModule(moduleContext, targetPlatform, analyzerServices, trace, languageVersionSettings)
|
configureModule(moduleContext, targetPlatform, analyzerServices, trace, languageVersionSettings,)
|
||||||
configureStandardResolveComponents()
|
configureStandardResolveComponents()
|
||||||
useInstance(moduleContentScope)
|
useInstance(moduleContentScope)
|
||||||
useInstance(declarationProviderFactory)
|
useInstance(declarationProviderFactory)
|
||||||
|
|||||||
+3
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
|
|||||||
import org.jetbrains.kotlin.platform.idePlatformKind
|
import org.jetbrains.kotlin.platform.idePlatformKind
|
||||||
import org.jetbrains.kotlin.platform.js.JsPlatforms
|
import org.jetbrains.kotlin.platform.js.JsPlatforms
|
||||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
||||||
|
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider
|
||||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||||
@@ -38,7 +39,8 @@ class JsResolverForModuleFactory(
|
|||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
moduleContent: ModuleContent<M>,
|
moduleContent: ModuleContent<M>,
|
||||||
resolverForProject: ResolverForProject<M>,
|
resolverForProject: ResolverForProject<M>,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
sealedInheritorsProvider: SealedClassInheritorsProvider
|
||||||
): ResolverForModule {
|
): ResolverForModule {
|
||||||
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
|
||||||
val project = moduleContext.project
|
val project = moduleContext.project
|
||||||
|
|||||||
+3
-1
@@ -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.caches.project.getNullableModuleInfo
|
||||||
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
|
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
|
||||||
import org.jetbrains.kotlin.idea.project.IdeaEnvironment
|
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.findAnalyzerServices
|
||||||
import org.jetbrains.kotlin.idea.project.useCompositeAnalysis
|
import org.jetbrains.kotlin.idea.project.useCompositeAnalysis
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||||
@@ -83,7 +84,8 @@ class IdeaResolverForProject(
|
|||||||
projectContext.withModule(descriptor),
|
projectContext.withModule(descriptor),
|
||||||
moduleContent,
|
moduleContent,
|
||||||
this,
|
this,
|
||||||
languageVersionSettings
|
languageVersionSettings,
|
||||||
|
sealedInheritorsProvider = IdeSealedClassInheritorsProvider
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+53
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.platform.TargetPlatform
|
|||||||
import org.jetbrains.kotlin.platform.idePlatformKind
|
import org.jetbrains.kotlin.platform.idePlatformKind
|
||||||
import org.jetbrains.kotlin.platform.konan.NativePlatforms
|
import org.jetbrains.kotlin.platform.konan.NativePlatforms
|
||||||
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
|
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
|
||||||
|
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider
|
||||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||||
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
|
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||||
@@ -32,7 +33,8 @@ class NativeResolverForModuleFactory(
|
|||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
moduleContent: ModuleContent<M>,
|
moduleContent: ModuleContent<M>,
|
||||||
resolverForProject: ResolverForProject<M>,
|
resolverForProject: ResolverForProject<M>,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
sealedInheritorsProvider: SealedClassInheritorsProvider
|
||||||
): ResolverForModule {
|
): ResolverForModule {
|
||||||
|
|
||||||
val declarationProviderFactory = createDeclarationProviderFactory(
|
val declarationProviderFactory = createDeclarationProviderFactory(
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// COMPILER_ARGUMENTS: -XXLanguage:+SealedInterfaces -XXLanguage:+FreedomForSealedClasses
|
||||||
|
|
||||||
|
package sealed
|
||||||
|
|
||||||
|
sealed class SealedDeclarationClass {
|
||||||
|
class AClass: SealedDeclarationClass()
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface SealedDeclarationInterface {
|
||||||
|
class A: SealedDeclarationInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
class B: SealedDeclarationInterface
|
||||||
|
class BClass: SealedDeclarationClass()
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// COMPILER_ARGUMENTS: -XXLanguage:+SealedInterfaces -XXLanguage:+FreedomForSealedClasses
|
||||||
|
package sealed
|
||||||
|
|
||||||
|
class C: SealedDeclarationInterface {}
|
||||||
|
class CClass: SealedDeclarationClass() {}
|
||||||
|
|
||||||
|
class D: SealedDeclarationInterface {
|
||||||
|
class E: SealedDeclarationInterface {
|
||||||
|
class F: SealedDeclarationInterface
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DClass: SealedDeclarationClass() {
|
||||||
|
class EClass: SealedDeclarationClass() {
|
||||||
|
class FClass: SealedDeclarationClass()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkWhenNone(value: SealedDeclarationInterface): Int = <error descr="[NO_ELSE_IN_WHEN] 'when' expression must be exhaustive, add necessary 'is A', 'is B', 'is C', 'is D', 'is E', 'is F' branches or 'else' branch instead">when</error> (<warning descr="[UNUSED_EXPRESSION] The expression is unused">value</warning>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkWhenNone(value: SealedDeclarationClass): Int = <error descr="[NO_ELSE_IN_WHEN] 'when' expression must be exhaustive, add necessary 'is AClass', 'is BClass', 'is CClass', 'is DClass', 'is EClass', 'is FClass' branches or 'else' branch instead">when</error> (<warning descr="[UNUSED_EXPRESSION] The expression is unused">value</warning>) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkWhenOneMissing(value: SealedDeclarationInterface): Int = <error descr="[NO_ELSE_IN_WHEN] 'when' expression must be exhaustive, add necessary 'is D', 'is E', 'is F' branches or 'else' branch instead">when</error> (value) {
|
||||||
|
is SealedDeclarationInterface.A -> 1
|
||||||
|
is B -> 2
|
||||||
|
is C -> 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkWhenOneMissing(value: SealedDeclarationClass): Int = <error descr="[NO_ELSE_IN_WHEN] 'when' expression must be exhaustive, add necessary 'is DClass', 'is EClass', 'is FClass' branches or 'else' branch instead">when</error> (value) {
|
||||||
|
is SealedDeclarationClass.AClass -> 1
|
||||||
|
is BClass -> 2
|
||||||
|
is CClass -> 3
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// COMPILER_ARGUMENTS: -XXLanguage:+SealedInterfaces -XXLanguage:+FreedomForSealedClasses
|
||||||
|
package sealed.otherpackage
|
||||||
|
import sealed.SealedDeclarationInterface
|
||||||
|
import sealed.SealedDeclarationClass
|
||||||
|
|
||||||
|
class D: <error descr="[SEALED_INHERITOR_IN_DIFFERENT_PACKAGE] Inheritor of sealed class or interface declared in package sealed but it must be in package {2} where base class is declared">SealedDeclarationInterface</error>
|
||||||
|
class DClass: <error descr="[SEALED_INHERITOR_IN_DIFFERENT_PACKAGE] Inheritor of sealed class or interface declared in package sealed but it must be in package {2} where base class is declared">SealedDeclarationClass</error>()
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.checkers
|
||||||
|
|
||||||
|
import com.intellij.testFramework.LightProjectDescriptor
|
||||||
|
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/checker/sealed")
|
||||||
|
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
|
||||||
|
class PsiCheckerSealedTest : AbstractPsiCheckerTest() {
|
||||||
|
|
||||||
|
fun testOutsideOfPackageInheritors() {
|
||||||
|
doTest(
|
||||||
|
"SealedOutsidePackageInheritors.kt", // opened in the test editor
|
||||||
|
"SealedDeclaration.kt"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testWhenExhaustiveness() {
|
||||||
|
doTest(
|
||||||
|
"SealedInheritors.kt", // opened in the test editor
|
||||||
|
"SealedDeclaration.kt"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getProjectDescriptor(): LightProjectDescriptor = getProjectDescriptorFromTestName()
|
||||||
|
}
|
||||||
+2
-3
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.descriptors.commonizer.builder
|
package org.jetbrains.kotlin.descriptors.commonizer.builder
|
||||||
|
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
|
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
|
||||||
@@ -15,7 +14,7 @@ import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase
|
|||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorFactory.createPrimaryConstructorForObject
|
import org.jetbrains.kotlin.resolve.DescriptorFactory.createPrimaryConstructorForObject
|
||||||
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProviderImpl
|
import org.jetbrains.kotlin.resolve.CliSealedClassInheritorsProvider
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.StaticScopeForKotlinEnum
|
import org.jetbrains.kotlin.resolve.scopes.StaticScopeForKotlinEnum
|
||||||
@@ -55,7 +54,7 @@ class CommonizedClassDescriptor(
|
|||||||
private val sealedSubclasses = targetComponents.storageManager.createLazyValue {
|
private val sealedSubclasses = targetComponents.storageManager.createLazyValue {
|
||||||
// TODO: pass proper language version settings
|
// TODO: pass proper language version settings
|
||||||
if (modality == Modality.SEALED) {
|
if (modality == Modality.SEALED) {
|
||||||
SealedClassInheritorsProviderImpl.computeSealedSubclasses(this, freedomForSealedInterfacesSupported = false)
|
CliSealedClassInheritorsProvider.computeSealedSubclasses(this, allowSealedInheritorsInDifferentFilesOfSamePackage = false)
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user