diff --git a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart index 7be1db5c165..a09c3b72637 100644 --- a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart +++ b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart @@ -232,7 +232,11 @@ class BulkFixProcessor { var analysisOptions = result.session.analysisContext.analysisOptions; for (var unitResult in result.units) { var overrideSet = _readOverrideSet(unitResult); - for (var error in unitResult.errors) { + + var errors = List.from(unitResult.errors, growable: false); + errors.sort((a, b) => a.offset.compareTo(b.offset)); + + for (var error in errors) { var processor = ErrorProcessor.getProcessor(analysisOptions, error); // Only fix errors not filtered out in analysis options. if (processor == null || processor.severity != null) { diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_const.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_const.dart index 3dcb6c7297a..74c7d313a05 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/add_const.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/add_const.dart @@ -8,18 +8,17 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/source/source_range.dart'; +import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart'; import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; class AddConst extends CorrectionProducer { @override - bool canBeAppliedInBulk; + bool get canBeAppliedInBulk => true; @override - bool canBeAppliedToFile; - - AddConst(this.canBeAppliedInBulk, this.canBeAppliedToFile); + bool get canBeAppliedToFile => true; @override FixKind get fixKind => DartFixKind.ADD_CONST; @@ -42,10 +41,29 @@ class AddConst extends CorrectionProducer { return; } + bool isParentConstant( + DartFileEditBuilderImpl builder, Expression targetNode) { + var edits = builder.fileEdit.edits; + var child = targetNode.parent; + while (child is Expression || child is ArgumentList) { + if (edits.any((element) => + element.replacement == 'const ' && + element.offset == child!.offset)) { + return true; + } + child = child!.parent; + } + return false; + } + Future insertAtOffset(Expression targetNode) async { var finder = _ConstRangeFinder(); targetNode.accept(finder); await builder.addDartFileEdit(file, (builder) { + if (builder is DartFileEditBuilderImpl && + isParentConstant(builder, targetNode)) { + return; + } builder.addSimpleInsertion(targetNode.offset, 'const '); for (var range in finder.ranges) { builder.addDeletion(range); @@ -76,16 +94,7 @@ class AddConst extends CorrectionProducer { } /// Return an instance of this class. Used as a tear-off in `FixProcessor`. - static AddConst toDeclaration() => AddConst(true, true); - - /// Return an instance of this class. Used as a tear-off in `FixProcessor`. - // TODO(brianwilkerson) This fix can produce changes that are inconsistent - // with the `unnecessary_const` lint. Fix it and then enable it for both - // uses. - static AddConst toInvocation() => AddConst(false, false); - - /// Return an instance of this class. Used as a tear-off in `FixProcessor`. - static AddConst toLiteral() => AddConst(true, true); + static AddConst newInstance() => AddConst(); } class _ConstRangeFinder extends RecursiveAstVisitor { 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 c99707b5e2f..9f2403c1d3e 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart @@ -441,17 +441,17 @@ class FixProcessor extends BaseProcessor { ReplaceWithConditionalAssignment.newInstance, ], LintNames.prefer_const_constructors: [ - AddConst.toInvocation, + AddConst.newInstance, ReplaceNewWithConst.newInstance, ], LintNames.prefer_const_constructors_in_immutables: [ - AddConst.toDeclaration, + AddConst.newInstance, ], LintNames.prefer_const_declarations: [ ReplaceFinalWithConst.newInstance, ], LintNames.prefer_const_literals_to_create_immutables: [ - AddConst.toLiteral, + AddConst.newInstance, ], LintNames.prefer_contains: [ ConvertToContains.newInstance, diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_const_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_const_test.dart index 5dc2905c5c7..c2f2e4addcb 100644 --- a/pkg/analysis_server/test/src/services/correction/fix/add_const_test.dart +++ b/pkg/analysis_server/test/src/services/correction/fix/add_const_test.dart @@ -26,8 +26,6 @@ class AddConst_PreferConstConstructorsBulkTest extends BulkFixProcessorTest { @override String get lintCode => LintNames.prefer_const_constructors; - /// Disabled in BulkFixProcessor. - @failingTest Future test_noKeyword() async { writeTestPackageConfig(meta: true); await resolveTestCode(r''' @@ -36,12 +34,11 @@ class C { } var c = C(C()); '''); - // TODO (pq): results are incompatible w/ `unnecessary_const` await assertHasFix(r''' class C { const C([C c]); } -var c = const C(const C()); +var c = const C(C()); '''); } }