diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt index 9fa9862c191..2cc78186c7b 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.kt @@ -317,6 +317,12 @@ abstract class CommonCompilerArguments : CommonToolArguments() { ) var useFir: Boolean by FreezableVar(false) + @Argument( + value = "-Xuse-fir-extended-checkers", + description = "Use extended analysis mode based on Front-end IR. Warning: this feature is far from being production-ready" + ) + var useFirExtendedCheckers: Boolean by FreezableVar(false) + @Argument( value = "-Xuse-mixed-named-arguments", description = "Enable Support named arguments in their own position even if the result appears as mixed" diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/arguments.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/arguments.kt index 272809785ca..e457826ed7c 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/arguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/arguments.kt @@ -23,6 +23,7 @@ fun CompilerConfiguration.setupCommonArguments( ) { put(CommonConfigurationKeys.DISABLE_INLINE, arguments.noInline) put(CommonConfigurationKeys.USE_FIR, arguments.useFir) + put(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS, arguments.useFirExtendedCheckers) put(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER, arguments.expectActualLinker) putIfNotNull(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, arguments.intellijPluginRoot) put(CommonConfigurationKeys.REPORT_OUTPUT_FILES, arguments.reportOutputFiles) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index 7af52d8b7c3..4dea7284200 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -58,6 +58,7 @@ import org.jetbrains.kotlin.fir.FirPsiSourceElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector import org.jetbrains.kotlin.fir.analysis.diagnostics.* +import org.jetbrains.kotlin.fir.analysis.registerExtendedCheckersComponent import org.jetbrains.kotlin.fir.backend.Fir2IrConverter import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver import org.jetbrains.kotlin.fir.backend.jvm.FirJvmClassCodegen @@ -198,7 +199,8 @@ object KotlinToJVMBytecodeCompiler { val projectConfiguration = environment.configuration if (projectConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR)) { - return compileModulesUsingFrontendIR(environment, buildFile, chunk) + val extendedAnalysisMode = projectConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS) + return compileModulesUsingFrontendIR(environment, buildFile, chunk, extendedAnalysisMode) } val result = repeatAnalysisIfNeeded(analyze(environment), environment) @@ -306,7 +308,12 @@ object KotlinToJVMBytecodeCompiler { configuration.addAll(JVMConfigurationKeys.MODULES, chunk) } - private fun compileModulesUsingFrontendIR(environment: KotlinCoreEnvironment, buildFile: File?, chunk: List): Boolean { + private fun compileModulesUsingFrontendIR( + environment: KotlinCoreEnvironment, + buildFile: File?, + chunk: List, + extendedAnalysisMode: Boolean + ): Boolean { val project = environment.project val performanceManager = environment.configuration.get(CLIConfigurationKeys.PERF_MANAGER) @@ -355,6 +362,9 @@ object KotlinToJVMBytecodeCompiler { project, environment.createPackagePartProvider(librariesScope) ) it.extensionService.registerExtensions(BunchOfRegisteredExtensions.empty()) + if (extendedAnalysisMode) { + it.registerExtendedCheckersComponent() + } } val firProvider = (session.firProvider as FirProviderImpl) val builder = RawFirBuilder(session, firProvider.kotlinScopeProvider, stubMode = false) diff --git a/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt b/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt index cef760c0c95..ff209598803 100644 --- a/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt +++ b/compiler/config/src/org/jetbrains/kotlin/config/CommonConfigurationKeys.kt @@ -50,6 +50,9 @@ object CommonConfigurationKeys { @JvmField val DESERIALIZE_FAKE_OVERRIDES = CompilerConfigurationKey.create("Deserialize fake overrides") + + @JvmField + val USE_FIR_EXTENDED_CHECKERS = CompilerConfigurationKey.create("fir extended checkers") } var CompilerConfiguration.languageVersionSettings: LanguageVersionSettings diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt index d2abed004b6..231c910a4a8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/CheckersComponent.kt @@ -52,6 +52,11 @@ fun FirSession.registerCheckersComponent() { register(CheckersComponent::class, CheckersComponent.componentWithDefaultCheckers()) } +fun FirSession.registerExtendedCheckersComponent() { + this.checkersComponent.register(ExtendedExpressionCheckers) + this.checkersComponent.register(ExtendedDeclarationCheckers) +} + private class ComposedDeclarationCheckers : DeclarationCheckers() { override val fileCheckers: List get() = _fileCheckers diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index e572aa5b90e..f65fe522952 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -286,17 +286,17 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { map.put(FirErrors.WRONG_IMPLIES_CONDITION, "Wrong implies condition") // Extended checkers group - map.put(REDUNDANT_VISIBILITY_MODIFIER, "redundant visibility modifier") - map.put(REDUNDANT_MODALITY_MODIFIER, "redundant modality modifier") - map.put(REDUNDANT_RETURN_UNIT_TYPE, "redundant return 'unit' type") - map.put(REDUNDANT_EXPLICIT_TYPE, "redundant explicit type") - map.put(REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE, "redundant string template") + map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier") + map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier") + map.put(REDUNDANT_RETURN_UNIT_TYPE, "Redundant return 'unit' type") + map.put(REDUNDANT_EXPLICIT_TYPE, "Redundant explicit type") + map.put(REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE, "Redundant string template") map.put(CAN_BE_VAL, "'var' can be 'val'") - map.put(CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT, "assignment can be replaced with operator assignment") - map.put(REDUNDANT_CALL_OF_CONVERSION_METHOD, "redundant call of conversion method") + map.put(CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT, "Assignment can be replaced with operator assignment") + map.put(REDUNDANT_CALL_OF_CONVERSION_METHOD, "Redundant call of conversion method") map.put(ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS, "Replace '==' with 'Arrays.equals'") - map.put(EMPTY_RANGE, "range is empty") - map.put(REDUNDANT_SETTER_PARAMETER_TYPE, "redundant setter parameter type") + map.put(EMPTY_RANGE, "Range is empty") + map.put(REDUNDANT_SETTER_PARAMETER_TYPE, "Redundant setter parameter type") } } } diff --git a/compiler/testData/cli/js/jsExtraHelp.out b/compiler/testData/cli/js/jsExtraHelp.out index 0dfae5897bb..14d2f4cdcae 100644 --- a/compiler/testData/cli/js/jsExtraHelp.out +++ b/compiler/testData/cli/js/jsExtraHelp.out @@ -70,6 +70,7 @@ where advanced options include: -Xskip-prerelease-check Allow to load pre-release classes -Xuse-experimental= Enable, but don't propagate usages of experimental API for marker annotation with the given fully qualified name -Xuse-fir Compile using Front-end IR. Warning: this feature is far from being production-ready + -Xuse-fir-extended-checkers Use extended analysis mode based on Front-end IR. Warning: this feature is far from being production-ready -Xuse-mixed-named-arguments Enable Support named arguments in their own position even if the result appears as mixed -Xverbose-phases Be verbose while performing these backend phases diff --git a/compiler/testData/cli/jvm/extendedCheckers.args b/compiler/testData/cli/jvm/extendedCheckers.args new file mode 100644 index 00000000000..730e0e1a775 --- /dev/null +++ b/compiler/testData/cli/jvm/extendedCheckers.args @@ -0,0 +1,5 @@ +$TESTDATA_DIR$/extendedCheckers.kt +-Xuse-fir +-Xuse-fir-extended-checkers +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/extendedCheckers.kt b/compiler/testData/cli/jvm/extendedCheckers.kt new file mode 100644 index 00000000000..098506bf41f --- /dev/null +++ b/compiler/testData/cli/jvm/extendedCheckers.kt @@ -0,0 +1,3 @@ +fun foo() { + val i: Int = 1 +} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/extendedCheckers.out b/compiler/testData/cli/jvm/extendedCheckers.out new file mode 100644 index 00000000000..892c5a5f895 --- /dev/null +++ b/compiler/testData/cli/jvm/extendedCheckers.out @@ -0,0 +1,4 @@ +compiler/testData/cli/jvm/extendedCheckers.kt:2:12: warning: redundant explicit type + val i: Int = 1 + ^ +OK diff --git a/compiler/testData/cli/jvm/extendedCheckersNoWarning.args b/compiler/testData/cli/jvm/extendedCheckersNoWarning.args new file mode 100644 index 00000000000..e75708410b4 --- /dev/null +++ b/compiler/testData/cli/jvm/extendedCheckersNoWarning.args @@ -0,0 +1,5 @@ +$TESTDATA_DIR$/extendedCheckersNoWarning.kt +-Xuse-fir +-Xuse-fir-extended-checkers +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/extendedCheckersNoWarning.kt b/compiler/testData/cli/jvm/extendedCheckersNoWarning.kt new file mode 100644 index 00000000000..c5c56521d12 --- /dev/null +++ b/compiler/testData/cli/jvm/extendedCheckersNoWarning.kt @@ -0,0 +1,3 @@ +fun foo() { + val s = "Say 'Hi!' to extended checkers" +} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/extendedCheckersNoWarning.out b/compiler/testData/cli/jvm/extendedCheckersNoWarning.out new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/cli/jvm/extendedCheckersNoWarning.out @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index 8fdb07e071c..56b149d7a2f 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -153,6 +153,7 @@ where advanced options include: -Xskip-prerelease-check Allow to load pre-release classes -Xuse-experimental= Enable, but don't propagate usages of experimental API for marker annotation with the given fully qualified name -Xuse-fir Compile using Front-end IR. Warning: this feature is far from being production-ready + -Xuse-fir-extended-checkers Use extended analysis mode based on Front-end IR. Warning: this feature is far from being production-ready -Xuse-mixed-named-arguments Enable Support named arguments in their own position even if the result appears as mixed -Xverbose-phases Be verbose while performing these backend phases diff --git a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java index 1c3cc5be89b..be7b7c7e445 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -250,6 +250,16 @@ public class CliTestGenerated extends AbstractCliTest { runTest("compiler/testData/cli/jvm/expression1.args"); } + @TestMetadata("extendedCheckers.args") + public void testExtendedCheckers() throws Exception { + runTest("compiler/testData/cli/jvm/extendedCheckers.args"); + } + + @TestMetadata("extendedCheckersNoWarning.args") + public void testExtendedCheckersNoWarning() throws Exception { + runTest("compiler/testData/cli/jvm/extendedCheckersNoWarning.args"); + } + @TestMetadata("extraArgumentPassedInObsoleteForm.args") public void testExtraArgumentPassedInObsoleteForm() throws Exception { runTest("compiler/testData/cli/jvm/extraArgumentPassedInObsoleteForm.args");