diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt index 2b3a0ebf71f..72c2fcc919e 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt @@ -95,6 +95,11 @@ internal class FirElementBuilder( } } +private fun KtDeclaration.isPartOf(callableDeclaration: KtCallableDeclaration): Boolean = when (this) { + is KtPropertyAccessor -> this.property == callableDeclaration + else -> false +} + internal fun PsiElement.getNonLocalContainingOrThisDeclaration(predicate: (KtDeclaration) -> Boolean = { true }): KtDeclaration? { var candidate: KtDeclaration? = null @@ -105,8 +110,8 @@ internal fun PsiElement.getNonLocalContainingOrThisDeclaration(predicate: (KtDec } for (parent in parentsWithSelf) { - if (candidate != null) { - if (parent is KtEnumEntry || parent is KtCallableDeclaration || parent is KtClassInitializer) { + candidate?.let { notNullCandidate -> + if (parent is KtEnumEntry || parent is KtCallableDeclaration && !notNullCandidate.isPartOf(parent) || parent is KtClassInitializer) { // Candidate turned out to be local. Let's find another one. candidate = null } @@ -138,6 +143,11 @@ internal fun PsiElement.getNonLocalContainingOrThisDeclaration(predicate: (KtDec propose(parent) } } + is KtPropertyAccessor -> { + if (predicate(parent)) { + propose(parent) + } + } } } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt index f3eac7070c8..f8eecb1be40 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt @@ -67,13 +67,16 @@ internal class FileStructure private constructor( private fun getStructureKtElement(element: KtElement): KtDeclaration? { val container = element.getNonLocalContainingOrThisDeclaration() - when { + val resultedContainer = when { container is KtClassOrObject && container.isInsideSuperClassCall(element) -> { - container.primaryConstructor?.let { return it } + container.primaryConstructor } + + container is KtPropertyAccessor -> container.property + else -> null } - return container + return resultedContainer ?: container } private fun KtClassOrObject.isInsideSuperClassCall(element: KtElement): Boolean { diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/state/LLFirResolvableResolveSession.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/state/LLFirResolvableResolveSession.kt index 36a5219c959..976da7422c2 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/state/LLFirResolvableResolveSession.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/state/LLFirResolvableResolveSession.kt @@ -124,15 +124,16 @@ internal abstract class LLFirResolvableResolveSession( require(getModuleKind(module) == ModuleKind.RESOLVABLE_MODULE) { "Declaration should be resolvable module, instead it had ${module::class}" } - val nonLocalNamedDeclaration = ktDeclaration.getNonLocalContainingOrThisDeclaration() + + val nonLocalDeclaration = ktDeclaration.getNonLocalContainingOrThisDeclaration() ?: buildErrorWithAttachment("Declaration should have non-local container") { withPsiEntry("ktDeclaration", ktDeclaration) withEntry("module", module) { it.moduleDescription } } - if (ktDeclaration == nonLocalNamedDeclaration) { + if (ktDeclaration == nonLocalDeclaration) { val session = getResolvableSessionFor(module) - return nonLocalNamedDeclaration.findSourceNonLocalFirDeclaration( + return nonLocalDeclaration.findSourceNonLocalFirDeclaration( firFileBuilder = session.moduleComponents.firFileBuilder, provider = session.firProvider, ).symbol diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt index df80816abb3..63f2342f1cb 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt @@ -110,6 +110,19 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider( firFile.declarations.firstOrNull { it.psi == this } } this is KtScript -> containerFirFile?.declarations?.singleOrNull { it is FirScript } + this is KtPropertyAccessor -> { + val firPropertyDeclaration = property.findSourceNonLocalFirDeclaration( + firFileBuilder, + provider, + containerFirFile, + ) as FirVariable + + if (isGetter) { + firPropertyDeclaration.getter + } else { + firPropertyDeclaration.setter + } + } else -> errorWithFirSpecificEntries("Invalid container", psi = this) } return candidate?.takeIf { it.realPsi == this }