[Analysis API] add API to get KtScope for resolve extensions

^KT-58262
This commit is contained in:
Ilya Kirillov
2023-04-26 00:19:01 +02:00
committed by teamcity
parent 06b616957c
commit 96b7abc6cf
8 changed files with 234 additions and 36 deletions
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.CompositeKotlinDeclarationProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.CompositeKotlinPackageProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.LLFirResolveExtensionTool
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.llResolveExtensionTool
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.allDirectDependencies
@@ -123,6 +124,8 @@ private constructor(
override val symbolProviderByJavaPsiImpl = KtFirSymbolProviderByJavaPsi(this)
override val resolveExtensionProviderImpl: KtSymbolFromResolveExtensionProvider = KtFirSymbolFromResolveExtensionProvider(this)
@Suppress("AnalysisApiMissingLifetimeCheck")
override fun createContextDependentCopy(originalKtFile: KtFile, elementToReanalyze: KtElement): KtAnalysisSession {
check(mode == AnalysisSessionMode.REGULAR) {
@@ -150,11 +153,13 @@ private constructor(
val useSiteAnalysisScope: GlobalSearchScope = analysisScopeProviderImpl.getAnalysisScope()
val extensionTools: List<LLFirResolveExtensionTool>
val useSiteScopeDeclarationProvider: KotlinDeclarationProvider
val useSitePackageProvider: KotlinPackageProvider
init {
val extensionTools = buildList {
extensionTools = buildList {
addIfNotNull(useSiteSession.llResolveExtensionTool)
useSiteModule.allDirectDependencies().mapNotNullTo(this) { dependency ->
firResolveSession.getSessionFor(dependency).llResolveExtensionTool
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.analysis.api.fir
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.analysis.api.KtStarTypeProjection
import org.jetbrains.kotlin.analysis.api.KtTypeArgumentWithVariance
@@ -25,7 +24,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecific
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withConeTypeEntry
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirSymbolEntry
import org.jetbrains.kotlin.analysis.providers.createPackageProvider
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
@@ -106,7 +105,7 @@ internal class KtSymbolByFirBuilder constructor(
fun buildScriptSymbol(firSymbol: FirScriptSymbol) = KtFirScriptSymbol(firSymbol, analysisSession)
private val packageProvider = project.createPackageProvider(GlobalSearchScope.allScope(project))//todo scope
private val packageProvider: KotlinPackageProvider get() = analysisSession.useSitePackageProvider
fun createPackageSymbolIfOneExists(packageFqName: FqName): KtFirPackageSymbol? {
val exists = packageProvider.doesPackageExist(packageFqName, analysisSession.targetPlatform)
@@ -0,0 +1,90 @@
/*
* Copyright 2010-2023 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.analysis.api.fir.components
import org.jetbrains.kotlin.analysis.api.components.KtSymbolFromResolveExtensionProvider
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.impl.base.scopes.KtEmptyScope
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
import org.jetbrains.kotlin.analysis.api.scopes.KtScope
import org.jetbrains.kotlin.analysis.api.scopes.KtScopeNameFilter
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.LLFirResolveExtensionTool
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.LLFirResolveExtensionToolDeclarationProvider
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedDeclaration
internal class KtFirSymbolFromResolveExtensionProvider(
override val analysisSession: KtFirAnalysisSession,
) : KtSymbolFromResolveExtensionProvider(), KtFirAnalysisSessionComponent {
override val token: KtLifetimeToken
get() = analysisSession.token
override fun getResolveExtensionScopeWithTopLevelDeclarations(): KtScope {
val tools = analysisSession.extensionTools
if (tools.isEmpty()) return KtEmptyScope(token)
return KtFirResolveExtensionScope(analysisSession, tools)
}
}
private class KtFirResolveExtensionScope(
private val analysisSession: KtFirAnalysisSession,
private val tools: List<LLFirResolveExtensionTool>,
) : KtScope {
init {
require(tools.isNotEmpty())
}
override val token: KtLifetimeToken get() = analysisSession.token
override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence<KtCallableSymbol> = withValidityAssertion {
gelTopLevelDeclarations(nameFilter) { it.getTopLevelCallables() }
}
override fun getClassifierSymbols(nameFilter: KtScopeNameFilter): Sequence<KtClassifierSymbol> = withValidityAssertion {
gelTopLevelDeclarations(nameFilter) { it.getTopLevelClassifiers() }
}
private inline fun <D : KtNamedDeclaration, reified S : KtDeclaration> gelTopLevelDeclarations(
crossinline nameFilter: KtScopeNameFilter,
crossinline getDeclarationsByProvider: (LLFirResolveExtensionToolDeclarationProvider) -> Sequence<D>,
): Sequence<S> = sequence {
for (tool in tools) {
for (declaration in getDeclarationsByProvider(tool.declarationProvider)) {
val declarationName = declaration.nameAsName ?: continue
if (!nameFilter(declarationName)) continue
with(analysisSession) {
yield(declaration.getSymbolOfType())
}
}
}
}
override fun getConstructors(): Sequence<KtConstructorSymbol> = withValidityAssertion {
emptySequence()
}
override fun getPackageSymbols(nameFilter: KtScopeNameFilter): Sequence<KtPackageSymbol> = withValidityAssertion {
sequence {
for (tool in tools) {
for (packageName in tool.packageFilter.getAllPackages()) {
if (!nameFilter(packageName.shortName())) continue
analysisSession.firSymbolBuilder.createPackageSymbol(packageName)
}
}
}
}
override fun getPossibleCallableNames(): Set<Name> = withValidityAssertion {
tools.flatMapTo(mutableSetOf()) { it.declarationProvider.getTopLevelCallableNames() }
}
override fun getPossibleClassifierNames(): Set<Name> = withValidityAssertion {
tools.flatMapTo(mutableSetOf()) { it.declarationProvider.getTopLevelClassifierNames() }
}
}