diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeAllSourceDependenciesSymbolProvider.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeAllSourceDependenciesSymbolProvider.kt new file mode 100644 index 00000000000..c10af6c9123 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeAllSourceDependenciesSymbolProvider.kt @@ -0,0 +1,71 @@ +/* + * 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.fir.low.level.api + +import com.intellij.openapi.module.impl.scopes.ModuleScopeProviderImpl +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration +import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider +import org.jetbrains.kotlin.fir.scopes.FirScope +import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo +import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtElement + +internal class FirIdeAllSourceDependenciesSymbolProvider( + project: Project, + moduleInfo: ModuleSourceInfo, + private val sessionProvider: FirIdeSessionProvider, + private val firBuilder: FirBuilder, +) : FirSymbolProvider() { + private val scope = ModuleScopeProviderImpl(moduleInfo.module).moduleWithDependenciesScope + private val indexHelper = IndexHelper(project) + private val packageExistenceChecker = PackageExistenceCheckerForMultipleModules(project, moduleInfo.dependencies()) + + private val cache = PsiToFirCacheImpl() + + override fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>? { + return executeOrReturnDefaultValueOnPCE(null) { + val ktClass = indexHelper.firstMatchingOrNull( + KotlinFullClassNameIndex.KEY, + classId.asSingleFqName().asString(), + scope + ) { candidate -> candidate.containingKtFile.packageFqName == classId.packageFqName } ?: return null + (ktClass.toFir() as FirClassLikeDeclaration<*>).symbol + } + } + + + @OptIn(ExperimentalStdlibApi::class) + override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List> { + val callableId = CallableId(packageFqName, name) + return executeOrReturnDefaultValueOnPCE(emptyList()) { + buildList { + indexHelper.getTopLevelFunctions(callableId, scope).mapTo(this) { (it.toFir() as FirCallableDeclaration<*>).symbol } + indexHelper.getTopLevelProperties(callableId, scope).mapTo(this) { (it.toFir() as FirCallableDeclaration<*>).symbol } + } + } + } + + private fun KtElement.toFir(): FirElement = + getOrBuildFir(cache, firBuilder, sessionProvider, FirResolvePhase.RAW_FIR) + + override fun getNestedClassifierScope(classId: ClassId): FirScope? { + val classifier = getClassLikeSymbolByFqName(classId) ?: return null + return classifier.fir.session.firIdeProvider.getNestedClassifierScope(classId) + } + + override fun getPackage(fqName: FqName): FqName? = + fqName.takeIf(packageExistenceChecker::isPackageExists) +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeModuleDependenciesSymbolProvider.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeModuleLibraryDependenciesSymbolProvider.kt similarity index 62% rename from idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeModuleDependenciesSymbolProvider.kt rename to idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeModuleLibraryDependenciesSymbolProvider.kt index 0c26f5d485f..807ac552fba 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeModuleDependenciesSymbolProvider.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeModuleLibraryDependenciesSymbolProvider.kt @@ -5,44 +5,38 @@ package org.jetbrains.kotlin.idea.fir.low.level.api -import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider -import org.jetbrains.kotlin.fir.resolve.providers.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.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.providers.impl.FirDependenciesSymbolProviderImpl +import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo import org.jetbrains.kotlin.idea.caches.project.isLibraryClasses import org.jetbrains.kotlin.idea.caches.resolve.IDEPackagePartProvider -internal class FirIdeModuleDependenciesSymbolProvider( +internal class FirIdeModuleLibraryDependenciesSymbolProvider( session: FirIdeJavaModuleBasedSession ) : FirDependenciesSymbolProviderImpl(session) { - + //todo invalidate cache on libraries changed override val dependencyProviders: List by lazy { val moduleInfo = session.moduleInfo - val sessionProvider = session.sessionProvider ?: return@lazy emptyList() + val sessionProvider = session.sessionProvider ?: error("No session provider found") 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() -> { + + moduleInfo.dependenciesWithoutSelf() + .filterIsInstance() + .mapNotNull { dependencyInfo -> + val dependencySession = if (dependencyInfo.isLibraryClasses()) { val dependencyScope = dependencyInfo.contentScope() FirLibrarySession.create( dependencyInfo, sessionProvider as FirProjectSessionProvider, dependencyScope, project, IDEPackagePartProvider(dependencyScope) ) - } - else -> return@mapNotNull null - } - dependencySession.firSymbolProvider - }.toList() + } else null + dependencySession?.firSymbolProvider + }.toList() } }