diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirImportResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirImportResolveTransformer.kt index 65b4f55b7c2..1a6f7b65494 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirImportResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirImportResolveTransformer.kt @@ -22,19 +22,21 @@ class FirImportResolveTransformer : FirTransformer() { return element.compose() } + private lateinit var symbolProvider: FirSymbolProvider + override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { + symbolProvider = FirSymbolProvider.getInstance(file.session) return file.also { it.transformChildren(this, null) }.compose() } override fun transformImport(import: FirImport, data: Nothing?): CompositeTransformResult { val fqName = import.importedFqName ?: return import.compose() - val firProvider = FirSymbolProvider.getInstance(import.session) if (!fqName.isRoot) { val lastPart = StringBuilder() var firstPart = fqName - if (import.isAllUnder && firProvider.getPackage(firstPart) != null) { + if (import.isAllUnder && symbolProvider.getPackage(firstPart) != null) { return FirResolvedPackageStarImport(import, firstPart).compose() } @@ -46,7 +48,7 @@ class FirImportResolveTransformer : FirTransformer() { firstPart = firstPart.parent() val resolvedFqName = ClassId(firstPart, FqName(lastPart.toString()), false) - val foundSymbol = firProvider.getSymbolByFqName(resolvedFqName) + val foundSymbol = symbolProvider.getSymbolByFqName(resolvedFqName) if (foundSymbol != null) { return FirResolvedImportImpl(import, resolvedFqName).compose() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractStarImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractStarImportingScope.kt index 1ed9d2a8c1c..812b6dcf350 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractStarImportingScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractStarImportingScope.kt @@ -8,22 +8,32 @@ package org.jetbrains.kotlin.fir.scopes.impl import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirResolvedImport import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider +import org.jetbrains.kotlin.fir.resolve.impl.FirLibrarySymbolProviderImpl import org.jetbrains.kotlin.fir.scopes.FirPosition import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.symbols.ConeSymbol import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name -abstract class FirAbstractStarImportingScope(val session: FirSession) : FirScope { +abstract class FirAbstractStarImportingScope(val session: FirSession, lookupInFir: Boolean = true) : FirScope { protected abstract val starImports: List + + // TODO: Abstractify this optimization + val provider = FirSymbolProvider.getInstance(session).let { + when { + it is FirCompositeSymbolProvider && !lookupInFir -> it.providers.first { it is FirLibrarySymbolProviderImpl } + else -> it + } + } + override fun processClassifiersByName( name: Name, position: FirPosition, processor: (ConeSymbol) -> Boolean ): Boolean { - val provider = FirSymbolProvider.getInstance(session) for (import in starImports) { val relativeClassName = import.relativeClassName val classId = if (relativeClassName == null) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDefaultStarImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDefaultStarImportingScope.kt index ab5b859b8a8..09907825846 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDefaultStarImportingScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDefaultStarImportingScope.kt @@ -10,7 +10,8 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedPackageStarImport import org.jetbrains.kotlin.name.FqName -class FirDefaultStarImportingScope(session: FirSession) : FirAbstractStarImportingScope(session) { +class FirDefaultStarImportingScope(session: FirSession, lookupInFir: Boolean = false) : + FirAbstractStarImportingScope(session, lookupInFir) { // TODO: move relevant code in TargetPlatform from compiler:frontend and use here override val starImports = listOf( "kotlin", diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSelfImportingScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSelfImportingScope.kt index 3ccb87d8efe..396af6b09b3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSelfImportingScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirSelfImportingScope.kt @@ -5,27 +5,42 @@ package org.jetbrains.kotlin.fir.scopes.impl +import com.intellij.util.containers.ContainerUtil import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.resolve.FirProvider +import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider import org.jetbrains.kotlin.fir.scopes.FirPosition import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.service import org.jetbrains.kotlin.fir.symbols.ConeSymbol import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name class FirSelfImportingScope(val fqName: FqName, val session: FirSession) : FirScope { + + private val symbolProvider = FirSymbolProvider.getInstance(session) + + private val cache = ContainerUtil.newConcurrentMap() + private val absentKeys = ContainerUtil.newConcurrentSet() + override fun processClassifiersByName( name: Name, position: FirPosition, processor: (ConeSymbol) -> Boolean ): Boolean { - val unambiguousFqName = ClassId(fqName, name) - val firProvider = session.service() - val symbol = firProvider.getSymbolByFqName(unambiguousFqName) + if (name in absentKeys) return true + val symbol = cache[name] ?: run { + val unambiguousFqName = ClassId(fqName, name) + val computed = symbolProvider.getSymbolByFqName(unambiguousFqName) + if (computed == null) { + absentKeys += name + } else { + cache[name] = computed + } + computed + } + return if (symbol != null) { processor(symbol) } else {