From aa71b4d2edaec48a8e8d42e18e9b6cb26a3388b7 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Tue, 18 Nov 2025 16:40:57 +0100 Subject: [PATCH 1/5] [Test] Reproduce non-suppressible OptIn CLI warnings (KT-48419) --- .../testData/cli/metadata/optInDiagnostics.kt | 10 ++++++++++ .../cli/metadata/optInErrorIsNotSuppressible.args | 7 +++++++ .../cli/metadata/optInErrorIsNotSuppressible.out | 2 ++ .../cli/metadata/optInWarningsAreDisabled.args | 11 +++++++++++ .../cli/metadata/optInWarningsAreDisabled.out | 5 +++++ .../cli/metadata/optInWarningsAsErrors.args | 10 ++++++++++ .../cli/metadata/optInWarningsAsErrors.out | 4 ++++ .../jetbrains/kotlin/cli/CliTestGenerated.java | 15 +++++++++++++++ 8 files changed, 64 insertions(+) create mode 100644 compiler/testData/cli/metadata/optInDiagnostics.kt create mode 100644 compiler/testData/cli/metadata/optInErrorIsNotSuppressible.args create mode 100644 compiler/testData/cli/metadata/optInErrorIsNotSuppressible.out create mode 100644 compiler/testData/cli/metadata/optInWarningsAreDisabled.args create mode 100644 compiler/testData/cli/metadata/optInWarningsAreDisabled.out create mode 100644 compiler/testData/cli/metadata/optInWarningsAsErrors.args create mode 100644 compiler/testData/cli/metadata/optInWarningsAsErrors.out diff --git a/compiler/testData/cli/metadata/optInDiagnostics.kt b/compiler/testData/cli/metadata/optInDiagnostics.kt new file mode 100644 index 0000000000000..5e4d4851405a3 --- /dev/null +++ b/compiler/testData/cli/metadata/optInDiagnostics.kt @@ -0,0 +1,10 @@ +interface NotAnAnnotation + +@Deprecated("Warning", level = DeprecationLevel.WARNING) +@RequiresOptIn +@Retention(AnnotationRetention.BINARY) +annotation class Warning + +@Deprecated("Error", level = DeprecationLevel.ERROR) +@RequiresOptIn +annotation class Error \ No newline at end of file diff --git a/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.args b/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.args new file mode 100644 index 0000000000000..cbb857714768c --- /dev/null +++ b/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.args @@ -0,0 +1,7 @@ +$TESTDATA_DIR$/optInDiagnostics.kt +-d +$TEMP_DIR$ +-cp +$TESTDATA_DIR$/../../../../dist/common/kotlin-stdlib-common.klib +-Xtarget-platform=JVM,JS,WasmJs,WasmWasi,Native +-opt-in=Error \ No newline at end of file diff --git a/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.out b/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.out new file mode 100644 index 0000000000000..e2ddfe549d5db --- /dev/null +++ b/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.out @@ -0,0 +1,2 @@ +error: opt-in requirement marker Error is deprecated. Error +COMPILATION_ERROR diff --git a/compiler/testData/cli/metadata/optInWarningsAreDisabled.args b/compiler/testData/cli/metadata/optInWarningsAreDisabled.args new file mode 100644 index 0000000000000..2180aab15c1c3 --- /dev/null +++ b/compiler/testData/cli/metadata/optInWarningsAreDisabled.args @@ -0,0 +1,11 @@ +$TESTDATA_DIR$/optInDiagnostics.kt +-d +$TEMP_DIR$ +-cp +$TESTDATA_DIR$/../../../../dist/common/kotlin-stdlib-common.klib +-Xtarget-platform=JVM,JS,WasmJs,WasmWasi,Native +-opt-in=Unresolved +-opt-in=NotAnAnnotation +-opt-in=kotlin.RequiresOptIn +-opt-in=Warning +-Werror \ No newline at end of file diff --git a/compiler/testData/cli/metadata/optInWarningsAreDisabled.out b/compiler/testData/cli/metadata/optInWarningsAreDisabled.out new file mode 100644 index 0000000000000..0111eb983bc64 --- /dev/null +++ b/compiler/testData/cli/metadata/optInWarningsAreDisabled.out @@ -0,0 +1,5 @@ +warning: opt-in requirement marker Unresolved is unresolved. Please make sure it's present in the module dependencies +warning: class NotAnAnnotation is not an opt-in requirement marker +warning: opt-in requirement marker Warning is deprecated. Warning +error: warnings found and -Werror specified +COMPILATION_ERROR diff --git a/compiler/testData/cli/metadata/optInWarningsAsErrors.args b/compiler/testData/cli/metadata/optInWarningsAsErrors.args new file mode 100644 index 0000000000000..8a70a217f3f27 --- /dev/null +++ b/compiler/testData/cli/metadata/optInWarningsAsErrors.args @@ -0,0 +1,10 @@ +$TESTDATA_DIR$/optInDiagnostics.kt +-d +$TEMP_DIR$ +-cp +$TESTDATA_DIR$/../../../../dist/common/kotlin-stdlib-common.klib +-Xtarget-platform=JVM,JS,WasmJs,WasmWasi,Native +-opt-in=Unresolved +-opt-in=NotAnAnnotation +-opt-in=kotlin.RequiresOptIn +-opt-in=Warning \ No newline at end of file diff --git a/compiler/testData/cli/metadata/optInWarningsAsErrors.out b/compiler/testData/cli/metadata/optInWarningsAsErrors.out new file mode 100644 index 0000000000000..9a33ddfcc8e3d --- /dev/null +++ b/compiler/testData/cli/metadata/optInWarningsAsErrors.out @@ -0,0 +1,4 @@ +warning: opt-in requirement marker Unresolved is unresolved. Please make sure it's present in the module dependencies +warning: class NotAnAnnotation is not an opt-in requirement marker +warning: opt-in requirement marker Warning is deprecated. Warning +OK diff --git a/compiler/tests-integration/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests-integration/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java index 77712806a216f..c4dec902cdc24 100644 --- a/compiler/tests-integration/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests-integration/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -2315,6 +2315,21 @@ public void testNoVirtualFileHiddenForMemberWithPlatformDependentAnnotation() { runTest("compiler/testData/cli/metadata/noVirtualFileHiddenForMemberWithPlatformDependentAnnotation.args"); } + @TestMetadata("optInErrorIsNotSuppressible.args") + public void testOptInErrorIsNotSuppressible() { + runTest("compiler/testData/cli/metadata/optInErrorIsNotSuppressible.args"); + } + + @TestMetadata("optInWarningsAreDisabled.args") + public void testOptInWarningsAreDisabled() { + runTest("compiler/testData/cli/metadata/optInWarningsAreDisabled.args"); + } + + @TestMetadata("optInWarningsAsErrors.args") + public void testOptInWarningsAsErrors() { + runTest("compiler/testData/cli/metadata/optInWarningsAsErrors.args"); + } + @TestMetadata("optionalAnnotationsFromMetadata.args") public void testOptionalAnnotationsFromMetadata() { runTest("compiler/testData/cli/metadata/optionalAnnotationsFromMetadata.args"); From 62729f4b48d379fd57efe45f134e9cfcc02e18f3 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Tue, 18 Nov 2025 17:43:33 +0100 Subject: [PATCH 2/5] Transform `AnalyzerWithCompilerReport.convertSeverity` to `Severity.toCompilerMessageSeverity` It allows using the function in `BaseDiagnosticsCollector` (for FIR CLI diagnostics) and refines the code --- .../fir/FirDiagnosticsCompilerResultsReporter.kt | 4 ++-- .../cli/common/messages/AnalyzerWithCompilerReport.kt | 8 -------- .../cli/common/messages/DefaultDiagnosticReporter.kt | 2 +- .../cli/src/org/jetbrains/kotlin/cli/common/utils.kt | 2 +- .../src/org/jetbrains/kotlin/diagnostics/Severity.kt | 11 ++++++++++- .../kotlin/test/backend/handlers/HandlerUtils.kt | 3 +-- .../backend/handlers/NoIrCompilationErrorsHandler.kt | 3 +-- .../frontend/fir/handlers/FirDiagnosticsHandler.kt | 3 +-- 8 files changed, 17 insertions(+), 19 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/fir/FirDiagnosticsCompilerResultsReporter.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/fir/FirDiagnosticsCompilerResultsReporter.kt index 2b94636a2c7f3..42d74a717e5da 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/fir/FirDiagnosticsCompilerResultsReporter.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/fir/FirDiagnosticsCompilerResultsReporter.kt @@ -112,7 +112,7 @@ object FirDiagnosticsCompilerResultsReporter { reporter: MessageCollector, renderDiagnosticName: Boolean ) { - val severity = AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity) + val severity = diagnostic.severity.toCompilerMessageSeverity() val message = diagnostic.renderMessage() val textToRender = when (renderDiagnosticName) { true -> "[${diagnostic.factoryName}] $message" @@ -128,7 +128,7 @@ object FirDiagnosticsCompilerResultsReporter { messageRenderer: MessageRenderer ) { if (diagnostic.severity == Severity.ERROR) { - val severity = AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity) + val severity = diagnostic.severity.toCompilerMessageSeverity() val message = diagnostic.renderMessage() val diagnosticText = messageRenderer.render(severity, message, location) throw IllegalStateException("${diagnostic.factory.name}: $diagnosticText") diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt index 0090123954e73..035a4260d0c4c 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt @@ -131,14 +131,6 @@ class AnalyzerWithCompilerReport( } companion object { - - fun convertSeverity(severity: Severity): CompilerMessageSeverity = when (severity) { - Severity.INFO -> INFO - Severity.ERROR -> ERROR - Severity.WARNING -> WARNING - Severity.FIXED_WARNING -> FIXED_WARNING - } - private val SYNTAX_ERROR_FACTORY = DiagnosticFactory0.create(Severity.ERROR) private fun reportDiagnostic(diagnostic: Diagnostic, reporter: DiagnosticMessageReporter, renderDiagnosticName: Boolean): Boolean { diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/DefaultDiagnosticReporter.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/DefaultDiagnosticReporter.kt index 2d82644bf95c7..1ba4bfd24f701 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/DefaultDiagnosticReporter.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/DefaultDiagnosticReporter.kt @@ -29,7 +29,7 @@ interface MessageCollectorBasedReporter : DiagnosticMessageReporter { val messageCollector: MessageCollector override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report( - AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity), + diagnostic.severity.toCompilerMessageSeverity(), render, MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumnRange(diagnostic)) ) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt index ef7f4b2e42309..7e59c7e8f732f 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt @@ -162,5 +162,5 @@ fun CompilerConfiguration.reportIfNeeded(factory: KtSourcelessDiagnosticFactory, get() = this@reportIfNeeded.languageVersionSettings }) ?: return - messageCollector.report(AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity), message) + messageCollector.report(diagnostic.severity.toCompilerMessageSeverity(), message) } \ No newline at end of file diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/Severity.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/Severity.kt index 4c03129255706..982f382b45d25 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/Severity.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/Severity.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.diagnostics +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity + enum class Severity { INFO, ERROR, @@ -13,5 +15,12 @@ enum class Severity { /** * see [org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.FIXED_WARNING] */ - FIXED_WARNING, + FIXED_WARNING; + + fun toCompilerMessageSeverity(): CompilerMessageSeverity = when (this) { + INFO -> CompilerMessageSeverity.INFO + ERROR -> CompilerMessageSeverity.ERROR + WARNING -> CompilerMessageSeverity.WARNING + FIXED_WARNING -> CompilerMessageSeverity.FIXED_WARNING + } } diff --git a/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/backend/handlers/HandlerUtils.kt b/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/backend/handlers/HandlerUtils.kt index d70502614ad37..79c546f0a7d07 100644 --- a/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/backend/handlers/HandlerUtils.kt +++ b/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/backend/handlers/HandlerUtils.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.test.backend.handlers import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.cli.common.fir.SequentialPositionFinder -import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.codeMetaInfo.model.DiagnosticCodeMetaInfo import org.jetbrains.kotlin.diagnostics.DiagnosticUtils import org.jetbrains.kotlin.diagnostics.Severity @@ -115,7 +114,7 @@ fun BinaryArtifactHandler<*>.checkFullDiagnosticRender() { } private fun renderDiagnosticMessage(fileName: String, severity: Severity, message: String?, line: Int, column: Int): String { - val severityString = AnalyzerWithCompilerReport.convertSeverity(severity).toString().toLowerCaseAsciiOnly() + val severityString = severity.toCompilerMessageSeverity().toString().toLowerCaseAsciiOnly() return "/${fileName}:$line:$column: $severityString: $message" } diff --git a/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/backend/handlers/NoIrCompilationErrorsHandler.kt b/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/backend/handlers/NoIrCompilationErrorsHandler.kt index 45548f43e0669..e05fc8672cadf 100644 --- a/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/backend/handlers/NoIrCompilationErrorsHandler.kt +++ b/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/backend/handlers/NoIrCompilationErrorsHandler.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.test.backend.handlers -import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.test.backend.ir.IrBackendInput import org.jetbrains.kotlin.test.model.BackendInputHandler @@ -39,7 +38,7 @@ class NoIrCompilationErrorsHandler(testServices: TestServices) : BackendInputHan diagnostic.severity == Severity.ERROR && diagnosticsService.shouldRenderDiagnostic(module, diagnostic.factoryName, diagnostic.severity) ) { - val severity = AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity).toString().toLowerCaseAsciiOnly() + val severity = diagnostic.severity.toCompilerMessageSeverity().toString().toLowerCaseAsciiOnly() val message = diagnostic.renderMessage() error("/$file:${diagnostic.firstRange}: $severity: $message") } diff --git a/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt b/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt index 53a87f0df7fcd..e2a7b35f7e0c8 100644 --- a/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt +++ b/compiler/tests-common-new/testFixtures/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.test.frontend.fir.handlers import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.* import org.jetbrains.kotlin.checkers.utils.TypeOfCall -import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.pipeline.metadata.MetadataFrontendPipelineArtifact import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.diagnostics.* @@ -116,7 +115,7 @@ class FullDiagnosticsRenderer(private val directive: SimpleDirective) { is KtDiagnosticWithSource -> it.textRanges is KtDiagnosticWithoutSource -> listOf(it.firstRange) }, - severity = AnalyzerWithCompilerReport.convertSeverity(it.severity).toString().toLowerCaseAsciiOnly(), + severity = it.severity.toCompilerMessageSeverity().toString().toLowerCaseAsciiOnly(), message = it.renderMessage() ) } From a9287b1d26dfd5034d1cbe6941cc2f9bfff59133 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Tue, 18 Nov 2025 17:47:31 +0100 Subject: [PATCH 3/5] Move `CliDiagnostics` from `org.jetbrains.kotlin.fir.cli` to `org.jetbrains.kotlin.fir.analysis.diagnostics` To make it possible to use them in FIR CLI checkers Also, now they live in a package where regular `FirErrors` live --- .../cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.kt | 2 +- .../kotlin/fir/analysis/diagnostics}/CliDiagnostics.kt | 4 ++-- .../org/jetbrains/kotlin/fir/session/ComponentsContainers.kt | 2 +- .../org/jetbrains/kotlin/checkers/DefaultMessagesTest.kt | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename compiler/fir/{entrypoint/src/org/jetbrains/kotlin/fir/cli => checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics}/CliDiagnostics.kt (88%) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.kt index 649c5ecf734ef..a65f58166fb7b 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.kt @@ -35,7 +35,7 @@ import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.config.* -import org.jetbrains.kotlin.fir.cli.CliDiagnostics +import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.progress.CompilationCanceledException diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/cli/CliDiagnostics.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/CliDiagnostics.kt similarity index 88% rename from compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/cli/CliDiagnostics.kt rename to compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/CliDiagnostics.kt index 6ad6b471184d2..6fee3f3509cef 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/cli/CliDiagnostics.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/CliDiagnostics.kt @@ -3,7 +3,7 @@ * 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.cli +package org.jetbrains.kotlin.fir.analysis.diagnostics import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap import org.jetbrains.kotlin.diagnostics.KtDiagnosticsContainer @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.diagnostics.KtSourcelessDiagnosticFactory import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory import org.jetbrains.kotlin.diagnostics.rendering.BaseSourcelessDiagnosticFactory import org.jetbrains.kotlin.diagnostics.warningWithoutSource -import org.jetbrains.kotlin.fir.cli.CliDiagnostics.CLI_COMPILER_PLUGIN_IS_EXPERIMENTAL +import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics.CLI_COMPILER_PLUGIN_IS_EXPERIMENTAL import kotlin.getValue object CliDiagnostics : KtDiagnosticsContainer() { diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt index a6878fec288bf..39b7e99554042 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.FirInlineCheckerPlatformSpecif import org.jetbrains.kotlin.fir.analysis.checkers.FirPrimaryConstructorSuperTypeCheckerPlatformComponent import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirNameConflictsTrackerImpl import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirGenericArrayClassLiteralSupport +import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics import org.jetbrains.kotlin.fir.analysis.diagnostics.FirComposedDiagnosticRendererFactory import org.jetbrains.kotlin.fir.analysis.diagnostics.diagnosticRendererFactory import org.jetbrains.kotlin.fir.analysis.jvm.FirJvmOverridesBackwardCompatibilityHelper @@ -24,7 +25,6 @@ import org.jetbrains.kotlin.fir.analysis.jvm.checkers.FirJvmInlineCheckerCompone import org.jetbrains.kotlin.fir.analysis.jvm.checkers.FirJvmPrimaryConstructorSuperTypeCheckerPlatformComponent import org.jetbrains.kotlin.fir.caches.FirCachesFactory import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory -import org.jetbrains.kotlin.fir.cli.CliDiagnostics import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.extensions.* import org.jetbrains.kotlin.fir.java.FirJavaVisibilityChecker diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DefaultMessagesTest.kt b/compiler/tests/org/jetbrains/kotlin/checkers/DefaultMessagesTest.kt index cc30ecc900f2e..96aefff3fe313 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DefaultMessagesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DefaultMessagesTest.kt @@ -5,8 +5,10 @@ package org.jetbrains.kotlin.checkers +import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrorsDefaultMessages +import org.jetbrains.kotlin.fir.analysis.diagnostics.KtDiagnosticMessagesCli import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrorsDefaultMessages import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors @@ -19,8 +21,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErro import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrorsDefaultMessages import org.jetbrains.kotlin.fir.builder.FirSyntaxErrors import org.jetbrains.kotlin.fir.builder.FirSyntaxErrorsDefaultMessages -import org.jetbrains.kotlin.fir.cli.CliDiagnostics -import org.jetbrains.kotlin.fir.cli.KtDiagnosticMessagesCli import org.jetbrains.kotlin.test.utils.verifyMessages import org.junit.Test From 524b4c7a501abbd87ab775b4526a87b9f56bbab1 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Tue, 18 Nov 2025 17:52:05 +0100 Subject: [PATCH 4/5] Introduce `BaseDiagnosticsCollector.reportIfNeeded` It required changing of `getEffectiveSeverity` visibility to public Simplify code of `CompilerConfiguration.reportIfNeeded` --- .../cli/src/org/jetbrains/kotlin/cli/common/utils.kt | 10 ++-------- .../kotlin/diagnostics/KtDiagnosticFactory.kt | 2 +- .../diagnostics/impl/BaseDiagnosticsCollector.kt | 11 +++++++++++ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt index 7e59c7e8f732f..186e21818ff28 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/utils.kt @@ -26,10 +26,8 @@ import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.messages.* import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.IncrementalCompilation -import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.messageCollector -import org.jetbrains.kotlin.diagnostics.DiagnosticBaseContext import org.jetbrains.kotlin.diagnostics.KtSourcelessDiagnosticFactory import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.packageFqName @@ -157,10 +155,6 @@ fun disposeRootInWriteAction(disposable: Disposable) { } fun CompilerConfiguration.reportIfNeeded(factory: KtSourcelessDiagnosticFactory, message: String) { - val diagnostic = factory.create(message, object : DiagnosticBaseContext { - override val languageVersionSettings: LanguageVersionSettings - get() = this@reportIfNeeded.languageVersionSettings - - }) ?: return - messageCollector.report(diagnostic.severity.toCompilerMessageSeverity(), message) + val effectiveSeverity = factory.getEffectiveSeverity(this@reportIfNeeded.languageVersionSettings) ?: return + messageCollector.report(effectiveSeverity.toCompilerMessageSeverity(), message) } \ No newline at end of file diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/KtDiagnosticFactory.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/KtDiagnosticFactory.kt index b29e787a5e6ed..cf940cca9b930 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/KtDiagnosticFactory.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/KtDiagnosticFactory.kt @@ -29,7 +29,7 @@ sealed class AbstractKtDiagnosticFactory( get() = rendererFactory.MAP[this] ?: error("Renderer is not found for factory $this inside ${rendererFactory.MAP.name} renderer map") - protected fun getEffectiveSeverity(languageVersionSettings: LanguageVersionSettings): Severity? { + fun getEffectiveSeverity(languageVersionSettings: LanguageVersionSettings): Severity? { return when (languageVersionSettings.getFlag(AnalysisFlags.warningLevels)[name]) { WarningLevel.Error -> Severity.ERROR WarningLevel.Warning -> Severity.FIXED_WARNING diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/BaseDiagnosticsCollector.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/BaseDiagnosticsCollector.kt index 92eb0cb31b918..a12c203588d68 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/BaseDiagnosticsCollector.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/BaseDiagnosticsCollector.kt @@ -6,8 +6,10 @@ package org.jetbrains.kotlin.diagnostics.impl import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.diagnostics.DiagnosticBaseContext import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.KtDiagnostic +import org.jetbrains.kotlin.diagnostics.KtSourcelessDiagnosticFactory abstract class BaseDiagnosticsCollector : DiagnosticReporter() { abstract val diagnostics: List @@ -29,5 +31,14 @@ abstract class BaseDiagnosticsCollector : DiagnosticReporter() { fun reportError(message: String) { report(message, CompilerMessageSeverity.ERROR) } + + fun reportIfNeeded( + factory: KtSourcelessDiagnosticFactory, + message: String, + context: DiagnosticBaseContext, + ) { + val refinedSeverity = factory.getEffectiveSeverity(context.languageVersionSettings)?.toCompilerMessageSeverity() ?: return + report(message, refinedSeverity) + } } } From 1429a28cf8337201752fc52dd5de160a39d075ac Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Tue, 18 Nov 2025 17:59:59 +0100 Subject: [PATCH 5/5] [FIR] Introduce identifiers for opt-in CLI diagnostics that can be configured using `-Xwarning-level` ^KT-48419 Fixed --- .../FirOptInLanguageVersionSettingsChecker.kt | 30 +++++++++++-------- .../analysis/diagnostics/CliDiagnostics.kt | 13 ++++++++ .../impl/BaseDiagnosticsCollector.kt | 4 --- .../metadata/optInErrorIsNotSuppressible.args | 3 +- .../metadata/optInErrorIsNotSuppressible.out | 2 +- .../metadata/optInWarningsAreDisabled.args | 5 +++- .../cli/metadata/optInWarningsAreDisabled.out | 6 +--- .../cli/metadata/optInWarningsAsErrors.args | 5 +++- .../cli/metadata/optInWarningsAsErrors.out | 8 ++--- 9 files changed, 47 insertions(+), 29 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/config/FirOptInLanguageVersionSettingsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/config/FirOptInLanguageVersionSettingsChecker.kt index 9894ab201f39c..749b3479cae90 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/config/FirOptInLanguageVersionSettingsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/config/FirOptInLanguageVersionSettingsChecker.kt @@ -5,10 +5,10 @@ package org.jetbrains.kotlin.fir.analysis.checkers.config -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics import org.jetbrains.kotlin.fir.declarations.hasAnnotationWithClassId import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.transformers.PackageResolutionResult @@ -36,25 +36,31 @@ object FirOptInLanguageVersionSettingsChecker : FirLanguageVersionSettingsChecke val symbol = (packageOrClass as? PackageResolutionResult.PackageOrClass)?.classSymbol if (symbol == null) { - reporter.reportWarning( - "Opt-in requirement marker $fqNameAsString is unresolved. Please make sure it's present in the module dependencies" + reporter.reportIfNeeded( + CliDiagnostics.CLI_OPT_IN_REQUIREMENT_MARKER_IS_UNRESOLVED, + "Opt-in requirement marker $fqNameAsString is unresolved. Please make sure it's present in the module dependencies", + context, ) return } if (!symbol.hasAnnotationWithClassId(OptInNames.REQUIRES_OPT_IN_CLASS_ID, context.session)) { - reporter.reportWarning("Class $fqNameAsString is not an opt-in requirement marker") + reporter.reportIfNeeded( + CliDiagnostics.CLI_NOT_AN_OPT_IN_REQUIREMENT_MARKER, + "Class $fqNameAsString is not an opt-in requirement marker", + context, + ) return } val deprecationInfo = symbol.getOwnDeprecation(context.languageVersionSettings)?.all ?: return - val severity = when (deprecationInfo.deprecationLevel) { - DeprecationLevelValue.WARNING -> CompilerMessageSeverity.WARNING - else -> CompilerMessageSeverity.ERROR - } - reporter.report( - "Opt-in requirement marker $fqNameAsString is deprecated" + - deprecationInfo.getMessage(context.session)?.let { ". $it" }.orEmpty(), - severity + val diagnosticFactory = if (deprecationInfo.deprecationLevel == DeprecationLevelValue.WARNING) + CliDiagnostics.CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED + else + CliDiagnostics.CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED_ERROR + reporter.reportIfNeeded( + diagnosticFactory, + "Opt-in requirement marker $fqNameAsString is deprecated" + deprecationInfo.getMessage(context.session)?.let { ". $it" }.orEmpty(), + context, ) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/CliDiagnostics.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/CliDiagnostics.kt index 6fee3f3509cef..3fb189cc21f55 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/CliDiagnostics.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/CliDiagnostics.kt @@ -8,14 +8,23 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap import org.jetbrains.kotlin.diagnostics.KtDiagnosticsContainer import org.jetbrains.kotlin.diagnostics.KtSourcelessDiagnosticFactory +import org.jetbrains.kotlin.diagnostics.errorWithoutSource import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory import org.jetbrains.kotlin.diagnostics.rendering.BaseSourcelessDiagnosticFactory import org.jetbrains.kotlin.diagnostics.warningWithoutSource import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics.CLI_COMPILER_PLUGIN_IS_EXPERIMENTAL +import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics.CLI_NOT_AN_OPT_IN_REQUIREMENT_MARKER +import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics.CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED +import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics.CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED_ERROR +import org.jetbrains.kotlin.fir.analysis.diagnostics.CliDiagnostics.CLI_OPT_IN_REQUIREMENT_MARKER_IS_UNRESOLVED import kotlin.getValue object CliDiagnostics : KtDiagnosticsContainer() { val CLI_COMPILER_PLUGIN_IS_EXPERIMENTAL: KtSourcelessDiagnosticFactory by warningWithoutSource() + val CLI_OPT_IN_REQUIREMENT_MARKER_IS_UNRESOLVED: KtSourcelessDiagnosticFactory by warningWithoutSource() + val CLI_NOT_AN_OPT_IN_REQUIREMENT_MARKER: KtSourcelessDiagnosticFactory by warningWithoutSource() + val CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED: KtSourcelessDiagnosticFactory by warningWithoutSource() + val CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED_ERROR: KtSourcelessDiagnosticFactory by errorWithoutSource() override fun getRendererFactory(): BaseDiagnosticRendererFactory = KtDiagnosticMessagesCli } @@ -23,5 +32,9 @@ object CliDiagnostics : KtDiagnosticsContainer() { object KtDiagnosticMessagesCli : BaseSourcelessDiagnosticFactory() { override val MAP: KtDiagnosticFactoryToRendererMap by KtDiagnosticFactoryToRendererMap("CLI") { map -> map.put(CLI_COMPILER_PLUGIN_IS_EXPERIMENTAL, MESSAGE_PLACEHOLDER) + map.put(CLI_OPT_IN_REQUIREMENT_MARKER_IS_UNRESOLVED, MESSAGE_PLACEHOLDER) + map.put(CLI_NOT_AN_OPT_IN_REQUIREMENT_MARKER, MESSAGE_PLACEHOLDER) + map.put(CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED, MESSAGE_PLACEHOLDER) + map.put(CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED_ERROR, MESSAGE_PLACEHOLDER) } } \ No newline at end of file diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/BaseDiagnosticsCollector.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/BaseDiagnosticsCollector.kt index a12c203588d68..4a9a1a15b04a3 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/BaseDiagnosticsCollector.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/BaseDiagnosticsCollector.kt @@ -24,10 +24,6 @@ abstract class BaseDiagnosticsCollector : DiagnosticReporter() { fun report(message: String, severity: CompilerMessageSeverity) - fun reportWarning(message: String) { - report(message, CompilerMessageSeverity.WARNING) - } - fun reportError(message: String) { report(message, CompilerMessageSeverity.ERROR) } diff --git a/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.args b/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.args index cbb857714768c..f662e8973336c 100644 --- a/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.args +++ b/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.args @@ -4,4 +4,5 @@ $TEMP_DIR$ -cp $TESTDATA_DIR$/../../../../dist/common/kotlin-stdlib-common.klib -Xtarget-platform=JVM,JS,WasmJs,WasmWasi,Native --opt-in=Error \ No newline at end of file +-opt-in=Error +-Xwarning-level=CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED_ERROR\:disabled \ No newline at end of file diff --git a/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.out b/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.out index e2ddfe549d5db..4b0c44c277868 100644 --- a/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.out +++ b/compiler/testData/cli/metadata/optInErrorIsNotSuppressible.out @@ -1,2 +1,2 @@ -error: opt-in requirement marker Error is deprecated. Error +error: diagnostic "CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED_ERROR" is an error. Changing the severity of errors is prohibited COMPILATION_ERROR diff --git a/compiler/testData/cli/metadata/optInWarningsAreDisabled.args b/compiler/testData/cli/metadata/optInWarningsAreDisabled.args index 2180aab15c1c3..fb93f70aa2142 100644 --- a/compiler/testData/cli/metadata/optInWarningsAreDisabled.args +++ b/compiler/testData/cli/metadata/optInWarningsAreDisabled.args @@ -8,4 +8,7 @@ $TESTDATA_DIR$/../../../../dist/common/kotlin-stdlib-common.klib -opt-in=NotAnAnnotation -opt-in=kotlin.RequiresOptIn -opt-in=Warning --Werror \ No newline at end of file +-Werror +-Xwarning-level=CLI_OPT_IN_REQUIREMENT_MARKER_IS_UNRESOLVED\:disabled +-Xwarning-level=CLI_NOT_AN_OPT_IN_REQUIREMENT_MARKER\:disabled +-Xwarning-level=CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED\:disabled \ No newline at end of file diff --git a/compiler/testData/cli/metadata/optInWarningsAreDisabled.out b/compiler/testData/cli/metadata/optInWarningsAreDisabled.out index 0111eb983bc64..d86bac9de59ab 100644 --- a/compiler/testData/cli/metadata/optInWarningsAreDisabled.out +++ b/compiler/testData/cli/metadata/optInWarningsAreDisabled.out @@ -1,5 +1 @@ -warning: opt-in requirement marker Unresolved is unresolved. Please make sure it's present in the module dependencies -warning: class NotAnAnnotation is not an opt-in requirement marker -warning: opt-in requirement marker Warning is deprecated. Warning -error: warnings found and -Werror specified -COMPILATION_ERROR +OK diff --git a/compiler/testData/cli/metadata/optInWarningsAsErrors.args b/compiler/testData/cli/metadata/optInWarningsAsErrors.args index 8a70a217f3f27..38f6c87f2f16e 100644 --- a/compiler/testData/cli/metadata/optInWarningsAsErrors.args +++ b/compiler/testData/cli/metadata/optInWarningsAsErrors.args @@ -7,4 +7,7 @@ $TESTDATA_DIR$/../../../../dist/common/kotlin-stdlib-common.klib -opt-in=Unresolved -opt-in=NotAnAnnotation -opt-in=kotlin.RequiresOptIn --opt-in=Warning \ No newline at end of file +-opt-in=Warning +-Xwarning-level=CLI_OPT_IN_REQUIREMENT_MARKER_IS_UNRESOLVED\:error +-Xwarning-level=CLI_NOT_AN_OPT_IN_REQUIREMENT_MARKER\:error +-Xwarning-level=CLI_OPT_IN_REQUIREMENT_MARKER_IS_DEPRECATED\:error \ No newline at end of file diff --git a/compiler/testData/cli/metadata/optInWarningsAsErrors.out b/compiler/testData/cli/metadata/optInWarningsAsErrors.out index 9a33ddfcc8e3d..e665f8164ab16 100644 --- a/compiler/testData/cli/metadata/optInWarningsAsErrors.out +++ b/compiler/testData/cli/metadata/optInWarningsAsErrors.out @@ -1,4 +1,4 @@ -warning: opt-in requirement marker Unresolved is unresolved. Please make sure it's present in the module dependencies -warning: class NotAnAnnotation is not an opt-in requirement marker -warning: opt-in requirement marker Warning is deprecated. Warning -OK +error: opt-in requirement marker Unresolved is unresolved. Please make sure it's present in the module dependencies +error: class NotAnAnnotation is not an opt-in requirement marker +error: opt-in requirement marker Warning is deprecated. Warning +COMPILATION_ERROR