[LL FIR] LLFirResolveTarget: make firFile property optional

Not all targets belonged to any files (e.g., fake overrides),
so we should be able to resolve them without a provided file

^KT-64243
This commit is contained in:
Dmitrii Gridin
2023-12-12 16:00:48 +01:00
committed by Space Team
parent a7cfbe6d50
commit 6ffa8e6e98
5 changed files with 34 additions and 19 deletions
@@ -25,9 +25,12 @@ import org.jetbrains.kotlin.fir.declarations.FirScript
*/
internal sealed class LLFirResolveTarget(
/**
* [FirFile] where the targets are located
* [FirFile] where the targets are located.
* Can be null if [target] does not belong to any file.
* E.g., fake overrides.
* @see org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
*/
val firFile: FirFile,
val firFile: FirFile?,
/**
* The list of [FirRegularClass] which are the required to go from file to target declarations in the top-down order.
@@ -48,19 +51,28 @@ internal sealed class LLFirResolveTarget(
/**
* Visit [path], [target] and optionally its subgraph.
* Each nested declaration will be wrapped with corresponding [withFile], [withClass] and [withScript] recursively.
* Each nested declaration will be wrapped with corresponding [LLFirResolveTargetVisitor.withFile],
* [LLFirResolveTargetVisitor.withRegularClass] and [LLFirResolveTargetVisitor.withScript] recursively.
*/
fun visit(visitor: LLFirResolveTargetVisitor) {
if (target is FirFile) {
visitor.performAction(target)
}
visitor.withFile(firFile) {
val pathIterator = path.iterator()
goToTarget(pathIterator, visitor)
if (firFile != null) {
visitor.withFile(firFile) {
goToTarget(visitor)
}
} else {
goToTarget(visitor)
}
}
private fun goToTarget(visitor: LLFirResolveTargetVisitor) {
val pathIterator = path.iterator()
goToTarget(pathIterator, visitor)
}
private fun goToTarget(
pathIterator: Iterator<FirDeclaration>,
visitor: LLFirResolveTargetVisitor,
@@ -102,7 +114,7 @@ internal sealed class LLFirResolveTarget(
append(this@LLFirResolveTarget::class.simpleName)
append("(")
buildList {
add(firFile.name)
firFile?.name?.let(::add)
path.mapTo(this) {
when (it) {
is FirRegularClass -> it.name
@@ -130,8 +142,8 @@ internal sealed class LLFirResolveTarget(
}
}
private fun pathWithScript(firFile: FirFile, path: List<FirRegularClass>, target: FirElementWithResolveState): List<FirDeclaration> {
if (target is FirFile || target is FirFileAnnotationsContainer || target is FirScript) return path
private fun pathWithScript(firFile: FirFile?, path: List<FirRegularClass>, target: FirElementWithResolveState): List<FirDeclaration> {
if (firFile == null || target is FirFile || target is FirFileAnnotationsContainer || target is FirScript) return path
val firScript = firFile.declarations.singleOrNull() as? FirScript ?: return path
return listOf(firScript) + path
}
@@ -11,12 +11,16 @@ import org.jetbrains.kotlin.fir.declarations.*
/**
* [LLFirResolveTarget] representing single target to resolve. The [target] can be any of [FirElementWithResolveState]
*/
internal class LLFirSingleResolveTarget(
firFile: FirFile,
containerClasses: List<FirRegularClass>,
target: FirElementWithResolveState,
) : LLFirResolveTarget(firFile, containerClasses, target) {
constructor(firFile: FirFile) : this(firFile, emptyList(), firFile)
internal class LLFirSingleResolveTarget : LLFirResolveTarget {
constructor(firFile: FirFile) : super(firFile, emptyList(), firFile)
constructor(
firFile: FirFile,
containerClasses: List<FirRegularClass>,
target: FirElementWithResolveState,
) : super(firFile, containerClasses, target)
constructor(target: FirElementWithResolveState) : super(null, emptyList(), target)
override fun visitTargetElement(
element: FirElementWithResolveState,
@@ -116,7 +116,7 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
towerDataContextCollector: FirResolveContextCollector?,
) {
try {
resolveFileToImportsWithLock(target.firFile)
target.firFile?.let(::resolveFileToImportsWithLock)
if (toPhase == FirResolvePhase.IMPORTS) return
lazyResolveTargets(
@@ -73,7 +73,7 @@ internal abstract class LLFirTargetResolver(
*/
private fun resolveDependencies(target: FirElementWithResolveState) {
if (skipDependencyTargetResolutionStep || target is FirFileAnnotationsContainer) return
resolveTarget.firFile.annotationsContainer?.lazyResolveToPhase(resolverPhase)
resolveTarget.firFile?.annotationsContainer?.lazyResolveToPhase(resolverPhase)
val originalDeclaration = (target as? FirCallableDeclaration)?.originalIfFakeOverrideOrDelegated()
when {
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.resolvePhase
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhaseRecursively
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
@@ -42,7 +41,7 @@ abstract class AbstractFirLazyDeclarationResolveOverAllPhasesTest : AbstractFirL
} else {
val firFile = firResolveSession.getOrBuildFirFile(ktFile)
val designations = LLFirResolveMultiDesignationCollector.getDesignationsToResolve(elementToResolve)
listOf(firFile).plus(designations.map { it.firFile }).distinct()
listOf(firFile).plus(designations.mapNotNull { it.firFile }).distinct()
}
val basePhase = elementToResolve.resolvePhase