diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt index 21774e03b98..38220fd4bfe 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionFactory.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.analysis.providers.createAnnotationResolver import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider import org.jetbrains.kotlin.analysis.providers.createPackageProvider import org.jetbrains.kotlin.analysis.utils.errors.checkIsInstance +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.fir.* @@ -81,7 +82,17 @@ internal object LLFirSessionFactory { configureSession: (LLFirSession.() -> Unit)? = null ): LLFirSourcesSession { sessionsCache[module]?.let { return it as LLFirSourcesSession } - val languageVersionSettings = module.languageVersionSettings + val languageVersionSettings = object : LanguageVersionSettings by module.languageVersionSettings { + override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State = + if (feature == LanguageFeature.EnableDfaWarningsInK2) LanguageFeature.State.ENABLED + else module.languageVersionSettings.getFeatureSupport(feature) + + override fun supportsFeature(feature: LanguageFeature): Boolean = + getFeatureSupport(feature).let { + it == LanguageFeature.State.ENABLED || it == LanguageFeature.State.ENABLED_WITH_WARNING + } + } + val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped) val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt index 3a5c803c502..8d22b002df4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirTopLevelPropertiesChecker.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.reportOn @@ -163,7 +164,9 @@ internal fun checkPropertyInitializer( } // TODO: like [BindingContext.MUST_BE_LATEINIT], we should consider variable with uninitialized error. if (backingFieldRequired && !inInterface && isInitialized) { - reporter.reportOn(propertySource, FirErrors.UNNECESSARY_LATEINIT, context) + if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) { + reporter.reportOn(propertySource, FirErrors.UNNECESSARY_LATEINIT, context) + } } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt index 94d5b9ee7d9..f6bbf6277d2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt @@ -5,6 +5,7 @@ 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.CastingType @@ -34,9 +35,13 @@ object FirCastOperatorsChecker : FirTypeOperatorCallChecker() { if (expression.operation == FirOperation.AS || isSafeAs) { val castType = checkCasting(actualType, targetType, isSafeAs, context) if (castType == CastingType.Impossible) { - reporter.reportOn(expression.source, FirErrors.CAST_NEVER_SUCCEEDS, context) + if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) { + reporter.reportOn(expression.source, FirErrors.CAST_NEVER_SUCCEEDS, context) + } } else if (castType == CastingType.Always) { - reporter.reportOn(expression.source, FirErrors.USELESS_CAST, context) + if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) { + reporter.reportOn(expression.source, FirErrors.USELESS_CAST, context) + } } else if (isCastErased(actualType, targetType, context)) { reporter.reportOn(expression.source, FirErrors.UNCHECKED_CAST, actualType, targetType, context) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNotNullAssertionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNotNullAssertionChecker.kt index 367331dc899..14982b331b2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNotNullAssertionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNotNullAssertionChecker.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors @@ -36,7 +37,7 @@ object FirNotNullAssertionChecker : FirCheckNotNullCallChecker() { val type = argument.typeRef.coneType.fullyExpandedType(context.session) - if (!type.canBeNull) { + if (!type.canBeNull && context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) { reporter.reportOn(expression.source, FirErrors.UNNECESSARY_NOT_NULL_ASSERTION, type, context) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnnecessarySafeCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnnecessarySafeCallChecker.kt index b7bc5d7309a..246ad63df73 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnnecessarySafeCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUnnecessarySafeCallChecker.kt @@ -26,7 +26,9 @@ object FirUnnecessarySafeCallChecker : FirSafeCallExpressionChecker() { return } if (!receiverType.canBeNull) { - reporter.reportOn(expression.source, FirErrors.UNNECESSARY_SAFE_CALL, receiverType, context) + if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) { + reporter.reportOn(expression.source, FirErrors.UNNECESSARY_SAFE_CALL, receiverType, context) + } if (!context.session.languageVersionSettings.supportsFeature(LanguageFeature.SafeCallsAreAlwaysNullable)) { reporter.reportOn(expression.source, FirErrors.SAFE_CALL_WILL_CHANGE_NULLABILITY, context) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUselessElvisChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUselessElvisChecker.kt index c1053e5fef3..d4f2a03e1e3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUselessElvisChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUselessElvisChecker.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors @@ -25,12 +26,16 @@ object FirUselessElvisChecker : FirElvisExpressionChecker() { val lhsType = expression.lhs.typeRef.coneType if (lhsType is ConeErrorType) return if (!lhsType.canBeNull) { - reporter.reportOn(expression.source, FirErrors.USELESS_ELVIS, lhsType, context) + if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) { + reporter.reportOn(expression.source, FirErrors.USELESS_ELVIS, lhsType, context) + } return } if (expression.rhs.isNullLiteral) { - reporter.reportOn(expression.source, FirErrors.USELESS_ELVIS_RIGHT_IS_NULL, context) + if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) { + reporter.reportOn(expression.source, FirErrors.USELESS_ELVIS_RIGHT_IS_NULL, context) + } } } } diff --git a/compiler/testData/cli/jvm/firDfa.args b/compiler/testData/cli/jvm/firDfa.args new file mode 100644 index 00000000000..876d1339bf6 --- /dev/null +++ b/compiler/testData/cli/jvm/firDfa.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/firDfa.kt +-Xuse-k2 +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/firDfa.kt b/compiler/testData/cli/jvm/firDfa.kt new file mode 100644 index 00000000000..a8b07438913 --- /dev/null +++ b/compiler/testData/cli/jvm/firDfa.kt @@ -0,0 +1,5 @@ +fun foo(x: String?) { + if (x != null) { + x!!.length + } +} diff --git a/compiler/testData/cli/jvm/firDfa.out b/compiler/testData/cli/jvm/firDfa.out new file mode 100644 index 00000000000..ffcff5c3b33 --- /dev/null +++ b/compiler/testData/cli/jvm/firDfa.out @@ -0,0 +1,4 @@ +warning: ATTENTION! + This build uses experimental K2 compiler: + -Xuse-k2 +OK diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/builders/RegisteredDirectivesBuilder.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/builders/RegisteredDirectivesBuilder.kt index 7e91a3e4a0f..ad65903cc4b 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/builders/RegisteredDirectivesBuilder.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/builders/RegisteredDirectivesBuilder.kt @@ -28,6 +28,11 @@ class RegisteredDirectivesBuilder { stringDirectives.putWithExistsCheck(this, values) } + operator fun StringDirective.plus(value: String) { + val previous = stringDirectives[this] ?: listOf() + stringDirectives[this] = previous + value + } + operator fun StringDirective.unaryMinus() { stringDirectives.remove(this) } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt index e818e277d9f..e96c42b1599 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt @@ -143,13 +143,17 @@ fun TestConfigurationBuilder.baseFirDiagnosticTestConfiguration( forTestsMatching("compiler/fir/analysis-tests/testData/resolveWithStdlib/properties/backingField/*") { defaultDirectives { - LANGUAGE with "+ExplicitBackingFields" + LANGUAGE + "+ExplicitBackingFields" } } forTestsMatching("compiler/testData/diagnostics/tests/multiplatform/*") { defaultDirectives { - LANGUAGE with "+MultiPlatformProjects" + LANGUAGE + "+MultiPlatformProjects" } } + + defaultDirectives { + LANGUAGE + "+EnableDfaWarningsInK2" + } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirForeignAnnotationsTest.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirForeignAnnotationsTest.kt index e623b045f54..590359d225a 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirForeignAnnotationsTest.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirForeignAnnotationsTest.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.configureFirHandlersStep import org.jetbrains.kotlin.test.builders.firFrontendStep import org.jetbrains.kotlin.test.builders.firHandlersStep +import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives import org.jetbrains.kotlin.test.frontend.classic.handlers.FirJspecifyDiagnosticComplianceHandler import org.jetbrains.kotlin.test.frontend.fir.FirFailingTestSuppressor import org.jetbrains.kotlin.test.frontend.fir.handlers.* @@ -22,6 +23,10 @@ abstract class AbstractFirForeignAnnotationsTestBase(kind: ForeignAnnotationsTes frontend = FrontendKinds.FIR } + defaultDirectives { + LanguageSettingsDirectives.LANGUAGE with "+EnableDfaWarningsInK2" + } + useMetaInfoProcessors(::PsiLightTreeMetaInfoProcessor) firFrontendStep() firHandlersStep { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java index 2018b9fa35d..46c09948989 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -364,6 +364,11 @@ public class CliTestGenerated extends AbstractCliTest { runTest("compiler/testData/cli/jvm/fileClassClashMultipleFiles.args"); } + @TestMetadata("firDfa.args") + public void testFirDfa() throws Exception { + runTest("compiler/testData/cli/jvm/firDfa.args"); + } + @TestMetadata("firError.args") public void testFirError() throws Exception { runTest("compiler/testData/cli/jvm/firError.args"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 4612ac7c422..690f92c703a 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -261,6 +261,7 @@ enum class LanguageFeature( ForbidUsingExtensionPropertyTypeParameterInDelegate(KOTLIN_1_8, kind = BUG_FIX), ModifierNonBuiltinSuspendFunError(KOTLIN_1_8), SynchronizedSuspendError(KOTLIN_1_8), + EnableDfaWarningsInK2(KOTLIN_1_8, kind = OTHER), // KT-50965 // 1.9