[FIR] Use both context and code fragment imports
This commit is contained in:
+10
-2
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.inference.FirInferenceSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.withScopeCleanup
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.computeImportingScopes
|
||||
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||
@@ -529,9 +530,16 @@ class BodyResolveContext(
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> withScopesForCodeFragment(codeFragment: FirCodeFragment, f: () -> T): T {
|
||||
fun <T> withScopesForCodeFragment(codeFragment: FirCodeFragment, holder: SessionHolder, f: () -> T): T {
|
||||
val towerDataContext = codeFragment.towerDataContext ?: error("Context is not set for a code fragment")
|
||||
val base = towerDataContext.addNonLocalTowerDataElements(towerDataContext.nonLocalTowerDataElements)
|
||||
|
||||
val fragmentImportTowerDataElements = computeImportingScopes(file, holder.session, holder.scopeSession)
|
||||
.map { it.asTowerDataElement(isLocal = false) }
|
||||
|
||||
val base = towerDataContext
|
||||
.addNonLocalTowerDataElements(towerDataContext.nonLocalTowerDataElements)
|
||||
.addNonLocalTowerDataElements(fragmentImportTowerDataElements)
|
||||
|
||||
val baseWithLocalScope = towerDataContext.localScopes.fold(base) { acc, scope -> acc.addLocalScope(scope) }
|
||||
|
||||
val newContext = FirRegularTowerDataContexts(
|
||||
|
||||
+1
-1
@@ -545,7 +545,7 @@ open class FirDeclarationsResolveTransformer(
|
||||
|
||||
override fun transformCodeFragment(codeFragment: FirCodeFragment, data: ResolutionMode): FirCodeFragment {
|
||||
dataFlowAnalyzer.enterCodeFragment(codeFragment)
|
||||
context.withScopesForCodeFragment(codeFragment) {
|
||||
context.withScopesForCodeFragment(codeFragment, components) {
|
||||
transformBlock(codeFragment.block, data)
|
||||
}
|
||||
dataFlowAnalyzer.exitCodeFragment()
|
||||
|
||||
@@ -27,16 +27,18 @@ fun createImportingScopes(
|
||||
useCaching: Boolean = true
|
||||
): List<FirScope> = if (useCaching) {
|
||||
scopeSession.getOrBuild(file, ALL_IMPORTS) {
|
||||
ListStorageFirScope(doCreateImportingScopes(file, session, scopeSession))
|
||||
ListStorageFirScope(computeImportingScopes(file, session, scopeSession))
|
||||
}.result
|
||||
} else {
|
||||
doCreateImportingScopes(file, session, scopeSession)
|
||||
computeImportingScopes(file, session, scopeSession)
|
||||
}
|
||||
|
||||
private fun doCreateImportingScopes(
|
||||
internal fun computeImportingScopes(
|
||||
file: FirFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
scopeSession: ScopeSession,
|
||||
includeDefaultImports: Boolean = true,
|
||||
includePackageImport: Boolean = true
|
||||
): List<FirScope> {
|
||||
file.lazyResolveToPhase(FirResolvePhase.IMPORTS)
|
||||
val excludedImportNames =
|
||||
@@ -47,38 +49,47 @@ private fun doCreateImportingScopes(
|
||||
if (it.parent() == file.packageFqName) it.shortName() else null
|
||||
}
|
||||
|
||||
return listOf(
|
||||
FirDefaultStarImportingScope(
|
||||
scopeSession.getOrBuild(DefaultStarImportKey(DefaultImportPriority.HIGH, excludedImportNames), DEFAULT_STAR_IMPORT) {
|
||||
FirSingleLevelDefaultStarImportingScope(session, scopeSession, DefaultImportPriority.HIGH, excludedImportNames)
|
||||
},
|
||||
scopeSession.getOrBuild(DefaultStarImportKey(DefaultImportPriority.LOW, excludedImportNames), DEFAULT_STAR_IMPORT) {
|
||||
FirSingleLevelDefaultStarImportingScope(session, scopeSession, DefaultImportPriority.LOW, excludedImportNames)
|
||||
},
|
||||
),
|
||||
return buildList {
|
||||
if (includeDefaultImports) {
|
||||
this += FirDefaultStarImportingScope(
|
||||
scopeSession.getOrBuild(DefaultStarImportKey(DefaultImportPriority.HIGH, excludedImportNames), DEFAULT_STAR_IMPORT) {
|
||||
FirSingleLevelDefaultStarImportingScope(session, scopeSession, DefaultImportPriority.HIGH, excludedImportNames)
|
||||
},
|
||||
scopeSession.getOrBuild(DefaultStarImportKey(DefaultImportPriority.LOW, excludedImportNames), DEFAULT_STAR_IMPORT) {
|
||||
FirSingleLevelDefaultStarImportingScope(session, scopeSession, DefaultImportPriority.LOW, excludedImportNames)
|
||||
},
|
||||
)
|
||||
|
||||
scopeSession.getOrBuild(DefaultImportPriority.KOTLIN_THROWS, DEFAULT_SIMPLE_IMPORT) {
|
||||
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.KOTLIN_THROWS)
|
||||
},
|
||||
FirExplicitStarImportingScope(file.imports, session, scopeSession, excludedImportNames),
|
||||
this += scopeSession.getOrBuild(DefaultImportPriority.KOTLIN_THROWS, DEFAULT_SIMPLE_IMPORT) {
|
||||
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.KOTLIN_THROWS)
|
||||
}
|
||||
}
|
||||
|
||||
scopeSession.getOrBuild(DefaultImportPriority.LOW, DEFAULT_SIMPLE_IMPORT) {
|
||||
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.LOW)
|
||||
},
|
||||
scopeSession.getOrBuild(DefaultImportPriority.HIGH, DEFAULT_SIMPLE_IMPORT) {
|
||||
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.HIGH)
|
||||
},
|
||||
when {
|
||||
excludedNamesInPackage.isEmpty() ->
|
||||
// Supposed to be the most common branch, so we cache it
|
||||
scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) {
|
||||
FirPackageMemberScope(file.packageFqName, session, excludedNames = emptySet())
|
||||
}
|
||||
else ->
|
||||
FirPackageMemberScope(file.packageFqName, session, excludedNames = excludedNamesInPackage)
|
||||
},
|
||||
FirExplicitSimpleImportingScope(file.imports, session, scopeSession)
|
||||
)
|
||||
this += FirExplicitStarImportingScope(file.imports, session, scopeSession, excludedImportNames)
|
||||
|
||||
if (includeDefaultImports) {
|
||||
this += scopeSession.getOrBuild(DefaultImportPriority.LOW, DEFAULT_SIMPLE_IMPORT) {
|
||||
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.LOW)
|
||||
}
|
||||
this += scopeSession.getOrBuild(DefaultImportPriority.HIGH, DEFAULT_SIMPLE_IMPORT) {
|
||||
FirDefaultSimpleImportingScope(session, scopeSession, priority = DefaultImportPriority.HIGH)
|
||||
}
|
||||
}
|
||||
|
||||
if (includePackageImport) {
|
||||
this += when {
|
||||
excludedNamesInPackage.isEmpty() ->
|
||||
// Supposed to be the most common branch, so we cache it
|
||||
scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) {
|
||||
FirPackageMemberScope(file.packageFqName, session, excludedNames = emptySet())
|
||||
}
|
||||
else ->
|
||||
FirPackageMemberScope(file.packageFqName, session, excludedNames = excludedNamesInPackage)
|
||||
}
|
||||
}
|
||||
// TODO: explicit simple importing scope should have highest priority (higher than inner scopes added in process)
|
||||
this += FirExplicitSimpleImportingScope(file.imports, session, scopeSession)
|
||||
}
|
||||
}
|
||||
|
||||
private class ListStorageFirScope(val result: List<FirScope>) : FirScope()
|
||||
Reference in New Issue
Block a user