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 e4aa45949a4..b4a436d2971 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 @@ -3056,6 +3056,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.SINGLE_ANONYMOUS_FUNCTION_WITH_NAME.errorFactory) { firDiagnostic -> + SingleAnonymousFunctionWithNameErrorImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.SINGLE_ANONYMOUS_FUNCTION_WITH_NAME.warningFactory) { firDiagnostic -> + SingleAnonymousFunctionWithNameWarningImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE) { firDiagnostic -> AnonymousFunctionParameterWithDefaultValueImpl( 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 a814df0d38e..55c03e9e95c 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 @@ -2164,6 +2164,14 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = AnonymousFunctionWithName::class } + interface SingleAnonymousFunctionWithNameError : KtFirDiagnostic { + override val diagnosticClass get() = SingleAnonymousFunctionWithNameError::class + } + + interface SingleAnonymousFunctionWithNameWarning : KtFirDiagnostic { + override val diagnosticClass get() = SingleAnonymousFunctionWithNameWarning::class + } + interface AnonymousFunctionParameterWithDefaultValue : KtFirDiagnostic { override val diagnosticClass get() = AnonymousFunctionParameterWithDefaultValue::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 89433008d51..8c3f40ab5d9 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 @@ -2592,6 +2592,16 @@ internal class AnonymousFunctionWithNameImpl( token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.AnonymousFunctionWithName +internal class SingleAnonymousFunctionWithNameErrorImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.SingleAnonymousFunctionWithNameError + +internal class SingleAnonymousFunctionWithNameWarningImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.SingleAnonymousFunctionWithNameWarning + internal class AnonymousFunctionParameterWithDefaultValueImpl( 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 cd430a9b8f6..49c93f87563 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 @@ -9212,6 +9212,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt"); } + @Test + @TestMetadata("kt47245.kt") + public void testKt47245() throws Exception { + runTest("compiler/testData/diagnostics/tests/declarationChecks/kt47245.kt"); + } + @Test @TestMetadata("kt559.kt") public void testKt559() throws Exception { 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 0834474277d..52d608eb647 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 @@ -9212,6 +9212,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt"); } + @Test + @TestMetadata("kt47245.kt") + public void testKt47245() throws Exception { + runTest("compiler/testData/diagnostics/tests/declarationChecks/kt47245.kt"); + } + @Test @TestMetadata("kt559.kt") public void testKt559() throws Exception { 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 87ab95559de..5742b5d5a59 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 @@ -9206,6 +9206,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt"); } + @Test + @TestMetadata("kt47245.kt") + public void testKt47245() throws Exception { + runTest("compiler/testData/diagnostics/tests/declarationChecks/kt47245.kt"); + } + @Test @TestMetadata("kt559.kt") public void testKt559() throws Exception { 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 af753bfed86..e44729491d6 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 @@ -9212,6 +9212,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt"); } + @Test + @TestMetadata("kt47245.kt") + public void testKt47245() throws Exception { + runTest("compiler/testData/diagnostics/tests/declarationChecks/kt47245.kt"); + } + @Test @TestMetadata("kt559.kt") public void testKt559() throws Exception { 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 39d1b91e643..bb48aa391f3 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 @@ -1096,6 +1096,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val FUNCTION_DECLARATION_WITH_NO_NAME by error(PositioningStrategy.DECLARATION_SIGNATURE) val ANONYMOUS_FUNCTION_WITH_NAME by error() + val SINGLE_ANONYMOUS_FUNCTION_WITH_NAME by deprecationError(LanguageFeature.ProhibitSingleNamedFunctionAsExpression) // TODO: val ANONYMOUS_FUNCTION_WITH_NAME by error1(SourceElementPositioningStrategies.DECLARATION_NAME) val ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE by error(PositioningStrategy.PARAMETER_DEFAULT_VALUE) 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 1f7ba617614..0ea94ac1379 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 @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.config.LanguageFeature.ProhibitInlineModifierOnPrima import org.jetbrains.kotlin.config.LanguageFeature.ProhibitInvisibleAbstractMethodsInSuperclasses import org.jetbrains.kotlin.config.LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments import org.jetbrains.kotlin.config.LanguageFeature.ProhibitScriptTopLevelInnerClasses +import org.jetbrains.kotlin.config.LanguageFeature.ProhibitSingleNamedFunctionAsExpression import org.jetbrains.kotlin.config.LanguageFeature.ProhibitUseSiteTargetAnnotationsOnSuperTypes import org.jetbrains.kotlin.config.LanguageFeature.RestrictRetentionForExpressionAnnotations import org.jetbrains.kotlin.config.LanguageFeature.RestrictionOfValReassignmentViaBackingField @@ -551,6 +552,7 @@ object FirErrors { val NON_MEMBER_FUNCTION_NO_BODY by error1>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val FUNCTION_DECLARATION_WITH_NO_NAME by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) val ANONYMOUS_FUNCTION_WITH_NAME by error0() + val SINGLE_ANONYMOUS_FUNCTION_WITH_NAME by deprecationError0(ProhibitSingleNamedFunctionAsExpression) val ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE by error0(SourceElementPositioningStrategies.PARAMETER_DEFAULT_VALUE) val USELESS_VARARG_ON_PARAMETER by warning0() val MULTIPLE_VARARG_PARAMETERS by error0(SourceElementPositioningStrategies.PARAMETER_VARARG_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt index 69aab7fc690..36289aad286 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt @@ -129,7 +129,8 @@ object CommonExpressionCheckers : ExpressionCheckers() { override val blockCheckers: Set get() = setOf( FirForLoopChecker, - FirConflictsExpressionChecker + FirConflictsExpressionChecker, + FirSingleNamedFunctionChecker ) override val checkNotNullCallCheckers: Set diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSingleNamedFunctionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSingleNamedFunctionChecker.kt new file mode 100644 index 00000000000..dd0ab0909d5 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSingleNamedFunctionChecker.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers.expression + +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.expressions.FirBlock +import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock + +object FirSingleNamedFunctionChecker : FirBlockChecker() { + override fun check(expression: FirBlock, context: CheckerContext, reporter: DiagnosticReporter) { + if (expression is FirSingleExpressionBlock && expression.statement is FirSimpleFunction) { + reporter.reportOn( + expression.statement.source, + FirErrors.SINGLE_ANONYMOUS_FUNCTION_WITH_NAME, + context + ) + } + } +} \ No newline at end of file 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 a3165434338..81cff9c7911 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 @@ -570,6 +570,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SENSELESS_NULL_IN import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SETTER_PROJECTED_OUT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SINGLETON_IN_SUPERTYPE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SINGLE_ANONYMOUS_FUNCTION_WITH_NAME import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SMARTCAST_IMPOSSIBLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SPREAD_OF_NULLABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUBCLASS_OPT_IN_INAPPLICABLE @@ -1783,6 +1784,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(NON_MEMBER_FUNCTION_NO_BODY, "Function ''{0}'' must have a body.", DECLARATION_NAME) map.put(FUNCTION_DECLARATION_WITH_NO_NAME, "Function declaration must have a name.") map.put(ANONYMOUS_FUNCTION_WITH_NAME, "Anonymous functions with names are prohibited.") + map.put(SINGLE_ANONYMOUS_FUNCTION_WITH_NAME, "Anonymous functions with names are prohibited.") map.put( ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE, diff --git a/compiler/testData/diagnostics/tests/declarationChecks/kt47245.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/kt47245.fir.kt new file mode 100644 index 00000000000..184e9b7f208 --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/kt47245.fir.kt @@ -0,0 +1,6 @@ +// !COMPILER_VERSION 2.0 +// SKIP_KT_DUMP + +fun test() { + for (i in 0..0) fun x() {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/kt47245.kt b/compiler/testData/diagnostics/tests/declarationChecks/kt47245.kt new file mode 100644 index 00000000000..91820a9b4f4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/kt47245.kt @@ -0,0 +1,6 @@ +// !COMPILER_VERSION 2.0 +// SKIP_KT_DUMP + +fun test() { + for (i in 0..0) fun x() {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt index 4afacf0b32c..2ec7658277c 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt @@ -1,5 +1,6 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER -UNUSED_VARIABLE // !CHECK_TYPE +// !COMPILER_VERSION 2.0 fun foo(block: () -> (() -> Int)) {} fun test() { @@ -26,15 +27,15 @@ fun test() { fun named7() = 1 val x3 = when (1) { - 0 -> fun named8(): Int {return 1} - else -> fun named9() = 1 + 0 -> fun named8(): Int {return 1} + else -> fun named9() = 1 } val x31 = when (1) { 0 -> { fun named10(): Int {return 1} } - else -> fun named11() = 1 + else -> fun named11() = 1 } val x4 = { diff --git a/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.kt b/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.kt index 8db8fecf91c..6f73969707c 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.kt @@ -1,5 +1,6 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER -UNUSED_VARIABLE // !CHECK_TYPE +// !COMPILER_VERSION 2.0 fun foo(block: () -> (() -> Int)) {} fun test() { 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 1b3033d4153..43fc4cc7268 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 @@ -9212,6 +9212,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/declarationChecks/kt2643MultiDeclInControlFlow.kt"); } + @Test + @TestMetadata("kt47245.kt") + public void testKt47245() throws Exception { + runTest("compiler/testData/diagnostics/tests/declarationChecks/kt47245.kt"); + } + @Test @TestMetadata("kt559.kt") public void testKt559() throws Exception { diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 2f6ea47635d..4ee8363e51e 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -314,6 +314,7 @@ enum class LanguageFeature( ProhibitImplementingVarByInheritedVal(KOTLIN_2_1, kind = BUG_FIX), // KT-56779 PrioritizedEnumEntries(KOTLIN_2_1, kind = UNSTABLE_FEATURE), // KT-58920 ProhibitInlineModifierOnPrimaryConstructorParameters(KOTLIN_2_1, kind = BUG_FIX), // KT-59664 + ProhibitSingleNamedFunctionAsExpression(KOTLIN_2_1, kind = BUG_FIX), // KT-62573 // End of 2.* language features --------------------------------------------------