Introduce FirIdeModuleDependenciesSymbolProvider #KT-35424 In Progress
This solves problems with inter-module dependencies, at least in small projects. However, Kotlin project still does not see stdlib. Also, we often have problems with untouched types during expected type checks (FirUserTypeRef instead of FirResolvedTypeRef)
This commit is contained in:
@@ -124,7 +124,7 @@ class FirLibrarySession private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
class FirProjectSessionProvider(val project: Project) : FirSessionProvider {
|
||||
class FirProjectSessionProvider(override val project: Project) : FirSessionProvider {
|
||||
override fun getSession(moduleInfo: ModuleInfo): FirSession? {
|
||||
return sessionCache[moduleInfo]
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,8 +19,8 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSymbolProvider<FirClassLikeSymbol<*>>() {
|
||||
private val dependencyProviders by lazy {
|
||||
open class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSymbolProvider<FirClassLikeSymbol<*>>() {
|
||||
protected open val dependencyProviders by lazy {
|
||||
val moduleInfo = session.moduleInfo ?: return@lazy emptyList()
|
||||
moduleInfo.dependenciesWithoutSelf().mapNotNull {
|
||||
session.sessionProvider?.getSession(it)?.firSymbolProvider
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.*
|
||||
@@ -53,6 +54,8 @@ class BuiltinTypes {
|
||||
}
|
||||
|
||||
interface FirSessionProvider {
|
||||
val project: Project
|
||||
|
||||
fun getSession(moduleInfo: ModuleInfo): FirSession?
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirDependenciesSymbolProviderImpl
|
||||
import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
|
||||
|
||||
|
||||
@@ -38,7 +37,7 @@ class FirIdeJavaModuleBasedSession(
|
||||
listOf(
|
||||
firProvider,
|
||||
JavaSymbolProvider(this, sessionProvider.project, scope),
|
||||
FirDependenciesSymbolProviderImpl(this)
|
||||
FirIdeModuleDependenciesSymbolProvider(this)
|
||||
)
|
||||
) as FirSymbolProvider
|
||||
)
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.idea.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirDependenciesSymbolProviderImpl
|
||||
import org.jetbrains.kotlin.fir.dependenciesWithoutSelf
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
import org.jetbrains.kotlin.fir.java.FirLibrarySession
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.isLibraryClasses
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.IDEPackagePartProvider
|
||||
|
||||
|
||||
class FirIdeModuleDependenciesSymbolProvider(
|
||||
session: FirIdeJavaModuleBasedSession
|
||||
) : FirDependenciesSymbolProviderImpl(session) {
|
||||
|
||||
override val dependencyProviders: List<FirSymbolProvider> by lazy {
|
||||
val moduleInfo = session.moduleInfo
|
||||
val sessionProvider = session.sessionProvider ?: return@lazy emptyList<FirSymbolProvider>()
|
||||
val project = sessionProvider.project
|
||||
val stateService = FirIdeResolveStateService.getInstance(project)
|
||||
moduleInfo.dependenciesWithoutSelf().filterIsInstance<IdeaModuleInfo>().mapNotNull { dependencyInfo ->
|
||||
val resolveState = stateService.getResolveState(dependencyInfo)
|
||||
val dependencySession = when {
|
||||
dependencyInfo is ModuleSourceInfo -> {
|
||||
resolveState.getSession(project, dependencyInfo)
|
||||
}
|
||||
dependencyInfo.isLibraryClasses() -> {
|
||||
val dependencyScope = dependencyInfo.contentScope()
|
||||
FirLibrarySession.create(
|
||||
dependencyInfo, sessionProvider as FirProjectSessionProvider,
|
||||
dependencyScope, project, IDEPackagePartProvider(dependencyScope)
|
||||
)
|
||||
}
|
||||
else -> return@mapNotNull null
|
||||
}
|
||||
dependencySession.firSymbolProvider
|
||||
}.toList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,54 +9,34 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.java.FirLibrarySession
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.isLibraryClasses
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.IDEPackagePartProvider
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
private fun createLibrarySession(moduleInfo: IdeaModuleInfo, project: Project, provider: FirProjectSessionProvider): FirLibrarySession {
|
||||
val contentScope = moduleInfo.contentScope()
|
||||
return FirLibrarySession.create(moduleInfo, provider, contentScope, project, IDEPackagePartProvider(contentScope))
|
||||
}
|
||||
|
||||
private fun getOrCreateIdeSession(
|
||||
sessionProvider: FirProjectSessionProvider,
|
||||
project: Project,
|
||||
moduleInfo: ModuleSourceInfo
|
||||
): FirSession {
|
||||
sessionProvider.getSession(moduleInfo)?.let { return it }
|
||||
return synchronized(moduleInfo.module) {
|
||||
sessionProvider.getSession(moduleInfo) ?: FirIdeJavaModuleBasedSession(
|
||||
project, moduleInfo, sessionProvider, moduleInfo.contentScope()
|
||||
).also { moduleBasedSession ->
|
||||
val ideaModuleInfo = moduleInfo.cast<IdeaModuleInfo>()
|
||||
ideaModuleInfo.dependenciesWithoutSelf().forEach {
|
||||
if (it is IdeaModuleInfo && it.isLibraryClasses()) {
|
||||
// TODO: consider caching / synchronization here
|
||||
createLibrarySession(it, project, sessionProvider)
|
||||
}
|
||||
}
|
||||
sessionProvider.sessionCache[moduleInfo] = moduleBasedSession
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface FirModuleResolveState {
|
||||
val sessionProvider: FirSessionProvider
|
||||
val sessionProvider: FirProjectSessionProvider
|
||||
|
||||
fun getSession(psi: KtElement): FirSession {
|
||||
val sessionProvider = sessionProvider as FirProjectSessionProvider
|
||||
val moduleInfo = psi.getModuleInfo() as ModuleSourceInfo
|
||||
return getOrCreateIdeSession(sessionProvider, psi.project, moduleInfo)
|
||||
return getSession(psi.project, moduleInfo)
|
||||
}
|
||||
|
||||
fun getSession(project: Project, moduleInfo: ModuleSourceInfo): FirSession {
|
||||
sessionProvider.getSession(moduleInfo)?.let { return it }
|
||||
return synchronized(moduleInfo.module) {
|
||||
sessionProvider.getSession(moduleInfo) ?: FirIdeJavaModuleBasedSession(
|
||||
project, moduleInfo, sessionProvider, moduleInfo.contentScope()
|
||||
).also { moduleBasedSession ->
|
||||
sessionProvider.sessionCache[moduleInfo] = moduleBasedSession
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(psi: KtElement): FirElement?
|
||||
@@ -72,7 +52,7 @@ interface FirModuleResolveState {
|
||||
fun setDiagnosticsForFile(file: KtFile, fir: FirFile, diagnostics: Iterable<ConeDiagnostic> = emptyList())
|
||||
}
|
||||
|
||||
class FirModuleResolveStateImpl(override val sessionProvider: FirSessionProvider) : FirModuleResolveState {
|
||||
class FirModuleResolveStateImpl(override val sessionProvider: FirProjectSessionProvider) : FirModuleResolveState {
|
||||
private val cache = mutableMapOf<KtElement, FirElement>()
|
||||
|
||||
private val diagnosticCache = mutableMapOf<KtElement, MutableList<Diagnostic>>()
|
||||
|
||||
Reference in New Issue
Block a user