From 6867dffff12d4c2ce98229d87b8eeb9ff2f88496 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Thu, 6 Jul 2023 11:02:35 +0200 Subject: [PATCH] [LL FIR] rewrite on-air resolve Now we will resolve declarations only ones and to the minimal required phase to get a fully resolved element depends on an insert position, because not all elements require body resolution A side change: `getOnAirGetTowerContextProvider` now won't do rebind to the original declaration. In the future, this part will be rewritten to avoid on-air resolution, so it is not a problem ^KT-59685 Fixed --- .../level/api/fir/DeclarationCopyBuilder.kt | 118 ---------- .../LowLevelFirApiFacadeForResolveOnAir.kt | 216 +++++++++++------- .../targets/LLFirWholeClassResolveTarget.kt | 41 ++++ .../LLFirModuleLazyDeclarationResolver.kt | 42 ++-- .../RawFirNonLocalDeclarationBuilder.kt | 37 +++ .../api/fir/lazy/resolve/RawFirReplacement.kt | 7 +- .../LLFirAbstractBodyTargetResolver.kt | 12 +- ...irAnnotationArgumentMappingLazyResolver.kt | 6 +- .../LLFirAnnotationArgumentsLazyResolver.kt | 49 +++- .../fir/transformers/LLFirBodyLazyResolver.kt | 31 +-- .../LLFirImplicitTypesLazyResolver.kt | 6 +- .../LLFirReturnTypeCalculatorWithJump.kt | 2 +- .../fir/transformers/LLFirTargetResolver.kt | 6 + .../level/api/fir/util/FirElementFinder.kt | 4 +- .../kotlin/fir/builder/PsiRawFirBuilder.kt | 24 +- ...irAnnotationArgumentsMappingTransformer.kt | 4 + ...irAnnotationArgumentsResolveTransformer.kt | 3 + 17 files changed, 345 insertions(+), 263 deletions(-) delete mode 100644 analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/DeclarationCopyBuilder.kt create mode 100644 analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirWholeClassResolveTarget.kt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/DeclarationCopyBuilder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/DeclarationCopyBuilder.kt deleted file mode 100644 index a8ed54e6be7..00000000000 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/DeclarationCopyBuilder.kt +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.analysis.low.level.api.fir - -import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.builder.* -import org.jetbrains.kotlin.fir.expressions.FirReturnExpression -import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid - -internal object DeclarationCopyBuilder { - fun FirSimpleFunction.withBodyFrom( - functionWithBody: FirSimpleFunction, - ): FirSimpleFunction = buildSimpleFunctionCopy(this) { - body = functionWithBody.body - symbol = functionWithBody.symbol - initDeclaration(this@withBodyFrom, functionWithBody) - }.apply { reassignAllReturnTargets(functionWithBody) } - - fun FirRegularClass.withBodyFrom( - classWithBody: FirRegularClass, - ): FirRegularClass = buildRegularClassCopy(this) { - declarations.clear() - declarations.addAll(classWithBody.declarations) - symbol = classWithBody.symbol - initDeclaration(this@withBodyFrom, classWithBody) - } - - fun FirScript.withBodyFrom( - scriptWithBody: FirScript - ): FirScript = buildScriptCopy(this) { - statements.clear() - statements.addAll(scriptWithBody.statements) - symbol = scriptWithBody.symbol - initDeclaration(this@withBodyFrom, scriptWithBody) - } - - fun FirProperty.withBodyFrom(propertyWithBody: FirProperty): FirProperty { - val newSetter = getAccessorToUse(this, propertyWithBody) { it.setter } - val newGetter = getAccessorToUse(this, propertyWithBody) { it.getter } - - val propertyResolvePhase = minOf( - this@withBodyFrom.resolvePhase, - FirResolvePhase.DECLARATIONS, - newGetter?.resolvePhase ?: FirResolvePhase.BODY_RESOLVE, - newSetter?.resolvePhase ?: FirResolvePhase.BODY_RESOLVE, - propertyWithBody.getter?.resolvePhase ?: FirResolvePhase.BODY_RESOLVE, - propertyWithBody.setter?.resolvePhase ?: FirResolvePhase.BODY_RESOLVE, - ) - - return buildPropertyCopy(this@withBodyFrom) { - symbol = propertyWithBody.symbol - initializer = propertyWithBody.initializer - - getter = newGetter - setter = newSetter - - if (propertyResolvePhase < FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { - bodyResolveState = FirPropertyBodyResolveState.NOTHING_RESOLVED - } - - initDeclaration(this@withBodyFrom, propertyWithBody) - resolvePhase = propertyResolvePhase - } - } - - private inline fun getAccessorToUse( - originalProperty: FirProperty, - replacementProperty: FirProperty, - getAccessor: (FirProperty) -> FirPropertyAccessor? - ): FirPropertyAccessor? { - val originalAccessor = getAccessor(originalProperty) - val replacementAccessor = getAccessor(replacementProperty) - - // accessor has a header type, and we want it type to be resolved - return if (originalAccessor != null && replacementAccessor != null) { - buildPropertyAccessorCopy(originalAccessor) { - body = replacementAccessor.body - symbol = replacementAccessor.symbol - initDeclaration(originalAccessor, replacementAccessor) - }.apply { reassignAllReturnTargets(replacementAccessor) } - } else { - replacementAccessor - } - } - - private fun FirDeclarationBuilder.initDeclaration( - originalDeclaration: FirDeclaration, - builtDeclaration: FirDeclaration, - ) { - resolvePhase = minOf(originalDeclaration.resolvePhase, FirResolvePhase.DECLARATIONS) - source = builtDeclaration.source - moduleData = originalDeclaration.moduleData - } - - private fun FirScriptBuilder.initDeclaration( - originalDeclaration: FirDeclaration, - builtDeclaration: FirDeclaration, - ) { - resolvePhase = minOf(originalDeclaration.resolvePhase, FirResolvePhase.DECLARATIONS) - source = builtDeclaration.source - moduleData = originalDeclaration.moduleData - } - - private fun FirFunction.reassignAllReturnTargets(from: FirFunction) { - this.accept(object : FirVisitorVoid() { - override fun visitElement(element: FirElement) { - if (element is FirReturnExpression && element.target.labeledElement == from) { - element.target.bind(this@reassignAllReturnTargets) - } - element.acceptChildren(this) - } - }) - } -} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacadeForResolveOnAir.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacadeForResolveOnAir.kt index ace2f383ec6..9d78c4d5ba9 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacadeForResolveOnAir.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacadeForResolveOnAir.kt @@ -7,12 +7,11 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.api import com.intellij.psi.PsiElement import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.analysis.low.level.api.fir.DeclarationCopyBuilder.withBodyFrom import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionDepended -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirWholeFileResolveTarget import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FileTowerProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerDataContextAllElementsCollector +import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.canBePartOfParentDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FirElementsRecorder import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping @@ -23,11 +22,11 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableM import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirResolvableSession import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableResolveSession +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirElementFinder import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry -import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext import org.jetbrains.kotlin.analysis.utils.printer.parentOfType import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType import org.jetbrains.kotlin.fir.FirElement @@ -41,27 +40,19 @@ import org.jetbrains.kotlin.fir.scopes.createImportingScopes import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.isAncestor +import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf object LowLevelFirApiFacadeForResolveOnAir { - private fun PsiElement.onAirGetNonLocalContainingOrThisDeclarationFor(): KtDeclaration? { + private fun KtDeclaration.isApplicableForOnAirResolve(): Boolean = when (this) { + is KtDestructuringDeclaration -> false + else -> true + } + + private fun PsiElement.onAirGetNonLocalContainingOrThisDeclaration(): KtDeclaration? { return getNonLocalContainingOrThisDeclaration { declaration -> - when (declaration) { - is KtNamedFunction, - is KtProperty, - is KtTypeAlias, - is KtScript -> { - true - } - - is KtClassOrObject -> { - declaration !is KtEnumEntry - } - - else -> { - false - } - } + declaration.isApplicableForOnAirResolve() && !declaration.canBePartOfParentDeclaration } } @@ -83,8 +74,9 @@ object LowLevelFirApiFacadeForResolveOnAir { val declaration = runBodyResolveOnAir( firResolveSession = firResolveSession, - replacement = RawFirReplacement(place, elementToResolve), - onAirCreatedDeclaration = true + originalPlace = place, + replacementElement = elementToResolve, + collector = null, ) val expressionLocator = object : FirVisitorVoid() { @@ -114,9 +106,12 @@ object LowLevelFirApiFacadeForResolveOnAir { val moduleComponents = session.moduleComponents val onAirFirFile = RawFirNonLocalDeclarationBuilder.buildNewFile(session, session.kotlinScopeProvider, ktFile) - val target = LLFirWholeFileResolveTarget(onAirFirFile) val collector = FirTowerDataContextAllElementsCollector() - moduleComponents.firModuleLazyDeclarationResolver.lazyResolveTarget(target, FirResolvePhase.BODY_RESOLVE, collector) + moduleComponents.firModuleLazyDeclarationResolver.runLazyDesignatedOnAirResolve( + FirDesignationWithFile(emptyList(), onAirFirFile, onAirFirFile), + collector, + ) + return collector } @@ -137,8 +132,8 @@ object LowLevelFirApiFacadeForResolveOnAir { runBodyResolveOnAir( firResolveSession = firResolveSession, collector = it, - onAirCreatedDeclaration = false, - replacement = RawFirReplacement(validPlace, validPlace), + originalPlace = validPlace, + replacementElement = validPlace, ) } } @@ -164,39 +159,48 @@ object LowLevelFirApiFacadeForResolveOnAir { return FirTowerDataContext().addNonLocalTowerDataElements(fileScopeElements) } + /** + * Makes a copy of the original fir declaration and resolves it to the minimum required phase + * depends on [elementToAnalyze] position inside a non-local containing declaration. + * + * If [elementToAnalyze] is non-local declaration then resolves it to [FirResolvePhase.BODY_RESOLVE]. + * + * Resulted [LLFirResolveSession] have [FirTowerDataContext] for elements from the copy. + */ fun getFirResolveSessionForDependentCopy( originalFirResolveSession: LLFirResolveSession, originalKtFile: KtFile, - elementToAnalyze: KtElement + elementToAnalyze: KtElement, ): LLFirResolveSession { require(originalFirResolveSession is LLFirResolvableResolveSession) require(elementToAnalyze !is KtFile) { "KtFile for dependency element not supported" } - val dependencyNonLocalDeclaration = elementToAnalyze.onAirGetNonLocalContainingOrThisDeclarationFor() as? KtNamedDeclaration + val minimalCopiedDeclaration = elementToAnalyze.getNonLocalContainingOrThisDeclaration { + it.isApplicableForOnAirResolve() + } - if (dependencyNonLocalDeclaration == null) { + val copiedNonLocalDeclaration = minimalCopiedDeclaration?.onAirGetNonLocalContainingOrThisDeclaration() + if (copiedNonLocalDeclaration == null) { val towerDataContext = onAirGetTowerContextForFile(originalFirResolveSession, originalKtFile) val fileTowerProvider = FileTowerProvider(elementToAnalyze.containingKtFile, towerDataContext) return LLFirResolveSessionDepended(originalFirResolveSession, fileTowerProvider, ktToFirMapping = null) } - val sameDeclarationInOriginalFile = PsiTreeUtil.findSameElementInCopy(dependencyNonLocalDeclaration, originalKtFile) + val originalNonLocalDeclaration = PsiTreeUtil.findSameElementInCopy(copiedNonLocalDeclaration, originalKtFile) ?: buildErrorWithAttachment("Cannot find original function matching") { - withPsiEntry("matchingPsi", dependencyNonLocalDeclaration, originalFirResolveSession::getModule) + withPsiEntry("matchingPsi", elementToAnalyze, originalFirResolveSession::getModule) withPsiEntry("originalFile", originalKtFile, originalFirResolveSession::getModule) } - recordOriginalDeclaration( - targetDeclaration = dependencyNonLocalDeclaration, - originalDeclaration = sameDeclarationInOriginalFile - ) + recordOriginalDeclaration(targetDeclaration = copiedNonLocalDeclaration, originalDeclaration = originalNonLocalDeclaration) val collector = FirTowerDataContextAllElementsCollector() val copiedFirDeclaration = runBodyResolveOnAir( originalFirResolveSession, - replacement = RawFirReplacement(sameDeclarationInOriginalFile, dependencyNonLocalDeclaration), - onAirCreatedDeclaration = true, + originalPlace = originalNonLocalDeclaration, + replacementElement = copiedNonLocalDeclaration, collector = collector, + forcedResolvePhase = requiredResolvePhase(minimalCopiedDeclaration, elementToAnalyze), ) val mapping = KtToFirMapping(copiedFirDeclaration, FirElementsRecorder()) @@ -229,10 +233,9 @@ object LowLevelFirApiFacadeForResolveOnAir { } val declarationResolver = llFirResolvableSession.moduleComponents.firModuleLazyDeclarationResolver - declarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock( + declarationResolver.runLazyDesignatedOnAirResolve( FirDesignationWithFile(path = emptyList(), target = fileAnnotationsContainer, firFile), - onAirCreatedDeclaration = true, - collector + collector, ) collector?.addFileContext(firFile, firFile.createTowerDataContext(firResolveSession.getScopeSessionFor(llFirResolvableSession))) @@ -241,70 +244,117 @@ object LowLevelFirApiFacadeForResolveOnAir { return fileAnnotationsContainer.annotations.single() } + /** + * Creates a new fir declaration from closer non-local declaration based on [originalPlace] position. + * The resulted [FirResolvePhase] depends on [forcedResolvePhase] or the position of [originalPlace] inside the non-local declaration. + * + * Note: the new declaration and its content won't be rebinded to the original. + * + * @see requiredResolvePhase + */ private fun runBodyResolveOnAir( firResolveSession: LLFirResolvableResolveSession, - replacement: RawFirReplacement, - onAirCreatedDeclaration: Boolean, - collector: FirResolveContextCollector? = null, + originalPlace: KtElement, + replacementElement: KtElement, + collector: FirResolveContextCollector?, + forcedResolvePhase: FirResolvePhase? = null, ): FirElement { - val nonLocalDeclaration = replacement.from.onAirGetNonLocalContainingOrThisDeclarationFor() - val originalFirFile = firResolveSession.getOrBuildFirFile(replacement.from.containingKtFile) + val minimalOriginalDeclarationToReplace = originalPlace.getNonLocalContainingOrThisDeclaration { + it.isApplicableForOnAirResolve() + } - if (nonLocalDeclaration == null) { + val originalFirFile = firResolveSession.getOrBuildFirFile(originalPlace.containingKtFile) + + val originalDeclaration = minimalOriginalDeclarationToReplace?.onAirGetNonLocalContainingOrThisDeclaration() + if (originalDeclaration == null) { //It is possible that it is file annotation is going to resolve - val annotationCall = replacement.from.parentOfType(withSelf = true) + val annotationCall = originalPlace.parentOfType(withSelf = true) if (annotationCall != null) { return tryResolveAsFileAnnotation( annotationEntry = annotationCall, - replacement = replacement, + replacement = RawFirReplacement(from = originalPlace, to = replacementElement), firFile = originalFirFile, collector = collector, firResolveSession = firResolveSession, ) } else { - error("Cannot find enclosing declaration for ${replacement.from.getElementTextInContext()}") + errorWithFirSpecificEntries( + "Cannot find enclosing declaration for ${originalPlace::class.simpleName}", + psi = originalPlace, + ) } } - val originalDeclaration = nonLocalDeclaration.getOrBuildFirOfType(firResolveSession) - val originalDesignation = originalDeclaration.collectDesignation() - val newDeclarationWithReplacement = RawFirNonLocalDeclarationBuilder.buildWithReplacement( - session = originalDeclaration.moduleData.session, - scopeProvider = originalDeclaration.moduleData.session.kotlinScopeProvider, - designation = originalDesignation, - rootNonLocalDeclaration = nonLocalDeclaration, + val originalDesignationPath = FirElementFinder.collectDesignationPath(originalFirFile, originalDeclaration) + ?: errorWithFirSpecificEntries(message = "Impossible to collect designation", fir = originalFirFile, psi = originalDeclaration) + + val originalFirDeclaration = originalDesignationPath.target + val session = originalFirDeclaration.llFirResolvableSession ?: error("Expected resolvable session") + + /** + * Special case for [getOnAirGetTowerContextProvider]. Can be dropped after KT-59498 + */ + val replacement = if (originalPlace === replacementElement) { + RawFirReplacement(from = originalDeclaration, to = originalDeclaration) + } else { + RawFirReplacement(from = originalPlace, to = replacementElement) + } + + val newFirDeclaration = RawFirNonLocalDeclarationBuilder.buildWithReplacement( + session = session, + scopeProvider = session.kotlinScopeProvider, + designation = FirDesignation(originalDesignationPath.path, originalFirDeclaration), + rootNonLocalDeclaration = originalDeclaration, replacement = replacement, ) - val isInBodyReplacement = isInBodyReplacement(nonLocalDeclaration, replacement) - val copiedFirDeclaration = if (isInBodyReplacement) { - when (originalDeclaration) { - is FirSimpleFunction -> originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirSimpleFunction) - is FirProperty -> originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirProperty) - is FirRegularClass -> originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirRegularClass) - is FirScript -> originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirScript) - is FirTypeAlias -> newDeclarationWithReplacement - else -> error("Not supported type ${originalDeclaration::class.simpleName}") - } - } else { - newDeclarationWithReplacement + session.moduleComponents.firModuleLazyDeclarationResolver.runLazyDesignatedOnAirResolve( + FirDesignationWithFile(originalDesignationPath.path, newFirDeclaration, originalFirFile), + collector, + forcedResolvePhase ?: requiredResolvePhase(minimalOriginalDeclarationToReplace, originalPlace), + ) + + return newFirDeclaration + } + + private fun requiredResolvePhase( + container: KtDeclaration, + elementToReplace: PsiElement, + ): FirResolvePhase = when { + bodyResolveRequired(container, elementToReplace) -> FirResolvePhase.BODY_RESOLVE + annotationMappingRequired(container, elementToReplace) -> FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING + + /** + * Currently it is a minimal phase there we can collect [FirResolveContextCollector] + */ + else -> FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS + } + + private fun annotationMappingRequired( + container: KtDeclaration, + elementToReplace: PsiElement, + ): Boolean = elementToReplace.parentsWithSelf.takeWhile { it != container }.any { + it is KtAnnotationEntry + } || elementToReplace.anyDescendantOfType( + canGoInside = { + // We shouldn't go inside a class body, because class resolution won't process such elements + // In case of container is class, we are interested only in elements outside its body + it !is KtClassBody + }, + ) + + private fun bodyResolveRequired(container: KtDeclaration, elementToReplace: PsiElement): Boolean = when { + container == elementToReplace -> true + container is KtDeclarationWithBody -> container.bodyExpression?.isAncestor(elementToReplace) + container is KtProperty -> container.delegateExpressionOrInitializer?.isAncestor(elementToReplace) + container is KtParameter -> container.defaultValue?.isAncestor(elementToReplace) + container is KtEnumEntry -> { + container.initializerList?.isAncestor(elementToReplace) == true || container.body?.isAncestor(elementToReplace) == true } - val onAirDesignation = FirDesignationWithFile( - path = originalDesignation.path, - target = copiedFirDeclaration, - firFile = originalFirFile - ) - - val resolvableSession = onAirDesignation.target.llFirResolvableSession ?: error("Expected resolvable session") - resolvableSession.moduleComponents.firModuleLazyDeclarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock( - designation = onAirDesignation, - onAirCreatedDeclaration = onAirCreatedDeclaration, - towerDataContextCollector = collector, - ) - - return copiedFirDeclaration - } + container is KtScript || container is KtAnonymousInitializer -> true + else -> false + } == true private fun isInBodyReplacement(ktDeclaration: KtDeclaration, replacement: RawFirReplacement): Boolean { fun check(container: KtElement?): Boolean { diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirWholeClassResolveTarget.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirWholeClassResolveTarget.kt new file mode 100644 index 00000000000..85b31b7828e --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirWholeClassResolveTarget.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets + +import org.jetbrains.kotlin.fir.FirElementWithResolveState +import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirRegularClass + +/** + * [LLFirResolveTarget] representing all declarations in a class (including nested classes). + * All of them are going to be resolved. + */ +class LLFirWholeClassResolveTarget( + override val firFile: FirFile, + override val path: List, + val target: FirRegularClass, +) : LLFirResolveTarget() { + override fun forEachTarget(action: (FirElementWithResolveState) -> Unit) { + action(target) + + fun goInside(target: FirElementWithResolveState) { + action(target) + if (target is FirRegularClass) { + target.declarations.forEach(::goInside) + } + } + + forEachDeclaration(::goInside) + } + + inline fun forEachDeclaration(action: (FirElementWithResolveState) -> Unit) { + for (member in target.declarations) { + action(member) + } + } + + override fun toStringForTarget(): String = "*" +} 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 6050c9073e0..892c2f6e083 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 @@ -7,9 +7,10 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirClassWithAllMembersResolveTarget import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirSingleResolveTarget +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirWholeClassResolveTarget +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirWholeFileResolveTarget import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.InvalidSessionException import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession @@ -106,6 +107,9 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod towerDataContextCollector: FirResolveContextCollector?, ) { try { + resolveFileToImportsWithLock(target.firFile) + if (toPhase == FirResolvePhase.IMPORTS) return + lazyResolveTargets( targets = listOf(target), moduleComponents.scopeSessionProvider.getScopeSession(), @@ -117,31 +121,35 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod } } - fun runLazyDesignatedOnAirResolveToBodyWithoutLock( + /** + * Resolve on-air created declaration in a context of real [FirDesignationWithFile.firFile] and [FirDesignationWithFile.path]. + * If target declaration is [FirFile] then the entire file will be resolved. + * The same for [FirRegularClass] if [resolvePhase] is [FirResolvePhase.BODY_RESOLVE]. + */ + fun runLazyDesignatedOnAirResolve( designation: FirDesignationWithFile, - onAirCreatedDeclaration: Boolean, towerDataContextCollector: FirResolveContextCollector?, + resolvePhase: FirResolvePhase = FirResolvePhase.BODY_RESOLVE, ) { resolveFileToImportsWithLock(designation.firFile) - val target = when (designation.target) { - is FirRegularClass -> LLFirClassWithAllMembersResolveTarget(designation.firFile, designation.path, designation.target) + val target = when { + designation.target is FirFile -> LLFirWholeFileResolveTarget(designation.firFile) + resolvePhase == FirResolvePhase.BODY_RESOLVE && designation.target is FirRegularClass -> { + LLFirWholeClassResolveTarget(designation.firFile, designation.path, designation.target) + } + else -> LLFirSingleResolveTarget(designation.firFile, designation.path, designation.target) } - fun runTransformation() { - val scopeSession = ScopeSession() - lazyResolveTargets(listOf(target), scopeSession, FirResolvePhase.BODY_RESOLVE, towerDataContextCollector) - } - try { - if (onAirCreatedDeclaration) { - withOnAirDesignation(designation, ::runTransformation) - } else { - runTransformation() + withOnAirDesignation(designation) { + // New session to avoid garbage in the original session + val scopeSession = ScopeSession() + lazyResolveTargets(listOf(target), scopeSession, resolvePhase, towerDataContextCollector) } } catch (e: Exception) { - handleExceptionFromResolve(e, target, FirResolvePhase.BODY_RESOLVE) + handleExceptionFromResolve(e, target, resolvePhase) } } @@ -200,7 +208,7 @@ private fun handleExceptionFromResolve( exception: Exception, firDeclarationToResolve: FirElementWithResolveState, fromPhase: FirResolvePhase, - toPhase: FirResolvePhase + toPhase: FirResolvePhase, ): Nothing { if (exception is InvalidSessionException) { throw exception @@ -235,7 +243,7 @@ private fun handleExceptionFromResolve( private fun handleExceptionFromResolve( exception: Exception, designation: LLFirResolveTarget, - toPhase: FirResolvePhase + toPhase: FirResolvePhase, ): Nothing { if (exception is InvalidSessionException) { throw exception diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt index 53cd6d1e9b9..12c40c5e138 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignation import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment +import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.builder.BodyBuildingMode @@ -23,6 +24,7 @@ import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.scopes.FirScopeProvider import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.name.NameUtils @@ -111,6 +113,12 @@ internal class RawFirNonLocalDeclarationBuilder private constructor( } private inner class VisitorWithReplacement(private val containingClass: FirRegularClass?) : Visitor() { + fun convertDestructuringDeclaration(element: KtDestructuringDeclaration): FirVariable { + val replacementDeclaration = replacementApplier?.tryReplace(element) ?: element + requireIsInstance(replacementDeclaration) + return buildErrorTopLevelDestructuringDeclaration(replacementDeclaration.toFirSourceElement()) + } + override fun convertElement(element: KtElement, original: FirElement?): FirElement? = super.convertElement(replacementApplier?.tryReplace(element) ?: element, original) @@ -128,6 +136,34 @@ internal class RawFirNonLocalDeclarationBuilder private constructor( ) } + override fun convertPropertyAccessor( + accessor: KtPropertyAccessor?, + property: KtProperty, + propertyTypeRef: FirTypeRef, + propertySymbol: FirPropertySymbol, + isGetter: Boolean, + accessorAnnotationsFromProperty: List, + parameterAnnotationsFromProperty: List, + ): FirPropertyAccessor? { + val replacementAccessor = if (accessor != null) { + val replacementAccessor = replacementApplier?.tryReplace(accessor) ?: accessor + check(replacementAccessor is KtPropertyAccessor) + replacementAccessor + } else { + accessor + } + + return super.convertPropertyAccessor( + replacementAccessor, + property, + propertyTypeRef, + propertySymbol, + isGetter, + accessorAnnotationsFromProperty, + parameterAnnotationsFromProperty + ) + } + override fun convertValueParameter( valueParameter: KtParameter, functionSymbol: FirFunctionSymbol<*>, @@ -273,6 +309,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor( else -> visitor.convertElement(declarationToBuild, originalDeclaration) } } + is KtDestructuringDeclaration -> visitor.convertDestructuringDeclaration(declarationToBuild) else -> visitor.convertElement(declarationToBuild, originalDeclaration) } as FirDeclaration } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirReplacement.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirReplacement.kt index 2195038663f..40583fabfcf 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirReplacement.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirReplacement.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.psi.* internal data class RawFirReplacement(val from: KtElement, val to: KtElement) { companion object { fun isApplicableForReplacement(element: KtElement) = when (element) { - is KtFile, is KtScript, is KtClassInitializer, is KtClassOrObject, is KtObjectLiteralExpression, is KtTypeAlias, + is KtFile, is KtScript, is KtClassInitializer, is KtPropertyAccessor, is KtConstructor<*>, is KtClassOrObject, is KtObjectLiteralExpression, is KtTypeAlias, is KtNamedFunction, is KtLambdaExpression, is KtAnonymousInitializer, is KtProperty, is KtTypeReference, is KtAnnotationEntry, is KtTypeParameter, is KtTypeProjection, is KtParameter, is KtBlockExpression, is KtSimpleNameExpression, is KtConstantExpression, is KtStringTemplateExpression, is KtReturnExpression, @@ -19,7 +19,8 @@ internal data class RawFirReplacement(val from: KtElement, val to: KtElement) { is KtIsExpression, is KtUnaryExpression, is KtCallExpression, is KtArrayAccessExpression, is KtQualifiedExpression, is KtThisExpression, is KtSuperExpression, is KtParenthesizedExpression, is KtLabeledExpression, is KtAnnotatedExpression, is KtThrowExpression, is KtDestructuringDeclaration, is KtClassLiteralExpression, is KtCallableReferenceExpression, - is KtCollectionLiteralExpression -> true + is KtCollectionLiteralExpression, + -> true else -> false } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAbstractBodyTargetResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAbstractBodyTargetResolver.kt index c60248ee3ec..69295b292d4 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAbstractBodyTargetResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAbstractBodyTargetResolver.kt @@ -29,12 +29,12 @@ internal abstract class LLFirAbstractBodyTargetResolver( isJumpingPhase: Boolean = false ) : LLFirTargetResolver(resolveTarget, lockProvider, resolvePhase, isJumpingPhase) { protected fun createReturnTypeCalculator( - towerDataContextCollector: FirResolveContextCollector?, + firResolveContextCollector: FirResolveContextCollector?, ): ReturnTypeCalculator = LLFirReturnTypeCalculatorWithJump( scopeSession, implicitBodyResolveComputationSession, lockProvider, - towerDataContextCollector, + firResolveContextCollector, ) abstract val transformer: FirAbstractBodyResolveTransformerDispatcher @@ -47,6 +47,10 @@ internal abstract class LLFirAbstractBodyTargetResolver( override fun withFile(firFile: FirFile, action: () -> Unit) { transformer.context.withFile(firFile, transformer.components) { + transformer.firResolveContextCollector?.let { collector -> + collector.addFileContext(firFile, transformer.context.towerDataContext) + } + action() } } @@ -55,6 +59,10 @@ internal abstract class LLFirAbstractBodyTargetResolver( override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) { transformer.declarationsTransformer.context.withContainingClass(firClass) { transformer.declarationsTransformer.withRegularClass(firClass) { + transformer.firResolveContextCollector?.let { collector -> + collector.addDeclarationContext(firClass, transformer.context) + } + action() firClass } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentMappingLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentMappingLazyResolver.kt index bf25ab8a105..5cdc865ed34 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentMappingLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentMappingLazyResolver.kt @@ -32,7 +32,7 @@ internal object LLFirAnnotationArgumentMappingLazyResolver : LLFirLazyResolver(F scopeSession: ScopeSession, towerDataContextCollector: FirResolveContextCollector?, ) { - val resolver = LLFirAnnotationArgumentsMappingTargetResolver(target, lockProvider, session, scopeSession) + val resolver = LLFirAnnotationArgumentsMappingTargetResolver(target, lockProvider, session, scopeSession, towerDataContextCollector) resolver.resolveDesignation() } @@ -57,6 +57,7 @@ private class LLFirAnnotationArgumentsMappingTargetResolver( lockProvider: LLFirLockProvider, session: FirSession, scopeSession: ScopeSession, + firResolveContextCollector: FirResolveContextCollector?, ) : LLFirAbstractBodyTargetResolver( resolveTarget, lockProvider, @@ -67,7 +68,8 @@ private class LLFirAnnotationArgumentsMappingTargetResolver( session, scopeSession, resolverPhase, - returnTypeCalculator = createReturnTypeCalculator(towerDataContextCollector = null) + returnTypeCalculator = createReturnTypeCalculator(firResolveContextCollector = firResolveContextCollector), + firResolveContextCollector = firResolveContextCollector, ) override fun doLazyResolveUnderLock(target: FirElementWithResolveState) { diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt index 6eecd874a99..4fbb2bb2eb5 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt @@ -17,9 +17,11 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.PrivateForInline import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ScopeSession +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirAnnotationArgumentsResolveTransformer import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef @@ -33,7 +35,7 @@ internal object LLFirAnnotationArgumentsLazyResolver : LLFirLazyResolver(FirReso scopeSession: ScopeSession, towerDataContextCollector: FirResolveContextCollector?, ) { - val resolver = LLFirAnnotationArgumentsTargetResolver(target, lockProvider, session, scopeSession) + val resolver = LLFirAnnotationArgumentsTargetResolver(target, lockProvider, session, scopeSession, towerDataContextCollector) resolver.resolveDesignation() } @@ -68,6 +70,7 @@ private class LLFirAnnotationArgumentsTargetResolver( lockProvider: LLFirLockProvider, session: FirSession, scopeSession: ScopeSession, + firResolveContextCollector: FirResolveContextCollector?, ) : LLFirAbstractBodyTargetResolver( target, lockProvider, @@ -78,13 +81,55 @@ private class LLFirAnnotationArgumentsTargetResolver( session, scopeSession, resolverPhase, - returnTypeCalculator = createReturnTypeCalculator(towerDataContextCollector = null) + returnTypeCalculator = createReturnTypeCalculator(firResolveContextCollector = firResolveContextCollector), + firResolveContextCollector = firResolveContextCollector, ) override fun doLazyResolveUnderLock(target: FirElementWithResolveState) { + collectTowerDataContext(target) + FirLazyBodiesCalculator.calculateAnnotations(target) transformAnnotations(target) } + + private fun collectTowerDataContext(target: FirElementWithResolveState) { + val contextCollector = transformer.firResolveContextCollector + if (contextCollector == null || target !is FirDeclaration) return + + val bodyResolveContext = transformer.context + withTypeParametersIfMemberDeclaration(bodyResolveContext, target) { + when (target) { + is FirRegularClass -> { + contextCollector.addClassHeaderContext(target, bodyResolveContext.towerDataContext) + } + + is FirFunction -> bodyResolveContext.forFunctionBody(target, transformer.components) { + contextCollector.addDeclarationContext(target, bodyResolveContext) + } + + else -> contextCollector.addDeclarationContext(target, bodyResolveContext) + } + } + + if (target is FirRegularClass) { + withRegularClass(target) { + contextCollector.addDeclarationContext(target, bodyResolveContext) + } + } + } + + private inline fun withTypeParametersIfMemberDeclaration( + context: BodyResolveContext, + target: FirElementWithResolveState, + action: () -> Unit, + ) { + if (target is FirMemberDeclaration) { + @OptIn(PrivateForInline::class) + context.withTypeParametersOf(target, action) + } else { + action() + } + } } internal fun LLFirAbstractBodyTargetResolver.transformAnnotations(target: FirElementWithResolveState) { diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt index cd3ded53c4a..d865bd002c1 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder import org.jetbrains.kotlin.fir.FirElementWithResolveState import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.PrivateForInline import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.getExplicitBackingField import org.jetbrains.kotlin.fir.expressions.* @@ -75,7 +74,7 @@ private class LLFirBodyTargetResolver( lockProvider: LLFirLockProvider, session: FirSession, scopeSession: ScopeSession, - towerDataContextCollector: FirResolveContextCollector?, + firResolveContextCollector: FirResolveContextCollector?, ) : LLFirAbstractBodyTargetResolver( target, lockProvider, @@ -87,8 +86,8 @@ private class LLFirBodyTargetResolver( phase = resolverPhase, implicitTypeOnly = false, scopeSession = scopeSession, - returnTypeCalculator = createReturnTypeCalculator(towerDataContextCollector = towerDataContextCollector), - firResolveContextCollector = towerDataContextCollector, + returnTypeCalculator = createReturnTypeCalculator(firResolveContextCollector = firResolveContextCollector), + firResolveContextCollector = firResolveContextCollector, ) { override val preserveCFGForClasses: Boolean get() = false } @@ -130,12 +129,7 @@ private class LLFirBodyTargetResolver( } private fun resolveMembersForControlFlowGraph(target: FirRegularClass) { - withTypeArguments(target) { - transformer.firResolveContextCollector?.addClassHeaderContext(target, transformer.context.towerDataContext) - } withRegularClass(target) { - transformer.firResolveContextCollector?.addDeclarationContext(target, transformer.context) - for (member in target.declarations) { if (member is FirControlFlowGraphOwner && member.isUsedInControlFlowGraphBuilderForClass) { member.lazyResolveToPhase(resolverPhase.previous) @@ -146,18 +140,6 @@ private class LLFirBodyTargetResolver( } override fun doLazyResolveUnderLock(target: FirElementWithResolveState) { - val contextCollector = transformer.firResolveContextCollector - if (contextCollector != null && target is FirDeclaration) { - val bodyResolveContext = transformer.context - if (target is FirFunction) { - bodyResolveContext.forFunctionBody(target, transformer.components) { - contextCollector.addDeclarationContext(target, bodyResolveContext) - } - } else { - contextCollector.addDeclarationContext(target, bodyResolveContext) - } - } - when (target) { is FirRegularClass -> error("Should have been resolved in ${::doResolveWithoutLock.name}") is FirConstructor -> resolve(target, BodyStateKeepers.CONSTRUCTOR) @@ -175,13 +157,6 @@ private class LLFirBodyTargetResolver( else -> throwUnexpectedFirElementError(target) } } - - private inline fun withTypeArguments(regularClass: FirRegularClass, action: () -> Unit) { - @OptIn(PrivateForInline::class) - transformer.declarationsTransformer.context.withTypeParametersOf(regularClass) { - action() - } - } } internal object BodyStateKeepers { diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirImplicitTypesLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirImplicitTypesLazyResolver.kt index c56a7005a6a..0eaf97fcd31 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirImplicitTypesLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirImplicitTypesLazyResolver.kt @@ -56,7 +56,7 @@ internal class LLFirImplicitBodyTargetResolver( lockProvider: LLFirLockProvider, session: FirSession, scopeSession: ScopeSession, - towerDataContextCollector: FirResolveContextCollector?, + firResolveContextCollector: FirResolveContextCollector?, implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession? = null, ) : LLFirAbstractBodyTargetResolver( target, @@ -72,8 +72,8 @@ internal class LLFirImplicitBodyTargetResolver( phase = resolverPhase, implicitTypeOnly = true, scopeSession = scopeSession, - firResolveContextCollector = towerDataContextCollector, - returnTypeCalculator = createReturnTypeCalculator(towerDataContextCollector = towerDataContextCollector), + firResolveContextCollector = firResolveContextCollector, + returnTypeCalculator = createReturnTypeCalculator(firResolveContextCollector = firResolveContextCollector), ) { override val preserveCFGForClasses: Boolean get() = false } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirReturnTypeCalculatorWithJump.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirReturnTypeCalculatorWithJump.kt index 85abb5248a9..9f62993c5bd 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirReturnTypeCalculatorWithJump.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirReturnTypeCalculatorWithJump.kt @@ -38,7 +38,7 @@ internal class LLFirReturnTypeCalculatorWithJump( lockProvider = lockProvider, session = declaration.moduleData.session, scopeSession = scopeSession, - towerDataContextCollector = towerDataContextCollector, + firResolveContextCollector = towerDataContextCollector, implicitBodyResolveComputationSession = implicitBodyResolveComputationSession, ) 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 104e035e1b8..10abb7489b1 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 @@ -79,6 +79,12 @@ internal abstract class LLFirTargetResolver( is LLFirWholeFileResolveTarget -> { resolveTarget.forEachTopLevelDeclaration(::resolveTargetWithNestedDeclarations) } + is LLFirWholeClassResolveTarget -> { + performResolve(resolveTarget.target) + withRegularClass(resolveTarget.target) { + resolveTarget.forEachDeclaration(::resolveTargetWithNestedDeclarations) + } + } } } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt index 53ef7a7e660..a5ec7434002 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt @@ -48,14 +48,14 @@ internal object FirElementFinder { nonLocalDeclaration = nonLocalDeclaration, )?.pathWithTarget - private class FirDeclarationDesignation( + class FirDeclarationDesignation( val path: List, val target: FirDeclaration, ) { val pathWithTarget: List get() = path + target } - private fun collectDesignationPath( + fun collectDesignationPath( firFile: FirFile, nonLocalDeclaration: KtDeclaration, ): FirDeclarationDesignation? = collectDesignationPath( diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt index 1d8867da4a2..294e66dabeb 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt @@ -228,6 +228,23 @@ open class PsiRawFirBuilder( context ) + open fun convertPropertyAccessor( + accessor: KtPropertyAccessor?, + property: KtProperty, + propertyTypeRef: FirTypeRef, + propertySymbol: FirPropertySymbol, + isGetter: Boolean, + accessorAnnotationsFromProperty: List, + parameterAnnotationsFromProperty: List, + ): FirPropertyAccessor? = accessor.toFirPropertyAccessor( + property, + propertyTypeRef, + propertySymbol, + isGetter, + accessorAnnotationsFromProperty, + parameterAnnotationsFromProperty, + ) + open fun convertValueParameter( valueParameter: KtParameter, functionSymbol: FirFunctionSymbol<*>, @@ -1914,7 +1931,8 @@ open class PsiRawFirBuilder( propertyAnnotations.filter { it.useSiteTarget == FIELD || it.useSiteTarget == PROPERTY_DELEGATE_FIELD }, ) - getter = this@toFirProperty.getter.toFirPropertyAccessor( + getter = convertPropertyAccessor( + this@toFirProperty.getter, this@toFirProperty, propertyType, propertySymbol = symbol, @@ -1922,7 +1940,9 @@ open class PsiRawFirBuilder( accessorAnnotationsFromProperty = propertyAnnotations.filterUseSiteTarget(PROPERTY_GETTER), parameterAnnotationsFromProperty = emptyList() ) - setter = this@toFirProperty.setter.toFirPropertyAccessor( + + setter = convertPropertyAccessor( + this@toFirProperty.setter, this@toFirProperty, propertyType, propertySymbol = symbol, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsMappingTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsMappingTransformer.kt index 9ee2e9203ee..4cb38c3450d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsMappingTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsMappingTransformer.kt @@ -19,6 +19,8 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveCon import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector +import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.visitors.transformSingle open class FirAnnotationArgumentsMappingTransformer( @@ -27,6 +29,7 @@ open class FirAnnotationArgumentsMappingTransformer( resolvePhase: FirResolvePhase, outerBodyResolveContext: BodyResolveContext? = null, returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve, + firResolveContextCollector: FirResolveContextCollector? = null, ) : FirAbstractBodyResolveTransformerDispatcher( session, resolvePhase, @@ -34,6 +37,7 @@ open class FirAnnotationArgumentsMappingTransformer( scopeSession, outerBodyResolveContext = outerBodyResolveContext, returnTypeCalculator = returnTypeCalculator, + firResolveContextCollector = firResolveContextCollector, ) { final override val expressionsTransformer: FirExpressionsResolveTransformer = FirExpressionTransformerForAnnotationArgumentsMapping(this) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt index 3a876de8da4..131cbf95c31 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirAnnotationArgumentsResolveTransformer.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclaration import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguouslyResolvedAnnotationArgument +import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector import org.jetbrains.kotlin.fir.symbols.impl.FirEnumEntrySymbol import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -38,6 +39,7 @@ open class FirAnnotationArgumentsResolveTransformer( resolvePhase: FirResolvePhase, outerBodyResolveContext: BodyResolveContext? = null, returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve, + firResolveContextCollector: FirResolveContextCollector? = null, ) : FirAbstractBodyResolveTransformerDispatcher( session, resolvePhase, @@ -45,6 +47,7 @@ open class FirAnnotationArgumentsResolveTransformer( scopeSession, outerBodyResolveContext = outerBodyResolveContext, returnTypeCalculator = returnTypeCalculator, + firResolveContextCollector = firResolveContextCollector, ) { final override val expressionsTransformer: FirExpressionsResolveTransformer = FirExpressionsResolveTransformerForSpecificAnnotations(this)