diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirResolveTarget.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirResolveTarget.kt index 1f11e4b1c04..55e98dd09ed 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirResolveTarget.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirResolveTarget.kt @@ -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, 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, target: FirElementWithResolveState): List { - if (target is FirFile || target is FirFileAnnotationsContainer || target is FirScript) return path +private fun pathWithScript(firFile: FirFile?, path: List, target: FirElementWithResolveState): List { + 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 } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirSingleResolveTarget.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirSingleResolveTarget.kt index 22121b0cd4b..5b9294345b4 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirSingleResolveTarget.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirSingleResolveTarget.kt @@ -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, - 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, + target: FirElementWithResolveState, + ) : super(firFile, containerClasses, target) + + constructor(target: FirElementWithResolveState) : super(null, emptyList(), target) override fun visitTargetElement( element: FirElementWithResolveState, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt index 2d852a583ab..db19829241a 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt @@ -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( diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt index 2d7649749a5..1d24dc966b2 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt @@ -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 { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveOverAllPhasesTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveOverAllPhasesTest.kt index 1b8bdcbc32f..055315278ab 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveOverAllPhasesTest.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveOverAllPhasesTest.kt @@ -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