From cd62f2f7a4fc37cf2c82969699c84a904b30dc76 Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Wed, 29 Nov 2023 13:13:06 +0100 Subject: [PATCH] KT-59732 [FIR] Do not perform an actual resolve during IMPORTS phase Use `FirSymbolProvider` to find the longest existing package, and assume that the rest of the import is class name --- .../FirImportResolveTransformer.kt | 25 ++----------------- .../fir/resolve/transformers/ImportUtils.kt | 22 ++++++++++++++-- 2 files changed, 22 insertions(+), 25 deletions(-) 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 62d8ec30833..612e9489716 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 @@ -5,18 +5,14 @@ package org.jetbrains.kotlin.fir.resolve.transformers -import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirImport -import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirResolvePhase -import org.jetbrains.kotlin.fir.declarations.builder.buildErrorImport import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport import org.jetbrains.kotlin.fir.lookupTracker import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeImportFromSingleton import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.withFileAnalysisExceptionWrapping @@ -76,25 +72,8 @@ open class FirImportResolveTransformer protected constructor( get() = true private fun transformImportForFqName(fqName: FqName, delegate: FirImport): FirImport { - val (packageFqName, relativeClassFqName, classSymbol) = when (val result = resolveToPackageOrClass(symbolProvider, fqName)) { - is PackageResolutionResult.Error -> - return if (delegate.source?.kind == KtFakeSourceElementKind.ImplicitImport) { - delegate - } else { - buildErrorImport { - this.delegate = delegate - this.diagnostic = result.diagnostic - } - } - is PackageResolutionResult.PackageOrClass -> result - } - val firClass = classSymbol?.fir as? FirRegularClass - if (delegate.isAllUnder && firClass?.classKind?.isSingleton == true) { - return buildErrorImport { - this.delegate = delegate - this.diagnostic = ConeImportFromSingleton(firClass.name) - } - } + val (packageFqName, relativeClassFqName) = findLongestExistingPackage(symbolProvider, fqName) + return buildResolvedImport { this.delegate = delegate this.packageFqName = packageFqName diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/transformers/ImportUtils.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/transformers/ImportUtils.kt index 0a25a7dd740..11f5cbfa822 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/transformers/ImportUtils.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/transformers/ImportUtils.kt @@ -12,7 +12,16 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName -fun resolveToPackageOrClass(symbolProvider: FirSymbolProvider, fqName: FqName): PackageResolutionResult { +/** + * Compared to [resolveToPackageOrClass], does not perform the actual resolve. + * + * Instead of it, it just looks for the longest existing package name prefix in the [fqName], + * and assumes that the rest of the name (if present) is a relative class name. + * + * Given that [FqName.ROOT] package is always present in any [FirSymbolProvider], + * this function **can never fail**. + */ +fun findLongestExistingPackage(symbolProvider: FirSymbolProvider, fqName: FqName): PackageAndClass { var currentPackage = fqName val pathSegments = fqName.pathSegments() @@ -25,9 +34,18 @@ fun resolveToPackageOrClass(symbolProvider: FirSymbolProvider, fqName: FqName): prefixSize-- } - if (currentPackage == fqName) return PackageResolutionResult.PackageOrClass(currentPackage, null, null) + if (currentPackage == fqName) return PackageAndClass(currentPackage, relativeClassFqName = null) val relativeClassFqName = FqName.fromSegments((prefixSize until pathSegments.size).map { pathSegments[it].asString() }) + return PackageAndClass(currentPackage, relativeClassFqName) +} + +data class PackageAndClass(val packageFqName: FqName, val relativeClassFqName: FqName?) + +fun resolveToPackageOrClass(symbolProvider: FirSymbolProvider, fqName: FqName): PackageResolutionResult { + val (currentPackage, relativeClassFqName) = findLongestExistingPackage(symbolProvider, fqName) + if (relativeClassFqName == null) return PackageResolutionResult.PackageOrClass(currentPackage, null, null) + val classId = ClassId(currentPackage, relativeClassFqName, isLocal = false) val symbol = symbolProvider.getClassLikeSymbolByClassId(classId) ?: return PackageResolutionResult.Error( ConeUnresolvedParentInImport(classId)