From 06d2befb726511fa91e5663d3c0adbe06b00c392 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Mon, 24 Jul 2023 15:53:15 +0200 Subject: [PATCH] [FIR] Implement DATA_CLASS_OVERRIDE_DEFAULT_VALUES diagnostic #KT-59415 Fixed --- .../fir/diagnostics/KtFirDataClassConverters.kt | 8 ++++++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 6 ++++++ .../api/fir/diagnostics/KtFirDiagnosticsImpl.kt | 7 +++++++ .../generator/diagnostics/FirDiagnosticsList.kt | 5 +++++ .../kotlin/fir/analysis/diagnostics/FirErrors.kt | 1 + .../checkers/declaration/FirOverrideChecker.kt | 16 ++++++++++++++++ .../diagnostics/FirErrorsDefaultMessages.kt | 7 +++++++ .../codegen/box/dataClasses/copy/kt12708.kt | 2 ++ ...lassExplicitlyOverridingCopyNoDefaults.fir.kt | 4 ++-- ...ssExplicitlyOverridingCopyWithDefaults.fir.kt | 2 +- .../dataClassOverridingCopy_lv12.fir.kt | 2 +- .../dataClassOverridingCopy_lv13.fir.kt | 2 +- 12 files changed, 57 insertions(+), 5 deletions(-) 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 f77ff7c43bf..e661e47a6c7 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 @@ -2463,6 +2463,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.DATA_CLASS_OVERRIDE_DEFAULT_VALUES) { firDiagnostic -> + DataClassOverrideDefaultValuesImpl( + firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a), + firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.b), + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.CANNOT_WEAKEN_ACCESS_PRIVILEGE) { firDiagnostic -> CannotWeakenAccessPrivilegeImpl( firDiagnostic.a, 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 a831038ceb5..c268e869dfd 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 @@ -1747,6 +1747,12 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { val baseMember: KtCallableSymbol } + interface DataClassOverrideDefaultValues : KtFirDiagnostic { + override val diagnosticClass get() = DataClassOverrideDefaultValues::class + val overridingMember: KtCallableSymbol + val baseType: KtClassLikeSymbol + } + interface CannotWeakenAccessPrivilege : KtFirDiagnostic { override val diagnosticClass get() = CannotWeakenAccessPrivilege::class val overridingVisibility: Visibility 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 b4f97b6d928..bc10e910081 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 @@ -2100,6 +2100,13 @@ internal class DataClassOverrideConflictImpl( token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.DataClassOverrideConflict +internal class DataClassOverrideDefaultValuesImpl( + override val overridingMember: KtCallableSymbol, + override val baseType: KtClassLikeSymbol, + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.DataClassOverrideDefaultValues + internal class CannotWeakenAccessPrivilegeImpl( override val overridingVisibility: Visibility, override val overridden: KtCallableSymbol, 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 4c04f466bc3..335cdc66852 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 @@ -823,6 +823,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter>("baseMember") } + val DATA_CLASS_OVERRIDE_DEFAULT_VALUES by error(PositioningStrategy.DATA_MODIFIER) { + parameter>("overridingMember") + parameter>("baseType") + } + val CANNOT_WEAKEN_ACCESS_PRIVILEGE by error(PositioningStrategy.VISIBILITY_MODIFIER) { parameter("overridingVisibility") parameter>("overridden") 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 492a80119ea..eed7de0956c 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 @@ -468,6 +468,7 @@ object FirErrors { val NOTHING_TO_OVERRIDE by error1>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER) val CANNOT_OVERRIDE_INVISIBLE_MEMBER by error2, FirCallableSymbol<*>>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER) val DATA_CLASS_OVERRIDE_CONFLICT by error2, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DATA_MODIFIER) + val DATA_CLASS_OVERRIDE_DEFAULT_VALUES by error2, FirClassSymbol<*>>(SourceElementPositioningStrategies.DATA_MODIFIER) val CANNOT_WEAKEN_ACCESS_PRIVILEGE by error3, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val CANNOT_CHANGE_ACCESS_PRIVILEGE by error3, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val OVERRIDING_FINAL_MEMBER by error2, Name>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt index bb37eb6e869..0a35a6fe9a6 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirOverrideChecker.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtRealSourceElementKind +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.diagnostics.DiagnosticReporter @@ -14,6 +15,7 @@ import org.jetbrains.kotlin.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirOptInUsageBaseChecker.Experimentality +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.overridesBackwardCompatibilityHelper @@ -230,6 +232,17 @@ object FirOverrideChecker : FirClassChecker() { } } + private fun FirCallableSymbol<*>.checkDataClassCopy( + reporter: DiagnosticReporter, + overriddenMemberSymbols: List>, + containingClass: FirClass, + context: CheckerContext, + ) { + val overridden = overriddenMemberSymbols.firstOrNull() ?: return + val overriddenClass = overridden.getContainingClassSymbol(context.session) as? FirClassSymbol<*> ?: return + reporter.reportOn(containingClass.source, FirErrors.DATA_CLASS_OVERRIDE_DEFAULT_VALUES, this, overriddenClass, context) + } + private fun checkMember( member: FirCallableSymbol<*>, containingClass: FirClass, @@ -259,6 +272,9 @@ object FirOverrideChecker : FirClassChecker() { context ) } + if (member.name == StandardNames.DATA_CLASS_COPY) { + member.checkDataClassCopy(reporter, overriddenMemberSymbols, containingClass, context) + } return } 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 2467179a2b4..46c373798ea 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 @@ -148,6 +148,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CYCLIC_INHERITANC import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DANGEROUS_CHARACTERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_OVERRIDE_CONFLICT +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_OVERRIDE_DEFAULT_VALUES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_VARARG_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_CLASS_WITHOUT_PARAMETERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DATA_OBJECT_CUSTOM_EQUALS_OR_HASH_CODE @@ -1521,6 +1522,12 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { FQ_NAMES_IN_TYPES, FQ_NAMES_IN_TYPES ) + map.put( + DATA_CLASS_OVERRIDE_DEFAULT_VALUES, + "Generated function ''{0}'' of the data class has default values for parameters which conflicts with the overriden member of supertype ''{1}''.", + DECLARATION_NAME, + DECLARATION_NAME + ) map.put( GENERIC_THROWABLE_SUBCLASS, diff --git a/compiler/testData/codegen/box/dataClasses/copy/kt12708.kt b/compiler/testData/codegen/box/dataClasses/copy/kt12708.kt index 7ad1584b800..4e1cdc24c1f 100644 --- a/compiler/testData/codegen/box/dataClasses/copy/kt12708.kt +++ b/compiler/testData/codegen/box/dataClasses/copy/kt12708.kt @@ -1,4 +1,6 @@ // !LANGUAGE: -ProhibitDataClassesOverridingCopy +// IGNORE_BACKEND_K2: ANY +// FIR status: Disabling ProhibitDataClassesOverridingCopy is not supported fun box(): String { val a: A = B(1) diff --git a/compiler/testData/diagnostics/tests/dataClasses/dataClassExplicitlyOverridingCopyNoDefaults.fir.kt b/compiler/testData/diagnostics/tests/dataClasses/dataClassExplicitlyOverridingCopyNoDefaults.fir.kt index f73857723f6..67177e2ebe9 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/dataClassExplicitlyOverridingCopyNoDefaults.fir.kt +++ b/compiler/testData/diagnostics/tests/dataClasses/dataClassExplicitlyOverridingCopyNoDefaults.fir.kt @@ -4,6 +4,6 @@ interface WithCopy { fun copy(str: T): WithCopy } -data class Test(val str: String) : WithCopy { +data class Test(val str: String) : WithCopy { override fun copy(str: String) = Test(str) -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/dataClasses/dataClassExplicitlyOverridingCopyWithDefaults.fir.kt b/compiler/testData/diagnostics/tests/dataClasses/dataClassExplicitlyOverridingCopyWithDefaults.fir.kt index 9a9905684e2..b41114558c9 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/dataClassExplicitlyOverridingCopyWithDefaults.fir.kt +++ b/compiler/testData/diagnostics/tests/dataClasses/dataClassExplicitlyOverridingCopyWithDefaults.fir.kt @@ -4,6 +4,6 @@ interface WithCopy { fun copy(str: T): WithCopy } -data class Test(val str: String) : WithCopy { +data class Test(val str: String) : WithCopy { override fun copy(str: String = this.str) = Test(str) } diff --git a/compiler/testData/diagnostics/tests/dataClasses/dataClassOverridingCopy_lv12.fir.kt b/compiler/testData/diagnostics/tests/dataClasses/dataClassOverridingCopy_lv12.fir.kt index 725649fc673..28953973da3 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/dataClassOverridingCopy_lv12.fir.kt +++ b/compiler/testData/diagnostics/tests/dataClasses/dataClassOverridingCopy_lv12.fir.kt @@ -4,4 +4,4 @@ interface WithCopy { fun copy(str: T): WithCopy } -data class Test(val str: String): WithCopy \ No newline at end of file +data class Test(val str: String): WithCopy diff --git a/compiler/testData/diagnostics/tests/dataClasses/dataClassOverridingCopy_lv13.fir.kt b/compiler/testData/diagnostics/tests/dataClasses/dataClassOverridingCopy_lv13.fir.kt index 78bbb6acfc6..1cedd66c332 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/dataClassOverridingCopy_lv13.fir.kt +++ b/compiler/testData/diagnostics/tests/dataClasses/dataClassOverridingCopy_lv13.fir.kt @@ -4,4 +4,4 @@ interface WithCopy { fun copy(str: T): WithCopy } -data class Test(val str: String): WithCopy \ No newline at end of file +data class Test(val str: String): WithCopy