Clean up API of AbstractResolverForProject
Resolution anchors are IDE-specific. Creating dedicated methods for them in AbstractResolverForProject leads to meaningless implementation in non-IDE resolvers. Now this method is implemented only for IDE resolver and accessed through JvmPlatformParameters. #KT-24309 In Progress
This commit is contained in:
+22
-13
@@ -38,7 +38,9 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
|
||||
class JvmPlatformParameters(
|
||||
val packagePartProviderFactory: (ModuleContent<*>) -> PackagePartProvider,
|
||||
val moduleByJavaClass: (JavaClass) -> ModuleInfo?
|
||||
val moduleByJavaClass: (JavaClass) -> ModuleInfo?,
|
||||
// params: referenced module info of target class, context module info of current resolver
|
||||
val resolverForReferencedModule: ((ModuleInfo, ModuleInfo) -> ResolverForModule?)? = null,
|
||||
) : PlatformAnalysisParameters
|
||||
|
||||
|
||||
@@ -63,14 +65,21 @@ class JvmResolverForModuleFactory(
|
||||
)
|
||||
|
||||
val moduleClassResolver = ModuleClassResolverImpl { javaClass ->
|
||||
val referencedClassModule = (platformParameters as JvmPlatformParameters).moduleByJavaClass(javaClass)
|
||||
// We don't have full control over idea resolve api so we allow for a situation which should not happen in Kotlin.
|
||||
// For example, type in a java library can reference a class declared in a source root (is valid but rare case)
|
||||
// Providing a fallback strategy in this case can hide future problems, so we should at least log to be able to diagnose those
|
||||
val referencedClassModule = platformParameters.moduleByJavaClass(javaClass)
|
||||
// A type in a java library can reference a class declared in a source root (is valid but rare case).
|
||||
// Resolving such a class with Kotlin resolver for libraries is guaranteed to fail, as libraries can't
|
||||
// have dependencies on the source roots. The chain of resolvers (sources -> libraries -> sdk) exists to prevent
|
||||
// potentially slow repetitive analysis of the same libraries after modifications in sources. The only way to mitigate
|
||||
// this restriction currently is to manually configure resolution anchors for known source-dependent libraries in a project.
|
||||
// See also KT-24309
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val resolverForReferencedModule = referencedClassModule?.let {
|
||||
resolverForProject.tryGetResolverForModuleWithResolutionAnchorFallback(it as M, moduleInfo)
|
||||
val resolverForReferencedModule = referencedClassModule?.let { referencedModuleInfo ->
|
||||
if (platformParameters.resolverForReferencedModule != null) {
|
||||
platformParameters.resolverForReferencedModule.invoke(referencedModuleInfo, moduleInfo)
|
||||
} else {
|
||||
resolverForProject.tryGetResolverForModule(referencedModuleInfo as M)
|
||||
}
|
||||
}
|
||||
|
||||
val resolverForModule = resolverForReferencedModule?.takeIf {
|
||||
@@ -111,12 +120,12 @@ class JvmResolverForModuleFactory(
|
||||
)
|
||||
|
||||
providersForModule +=
|
||||
PackageFragmentProviderExtension.getInstances(project)
|
||||
.mapNotNull {
|
||||
it.getPackageFragmentProvider(
|
||||
project, moduleDescriptor, moduleContext.storageManager, trace, moduleInfo, lookupTracker
|
||||
)
|
||||
}
|
||||
PackageFragmentProviderExtension.getInstances(project)
|
||||
.mapNotNull {
|
||||
it.getPackageFragmentProvider(
|
||||
project, moduleDescriptor, moduleContext.storageManager, trace, moduleInfo, lookupTracker
|
||||
)
|
||||
}
|
||||
|
||||
return ResolverForModule(CompositePackageFragmentProvider(providersForModule), container)
|
||||
}
|
||||
|
||||
@@ -64,9 +64,6 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
return resolverForModuleDescriptor(doGetDescriptorForModule(moduleInfo))
|
||||
}
|
||||
|
||||
override fun tryGetResolverForModuleWithResolutionAnchorFallback(targetModuleInfo: M, referencingModuleInfo: M): ResolverForModule? =
|
||||
tryGetResolverForModule(targetModuleInfo)
|
||||
|
||||
private fun setupModuleDescriptor(module: M, moduleDescriptor: ModuleDescriptorImpl) {
|
||||
moduleDescriptor.setDependencies(
|
||||
LazyModuleDependencies(
|
||||
|
||||
@@ -43,7 +43,6 @@ class ResolverForModule(
|
||||
abstract class ResolverForProject<M : ModuleInfo> {
|
||||
fun resolverForModule(moduleInfo: M): ResolverForModule = resolverForModuleDescriptor(descriptorForModule(moduleInfo))
|
||||
abstract fun tryGetResolverForModule(moduleInfo: M): ResolverForModule?
|
||||
abstract fun tryGetResolverForModuleWithResolutionAnchorFallback(targetModuleInfo: M, referencingModuleInfo: M): ResolverForModule?
|
||||
abstract fun descriptorForModule(moduleInfo: M): ModuleDescriptor
|
||||
abstract fun moduleInfoForModuleDescriptor(moduleDescriptor: ModuleDescriptor): M
|
||||
abstract fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule
|
||||
@@ -76,9 +75,6 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
|
||||
override val allModules: Collection<M> = listOf()
|
||||
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos")
|
||||
|
||||
override fun tryGetResolverForModuleWithResolutionAnchorFallback(targetModuleInfo: M, referencingModuleInfo: M) =
|
||||
diagnoseUnknownModuleInfo(listOf(targetModuleInfo))
|
||||
|
||||
override fun moduleInfoForModuleDescriptor(descriptor: ModuleDescriptor): M {
|
||||
throw IllegalStateException("$descriptor is not contained in this resolver")
|
||||
}
|
||||
|
||||
+12
-5
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.ResolutionAnchorProvider
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class IdeaResolverForProject(
|
||||
debugName: String,
|
||||
@@ -96,6 +95,12 @@ class IdeaResolverForProject(
|
||||
moduleByJavaClass = { javaClass: JavaClass ->
|
||||
val psiClass = (javaClass as JavaClassImpl).psi
|
||||
psiClass.getPlatformModuleInfo(JvmPlatforms.unspecifiedJvmPlatform)?.platformModule ?: psiClass.getNullableModuleInfo()
|
||||
},
|
||||
resolverForReferencedModule = { targetModuleInfo, referencingModuleInfo ->
|
||||
require(targetModuleInfo is IdeaModuleInfo && referencingModuleInfo is IdeaModuleInfo) {
|
||||
"Unexpected modules passed through JvmPlatformParameters to IDE resolver ($targetModuleInfo, $referencingModuleInfo)"
|
||||
}
|
||||
tryGetResolverForModuleWithResolutionAnchorFallback(targetModuleInfo, referencingModuleInfo)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -150,7 +155,7 @@ class IdeaResolverForProject(
|
||||
}
|
||||
}
|
||||
|
||||
override fun tryGetResolverForModuleWithResolutionAnchorFallback(
|
||||
private fun tryGetResolverForModuleWithResolutionAnchorFallback(
|
||||
targetModuleInfo: IdeaModuleInfo,
|
||||
referencingModuleInfo: IdeaModuleInfo,
|
||||
): ResolverForModule? {
|
||||
@@ -158,9 +163,9 @@ class IdeaResolverForProject(
|
||||
|
||||
return getResolverForProjectUsingResolutionAnchor(targetModuleInfo, referencingModuleInfo)
|
||||
}
|
||||
|
||||
|
||||
private fun getResolverForProjectUsingResolutionAnchor(
|
||||
targetModuleInfo: IdeaModuleInfo,
|
||||
targetModuleInfo: IdeaModuleInfo,
|
||||
referencingModuleInfo: IdeaModuleInfo
|
||||
): ResolverForModule? {
|
||||
val moduleDescriptorOfReferencingModule = descriptorByModule[referencingModuleInfo]?.moduleDescriptor
|
||||
@@ -173,7 +178,9 @@ class IdeaResolverForProject(
|
||||
?.getResolverForProject()
|
||||
?: return null
|
||||
|
||||
if (resolverForProjectFromAnchorModule !is IdeaResolverForProject) return null
|
||||
require(resolverForProjectFromAnchorModule is IdeaResolverForProject) {
|
||||
"Resolution via anchor modules is expected to be used only from IDE resolvers"
|
||||
}
|
||||
|
||||
return resolverForProjectFromAnchorModule.tryGetResolverForModule(targetModuleInfo)
|
||||
}
|
||||
|
||||
+7
@@ -21,6 +21,13 @@ import org.jetbrains.kotlin.idea.project.libraryToSourceAnalysisEnabled
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.resolve.ResolutionAnchorProvider
|
||||
|
||||
/**
|
||||
* This component provides capabilities for correct highlighting for projects with source-dependent libraries.
|
||||
* The issue with this kind of libraries is that their declarations are resolved by ResolverForProject
|
||||
* that have no access to project sources by itself. The necessary path back to project sources can be provided
|
||||
* manually for the libraries in project via resolution anchors. Anchor by itself is a source module which is mapped
|
||||
* to a library and used during resolution as a fallback.
|
||||
*/
|
||||
@State(name = "KotlinIdeAnchorService", storages = [Storage("anchors.xml")])
|
||||
class KotlinIdeResolutionAnchorService(
|
||||
val project: Project
|
||||
|
||||
Reference in New Issue
Block a user