diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/expressionTypeProvider/Fe10IdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/expressionTypeProvider/Fe10IdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java
index e71aab4ad2d..f895c636717 100644
--- a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/expressionTypeProvider/Fe10IdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java
+++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/components/expressionTypeProvider/Fe10IdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java
@@ -142,6 +142,12 @@ public class Fe10IdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated exte
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/list_mutableListOf.kt");
}
+ @Test
+ @TestMetadata("nameReference.kt")
+ public void testNameReference() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.kt");
+ }
+
@Test
@TestMetadata("nonExpression.kt")
public void testNonExpression() throws Exception {
diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionTypeProvider/FirIdeDependentAnalysisSourceModuleHLExpressionTypeTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionTypeProvider/FirIdeDependentAnalysisSourceModuleHLExpressionTypeTestGenerated.java
index 61e51c96204..6676e62e66e 100644
--- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionTypeProvider/FirIdeDependentAnalysisSourceModuleHLExpressionTypeTestGenerated.java
+++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionTypeProvider/FirIdeDependentAnalysisSourceModuleHLExpressionTypeTestGenerated.java
@@ -142,6 +142,12 @@ public class FirIdeDependentAnalysisSourceModuleHLExpressionTypeTestGenerated ex
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/list_mutableListOf.kt");
}
+ @Test
+ @TestMetadata("nameReference.kt")
+ public void testNameReference() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.kt");
+ }
+
@Test
@TestMetadata("nonExpression.kt")
public void testNonExpression() throws Exception {
diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionTypeProvider/FirIdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionTypeProvider/FirIdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java
index fcdfd274911..d675fc50996 100644
--- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionTypeProvider/FirIdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java
+++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/expressionTypeProvider/FirIdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java
@@ -142,6 +142,12 @@ public class FirIdeNormalAnalysisSourceModuleHLExpressionTypeTestGenerated exten
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/list_mutableListOf.kt");
}
+ @Test
+ @TestMetadata("nameReference.kt")
+ public void testNameReference() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.kt");
+ }
+
@Test
@TestMetadata("nonExpression.kt")
public void testNonExpression() throws Exception {
diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/expressionTypeProvider/FirStandaloneNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/expressionTypeProvider/FirStandaloneNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java
index d154b072e8c..3fc3556689c 100644
--- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/expressionTypeProvider/FirStandaloneNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java
+++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/expressionTypeProvider/FirStandaloneNormalAnalysisSourceModuleHLExpressionTypeTestGenerated.java
@@ -142,6 +142,12 @@ public class FirStandaloneNormalAnalysisSourceModuleHLExpressionTypeTestGenerate
runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/list_mutableListOf.kt");
}
+ @Test
+ @TestMetadata("nameReference.kt")
+ public void testNameReference() throws Exception {
+ runTest("analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.kt");
+ }
+
@Test
@TestMetadata("nonExpression.kt")
public void testNonExpression() throws Exception {
diff --git a/analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.kt b/analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.kt
new file mode 100644
index 00000000000..0a5dfdfca53
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.kt
@@ -0,0 +1,5 @@
+var first = -1
+var last = -1
+val pair = Pair(first, last)
+
+val (first, last) = pair
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.txt b/analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.txt
new file mode 100644
index 00000000000..63b88eb2175
--- /dev/null
+++ b/analysis/analysis-api/testData/components/expressionTypeProvider/expressionType/nameReference.txt
@@ -0,0 +1,2 @@
+expression: pair
+type: kotlin.Unit
diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/FirDeclarationDesignation.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/FirDeclarationDesignation.kt
index 42f64473cf0..058c8f7bff7 100644
--- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/FirDeclarationDesignation.kt
+++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/FirDeclarationDesignation.kt
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder
+import org.jetbrains.kotlin.fir.diagnostics.ConeDestructuringDeclarationsOnTopLevel
import org.jetbrains.kotlin.fir.java.javaSymbolProvider
class FirDeclarationDesignationWithFile(
@@ -69,6 +70,13 @@ private fun collectDesignationPath(declaration: FirDeclaration): List {
+ return if (declaration.diagnostic == ConeDestructuringDeclarationsOnTopLevel) {
+ emptyList()
+ } else {
+ null
+ }
+ }
else -> return null
}
}
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 1eb83488185..7c98ef754a9 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
@@ -103,7 +103,7 @@ internal class FirElementBuilder(
}
// TODO: simplify
-internal inline fun PsiElement.getNonLocalContainingOrThisDeclaration(predicate: (KtDeclaration) -> Boolean = { true }): KtNamedDeclaration? {
+internal inline fun PsiElement.getNonLocalContainingOrThisDeclaration(predicate: (KtDeclaration) -> Boolean = { true }): KtDeclaration? {
var container: PsiElement? = this
while (container != null && container !is KtFile) {
if (container is KtNamedDeclaration
@@ -116,12 +116,15 @@ internal inline fun PsiElement.getNonLocalContainingOrThisDeclaration(predicate:
) {
return container
}
+ if (container is KtDestructuringDeclaration && container.parent is KtFile) {
+ return container
+ }
container = container.parent
}
return null
}
-fun PsiElement.getNonLocalContainingInBodyDeclarationWith(): KtNamedDeclaration? =
+fun PsiElement.getNonLocalContainingInBodyDeclarationWith(): KtDeclaration? =
getNonLocalContainingOrThisDeclaration { declaration ->
when (declaration) {
is KtNamedFunction -> declaration.bodyExpression?.isAncestor(this) == true
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 d17c585899b..33be04e81f1 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
@@ -99,6 +99,10 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider(
containerClassFir.declarations.firstOrNull { it.psi === this }
}
this is KtTypeAlias -> findFir(provider)
+ this is KtDestructuringDeclaration -> {
+ val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile)
+ firFile.declarations.firstOrNull { it.psi == this }
+ }
else -> errorWithFirSpecificEntries("Invalid container", psi = this)
}
return candidate?.takeIf { it.realPsi == this }
diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/destructuring.kt b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/destructuring.kt
new file mode 100644
index 00000000000..d9a17a1d639
--- /dev/null
+++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/destructuring.kt
@@ -0,0 +1,6 @@
+// WITH_STDLIB
+var a = -1
+var b = 0
+val pair = Pair(a, b)
+
+val (first, last) = pair
\ No newline at end of file
diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/destructuring.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/destructuring.txt
new file mode 100644
index 00000000000..35d64299176
--- /dev/null
+++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/destructuring.txt
@@ -0,0 +1,6 @@
+KT element: KtNameReferenceExpression
+FIR element: FirErrorPropertyImpl
+FIR source kind: KtRealSourceElementKind
+
+FIR element rendered:
+
\ No newline at end of file
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/GetOrBuildFirTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/GetOrBuildFirTestGenerated.java
index ebadbcd07a9..eff086667d3 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/GetOrBuildFirTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/GetOrBuildFirTestGenerated.java
@@ -215,6 +215,12 @@ public class GetOrBuildFirTestGenerated extends AbstractGetOrBuildFirTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/getOrBuildFir/declarations"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
+ @Test
+ @TestMetadata("destructuring.kt")
+ public void testDestructuring() throws Exception {
+ runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/declarations/destructuring.kt");
+ }
+
@Test
@TestMetadata("objectLiteral.kt")
public void testObjectLiteral() throws Exception {
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt
index 9b2c0954b88..b75c7c943aa 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
-import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
-import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeConstraintSystemHasContradiction
-import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
-import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
+import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.resolvedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
index dc751bc6937..da14e4495cd 100644
--- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
+++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt
@@ -113,6 +113,7 @@ private fun ConeDiagnostic.toKtDiagnostic(
else -> this.getFactory(source).createOn(qualifiedAccessSource ?: source)
}
+ is ConeDestructuringDeclarationsOnTopLevel -> FirSyntaxErrors.SYNTAX.createOn(source)
is ConeCannotInferParameterType -> FirErrors.CANNOT_INFER_PARAMETER_TYPE.createOn(source)
is ConeInstanceAccessBeforeSuperCall -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.createOn(source, this.target)
is ConeStubDiagnostic -> null
diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt
index d9df4488367..f3036e809a1 100644
--- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt
+++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.utils.addDeclaration
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
+import org.jetbrains.kotlin.fir.diagnostics.ConeDestructuringDeclarationsOnTopLevel
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeUnderscoreIsReserved
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
@@ -1276,9 +1277,7 @@ abstract class BaseFirBuilder(val baseSession: FirSession, val context: Conte
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
name = Name.special("")
- diagnostic = ConeSimpleDiagnostic(
- "Destructuring declarations are only allowed for local variables/values", DiagnosticKind.Syntax
- )
+ diagnostic = ConeDestructuringDeclarationsOnTopLevel
symbol = FirErrorPropertySymbol(diagnostic)
}
diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt
index 39c8aae0b38..008559028d6 100644
--- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt
+++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt
@@ -242,4 +242,4 @@ class ConeAmbiguousAlteredAssign(val altererNames: List) : ConeDiagnost
object ConeForbiddenIntersection : ConeDiagnostic {
override val reason: String get() = "Such an intersection type is not allowed"
-}
+}
\ No newline at end of file
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt
index 21b8d53087d..e048cc6566b 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt
@@ -6,9 +6,7 @@
package org.jetbrains.kotlin.fir.diagnostics
import org.jetbrains.kotlin.KtSourceElement
-import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
-import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.Name
@@ -43,6 +41,11 @@ class ConeRecursiveTypeParameterDuringErasureError(val typeParameterName: Name)
get() = "self-recursive type parameter $typeParameterName"
}
+object ConeDestructuringDeclarationsOnTopLevel : ConeDiagnostic {
+ override val reason: String
+ get() = "Destructuring declarations are only allowed for local variables/values"
+}
+
enum class DiagnosticKind {
Syntax,
ExpressionExpected,