From 162a2ac7b0a27e44c46455555dd399851207ec44 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 31 Aug 2020 19:27:20 +0300 Subject: [PATCH] FIR IDE: fix lazy resolve for non local declaration without containing class --- .../low/level/api/FirModuleResolveState.kt | 1 + .../resolve/FirLazyDeclarationResolver.kt | 77 +++++++++++++------ 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt index dec3de26d0e..ba491e56a3e 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveState.kt @@ -100,6 +100,7 @@ internal open class FirModuleResolveStateImpl( ) { firLazyDeclarationResolver.runLazyResolveWithoutLock( firFunction, + fileCache, containerFirFile, firIdeProvider, toPhase, diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt index 46b5ad33a6e..16db15af282 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/lazy/resolve/FirLazyDeclarationResolver.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled import org.jetbrains.kotlin.idea.fir.low.level.api.util.executeWithoutPCE import org.jetbrains.kotlin.idea.fir.low.level.api.util.getContainingFile import org.jetbrains.kotlin.idea.util.classIdIfNonLocal +import org.jetbrains.kotlin.idea.util.getElementTextInContext import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject @@ -40,12 +41,28 @@ internal class FirLazyDeclarationResolver( val provider = firFile.session.firIdeProvider if (checkPCE) { firFileBuilder.runCustomResolveWithPCECheck(firFile, moduleFileCache) { - runLazyResolveWithoutLock(declaration, firFile, provider, toPhase, towerDataContextCollector, checkPCE = true) + runLazyResolveWithoutLock( + declaration, + moduleFileCache, + firFile, + provider, + toPhase, + towerDataContextCollector, + checkPCE = true + ) } } else { firFileBuilder.runCustomResolveUnderLock(firFile, moduleFileCache) { executeWithoutPCE { - runLazyResolveWithoutLock(declaration, firFile, provider, toPhase, towerDataContextCollector, checkPCE = false) + runLazyResolveWithoutLock( + declaration, + moduleFileCache, + firFile, + provider, + toPhase, + towerDataContextCollector, + checkPCE = false + ) } } } @@ -53,6 +70,7 @@ internal class FirLazyDeclarationResolver( fun runLazyResolveWithoutLock( firDeclarationToResolve: FirDeclaration, + moduleFileCache: ModuleFileCache, containerFirFile: FirFile, provider: FirProvider, toPhase: FirResolvePhase, @@ -70,17 +88,18 @@ internal class FirLazyDeclarationResolver( } if (toPhase <= nonLazyPhase) return if (checkPCE) checkCanceled() - runLazyResolvePhase(firDeclarationToResolve, containerFirFile, provider, toPhase, towerDataContextCollector) + runLazyResolvePhase(firDeclarationToResolve, containerFirFile, moduleFileCache, provider, toPhase, towerDataContextCollector) } private fun runLazyResolvePhase( firDeclarationToResolve: FirDeclaration, containerFirFile: FirFile, + moduleFileCache: ModuleFileCache, provider: FirProvider, toPhase: FirResolvePhase, towerDataContextCollector: FirTowerDataContextCollector?, ) { - val nonLocalDeclarationToResolve = firDeclarationToResolve.getNonLocalDeclarationToResolve(provider) + val nonLocalDeclarationToResolve = firDeclarationToResolve.getNonLocalDeclarationToResolve(provider, moduleFileCache) val designation = mutableListOf(containerFirFile) if (nonLocalDeclarationToResolve !is FirFile) { @@ -113,27 +132,37 @@ internal class FirLazyDeclarationResolver( ) containerFirFile.transform(transformer, ResolutionMode.ContextDependent) } -} - -private fun FirDeclaration.getNonLocalDeclarationToResolve(provider: FirProvider): FirDeclaration { - if (this is FirFile) return this - val ktDeclaration = psi as? KtDeclaration ?: error("FirDeclaration should have a PSI of type KtDeclaration") - if (!KtPsiUtil.isLocal(ktDeclaration)) return this - return when (val nonLocalPsi = ktDeclaration.getNonLocalContainingDeclarationWithFqName()) { - is KtClassOrObject -> provider.getFirClassifierByFqName( - nonLocalPsi.classIdIfNonLocal() - ?: error("Container classId should not be null for non-local declaration") - ) ?: error("Could not find class ${nonLocalPsi.classIdIfNonLocal()}") - is KtProperty, is KtNamedFunction -> { - val containerClass = nonLocalPsi.containingClassOrObject - ?: error("Container class should not be null for non-local declaration") - val containerClassId = containerClass.classIdIfNonLocal() - ?: error("Container classId should not be null for non-local declaration") - val containingFir = provider.getFirClassifierByFqName(containerClassId) as? FirRegularClass - ?: error("Could not find class $containerClassId") - containingFir.declarations.first { it.psi === nonLocalPsi } + private fun FirDeclaration.getNonLocalDeclarationToResolve(provider: FirProvider, moduleFileCache: ModuleFileCache): FirDeclaration { + if (this is FirFile) return this + val ktDeclaration = psi as? KtDeclaration ?: error("FirDeclaration should have a PSI of type KtDeclaration") + if (!KtPsiUtil.isLocal(ktDeclaration)) return this + return when (val nonLocalPsi = ktDeclaration.getNonLocalContainingDeclarationWithFqName()) { + is KtClassOrObject -> provider.getFirClassifierByFqName( + nonLocalPsi.classIdIfNonLocal() + ?: error("Container classId should not be null for non-local declaration") + ) ?: error("Could not find class ${nonLocalPsi.classIdIfNonLocal()}") + is KtProperty, is KtNamedFunction -> { + val containerClass = nonLocalPsi.containingClassOrObject + if (containerClass != null) { + val containerClassId = containerClass.classIdIfNonLocal() + ?: error("Container classId should not be null for non-local declaration") + val containingFir = provider.getFirClassifierByFqName(containerClassId) as? FirRegularClass + ?: error("Could not find class $containerClassId") + containingFir.declarations.first { it.psi === nonLocalPsi } + } else { + val packageFqName = ktDeclaration.containingKtFile.packageFqName + provider.symbolProvider.getTopLevelCallableSymbols(packageFqName, nonLocalPsi.nameAsSafeName) + .firstOrNull { it.fir.psi === nonLocalPsi } + val ktFile = ktDeclaration.containingKtFile + val firFile = firFileBuilder.buildRawFirFileWithCaching(ktFile, moduleFileCache) + firFile.declarations.firstOrNull { it.psi === nonLocalPsi } + ?: error("Cannot find FIR for\n${nonLocalPsi.getElementTextInContext()}") + } + } + else -> error("Invalid container ${nonLocalPsi?.let { it::class } ?: "null"}") } - else -> error("Invalid container ${nonLocalPsi?.let { it::class } ?: "null"}") } } + +