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 661a51782e0..93efa5226e9 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 @@ -3451,6 +3451,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.NOT_A_MULTIPLATFORM_COMPILATION) { firDiagnostic -> + NotAMultiplatformCompilationImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION) { firDiagnostic -> InitializerRequiredForDestructuringDeclarationImpl( 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 bb8105b2a07..f62277e3aa1 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 @@ -2411,6 +2411,10 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ActualMissing::class } + interface NotAMultiplatformCompilation : KtFirDiagnostic { + override val diagnosticClass get() = NotAMultiplatformCompilation::class + } + interface InitializerRequiredForDestructuringDeclaration : KtFirDiagnostic { override val diagnosticClass get() = InitializerRequiredForDestructuringDeclaration::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 bf95d9c38f5..11db3b1f65b 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 @@ -2907,6 +2907,11 @@ internal class ActualMissingImpl( token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.ActualMissing +internal class NotAMultiplatformCompilationImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.NotAMultiplatformCompilation + internal class InitializerRequiredForDestructuringDeclarationImpl( firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken, 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 a15ea3523f6..3bf1643d7aa 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 @@ -1170,6 +1170,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { } val ACTUAL_MISSING by error(PositioningStrategy.ACTUAL_DECLARATION_NAME) + + val NOT_A_MULTIPLATFORM_COMPILATION by error() } val DESTRUCTING_DECLARATION by object : DiagnosticGroup("Destructuring declaration") { 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 1fce6f04b8a..3c99937662c 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 @@ -625,6 +625,7 @@ object FirErrors { val AMBIGUOUS_EXPECTS by error2, Collection>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION) val NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS by error2, List, Map>, Collection>>>>>(SourceElementPositioningStrategies.ACTUAL_DECLARATION_NAME) val ACTUAL_MISSING by error0(SourceElementPositioningStrategies.ACTUAL_DECLARATION_NAME) + val NOT_A_MULTIPLATFORM_COMPILATION by error0() // Destructuring declaration val INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION by error0() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt index 9bfafd150e2..707162fba94 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt @@ -41,8 +41,7 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { if ((declaration.isExpect || declaration.isActual) && containsExpectOrActualModifier(declaration)) { reporter.reportOn( declaration.source, - FirErrors.UNSUPPORTED_FEATURE, - LanguageFeature.MultiPlatformProjects to context.session.languageVersionSettings, + FirErrors.NOT_A_MULTIPLATFORM_COMPILATION, context, positioningStrategy = SourceElementPositioningStrategies.EXPECT_ACTUAL_MODIFIER ) 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 3050e034c2f..a338b250ea9 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 @@ -343,6 +343,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_STDLIB_CL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND_FUN +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_MULTIPLATFORM_COMPILATION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER @@ -1843,6 +1844,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { FirIncompatibleExpectedActualClassScopesRenderer.TEXT ) map.put(ACTUAL_MISSING, "Declaration must be marked with 'actual'") + map.put(NOT_A_MULTIPLATFORM_COMPILATION, "'expect' and 'actual' declarations can be used only in multiplatform projects. Learn more about Kotlin Multiplatform: https://kotl.in/multiplatform-setup") // Destructuring declaration map.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index a65c8aa180a..93ccf4fbdf4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -835,6 +835,7 @@ public interface Errors { DiagnosticFactory0 OPTIONAL_EXPECTATION_NOT_ON_EXPECTED = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 NOT_A_MULTIPLATFORM_COMPILATION = DiagnosticFactory0.create(ERROR); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index b03427770ff..a72c1bdd64d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -391,6 +391,7 @@ public class DefaultErrorMessages { MAP.put(OPTIONAL_EXPECTATION_NOT_ON_EXPECTED, "'@OptionalExpectation' can only be used on an expected annotation class"); MAP.put(OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, "Declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry"); MAP.put(OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE, "Declaration annotated with '@OptionalExpectation' can only be used in common module sources"); + MAP.put(NOT_A_MULTIPLATFORM_COMPILATION, "'expect' and 'actual' declarations can be used only in multiplatform projects. Learn more about Kotlin Multiplatform: https://kotl.in/multiplatform-setup"); MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties"); MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt index 5a7039c6945..66b1d6644db 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt @@ -216,8 +216,6 @@ object ModifierCheckerCore { continue } - val featureSupport = languageVersionSettings.getFeatureSupport(dependency) - if (dependency == LanguageFeature.Coroutines) { checkCoroutinesFeature(languageVersionSettings, trace, node.psi) continue @@ -230,6 +228,13 @@ object ModifierCheckerCore { } } + val featureSupport = languageVersionSettings.getFeatureSupport(dependency) + + if (dependency == LanguageFeature.MultiPlatformProjects && featureSupport == LanguageFeature.State.DISABLED) { + trace.report(Errors.NOT_A_MULTIPLATFORM_COMPILATION.on(node.psi)) + continue + } + val diagnosticData = dependency to languageVersionSettings when (featureSupport) { LanguageFeature.State.ENABLED_WITH_WARNING -> { diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt index 694dba2a20e..4bc6de41916 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/noMultiplatformProjects.kt @@ -1,17 +1,17 @@ // FIR_IDENTICAL -expect fun foo1() -expect val bar1 = 42 -expect class Baz1 { +expect fun foo1() +expect val bar1 = 42 +expect class Baz1 { fun foo() class Baz12 } -actual fun foo2() = 42 -actual val bar2: Int -actual interface Baz2 +actual fun foo2() = 42 +actual val bar2: Int +actual interface Baz2 -actual class Baz1 { - actual fun foo() { +actual class Baz1 { + actual fun foo() { } -} \ No newline at end of file +}