Introduce components for library-to-source resolution in IDE
#KT-24309 In progress
This commit is contained in:
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.AnchorProvider
|
||||
|
||||
class FirModuleDescriptor(val session: FirSession) : ModuleDescriptor {
|
||||
override val builtIns: KotlinBuiltIns
|
||||
@@ -57,6 +58,9 @@ class FirModuleDescriptor(val session: FirSession) : ModuleDescriptor {
|
||||
|
||||
}
|
||||
|
||||
override val anchorProvider: AnchorProvider
|
||||
get() = AnchorProvider.Default
|
||||
|
||||
override fun getOriginal(): DeclarationDescriptor {
|
||||
return this
|
||||
}
|
||||
|
||||
+3
-2
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolverImpl
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
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.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.TargetEnvironment
|
||||
@@ -70,7 +69,9 @@ class JvmResolverForModuleFactory(
|
||||
// Providing a fallback strategy in this case can hide future problems, so we should at least log to be able to diagnose those
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val resolverForReferencedModule = referencedClassModule?.let { resolverForProject.tryGetResolverForModule(it as M) }
|
||||
val resolverForReferencedModule = referencedClassModule?.let {
|
||||
resolverForProject.tryGetResolverForModuleWithAnchorCheck(it as M, moduleInfo)
|
||||
}
|
||||
|
||||
val resolverForModule = resolverForReferencedModule?.takeIf {
|
||||
referencedClassModule.platform.isJvm() || referencedClassModule.platform == null
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.AnchorProvider
|
||||
|
||||
abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
private val debugName: String,
|
||||
@@ -21,7 +22,8 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
modules: Collection<M>,
|
||||
protected val fallbackModificationTracker: ModificationTracker? = null,
|
||||
private val delegateResolver: ResolverForProject<M> = EmptyResolverForProject(),
|
||||
private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory
|
||||
private val packageOracleFactory: PackageOracleFactory = PackageOracleFactory.OptimisticFactory,
|
||||
protected val anchorProvider: AnchorProvider = AnchorProvider.Default,
|
||||
) : ResolverForProject<M>() {
|
||||
|
||||
protected class ModuleData(
|
||||
@@ -54,6 +56,13 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
abstract fun modulesContent(module: M): ModuleContent<M>
|
||||
abstract fun builtInsForModule(module: M): KotlinBuiltIns
|
||||
abstract fun createResolverForModule(descriptor: ModuleDescriptor, moduleInfo: M): ResolverForModule
|
||||
|
||||
protected open fun registerModuleDescriptorUpdate(
|
||||
newDescriptor: ModuleDescriptor,
|
||||
oldDescriptor: ModuleDescriptor?,
|
||||
) {
|
||||
// Nothing by default
|
||||
}
|
||||
|
||||
override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? {
|
||||
if (!isCorrectModuleInfo(moduleInfo)) {
|
||||
@@ -62,6 +71,9 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
return resolverForModuleDescriptor(doGetDescriptorForModule(moduleInfo))
|
||||
}
|
||||
|
||||
override fun tryGetResolverForModuleWithAnchorCheck(targetModuleInfo: M, referencingModuleInfo: M): ResolverForModule? =
|
||||
tryGetResolverForModule(targetModuleInfo)
|
||||
|
||||
private fun setupModuleDescriptor(module: M, moduleDescriptor: ModuleDescriptorImpl) {
|
||||
moduleDescriptor.setDependencies(
|
||||
LazyModuleDependencies(
|
||||
@@ -122,6 +134,10 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
return doGetDescriptorForModule(moduleInfo)
|
||||
}
|
||||
|
||||
override fun moduleInfoForModuleDescriptor(moduleDescriptor: ModuleDescriptor): M {
|
||||
return moduleInfoByDescriptor[moduleDescriptor] ?: delegateResolver.moduleInfoForModuleDescriptor(moduleDescriptor)
|
||||
}
|
||||
|
||||
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>): Nothing {
|
||||
DiagnoseUnknownModuleInfoReporter.report(name, infos, allModules)
|
||||
}
|
||||
@@ -142,6 +158,8 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
}
|
||||
if (moduleData.isOutOfDate()) {
|
||||
moduleData = recreateModuleDescriptor(moduleFromThisResolver)
|
||||
} else {
|
||||
registerModuleDescriptorUpdate(moduleData.moduleDescriptor, null)
|
||||
}
|
||||
moduleData.moduleDescriptor
|
||||
}
|
||||
@@ -158,6 +176,9 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
|
||||
val moduleData = createModuleDescriptor(module)
|
||||
descriptorByModule[module] = moduleData
|
||||
|
||||
registerModuleDescriptorUpdate(moduleData.moduleDescriptor, oldDescriptor)
|
||||
|
||||
return moduleData
|
||||
}
|
||||
|
||||
@@ -168,7 +189,8 @@ abstract class AbstractResolverForProject<M : ModuleInfo>(
|
||||
builtInsForModule(module),
|
||||
module.platform,
|
||||
module.capabilities,
|
||||
module.stableName
|
||||
module.stableName,
|
||||
anchorProvider
|
||||
)
|
||||
moduleInfoByDescriptor[moduleDescriptor] = module
|
||||
setupModuleDescriptor(module, moduleDescriptor)
|
||||
|
||||
@@ -43,7 +43,9 @@ class ResolverForModule(
|
||||
abstract class ResolverForProject<M : ModuleInfo> {
|
||||
fun resolverForModule(moduleInfo: M): ResolverForModule = resolverForModuleDescriptor(descriptorForModule(moduleInfo))
|
||||
abstract fun tryGetResolverForModule(moduleInfo: M): ResolverForModule?
|
||||
abstract fun tryGetResolverForModuleWithAnchorCheck(targetModuleInfo: M, referencingModuleInfo: M): ResolverForModule?
|
||||
abstract fun descriptorForModule(moduleInfo: M): ModuleDescriptor
|
||||
abstract fun moduleInfoForModuleDescriptor(moduleDescriptor: ModuleDescriptor): M
|
||||
abstract fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule
|
||||
abstract fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>): Nothing
|
||||
|
||||
@@ -73,6 +75,13 @@ class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M>() {
|
||||
override fun descriptorForModule(moduleInfo: M) = diagnoseUnknownModuleInfo(listOf(moduleInfo))
|
||||
override val allModules: Collection<M> = listOf()
|
||||
override fun diagnoseUnknownModuleInfo(infos: List<ModuleInfo>) = throw IllegalStateException("Should not be called for $infos")
|
||||
|
||||
override fun tryGetResolverForModuleWithAnchorCheck(targetModuleInfo: M, referencingModuleInfo: M) =
|
||||
diagnoseUnknownModuleInfo(listOf(targetModuleInfo))
|
||||
|
||||
override fun moduleInfoForModuleDescriptor(descriptor: ModuleDescriptor): M {
|
||||
throw IllegalStateException("$descriptor is not contained in this resolver")
|
||||
}
|
||||
}
|
||||
|
||||
data class ModuleContent<out M : ModuleInfo>(
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.analyzer
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
open class ModuleResolverTracker<M : ModuleInfo> {
|
||||
open fun registerModuleUpdate(
|
||||
newModule: ModuleDescriptor,
|
||||
oldModule: ModuleDescriptor?,
|
||||
resolverForProject: ResolverForProject<M>
|
||||
) {
|
||||
}
|
||||
|
||||
open fun findResolverForProjectByModuleDescriptor(moduleDescriptor: ModuleDescriptor): ResolverForProject<M>? = null
|
||||
|
||||
companion object {
|
||||
val Default = ModuleResolverTracker<ModuleInfo>()
|
||||
|
||||
fun getInstance(project: Project): ModuleResolverTracker<*> =
|
||||
ServiceManager.getService(project, ModuleResolverTracker::class.java) ?: Default
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.AnchorProvider
|
||||
|
||||
interface ModuleDescriptor : DeclarationDescriptor {
|
||||
override fun getContainingDeclaration(): DeclarationDescriptor? = null
|
||||
@@ -61,4 +62,6 @@ interface ModuleDescriptor : DeclarationDescriptor {
|
||||
val isValid: Boolean
|
||||
|
||||
fun assertValid()
|
||||
|
||||
val anchorProvider: AnchorProvider
|
||||
}
|
||||
|
||||
@@ -19,21 +19,28 @@ package org.jetbrains.kotlin.descriptors
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
fun ModuleDescriptor.findClassifierAcrossModuleDependencies(classId: ClassId): ClassifierDescriptor? {
|
||||
fun ModuleDescriptor.findClassifierAcrossModuleDependencies(classId: ClassId): ClassifierDescriptor? = withAnchorFallback {
|
||||
val packageViewDescriptor = getPackage(classId.packageFqName)
|
||||
val segments = classId.relativeClassName.pathSegments()
|
||||
val topLevelClass = packageViewDescriptor.memberScope.getContributedClassifier(
|
||||
segments.first(),
|
||||
NoLookupLocation.FROM_DESERIALIZATION
|
||||
) ?: return null
|
||||
) ?: return@withAnchorFallback null
|
||||
var result = topLevelClass
|
||||
for (name in segments.subList(1, segments.size)) {
|
||||
if (result !is ClassDescriptor) return null
|
||||
if (result !is ClassDescriptor) return@withAnchorFallback null
|
||||
result = result.unsubstitutedInnerClassesScope
|
||||
.getContributedClassifier(name, NoLookupLocation.FROM_DESERIALIZATION) as? ClassDescriptor
|
||||
?: return null
|
||||
?: return@withAnchorFallback null
|
||||
}
|
||||
return result
|
||||
return@withAnchorFallback result
|
||||
}
|
||||
|
||||
private inline fun ModuleDescriptor.withAnchorFallback(
|
||||
crossinline doSearch: ModuleDescriptor.() -> ClassifierDescriptor?
|
||||
): ClassifierDescriptor? {
|
||||
val anchor = anchorProvider.getAnchor(this)
|
||||
return if (anchor == null) doSearch() else doSearch() ?: anchor.doSearch()
|
||||
}
|
||||
|
||||
fun ModuleDescriptor.findClassAcrossModuleDependencies(classId: ClassId): ClassDescriptor? =
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.AnchorProvider
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.checker.REFINER_CAPABILITY
|
||||
import org.jetbrains.kotlin.types.checker.Ref
|
||||
@@ -38,7 +39,8 @@ class ModuleDescriptorImpl @JvmOverloads constructor(
|
||||
// May be null in compiler context, should be not-null in IDE context
|
||||
override val platform: TargetPlatform? = null,
|
||||
capabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap(),
|
||||
override val stableName: Name? = null
|
||||
override val stableName: Name? = null,
|
||||
override val anchorProvider: AnchorProvider = AnchorProvider.Default,
|
||||
) : DeclarationDescriptorImpl(Annotations.EMPTY, moduleName), ModuleDescriptor {
|
||||
private val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
|
||||
abstract class AnchorProvider {
|
||||
open fun getAnchor(moduleDescriptor: ModuleDescriptor): ModuleDescriptor? = null
|
||||
|
||||
companion object Default : AnchorProvider()
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform;
|
||||
import org.jetbrains.kotlin.resolve.AnchorProvider;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
@@ -53,6 +54,12 @@ public class ErrorUtils {
|
||||
|
||||
static {
|
||||
ERROR_MODULE = new ModuleDescriptor() {
|
||||
@NotNull
|
||||
@Override
|
||||
public AnchorProvider getAnchorProvider() {
|
||||
return AnchorProvider.Default;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getCapability(@NotNull Capability<T> capability) {
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.caches.resolve
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analyzer.ModuleResolverTracker
|
||||
import org.jetbrains.kotlin.analyzer.ResolverForProject
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
import org.jetbrains.kotlin.idea.project.useAnchorServices
|
||||
|
||||
class IdeaModuleResolverTrackerImpl(private val project: Project) : ModuleResolverTracker<IdeaModuleInfo>() {
|
||||
private val resolversForModules by lazy {
|
||||
mutableMapOf<ModuleDescriptor, ResolverForProject<IdeaModuleInfo>>()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun registerModuleUpdate(
|
||||
newModule: ModuleDescriptor,
|
||||
oldModule: ModuleDescriptor?,
|
||||
resolverForProject: ResolverForProject<IdeaModuleInfo>
|
||||
) {
|
||||
if (!project.useAnchorServices) return
|
||||
|
||||
if (oldModule != null) resolversForModules.remove(oldModule)
|
||||
resolversForModules[newModule] = resolverForProject
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun findResolverForProjectByModuleDescriptor(moduleDescriptor: ModuleDescriptor): ResolverForProject<IdeaModuleInfo>? {
|
||||
if (!project.useAnchorServices) return null
|
||||
|
||||
return resolversForModules[moduleDescriptor]
|
||||
}
|
||||
}
|
||||
+32
-2
@@ -31,9 +31,10 @@ import org.jetbrains.kotlin.platform.idePlatformKind
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlin.platform.toTargetPlatform
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.AnchorProvider
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class IdeaResolverForProject(
|
||||
debugName: String,
|
||||
@@ -51,7 +52,8 @@ class IdeaResolverForProject(
|
||||
modules,
|
||||
fallbackModificationTracker,
|
||||
delegateResolver,
|
||||
ServiceManager.getService(projectContext.project, IdePackageOracleFactory::class.java)
|
||||
ServiceManager.getService(projectContext.project, IdePackageOracleFactory::class.java),
|
||||
ServiceManager.getService(projectContext.project, AnchorProvider::class.java)
|
||||
) {
|
||||
private val builtInsCache: BuiltInsCache =
|
||||
(delegateResolver as? IdeaResolverForProject)?.builtInsCache ?: BuiltInsCache(projectContext, this)
|
||||
@@ -146,6 +148,34 @@ class IdeaResolverForProject(
|
||||
return@compute newBuiltIns
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerModuleDescriptorUpdate(
|
||||
newDescriptor: ModuleDescriptor,
|
||||
oldDescriptor: ModuleDescriptor?
|
||||
) {
|
||||
ModuleResolverTracker
|
||||
.getInstance(projectContext.project)
|
||||
.safeAs<IdeaModuleResolverTrackerImpl>()
|
||||
?.registerModuleUpdate(newDescriptor, oldDescriptor, this)
|
||||
}
|
||||
|
||||
override fun tryGetResolverForModuleWithAnchorCheck(
|
||||
targetModuleInfo: IdeaModuleInfo,
|
||||
referencingModuleInfo: IdeaModuleInfo,
|
||||
): ResolverForModule? {
|
||||
tryGetResolverForModule(targetModuleInfo)?.let { return it }
|
||||
|
||||
val moduleDescriptorOfReferencingModule = descriptorByModule[referencingModuleInfo]?.moduleDescriptor
|
||||
?: error("$referencingModuleInfo is not contained in this resolver, which means incorrect use of anchor-aware search")
|
||||
|
||||
val anchorModuleDescriptor = anchorProvider.getAnchor(moduleDescriptorOfReferencingModule) ?: return null
|
||||
|
||||
val moduleResolverTracker =
|
||||
ModuleResolverTracker.getInstance(projectContext.project).safeAs<IdeaModuleResolverTrackerImpl>() ?: return null
|
||||
|
||||
return moduleResolverTracker.findResolverForProjectByModuleDescriptor(anchorModuleDescriptor)
|
||||
?.tryGetResolverForModule(targetModuleInfo)
|
||||
}
|
||||
}
|
||||
|
||||
interface BuiltInsCacheKey {
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.caches.resolve
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent
|
||||
import com.intellij.openapi.components.State
|
||||
import com.intellij.openapi.components.Storage
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.analyzer.ModuleResolverTracker
|
||||
import org.jetbrains.kotlin.caches.project.cacheInvalidatingOnRootModifications
|
||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.project.*
|
||||
import org.jetbrains.kotlin.idea.project.useAnchorServices
|
||||
import org.jetbrains.kotlin.resolve.AnchorProvider
|
||||
|
||||
@State(name = "KotlinIdeAnchorService", storages = [Storage("anchors.xml")])
|
||||
class KotlinIdeAnchorService(
|
||||
val project: Project
|
||||
) : AnchorProvider(),
|
||||
PersistentStateComponent<KotlinIdeAnchorService.State> {
|
||||
|
||||
data class State(
|
||||
var moduleNameToAnchorName: Map<String, String> = emptyMap()
|
||||
)
|
||||
|
||||
@JvmField
|
||||
var myState: State = State()
|
||||
|
||||
private fun buildMapping(): Map<ModuleInfo, ModuleInfo> {
|
||||
val modulesByNames = getModuleInfosFromIdeaModel(project).associateBy { moduleInfo ->
|
||||
when (moduleInfo) {
|
||||
is LibraryInfo -> moduleInfo.library.name
|
||||
is ModuleSourceInfo -> moduleInfo.module.name
|
||||
else -> moduleInfo.name.asString()
|
||||
}
|
||||
}
|
||||
|
||||
return myState.moduleNameToAnchorName.entries.mapNotNull { (moduleName, anchorName) ->
|
||||
val module = modulesByNames[moduleName] ?: return@mapNotNull notFoundModule(moduleName)
|
||||
val anchor = modulesByNames[anchorName] ?: return@mapNotNull notFoundModule(moduleName)
|
||||
module to anchor
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
private fun notFoundModule(moduleName: String): Nothing? {
|
||||
logger<KotlinIdeAnchorService>().warn("Module <${moduleName}> not found in project model")
|
||||
return null
|
||||
}
|
||||
|
||||
private val moduleToAnchor: Map<ModuleInfo, ModuleInfo>
|
||||
get() = project.cacheInvalidatingOnRootModifications {
|
||||
buildMapping()
|
||||
}
|
||||
|
||||
private fun getAnchorModuleDescriptorIfAny(moduleInfo: ModuleInfo): ModuleDescriptor? {
|
||||
val mapped = moduleToAnchor[moduleInfo] ?: return null
|
||||
return KotlinCacheService.getInstance(project)
|
||||
.getResolutionFacadeByModuleInfo(mapped, mapped.platform)
|
||||
?.moduleDescriptor
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun getState(): State = myState
|
||||
|
||||
@Synchronized
|
||||
override fun loadState(state: State) {
|
||||
XmlSerializerUtil.copyBean(state, myState)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun getAnchor(moduleDescriptor: ModuleDescriptor): ModuleDescriptor? {
|
||||
if (!project.useAnchorServices) return null
|
||||
val resolver = ModuleResolverTracker.getInstance(project)
|
||||
.findResolverForProjectByModuleDescriptor(moduleDescriptor)
|
||||
?: return null
|
||||
return getAnchorModuleDescriptorIfAny(resolver.moduleInfoForModuleDescriptor(moduleDescriptor))
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -6,8 +6,10 @@
|
||||
package org.jetbrains.kotlin.idea.caches.resolve.util
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import org.jetbrains.kotlin.context.GlobalContextImpl
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings
|
||||
import org.jetbrains.kotlin.idea.project.useAnchorServices
|
||||
import org.jetbrains.kotlin.idea.project.useCompositeAnalysis
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.storage.ExceptionTracker
|
||||
@@ -32,7 +34,7 @@ private fun GlobalContextImpl.contextWithNewLockAndCompositeExceptionTracker(deb
|
||||
}
|
||||
|
||||
internal fun GlobalContextImpl.contextWithCompositeExceptionTracker(project: Project, debugName: String): GlobalContextImpl =
|
||||
if (project.useCompositeAnalysis) {
|
||||
if (project.useCompositeAnalysis || project.useAnchorServices) {
|
||||
this.contextWithCompositeExceptionTracker(debugName)
|
||||
} else {
|
||||
this.contextWithNewLockAndCompositeExceptionTracker(debugName)
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.project
|
||||
|
||||
import com.intellij.ide.util.PropertiesComponent
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
object KotlinAnchorSupportForLibraryAnalysisComponent {
|
||||
private const val anchorSupportOption = "kotlin.use.anchor.services"
|
||||
|
||||
@JvmStatic
|
||||
fun setState(project: Project, isEnabled: Boolean) {
|
||||
PropertiesComponent.getInstance(project).setValue(anchorSupportOption, isEnabled, false)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isEnabled(project: Project): Boolean =
|
||||
PropertiesComponent.getInstance(project).getBoolean(anchorSupportOption)
|
||||
}
|
||||
|
||||
val Project.useAnchorServices: Boolean
|
||||
get() = KotlinAnchorSupportForLibraryAnalysisComponent.isEnabled(this)
|
||||
+3
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.externalDescriptors
|
||||
import org.jetbrains.kotlin.resolve.AnchorProvider
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -195,6 +196,8 @@ private object DebugLabelModuleDescriptor : DeclarationDescriptorImpl(Annotation
|
||||
get() = true
|
||||
|
||||
override fun assertValid() {}
|
||||
override val anchorProvider: AnchorProvider
|
||||
get() = AnchorProvider.Default
|
||||
}
|
||||
|
||||
internal class DebugLabelPropertyDescriptor(
|
||||
|
||||
@@ -1918,6 +1918,8 @@ signature.preview=Signature Preview
|
||||
move.members.from=Move members from:
|
||||
open.moved.members.in.editor=Open moved members in editor
|
||||
to.fully.qualified.name=To (fully qualified name):
|
||||
toggle.anchor.support.for.library.analysis=Toggle anchor support for library analysis
|
||||
enable.components.for.library.to.source.analysis.in.kotlin=Enable components for library-to-source analysis in Kotlin
|
||||
|
||||
action.Kotlin.StopScratch.text=Stop Scratch Execution
|
||||
action.Kotlin.StopScratch.description=Stop scratch execution
|
||||
@@ -1973,6 +1975,7 @@ action.ShowKotlinBytecode.text=Show Kotlin Bytecode
|
||||
action.ConfigureKotlinJsInProject.text=Configure Kotlin (JavaScript) in Project
|
||||
action.ConfigureKotlinInProject.text=Configure Kotlin in Project
|
||||
action.KotlinConsoleREPL.text=Kotlin REPL
|
||||
action.AnchorSupportForLibraryAnalysisToggleAction.text=Toggle Anchor Support For Modules
|
||||
|
||||
inspection.unused.unary.operator.display.name=Unused unary operator
|
||||
inspection.replace.guard.clause.with.function.call.display.name=Replace guard clause with kotlin's function call
|
||||
|
||||
@@ -90,6 +90,8 @@
|
||||
|
||||
<action id="MultiplatformCompositeAnalysisToggleAction" class="org.jetbrains.kotlin.idea.actions.internal.MultiplatformCompositeAnalysisToggleAction"/>
|
||||
|
||||
<action id="AnchorSupportForLibraryAnalysisToggleAction" class="org.jetbrains.kotlin.idea.actions.internal.AnchorSupportForLibraryAnalysisToggleAction"/>
|
||||
|
||||
<action id="CopyAsDiagnosticTest" class="org.jetbrains.kotlin.idea.actions.internal.CopyAsDiagnosticTestAction"/>
|
||||
|
||||
<action id="KotlinFormattingSettingsStatusAction" class="org.jetbrains.kotlin.idea.actions.internal.KotlinFormattingSettingsStatusAction"/>
|
||||
@@ -189,6 +191,12 @@
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.caches.resolve.KotlinCacheService"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheServiceImpl"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.resolve.AnchorProvider"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.KotlinIdeAnchorService"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.analyzer.ModuleResolverTracker"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.IdeaModuleResolverTrackerImpl"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.fir.FirIdeResolveStateService"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.fir.FirIdeResolveStateServiceImpl"/>
|
||||
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.actions.internal
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.ToggleAction
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.project.KotlinAnchorSupportForLibraryAnalysisComponent
|
||||
import org.jetbrains.kotlin.idea.project.useAnchorServices
|
||||
|
||||
class AnchorSupportForLibraryAnalysisToggleAction : ToggleAction(
|
||||
KotlinBundle.message("toggle.anchor.support.for.library.analysis"),
|
||||
KotlinBundle.message("enable.components.for.library.to.source.analysis.in.kotlin"),
|
||||
null
|
||||
) {
|
||||
override fun isSelected(e: AnActionEvent): Boolean =
|
||||
e.project?.useAnchorServices == true
|
||||
|
||||
override fun setSelected(e: AnActionEvent, state: Boolean) {
|
||||
e.project?.let {
|
||||
KotlinAnchorSupportForLibraryAnalysisComponent.setState(it, state)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user