diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiLocalVariableSymbol.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiLocalVariableSymbol.kt index 71292dfddd6..4e160165e67 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiLocalVariableSymbol.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiLocalVariableSymbol.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased +import com.intellij.extapi.psi.StubBasedPsiElementBase import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode @@ -23,6 +24,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.KtVariableDeclaration import org.jetbrains.kotlin.resolve.BindingContext @@ -36,8 +38,12 @@ internal class KtFe10PsiLocalVariableSymbol( } override val name: Name - get() = withValidityAssertion { psi.nameAsSafeName } - + get() = withValidityAssertion { + when { + psi.nameIdentifier?.text == "_" -> SpecialNames.UNDERSCORE_FOR_UNUSED_VAR + else -> psi.nameAsSafeName + } + } override val returnType: KtType get() = withValidityAssertion { descriptor?.type?.toKtType(analysisContext) ?: createErrorType() } diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiValueParameterSymbol.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiValueParameterSymbol.kt index 2ab99c50fb7..ccd77d4958a 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiValueParameterSymbol.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/symbols/psiBased/KtFe10PsiValueParameterSymbol.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.resolve.BindingContext @@ -68,7 +69,10 @@ internal class KtFe10PsiValueParameterSymbol( } override val name: Name - get() = withValidityAssertion { psi.nameAsSafeName } + get() = withValidityAssertion { + if (psi.destructuringDeclaration != null) SpecialNames.DESTRUCT + else psi.nameAsSafeName + } context(KtAnalysisSession) override fun createPointer(): KtSymbolPointer = withValidityAssertion { diff --git a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/symbols/Fe10IdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/symbols/Fe10IdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java index ae56f26d0a4..0fa25e9389f 100644 --- a/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/symbols/Fe10IdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java +++ b/analysis/analysis-api-fe10/tests-gen/org/jetbrains/kotlin/analysis/api/fe10/test/cases/generated/cases/symbols/Fe10IdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java @@ -314,6 +314,46 @@ public class Fe10IdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated extends } } + @Nested + @TestMetadata("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring") + @TestDataPath("$PROJECT_ROOT") + public class Destructuring { + @Test + public void testAllFilesPresentInDestructuring() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("destructuringDeclarationParameterInLambda.kt") + public void testDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.kt"); + } + + @Test + @TestMetadata("entryInDestructuringDeclaration.kt") + public void testEntryInDestructuringDeclaration() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.kt"); + } + + @Test + @TestMetadata("entryInDestructuringDeclarationParameterInLambda.kt") + public void testEntryInDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.kt"); + } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclaration.kt") + public void testEntryUnderscoreInDestructuringDeclaration() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.kt"); + } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclarationParameterInLambda.kt") + public void testEntryUnderscoreInDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt"); + } + } + @Nested @TestMetadata("analysis/analysis-api/testData/symbols/singleSymbolByPsi/errors") @TestDataPath("$PROJECT_ROOT") diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt index 5a511e8d453..29293e1442f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirFile +import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.psi @@ -130,6 +131,11 @@ internal class KtFirImportOptimizer( super.visitImplicitInvokeCall(implicitInvokeCall) } + override fun visitProperty(property: FirProperty) { + if (property.name == SpecialNames.UNDERSCORE_FOR_UNUSED_VAR) return + super.visitProperty(property) + } + override fun visitComponentCall(componentCall: FirComponentCall) { processFunctionCall(componentCall) super.visitComponentCall(componentCall) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt index 49fb1b7a066..d7f4e4ffe51 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.analysis.api.fir.components.KtFirAnalysisSessionComp import org.jetbrains.kotlin.analysis.api.getModule import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbolOfType import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries @@ -25,6 +26,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral +import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore internal class KtFirSymbolProvider( override val analysisSession: KtFirAnalysisSession, @@ -186,11 +188,14 @@ internal class KtFirSymbolProvider( override val ROOT_PACKAGE_SYMBOL: KtPackageSymbol = KtFirPackageSymbol(FqName.ROOT, firResolveSession.project, token) - override fun getDestructuringDeclarationEntrySymbol(psi: KtDestructuringDeclarationEntry): KtFirLocalOrErrorVariableSymbol<*, *> { - return when (val firSymbol = psi.resolveToFirSymbolOfType>(firResolveSession)) { + override fun getDestructuringDeclarationEntrySymbol(psi: KtDestructuringDeclarationEntry): KtLocalVariableSymbol { + return when (val firSymbol = psi.resolveToFirSymbol(firResolveSession)) { is FirPropertySymbol -> firSymbolBuilder.variableLikeBuilder.buildLocalVariableSymbol(firSymbol) is FirErrorPropertySymbol -> firSymbolBuilder.variableLikeBuilder.buildErrorVariableSymbol(firSymbol) - else -> throwUnexpectedFirElementError(firSymbol, psi, FirPropertySymbol::class, FirErrorPropertySymbol::class) + else -> throwUnexpectedFirElementError( + firSymbol, psi, + FirPropertySymbol::class, FirErrorPropertySymbol::class, FirValueParameterSymbol::class + ) } } } diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java index 96f6cf774aa..0a2c45e90e1 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/symbols/FirIdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java @@ -314,6 +314,46 @@ public class FirIdeNormalAnalysisSourceModuleSingleSymbolByPsiGenerated extends } } + @Nested + @TestMetadata("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring") + @TestDataPath("$PROJECT_ROOT") + public class Destructuring { + @Test + public void testAllFilesPresentInDestructuring() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("destructuringDeclarationParameterInLambda.kt") + public void testDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.kt"); + } + + @Test + @TestMetadata("entryInDestructuringDeclaration.kt") + public void testEntryInDestructuringDeclaration() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.kt"); + } + + @Test + @TestMetadata("entryInDestructuringDeclarationParameterInLambda.kt") + public void testEntryInDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.kt"); + } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclaration.kt") + public void testEntryUnderscoreInDestructuringDeclaration() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.kt"); + } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclarationParameterInLambda.kt") + public void testEntryUnderscoreInDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt"); + } + } + @Nested @TestMetadata("analysis/analysis-api/testData/symbols/singleSymbolByPsi/errors") @TestDataPath("$PROJECT_ROOT") diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java index 3ea2fb55873..e5b179288ae 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/symbols/FirStandaloneNormalAnalysisSourceModuleSingleSymbolByPsiGenerated.java @@ -314,6 +314,46 @@ public class FirStandaloneNormalAnalysisSourceModuleSingleSymbolByPsiGenerated e } } + @Nested + @TestMetadata("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring") + @TestDataPath("$PROJECT_ROOT") + public class Destructuring { + @Test + public void testAllFilesPresentInDestructuring() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("destructuringDeclarationParameterInLambda.kt") + public void testDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.kt"); + } + + @Test + @TestMetadata("entryInDestructuringDeclaration.kt") + public void testEntryInDestructuringDeclaration() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.kt"); + } + + @Test + @TestMetadata("entryInDestructuringDeclarationParameterInLambda.kt") + public void testEntryInDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.kt"); + } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclaration.kt") + public void testEntryUnderscoreInDestructuringDeclaration() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.kt"); + } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclarationParameterInLambda.kt") + public void testEntryUnderscoreInDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt"); + } + } + @Nested @TestMetadata("analysis/analysis-api/testData/symbols/singleSymbolByPsi/errors") @TestDataPath("$PROJECT_ROOT") diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.kt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.kt new file mode 100644 index 00000000000..db57401862e --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.kt @@ -0,0 +1,12 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: KtParameter +// DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE + +data class X(val a: Int, val b: Int) + +fun x(action: (X, Int) -> Unit) {} + +fun main() { + x { (a, b), i -> + + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.pretty.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.pretty.txt new file mode 100644 index 00000000000..39cbaa2c4fc --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.pretty.txt @@ -0,0 +1 @@ +``: X diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.txt new file mode 100644 index 00000000000..2c19dbaab4b --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/destructuringDeclarationParameterInLambda.txt @@ -0,0 +1,22 @@ +KtValueParameterSymbol: + annotationsList: [] + callableIdIfNonLocal: null + contextReceivers: [] + generatedPrimaryConstructorProperty: null + hasDefaultValue: false + isCrossinline: false + isExtension: false + isImplicitLambdaParameter: false + isNoinline: false + isVararg: false + name: + origin: SOURCE + receiverParameter: null + returnType: KtUsualClassType: + annotationsList: [] + ownTypeArguments: [] + type: X + symbolKind: LOCAL + typeParameters: [] + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.kt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.kt new file mode 100644 index 00000000000..ac001e6abd0 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.kt @@ -0,0 +1,8 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: KtDestructuringDeclarationEntry +// DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE + +data class X(val a: Int, val b: Int) + +fun main(x: X) { + val (a, b) = x +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.pretty.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.pretty.txt new file mode 100644 index 00000000000..cda9c0ee9cc --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.pretty.txt @@ -0,0 +1 @@ +val a: kotlin.Int diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.txt new file mode 100644 index 00000000000..173fc07d194 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclaration.txt @@ -0,0 +1,17 @@ +KtLocalVariableSymbol: + annotationsList: [] + callableIdIfNonLocal: null + contextReceivers: [] + isExtension: false + isVal: true + name: a + origin: SOURCE + receiverParameter: null + returnType: KtUsualClassType: + annotationsList: [] + ownTypeArguments: [] + type: kotlin/Int + symbolKind: LOCAL + typeParameters: [] + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.kt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.kt new file mode 100644 index 00000000000..fcd5698ab56 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.kt @@ -0,0 +1,12 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: KtDestructuringDeclarationEntry +// DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE + +data class X(val a: Int, val b: Int) + +fun x(action: (X) -> Unit) {} + +fun main() { + x { (a, b) -> + + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.pretty.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.pretty.txt new file mode 100644 index 00000000000..cda9c0ee9cc --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.pretty.txt @@ -0,0 +1 @@ +val a: kotlin.Int diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.txt new file mode 100644 index 00000000000..173fc07d194 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryInDestructuringDeclarationParameterInLambda.txt @@ -0,0 +1,17 @@ +KtLocalVariableSymbol: + annotationsList: [] + callableIdIfNonLocal: null + contextReceivers: [] + isExtension: false + isVal: true + name: a + origin: SOURCE + receiverParameter: null + returnType: KtUsualClassType: + annotationsList: [] + ownTypeArguments: [] + type: kotlin/Int + symbolKind: LOCAL + typeParameters: [] + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.kt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.kt new file mode 100644 index 00000000000..732b43e12d9 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.kt @@ -0,0 +1,8 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: KtDestructuringDeclarationEntry +// DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE + +data class X(val a: Int, val b: Int) + +fun main(x: X) { + val (_, b) = x +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.pretty.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.pretty.txt new file mode 100644 index 00000000000..6bcb7900947 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.pretty.txt @@ -0,0 +1 @@ +val ``: kotlin.Int \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.txt new file mode 100644 index 00000000000..784908dbbe4 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclaration.txt @@ -0,0 +1,17 @@ +KtLocalVariableSymbol: + annotationsList: [] + callableIdIfNonLocal: null + contextReceivers: [] + isExtension: false + isVal: true + name: + origin: SOURCE + receiverParameter: null + returnType: KtUsualClassType: + annotationsList: [] + ownTypeArguments: [] + type: kotlin/Int + symbolKind: LOCAL + typeParameters: [] + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt new file mode 100644 index 00000000000..6a9ffd09dc4 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt @@ -0,0 +1,12 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: KtDestructuringDeclarationEntry +// DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE + +data class X(val a: Int, val b: Int) + +fun x(action: (X) -> Unit) {} + +fun main() { + x { (_, b) -> + + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.pretty.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.pretty.txt new file mode 100644 index 00000000000..6bcb7900947 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.pretty.txt @@ -0,0 +1 @@ +val ``: kotlin.Int \ No newline at end of file diff --git a/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.txt b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.txt new file mode 100644 index 00000000000..784908dbbe4 --- /dev/null +++ b/analysis/analysis-api/testData/symbols/singleSymbolByPsi/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.txt @@ -0,0 +1,17 @@ +KtLocalVariableSymbol: + annotationsList: [] + callableIdIfNonLocal: null + contextReceivers: [] + isExtension: false + isVal: true + name: + origin: SOURCE + receiverParameter: null + returnType: KtUsualClassType: + annotationsList: [] + ownTypeArguments: [] + type: kotlin/Int + symbolKind: LOCAL + typeParameters: [] + getContainingModule: KtSourceModule "Sources of main" + deprecationStatus: null \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclaration.kt b/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclaration.kt new file mode 100644 index 00000000000..a1c64b4f61e --- /dev/null +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclaration.kt @@ -0,0 +1,7 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry + +data class X(val a: Int, val b: Int) + +fun main(x: X) { + val (_, b) = x +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclaration.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclaration.txt new file mode 100644 index 00000000000..753b74a2cfb --- /dev/null +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclaration.txt @@ -0,0 +1,32 @@ +KT element: KtDestructuringDeclarationEntry +FIR element: FirPropertyImpl +FIR source kind: KtRealSourceElementKind + +FIR element rendered: +[ResolvedTo(BODY_RESOLVE)] lval : R|kotlin/Int| = R|/|.R|/X.component1|() + +FIR FILE: +FILE: [ResolvedTo(IMPORTS)] entryUnderscoreInDestructuringDeclaration.kt + public final data [ResolvedTo(STATUS)] class X : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=X] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/X.a] a: R|kotlin/Int|, [ResolvedTo(STATUS)] [CorrespondingProperty=/X.b] b: R|kotlin/Int|): R|X| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [ComponentFunctionSymbolKey=/X.component1, IsFromPrimaryConstructor=true] val a: R|kotlin/Int| = R|/a| + public [ResolvedTo(STATUS)] [ContainingClassKey=X] get(): R|kotlin/Int| + + public final [ResolvedTo(STATUS)] [ComponentFunctionSymbolKey=/X.component2, IsFromPrimaryConstructor=true] val b: R|kotlin/Int| = R|/b| + public [ResolvedTo(STATUS)] [ContainingClassKey=X] get(): R|kotlin/Int| + + public final operator [ResolvedTo(CONTRACTS)] fun component1(): R|kotlin/Int| + + public final operator [ResolvedTo(CONTRACTS)] fun component2(): R|kotlin/Int| + + public final [ResolvedTo(STATUS)] fun copy([ResolvedTo(STATUS)] a: R|kotlin/Int| = this@R|/X|.R|/X.a|, [ResolvedTo(STATUS)] b: R|kotlin/Int| = this@R|/X|.R|/X.b|): R|X| + + } + public final [ResolvedTo(BODY_RESOLVE)] fun main([ResolvedTo(BODY_RESOLVE)] x: R|X|): R|kotlin/Unit| { + [ResolvedTo(BODY_RESOLVE)] lval : R|X| = R|/x| + [ResolvedTo(BODY_RESOLVE)] lval : R|kotlin/Int| = R|/|.R|/X.component1|() + [ResolvedTo(BODY_RESOLVE)] lval b: R|kotlin/Int| = R|/|.R|/X.component2|() + } \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt b/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt new file mode 100644 index 00000000000..5647ae3a77c --- /dev/null +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt @@ -0,0 +1,11 @@ +// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry + +data class X(val a: Int, val b: Int) + +fun x(action: (X) -> Unit) {} + +fun main() { + x { (_, b) -> + + } +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.txt new file mode 100644 index 00000000000..c984dee6119 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.txt @@ -0,0 +1,37 @@ +KT element: KtDestructuringDeclarationEntry +FIR element: FirPropertyImpl +FIR source kind: KtRealSourceElementKind + +FIR element rendered: +[ResolvedTo(BODY_RESOLVE)] lval : R|kotlin/Int| = R|/|.R|/X.component1|() + +FIR FILE: +FILE: [ResolvedTo(IMPORTS)] entryUnderscoreInDestructuringDeclarationParameterInLambda.kt + public final data [ResolvedTo(STATUS)] class X : R|kotlin/Any| { + public [ResolvedTo(STATUS)] [ContainingClassKey=X] constructor([ResolvedTo(STATUS)] [CorrespondingProperty=/X.a] a: R|kotlin/Int|, [ResolvedTo(STATUS)] [CorrespondingProperty=/X.b] b: R|kotlin/Int|): R|X| { + LAZY_super + } + + public final [ResolvedTo(STATUS)] [ComponentFunctionSymbolKey=/X.component1, IsFromPrimaryConstructor=true] val a: R|kotlin/Int| = R|/a| + public [ResolvedTo(STATUS)] [ContainingClassKey=X] get(): R|kotlin/Int| + + public final [ResolvedTo(STATUS)] [ComponentFunctionSymbolKey=/X.component2, IsFromPrimaryConstructor=true] val b: R|kotlin/Int| = R|/b| + public [ResolvedTo(STATUS)] [ContainingClassKey=X] get(): R|kotlin/Int| + + public final operator [ResolvedTo(CONTRACTS)] fun component1(): R|kotlin/Int| + + public final operator [ResolvedTo(CONTRACTS)] fun component2(): R|kotlin/Int| + + public final [ResolvedTo(STATUS)] fun copy([ResolvedTo(STATUS)] a: R|kotlin/Int| = this@R|/X|.R|/X.a|, [ResolvedTo(STATUS)] b: R|kotlin/Int| = this@R|/X|.R|/X.b|): R|X| + + } + public final [ResolvedTo(CONTRACTS)] fun x([ResolvedTo(CONTRACTS)] action: R|(X) -> kotlin/Unit|): R|kotlin/Unit| { + } + public final [ResolvedTo(BODY_RESOLVE)] fun main(): R|kotlin/Unit| { + R|/x|( = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=kotlin/Function1] x@fun ([ResolvedTo(BODY_RESOLVE)] : R|X|): R|kotlin/Unit| { + [ResolvedTo(BODY_RESOLVE)] lval : R|kotlin/Int| = R|/|.R|/X.component1|() + [ResolvedTo(BODY_RESOLVE)] lval b: R|kotlin/Int| = R|/|.R|/X.component2|() + ^@x Unit + } + ) + } \ No newline at end of file diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/OutOfContentRootGetOrBuildFirTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/OutOfContentRootGetOrBuildFirTestGenerated.java index 63e55de63a0..2cff3baf06d 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/OutOfContentRootGetOrBuildFirTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/OutOfContentRootGetOrBuildFirTestGenerated.java @@ -606,6 +606,18 @@ public class OutOfContentRootGetOrBuildFirTestGenerated extends AbstractOutOfCon public void testEntryInDestructuringDeclarationParameterInLambda() throws Exception { runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryInDestructuringDeclarationParameterInLambda.kt"); } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclaration.kt") + public void testEntryUnderscoreInDestructuringDeclaration() throws Exception { + runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclaration.kt"); + } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclarationParameterInLambda.kt") + public void testEntryUnderscoreInDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt"); + } } @Nested diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/SourceGetOrBuildFirTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/SourceGetOrBuildFirTestGenerated.java index 32e0046eac2..7df419920f7 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/SourceGetOrBuildFirTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/SourceGetOrBuildFirTestGenerated.java @@ -606,6 +606,18 @@ public class SourceGetOrBuildFirTestGenerated extends AbstractSourceGetOrBuildFi public void testEntryInDestructuringDeclarationParameterInLambda() throws Exception { runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryInDestructuringDeclarationParameterInLambda.kt"); } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclaration.kt") + public void testEntryUnderscoreInDestructuringDeclaration() throws Exception { + runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclaration.kt"); + } + + @Test + @TestMetadata("entryUnderscoreInDestructuringDeclarationParameterInLambda.kt") + public void testEntryUnderscoreInDestructuringDeclarationParameterInLambda() throws Exception { + runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/destructuring/entryUnderscoreInDestructuringDeclarationParameterInLambda.kt"); + } } @Nested 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 c55cc515c2a..42c28e2e0af 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 @@ -26,11 +26,13 @@ import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.types.AbstractTypeChecker object FirDestructuringDeclarationChecker : FirPropertyChecker() { override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { val source = declaration.source ?: return + if (declaration.name == SpecialNames.UNDERSCORE_FOR_UNUSED_VAR) return // val (...) = `destructuring_declaration` if (source.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION) { checkInitializer(source, declaration.initializer, reporter, context) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReservedUnderscoreDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReservedUnderscoreDeclarationChecker.kt index 143c39e36d8..df4fe5f0ebb 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReservedUnderscoreDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirReservedUnderscoreDeclarationChecker.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirUserTypeRef +import org.jetbrains.kotlin.name.SpecialNames object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() { override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { @@ -55,7 +56,10 @@ object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() { isSingleUnderscoreAllowed: Boolean = false ) { val declarationSource = declaration.source - if (declarationSource != null && declarationSource.kind !is KtFakeSourceElementKind) { + if (declarationSource != null && + declarationSource.kind !is KtFakeSourceElementKind && + (declaration as? FirProperty)?.name != SpecialNames.UNDERSCORE_FOR_UNUSED_VAR + ) { with(SourceNavigator.forElement(declaration)) { val rawName = declaration.getRawName() if (rawName?.isUnderscore == true && !(isSingleUnderscoreAllowed && rawName == "_")) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt index 236d58466a0..16341127980 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/UnusedChecker.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.isBasicFunctionType +import org.jetbrains.kotlin.name.SpecialNames object UnusedChecker : AbstractFirPropertyInitializationChecker() { override fun analyze(data: PropertyInitializationInfoData, reporter: DiagnosticReporter, context: CheckerContext) { @@ -62,6 +63,7 @@ object UnusedChecker : AbstractFirPropertyInitializationChecker() { val variableSymbol = node.fir.symbol if (node.fir.source == null) return if (variableSymbol.isLoopIterator) return + if (variableSymbol.name == SpecialNames.UNDERSCORE_FOR_UNUSED_VAR) return val dataPerNode = data[node] ?: return val data = dataPerNode.values.mapNotNull { it[variableSymbol] }.reduceOrNull { acc, it -> acc.merge(it) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 51aba36cf7e..f5e9f5ef821 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -251,6 +251,9 @@ class Fir2IrVisitor( for (statement in script.statements) { val irStatement = if (statement is FirDeclaration) { when { + statement is FirProperty && statement.name == SpecialNames.UNDERSCORE_FOR_UNUSED_VAR -> { + continue + } statement is FirProperty && statement.origin == FirDeclarationOrigin.ScriptCustomization.ResultProperty -> { // Generating the result property only for expressions with a meaningful result type // otherwise skip the property and convert the expression into the statement @@ -820,6 +823,7 @@ class Fir2IrVisitor( } if (this is FirContractCallBlock) return null if (this is FirBlock) return convertToIrExpression(this) + if (this is FirProperty && name == SpecialNames.UNDERSCORE_FOR_UNUSED_VAR) return null return accept(this@Fir2IrVisitor, null) as IrStatement } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt index 4a18d2756b5..fbd200f77a9 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt @@ -1390,8 +1390,11 @@ class LightTreeRawFirDeclarationBuilder( } } - if (identifier == "_") return null - val name = identifier.nameAsSafeName() + val name = if (identifier == "_") { + SpecialNames.UNDERSCORE_FOR_UNUSED_VAR + } else { + identifier.nameAsSafeName() + } return buildProperty { source = entry.toFirSourceElement() moduleData = baseModuleData diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt index b429c3b0901..440d553f5b8 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.* internal fun KtWhenCondition.toFirWhenCondition( @@ -135,9 +136,12 @@ internal fun generateDestructuringBlock( } val isVar = multiDeclaration.isVar for ((index, entry) in multiDeclaration.entries.withIndex()) { - if (entry.nameIdentifier?.text == "_") continue + val name = if (entry.nameIdentifier?.text == "_") { + SpecialNames.UNDERSCORE_FOR_UNUSED_VAR + } else { + entry.nameAsSafeName + } val entrySource = entry.toKtPsiSourceElement() - val name = entry.nameAsSafeName statements += buildProperty { source = entrySource this.moduleData = moduleData diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.txt index dbd60d8c0d7..ef0e14f4450 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/destructuring.txt @@ -34,5 +34,6 @@ FILE: destructuring.kt public? final? fun bar(some: Some): R|kotlin/Unit| { lval : = some# lval a: = R|/|.component1#() + lval : = R|/|.component2#() lval _: = R|/|.component3#() } diff --git a/compiler/testData/diagnostics/tests/redeclarations/RedeclaredValsAndVars.fir.txt b/compiler/testData/diagnostics/tests/redeclarations/RedeclaredValsAndVars.fir.txt index bedcff1dabc..c37e081074d 100644 --- a/compiler/testData/diagnostics/tests/redeclarations/RedeclaredValsAndVars.fir.txt +++ b/compiler/testData/diagnostics/tests/redeclarations/RedeclaredValsAndVars.fir.txt @@ -48,4 +48,5 @@ FILE: RedeclaredValsAndVars.fir.kt lval : R|A| = R|/A.A|() lval _: R|kotlin/Int| = R|/|.R|/A.component1|() + lval : R|kotlin/String| = R|/|.R|/A.component2|() }