diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt index 5d507eb0690..78477ed3cf4 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaModuleBasedSession.kt @@ -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] } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirDependenciesSymbolProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirDependenciesSymbolProviderImpl.kt index 46c1a4b12d5..f77aa96ad0b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirDependenciesSymbolProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/impl/FirDependenciesSymbolProviderImpl.kt @@ -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>() { - private val dependencyProviders by lazy { +open class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSymbolProvider>() { + protected open val dependencyProviders by lazy { val moduleInfo = session.moduleInfo ?: return@lazy emptyList() moduleInfo.dependenciesWithoutSelf().mapNotNull { session.sessionProvider?.getSession(it)?.firSymbolProvider diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt index 35bb04b6033..8c3d1d36718 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSession.kt @@ -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? } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirIdeJavaModuleBasedSession.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirIdeJavaModuleBasedSession.kt index faaf32ddce8..90b6db4c95b 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirIdeJavaModuleBasedSession.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirIdeJavaModuleBasedSession.kt @@ -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 ) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirIdeModuleDependenciesSymbolProvider.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirIdeModuleDependenciesSymbolProvider.kt new file mode 100644 index 00000000000..5d08b5951c9 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirIdeModuleDependenciesSymbolProvider.kt @@ -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 by lazy { + val moduleInfo = session.moduleInfo + val sessionProvider = session.sessionProvider ?: return@lazy emptyList() + val project = sessionProvider.project + val stateService = FirIdeResolveStateService.getInstance(project) + moduleInfo.dependenciesWithoutSelf().filterIsInstance().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() + } +} + diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirModuleResolveState.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirModuleResolveState.kt index 23a05183973..60bdb9e6ea3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirModuleResolveState.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/fir/FirModuleResolveState.kt @@ -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.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 = emptyList()) } -class FirModuleResolveStateImpl(override val sessionProvider: FirSessionProvider) : FirModuleResolveState { +class FirModuleResolveStateImpl(override val sessionProvider: FirProjectSessionProvider) : FirModuleResolveState { private val cache = mutableMapOf() private val diagnosticCache = mutableMapOf>()