diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_class_modifier.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_class_modifier.dart index 6dfb3795cfb..68ed2ddd17a 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/add_class_modifier.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/add_class_modifier.dart @@ -9,26 +9,43 @@ import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dar import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; class AddClassModifier extends ResolvedCorrectionProducer { - final String _modifier; + final String modifier; - AddClassModifier.base({required CorrectionProducerContext context}) - : this._('base', context: context); + @override + final FixKind fixKind; - AddClassModifier._(this._modifier, {required super.context}); + @override + final FixKind multiFixKind; + + AddClassModifier.baseModifier({required CorrectionProducerContext context}) + : this._( + context: context, + modifier: 'base', + fixKind: DartFixKind.ADD_CLASS_MODIFIER_BASE, + multiFixKind: DartFixKind.ADD_CLASS_MODIFIER_BASE_MULTI); + AddClassModifier.finalModifier({required CorrectionProducerContext context}) + : this._( + context: context, + modifier: 'final', + fixKind: DartFixKind.ADD_CLASS_MODIFIER_FINAL, + multiFixKind: DartFixKind.ADD_CLASS_MODIFIER_FINAL_MULTI); + AddClassModifier.sealedModifier({required CorrectionProducerContext context}) + : this._( + context: context, + modifier: 'sealed', + fixKind: DartFixKind.ADD_CLASS_MODIFIER_SEALED, + multiFixKind: DartFixKind.ADD_CLASS_MODIFIER_SEALED_MULTI); + + AddClassModifier._( + {required super.context, + required this.modifier, + required this.fixKind, + required this.multiFixKind}); @override CorrectionApplicability get applicability => CorrectionApplicability.acrossSingleFile; - @override - List get fixArguments => [_modifier]; - - @override - FixKind get fixKind => DartFixKind.ADD_CLASS_MODIFIER; - - @override - FixKind get multiFixKind => DartFixKind.ADD_CLASS_MODIFIER_MULTI; - @override Future compute(ChangeBuilder builder) async { var node = this.node; @@ -36,7 +53,7 @@ class AddClassModifier extends ResolvedCorrectionProducer { await builder.addDartFileEdit(file, (builder) { builder.addSimpleInsertion( - node.firstTokenAfterCommentAndMetadata.offset, '$_modifier '); + node.firstTokenAfterCommentAndMetadata.offset, '$modifier '); }); } } diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml index 5615fe9000d..dcf2219c087 100644 --- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml +++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml @@ -45,8 +45,8 @@ # # Stats: # - 42 "needsEvaluation" -# - 321 "needsFix" -# - 426 "hasFix" +# - 318 "needsFix" +# - 429 "hasFix" # - 517 "noFix" AnalysisOptionsErrorCode.INCLUDED_FILE_PARSE_ERROR: @@ -1457,13 +1457,9 @@ CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY: CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER: status: noFix CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED: - status: needsFix - notes: |- - Add `base`, `final`, or `sealed`. + status: hasFix CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED: - status: needsFix - notes: |- - Add `base`, `final`, or `sealed`. + status: hasFix CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED: status: hasFix since: 2.17 diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart index e72157fee30..a70292a5016 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix.dart @@ -61,15 +61,35 @@ class DartFixKind { DartFixKindPriority.IN_FILE, 'Add empty argument lists everywhere in file', ); - static const ADD_CLASS_MODIFIER = FixKind( - 'dart.fix.add.class.modifier', + static const ADD_CLASS_MODIFIER_BASE = FixKind( + 'dart.fix.add.class.modifier.base', DartFixKindPriority.DEFAULT, - "Add ''{0}'' modifier", + "Add 'base' modifier", ); - static const ADD_CLASS_MODIFIER_MULTI = FixKind( - 'dart.fix.add.class.modifier.multi', + static const ADD_CLASS_MODIFIER_BASE_MULTI = FixKind( + 'dart.fix.add.class.modifier.base.multi', DartFixKindPriority.IN_FILE, - "Add ''{0}'' modifier everywhere in file", + "Add 'base' modifier everywhere in file", + ); + static const ADD_CLASS_MODIFIER_FINAL = FixKind( + 'dart.fix.add.class.modifier.final', + DartFixKindPriority.DEFAULT, + "Add 'final' modifier", + ); + static const ADD_CLASS_MODIFIER_FINAL_MULTI = FixKind( + 'dart.fix.add.class.modifier.final.multi', + DartFixKindPriority.IN_FILE, + "Add 'final' modifier everywhere in file", + ); + static const ADD_CLASS_MODIFIER_SEALED = FixKind( + 'dart.fix.add.class.modifier.sealed', + DartFixKindPriority.DEFAULT, + "Add 'sealed' modifier", + ); + static const ADD_CLASS_MODIFIER_SEALED_MULTI = FixKind( + 'dart.fix.add.class.modifier.sealed.multi', + DartFixKindPriority.IN_FILE, + "Add 'sealed' modifier everywhere in file", ); static const ADD_CONST = FixKind( 'dart.fix.add.const', diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart index 7853aed5e71..87cf2e6e08c 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart @@ -1072,10 +1072,10 @@ final _builtInNonLintProducers = >{ RemoveExtendsClause.new, ], CompileTimeErrorCode.MIXIN_SUBTYPE_OF_BASE_IS_NOT_BASE: [ - AddClassModifier.base, + AddClassModifier.baseModifier, ], CompileTimeErrorCode.MIXIN_SUBTYPE_OF_FINAL_IS_NOT_BASE: [ - AddClassModifier.base, + AddClassModifier.baseModifier, ], CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS: [ RemoveNameFromDeclarationClause.new, @@ -1185,6 +1185,16 @@ final _builtInNonLintProducers = >{ MakeReturnTypeNullable.new, ReplaceReturnType.new, ], + CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED: [ + AddClassModifier.baseModifier, + AddClassModifier.finalModifier, + AddClassModifier.sealedModifier, + ], + CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED: [ + AddClassModifier.baseModifier, + AddClassModifier.finalModifier, + AddClassModifier.sealedModifier, + ], CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED: [ RemoveTypeAnnotation.other, diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_class_modifier_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_class_modifier_test.dart index 8f0f4ef3496..be322fab0d4 100644 --- a/pkg/analysis_server/test/src/services/correction/fix/add_class_modifier_test.dart +++ b/pkg/analysis_server/test/src/services/correction/fix/add_class_modifier_test.dart @@ -10,14 +10,16 @@ import 'fix_processor.dart'; void main() { defineReflectiveSuite(() { - defineReflectiveTests(AddClassModifierTest); + defineReflectiveTests(AddClassModifierBaseTest); + defineReflectiveTests(AddClassModifierFinalTest); + defineReflectiveTests(AddClassModifierSealedTest); }); } @reflectiveTest -class AddClassModifierTest extends FixProcessorTest { +class AddClassModifierBaseTest extends FixProcessorTest { @override - FixKind get kind => DartFixKind.ADD_CLASS_MODIFIER; + FixKind get kind => DartFixKind.ADD_CLASS_MODIFIER_BASE; Future test_mixinSubtypeOfBaseIsNotBase() async { await resolveTestCode(''' @@ -51,6 +53,84 @@ mixin B implements A {} await assertHasFix(''' final class A {} base mixin B implements A {} +'''); + } + + Future test_subtypeOfBaseIsNotBaseFinalOrSealed() async { + await resolveTestCode(''' +base class A {} +class B extends A {} +'''); + await assertHasFix(''' +base class A {} +base class B extends A {} +'''); + } + + Future test_subtypeOfFinalIsNotBaseFinalOrSealed() async { + await resolveTestCode(''' +final class A {} +class B extends A {} +'''); + await assertHasFix(''' +final class A {} +base class B extends A {} +'''); + } +} + +@reflectiveTest +class AddClassModifierFinalTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_CLASS_MODIFIER_FINAL; + + Future test_subtypeOfBaseIsNotBaseFinalOrSealed() async { + await resolveTestCode(''' +base class A {} +class B extends A {} +'''); + await assertHasFix(''' +base class A {} +final class B extends A {} +'''); + } + + Future test_subtypeOfFinalIsNotBaseFinalOrSealed() async { + await resolveTestCode(''' +final class A {} +class B extends A {} +'''); + await assertHasFix(''' +final class A {} +final class B extends A {} +'''); + } +} + +@reflectiveTest +class AddClassModifierSealedTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.ADD_CLASS_MODIFIER_SEALED; + + Future test_subtypeOfBaseIsNotBaseFinalOrSealed() async { + await resolveTestCode(''' +base class A {} +class B extends A {} +'''); + await assertHasFix(''' +base class A {} +sealed class B extends A {} +'''); + } + + Future test_subtypeOfFinalIsNotBaseFinalOrSealed() async { + await resolveTestCode(''' +final class A {} +class B extends A {} +'''); + await assertHasFix(''' +final class A {} +sealed class B extends A {} '''); } }