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 4925c2a3f24..0cadcf27af7 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 @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder import com.intellij.psi.PsiElement +import com.intellij.psi.PsiErrorElement import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.ThreadSafe import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents @@ -290,7 +291,8 @@ internal fun getNonLocalContainingDeclaration( parent is KtAnonymousInitializer || parent is KtObjectLiteralExpression || parent is KtCallElement || - parent is KtCodeFragment + parent is KtCodeFragment || + parent is PsiErrorElement ) { // Candidate turned out to be local. Let's find another one. candidate = null @@ -302,6 +304,7 @@ internal fun getNonLocalContainingDeclaration( when (parent) { is KtScript -> propose(parent) is KtDestructuringDeclaration -> propose(parent) + is KtDestructuringDeclarationEntry -> propose(parent) is KtScriptInitializer -> propose(parent) is KtClassInitializer -> { val container = parent.containingDeclaration 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 54840fba4df..3b6096172b8 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 @@ -144,7 +144,7 @@ internal class FileStructure private constructor( structureElements += structureElement // Go down only in the case of container declaration - val canHaveInnerStructure = dcl is KtClassOrObject || dcl is KtScript + val canHaveInnerStructure = dcl is KtClassOrObject || dcl is KtScript || dcl is KtDestructuringDeclaration if (canHaveInnerStructure) { dcl.acceptChildren(this) } 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 0ba1288fc52..2b5c3273e2b 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 @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirScript import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.declarations.destructuringDeclarationContainerVariable import org.jetbrains.kotlin.fir.declarations.utils.componentFunctionSymbol import org.jetbrains.kotlin.fir.declarations.utils.correspondingValueParameterFromPrimaryConstructor import org.jetbrains.kotlin.fir.declarations.utils.fromPrimaryConstructor @@ -98,8 +99,14 @@ internal abstract class LLFirTargetResolver( // Fake or delegate declaration shared types and annotations from the original one originalDeclaration != null -> originalDeclaration.lazyResolveToPhase(resolverPhase) - // We share type references and annotations with the original parameter - target is FirProperty -> target.correspondingValueParameterFromPrimaryConstructor?.lazyResolveToPhase(resolverPhase) + target is FirProperty -> { + // We share type references and annotations with the original parameter + target.correspondingValueParameterFromPrimaryConstructor?.lazyResolveToPhase(resolverPhase) + + // Destructuring declaration entries depends on the container property + target.destructuringDeclarationContainerVariable?.lazyResolveToPhase(resolverPhase) + } + target is FirSimpleFunction && target.origin == FirDeclarationOrigin.Synthetic.DataClassMember -> { resolveDataClassMemberDependencies(target) } 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 4e514491356..bf4795cb365 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 @@ -125,6 +125,7 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider( is KtAnonymousInitializer, is KtTypeAlias, is KtDestructuringDeclaration, + is KtDestructuringDeclarationEntry, is KtScript, -> firDeclarationProvider(this) @@ -235,8 +236,14 @@ internal val FirCallableSymbol<*>.isLocalForLazyResolutionPurposes: Boolean // We should treat result$$ property as non-local explicitly as its CallableId is local // TODO: can be dropped after KT-65523 fir.origin == FirDeclarationOrigin.ScriptCustomization.ResultProperty -> false + // Destructuring declaration container should be treated as a non-local as it is a top-level script declaration fir.origin == FirDeclarationOrigin.Synthetic.ScriptTopLevelDestructuringDeclarationContainer -> false + + // We should treat destructuring declaration entries as non-local explicitly as its CallableId is local + // TODO: can be dropped after KT-65727 + (fir as? FirProperty)?.destructuringDeclarationContainerVariable != null -> false + else -> callableId.isLocal || fir.status.visibility == Visibilities.Local } diff --git a/analysis/low-level-api-fir/testData/fileStructure/destructuring.kts b/analysis/low-level-api-fir/testData/fileStructure/destructuring.kts new file mode 100644 index 00000000000..5a16891c127 --- /dev/null +++ b/analysis/low-level-api-fir/testData/fileStructure/destructuring.kts @@ -0,0 +1,8 @@ +/* RootScriptStructureElement */var a = -1/* DeclarationStructureElement */ +var b = 0/* DeclarationStructureElement */ + +data class MyPair(val i: Int, val b: Int)/* DeclarationStructureElement *//* ClassDeclarationStructureElement */ + +val pair = MyPair(a, b)/* DeclarationStructureElement */ + +val (first/* DeclarationStructureElement */, last/* DeclarationStructureElement */) = pair/* DeclarationStructureElement */ diff --git a/analysis/low-level-api-fir/testData/fileStructure/destructuring.lazy.resolve.txt b/analysis/low-level-api-fir/testData/fileStructure/destructuring.lazy.resolve.txt new file mode 100644 index 00000000000..20ea05eb5bb --- /dev/null +++ b/analysis/low-level-api-fir/testData/fileStructure/destructuring.lazy.resolve.txt @@ -0,0 +1,40 @@ +FILE: [ResolvedTo(BODY_RESOLVE)] destructuring.kts + context(