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
This commit is contained in:
Roman Golyshev
2023-11-29 13:13:06 +01:00
committed by Space Team
parent 476a0b6783
commit cd62f2f7a4
2 changed files with 22 additions and 25 deletions
@@ -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
@@ -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)