diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index 209c78010ba..ecb30cc4b26 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -4957,6 +4957,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.MULTIPLE_LABELS_ARE_FORBIDDEN) { firDiagnostic -> + MultipleLabelsAreForbiddenImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.DEPRECATED_ACCESS_TO_ENUM_ENTRY_COMPANION_PROPERTY) { firDiagnostic -> DeprecatedAccessToEnumEntryCompanionPropertyImpl( firDiagnostic as KtPsiDiagnostic, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 26e78ae18eb..944b3c5c14c 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -3450,6 +3450,10 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = RedundantLabelWarning::class } + interface MultipleLabelsAreForbidden : KtFirDiagnostic { + override val diagnosticClass get() = MultipleLabelsAreForbidden::class + } + interface DeprecatedAccessToEnumEntryCompanionProperty : KtFirDiagnostic { override val diagnosticClass get() = DeprecatedAccessToEnumEntryCompanionProperty::class } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 3384d150950..ad788e53eb8 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -4161,6 +4161,11 @@ internal class RedundantLabelWarningImpl( token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.RedundantLabelWarning +internal class MultipleLabelsAreForbiddenImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.MultipleLabelsAreForbidden + internal class DeprecatedAccessToEnumEntryCompanionPropertyImpl( firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken, diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 4bd89816b3d..7b8c8628efa 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -23901,6 +23901,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia public void testLabelsMustBeNamed() throws Exception { runTest("compiler/testData/diagnostics/tests/labels/labelsMustBeNamed.kt"); } + + @Test + @TestMetadata("multipleLabels.kt") + public void testMultipleLabels() throws Exception { + runTest("compiler/testData/diagnostics/tests/labels/multipleLabels.kt"); + } } @Nested diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index e2b7f4b9f6c..8bfde0d50b3 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -23901,6 +23901,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated public void testLabelsMustBeNamed() throws Exception { runTest("compiler/testData/diagnostics/tests/labels/labelsMustBeNamed.kt"); } + + @Test + @TestMetadata("multipleLabels.kt") + public void testMultipleLabels() throws Exception { + runTest("compiler/testData/diagnostics/tests/labels/multipleLabels.kt"); + } } @Nested diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index e21f32a453d..f9440b7a1a8 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -23895,6 +23895,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir public void testLabelsMustBeNamed() throws Exception { runTest("compiler/testData/diagnostics/tests/labels/labelsMustBeNamed.kt"); } + + @Test + @TestMetadata("multipleLabels.kt") + public void testMultipleLabels() throws Exception { + runTest("compiler/testData/diagnostics/tests/labels/multipleLabels.kt"); + } } @Nested diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index dfa824a937d..32f801d201a 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -23901,6 +23901,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia public void testLabelsMustBeNamed() throws Exception { runTest("compiler/testData/diagnostics/tests/labels/labelsMustBeNamed.kt"); } + + @Test + @TestMetadata("multipleLabels.kt") + public void testMultipleLabels() throws Exception { + runTest("compiler/testData/diagnostics/tests/labels/multipleLabels.kt"); + } } @Nested diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 94e59b4c689..cf48bf9504f 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -1751,6 +1751,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val LABEL by object : DiagnosticGroup("label") { val REDUNDANT_LABEL_WARNING by warning(PositioningStrategy.LABEL) + val MULTIPLE_LABELS_ARE_FORBIDDEN by error(PositioningStrategy.LABEL) } val ENUM_ENTRIES_DEPRECATIONS by object : DiagnosticGroup("Enum.entries resolve deprecations") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 55ce585ebda..0619158ef48 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -872,6 +872,7 @@ object FirErrors { // label val REDUNDANT_LABEL_WARNING: KtDiagnosticFactory0 by warning0(SourceElementPositioningStrategies.LABEL) + val MULTIPLE_LABELS_ARE_FORBIDDEN: KtDiagnosticFactory0 by error0(SourceElementPositioningStrategies.LABEL) // Enum.entries resolve deprecations val DEPRECATED_ACCESS_TO_ENUM_ENTRY_COMPANION_PROPERTY: KtDiagnosticFactory0 by warning0() diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt index 88f4bd89a9e..bdb3a4fdd55 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirNonSuppressibleErrorNames.kt @@ -572,6 +572,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set = setOf( "RETURN_FOR_BUILT_IN_SUSPEND", "MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES", "MIXING_FUNCTIONAL_KINDS_IN_SUPERTYPES", + "MULTIPLE_LABELS_ARE_FORBIDDEN", "INCOMPATIBLE_CLASS", "PRE_RELEASE_CLASS", "IR_WITH_UNSTABLE_ABI_COMPILED_CLASS", diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index f8fed1c4800..3c843640f37 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -501,6 +501,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PACKAGE_CANNOT_BE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PACKAGE_OR_CLASSIFIER_REDECLARATION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PLATFORM_CLASS_MAPPED_TO_KOTLIN import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPILER_REQUIRED_ANNOTATION_AMBIGUITY +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_LABELS_ARE_FORBIDDEN import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.POTENTIALLY_NON_REPORTED_ANNOTATION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRE_RELEASE_CLASS @@ -2538,6 +2539,8 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { "Label is redundant, because it cannot be referenced in a 'break', 'continue', or 'return' expression." ) + map.put(MULTIPLE_LABELS_ARE_FORBIDDEN, "Multiple labels per statement are forbidden.") + // Enum entries deprecations map.put( DEPRECATED_ACCESS_TO_ENUM_ENTRY_COMPANION_PROPERTY, 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 e53da2d9414..da526d9de79 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 @@ -194,6 +194,7 @@ private fun ConeDiagnostic.toKtDiagnostic( is ConeAmbiguousFunctionTypeKinds -> FirErrors.AMBIGUOUS_FUNCTION_TYPE_KIND.createOn(source, kinds) is ConeUnsupportedClassLiteralsWithEmptyLhs -> FirErrors.UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS.createOn(source) is ConeMissingConstructorKeyword -> FirErrors.MISSING_CONSTRUCTOR_KEYWORD.createOn(source) + is ConeMultipleLabelsAreForbidden -> FirErrors.MULTIPLE_LABELS_ARE_FORBIDDEN.createOn(this.source) else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}") } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt index 70dd18ec035..b3542686125 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt @@ -397,19 +397,19 @@ class LightTreeRawFirExpressionBuilder( */ private fun convertLabeledExpression(labeledExpression: LighterASTNode): FirElement { var firExpression: FirElement? = null - var errorLabelSource: KtSourceElement? = null + var labelSource: KtSourceElement? = null + var forbiddenLabelKind: ForbiddenLabelKind? = null + + val isRepetitiveLabel = labeledExpression.getLabeledExpression()?.tokenType == LABELED_EXPRESSION labeledExpression.forEachChildren { context.setNewLabelUserNode(it) when (it.tokenType) { LABEL_QUALIFIER -> { - val rawName = it.toString() - val pair = buildLabelAndErrorSource( - rawName.substring(0, rawName.length - 1), - it.getChildNodesByType(LABEL).single().toFirSourceElement() - ) - context.addNewLabel(pair.first) - errorLabelSource = pair.second + val name = it.asText.dropLast(1) + labelSource = it.getChildNodesByType(LABEL).single().toFirSourceElement() + context.addNewLabel(buildLabel(name, labelSource!!)) + forbiddenLabelKind = getForbiddenLabelKind(name, isRepetitiveLabel) } BLOCK -> firExpression = declarationBuilder.convertBlock(it) PROPERTY -> firExpression = declarationBuilder.convertPropertyDeclaration(it) @@ -419,7 +419,7 @@ class LightTreeRawFirExpressionBuilder( context.dropLastLabel() - return buildExpressionWithErrorLabel(firExpression, errorLabelSource, labeledExpression.toFirSourceElement()) + return buildExpressionHandlingErrors(firExpression, labeledExpression.toFirSourceElement(), forbiddenLabelKind, labelSource) } /** 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 0f529407cc7..c4f2126b919 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 @@ -51,7 +51,10 @@ import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.util.OperatorNameConventions -import org.jetbrains.kotlin.utils.addToStdlib.* +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull +import org.jetbrains.kotlin.utils.addToStdlib.runIf +import org.jetbrains.kotlin.utils.addToStdlib.runUnless +import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment import org.jetbrains.kotlin.utils.exceptions.withPsiEntry @@ -3135,20 +3138,24 @@ open class PsiRawFirBuilder( override fun visitLabeledExpression(expression: KtLabeledExpression, data: FirElement?): FirElement { val label = expression.getTargetLabel() - var errorLabelSource: KtSourceElement? = null + var labelSource: KtSourceElement? = null + var forbiddenLabelKind: ForbiddenLabelKind? = null + + val isRepetitiveLabel = expression.baseExpression is KtLabeledExpression val result = if (label != null) { - val rawName = label.getReferencedNameElement().node!!.text - val labelAndErrorSource = buildLabelAndErrorSource(rawName, label.toKtPsiSourceElement()) - errorLabelSource = labelAndErrorSource.second - context.withNewLabel(labelAndErrorSource.first, expression.baseExpression) { + val name = label.getReferencedNameElement().node!!.text + forbiddenLabelKind = getForbiddenLabelKind(name, isRepetitiveLabel) + labelSource = label.toKtPsiSourceElement() + val firLabel = buildLabel(name, labelSource) + context.withNewLabel(firLabel, expression.baseExpression) { expression.baseExpression?.accept(this, data) } } else { expression.baseExpression?.accept(this, data) } - return buildExpressionWithErrorLabel(result, errorLabelSource, expression.toFirSourceElement()) + return buildExpressionHandlingErrors(result, expression.toFirSourceElement(), forbiddenLabelKind, labelSource) } override fun visitAnnotatedExpression(expression: KtAnnotatedExpression, data: FirElement?): FirElement { diff --git a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilder.kt b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilder.kt index 3ae18f35f93..f84bca473b3 100644 --- a/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilder.kt +++ b/compiler/fir/raw-fir/raw-fir.common/src/org/jetbrains/kotlin/fir/builder/AbstractRawFirBuilder.kt @@ -1044,26 +1044,41 @@ abstract class AbstractRawFirBuilder(val baseSession: FirSession, val context initContainingClassAttr(context) } - protected fun buildLabelAndErrorSource(rawName: String, source: KtSourceElement): Pair { + protected fun buildLabel(rawName: String, source: KtSourceElement): FirLabel { val firLabel = buildLabel { name = KtPsiUtil.unquoteIdentifier(rawName) this.source = source } - return Pair(firLabel, if (rawName.isUnderscore) firLabel.source else null) + return firLabel } - protected fun buildExpressionWithErrorLabel( + protected fun getForbiddenLabelKind(rawName: String, isMultipleLabel: Boolean): ForbiddenLabelKind? = when { + rawName.isUnderscore -> ForbiddenLabelKind.UNDERSCORE_IS_RESERVED + isMultipleLabel -> ForbiddenLabelKind.MULTIPLE_LABEL + else -> null + } + + protected enum class ForbiddenLabelKind { + UNDERSCORE_IS_RESERVED, MULTIPLE_LABEL + } + + protected fun buildExpressionHandlingErrors( element: FirElement?, - errorLabelSource: KtSourceElement?, elementSource: KtSourceElement, + forbiddenLabelKind: ForbiddenLabelKind?, + forbiddenLabelSource: KtSourceElement?, ): FirElement { return if (element != null) { - if (errorLabelSource != null) { + if (forbiddenLabelKind != null) { + require(forbiddenLabelSource != null) buildErrorExpression { this.source = element.source this.expression = element as? FirExpression - diagnostic = ConeUnderscoreIsReserved(errorLabelSource) + diagnostic = when (forbiddenLabelKind) { + ForbiddenLabelKind.UNDERSCORE_IS_RESERVED -> ConeUnderscoreIsReserved(forbiddenLabelSource) + ForbiddenLabelKind.MULTIPLE_LABEL -> ConeMultipleLabelsAreForbidden(forbiddenLabelSource) + } } } else { element 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 7c4d22b8d1b..5168d75b880 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 @@ -27,6 +27,10 @@ class ConeUnderscoreIsReserved(source: KtSourceElement) : ConeDiagnosticWithSour override val reason: String get() = "Names _, __, ___, ..., are reserved in Kotlin" } +class ConeMultipleLabelsAreForbidden(source: KtSourceElement) : ConeDiagnosticWithSource(source) { + override val reason: String get() = "Multiple labels per statement are forbidden" +} + class ConeCannotInferTypeParameterType( val typeParameter: FirTypeParameterSymbol, override val reason: String = "Cannot infer type for parameter ${typeParameter.name}" diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt index 5f4ea5f60f3..77da8ac00b8 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirExpressionUtil.kt @@ -102,7 +102,7 @@ fun FirBlock.replaceFirstStatement(factory: (T) -> FirStateme } fun FirExpression.unwrapErrorExpression(): FirExpression? = - if (this is FirErrorExpression) expression?.run { unwrapErrorExpression() } else this + if (this is FirErrorExpression) expression?.unwrapErrorExpression() else this fun FirExpression.unwrapArgument(): FirExpression = (this as? FirWrappedArgumentExpression)?.expression ?: this diff --git a/compiler/testData/diagnostics/tests/controlStructures/nestedLoopsWithMultipleLabels.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/nestedLoopsWithMultipleLabels.fir.kt new file mode 100644 index 00000000000..4f4eff7fd19 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/nestedLoopsWithMultipleLabels.fir.kt @@ -0,0 +1,10 @@ +// K2: See KT-65342 + +fun test() { + a@ b@ while(true) { + val f = { + return@a + } + break@b + } +} diff --git a/compiler/testData/diagnostics/tests/controlStructures/nestedLoopsWithMultipleLabels.kt b/compiler/testData/diagnostics/tests/controlStructures/nestedLoopsWithMultipleLabels.kt index 94fa8b2517b..715249d1c69 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/nestedLoopsWithMultipleLabels.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/nestedLoopsWithMultipleLabels.kt @@ -1,4 +1,5 @@ -// FIR_IDENTICAL +// K2: See KT-65342 + fun test() { a@ b@ while(true) { val f = { diff --git a/compiler/testData/diagnostics/tests/controlStructures/notAFunctionLabel_after.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/notAFunctionLabel_after.fir.kt index c5e6fe20f02..70d1284a099 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/notAFunctionLabel_after.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/notAFunctionLabel_after.fir.kt @@ -30,12 +30,12 @@ fun testAnnotatedLambdaLabel() = } fun testLambdaMultipleLabels1() = - lambda1@ lambda2@ { + lambda1@ lambda2@ { return@lambda1 } fun testLambdaMultipleLabels2() = - lambda1@ lambda2@ { + lambda1@ lambda2@ { return@lambda2 } @@ -62,7 +62,7 @@ fun testHighOrderFunctionCallLabelInReturn() { } fun testMultipleLabelsWithNestedLambda() { - l1@ l2@{ + l1@ l2@{ { return@l1 } diff --git a/compiler/testData/diagnostics/tests/controlStructures/notAFunctionLabel_before.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/notAFunctionLabel_before.fir.kt index 237beb97d69..744944eb0e4 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/notAFunctionLabel_before.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/notAFunctionLabel_before.fir.kt @@ -30,12 +30,12 @@ fun testAnnotatedLambdaLabel() = } fun testLambdaMultipleLabels1() = - lambda1@ lambda2@ { + lambda1@ lambda2@ { return@lambda1 } fun testLambdaMultipleLabels2() = - lambda1@ lambda2@ { + lambda1@ lambda2@ { return@lambda2 } @@ -62,7 +62,7 @@ fun testHighOrderFunctionCallLabelInReturn() { } fun testMultipleLabelsWithNestedLambda() { - l1@ l2@{ + l1@ l2@{ { return@l1 } diff --git a/compiler/testData/diagnostics/tests/inline/labelsAndNonInlineUsage.fir.kt b/compiler/testData/diagnostics/tests/inline/labelsAndNonInlineUsage.fir.kt index 3f4aba8cad5..84a9c269077 100644 --- a/compiler/testData/diagnostics/tests/inline/labelsAndNonInlineUsage.fir.kt +++ b/compiler/testData/diagnostics/tests/inline/labelsAndNonInlineUsage.fir.kt @@ -1,4 +1,4 @@ -// !DIAGNOSTICS: -REDUNDANT_LABEL_WARNING -UNDERSCORE_IS_RESERVED +// !DIAGNOSTICS: -REDUNDANT_LABEL_WARNING -UNDERSCORE_IS_RESERVED -MULTIPLE_LABELS_ARE_FORBIDDEN // See KT-65337 // !DIAGNOSTICS: -UNRESOLVED_REFERENCE diff --git a/compiler/testData/diagnostics/tests/inline/labelsAndNonInlineUsage.kt b/compiler/testData/diagnostics/tests/inline/labelsAndNonInlineUsage.kt index 52d054200c9..ee50ce439eb 100644 --- a/compiler/testData/diagnostics/tests/inline/labelsAndNonInlineUsage.kt +++ b/compiler/testData/diagnostics/tests/inline/labelsAndNonInlineUsage.kt @@ -1,4 +1,4 @@ -// !DIAGNOSTICS: -REDUNDANT_LABEL_WARNING -UNDERSCORE_IS_RESERVED +// !DIAGNOSTICS: -REDUNDANT_LABEL_WARNING -UNDERSCORE_IS_RESERVED -MULTIPLE_LABELS_ARE_FORBIDDEN // See KT-65337 // !DIAGNOSTICS: -UNRESOLVED_REFERENCE diff --git a/compiler/testData/diagnostics/tests/inline/parenthesized.fir.kt b/compiler/testData/diagnostics/tests/inline/parenthesized.fir.kt index 49451133b4c..77a90cf8dc3 100644 --- a/compiler/testData/diagnostics/tests/inline/parenthesized.fir.kt +++ b/compiler/testData/diagnostics/tests/inline/parenthesized.fir.kt @@ -23,5 +23,5 @@ inline fun inlineFunWithInvoke2(s: (p: Int) -> Unit) { inline fun propagation(s: (p: Int) -> Unit) { inlineFunWithInvoke((label@ s)) - inlineFunWithInvoke((label2@ label@ s)) + inlineFunWithInvoke((label2@ label@ s)) } diff --git a/compiler/testData/diagnostics/tests/labels/multipleLabels.fir.kt b/compiler/testData/diagnostics/tests/labels/multipleLabels.fir.kt new file mode 100644 index 00000000000..957ec9df94e --- /dev/null +++ b/compiler/testData/diagnostics/tests/labels/multipleLabels.fir.kt @@ -0,0 +1,37 @@ +// !DIAGNOSTICS: -REDUNDANT_LABEL_WARNING + +fun foo1() { + l2@ l1@ do { + } while (true) +} + +fun foo2() { + l4@ _@ l3@ __@ l2@ l1@ while (true) { + } +} + +fun foo3() { + l2@ l1@ 42 +} + +fun foo4() { + l1@ do { + l4@ { false } + } while (true) +} + +fun foo5() { + l2@ l1@ do { + l4@ { false } + } while (true) +} + +fun foo6() { + l2@ l1@ do { + l4@ l3@{ true } + } while (true) +} + +fun foo7() { + l3@ l2@ l1@ fun bar() {} +} diff --git a/compiler/testData/diagnostics/tests/labels/multipleLabels.kt b/compiler/testData/diagnostics/tests/labels/multipleLabels.kt new file mode 100644 index 00000000000..7f6a3cb4a47 --- /dev/null +++ b/compiler/testData/diagnostics/tests/labels/multipleLabels.kt @@ -0,0 +1,37 @@ +// !DIAGNOSTICS: -REDUNDANT_LABEL_WARNING + +fun foo1() { + l2@ l1@ do { + } while (true) +} + +fun foo2() { + l4@ _@ l3@ __@ l2@ l1@ while (true) { + } +} + +fun foo3() { + l2@ l1@ 42 +} + +fun foo4() { + l1@ do { + l4@ { false } + } while (true) +} + +fun foo5() { + l2@ l1@ do { + l4@ { false } + } while (true) +} + +fun foo6() { + l2@ l1@ do { + l4@ l3@{ true } + } while (true) +} + +fun foo7() { + l3@ l2@ l1@ fun bar() {} +} diff --git a/compiler/testData/diagnostics/tests/regressions/TypeMismatchOnUnaryOperations.fir.kt b/compiler/testData/diagnostics/tests/regressions/TypeMismatchOnUnaryOperations.fir.kt index 19cf94f6a89..c85184cebf4 100644 --- a/compiler/testData/diagnostics/tests/regressions/TypeMismatchOnUnaryOperations.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/TypeMismatchOnUnaryOperations.fir.kt @@ -1,3 +1,5 @@ +// K2: See KT-65342 + fun main() { val a : Int? = null; var v = 1 @@ -9,7 +11,7 @@ fun main() { val h1 : String = --v; val i : String = !true; val j : String = foo@ true; - val k : String = foo@ bar@ true; + val k : String = foo@ bar@ true; val l : String = -1; val m : String = +1; } diff --git a/compiler/testData/diagnostics/tests/regressions/TypeMismatchOnUnaryOperations.kt b/compiler/testData/diagnostics/tests/regressions/TypeMismatchOnUnaryOperations.kt index 6465489194a..6a11738d64c 100644 --- a/compiler/testData/diagnostics/tests/regressions/TypeMismatchOnUnaryOperations.kt +++ b/compiler/testData/diagnostics/tests/regressions/TypeMismatchOnUnaryOperations.kt @@ -1,3 +1,5 @@ +// K2: See KT-65342 + fun main() { val a : Int? = null; var v = 1 diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 654e1584b0c..072c41b8c3b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -23901,6 +23901,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { public void testLabelsMustBeNamed() throws Exception { runTest("compiler/testData/diagnostics/tests/labels/labelsMustBeNamed.kt"); } + + @Test + @TestMetadata("multipleLabels.kt") + public void testMultipleLabels() throws Exception { + runTest("compiler/testData/diagnostics/tests/labels/multipleLabels.kt"); + } } @Nested