diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index 5a34e8aca31..533a2d8e4ad 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -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 withScopesForCodeFragment(codeFragment: FirCodeFragment, f: () -> T): T { + fun 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( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 4c1b0c97200..7a9541c5ef0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -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() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/ImportingScopes.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/ImportingScopes.kt index 24476125c4a..487c93eddf9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/ImportingScopes.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/ImportingScopes.kt @@ -27,16 +27,18 @@ fun createImportingScopes( useCaching: Boolean = true ): List = 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 { 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() \ No newline at end of file