Version 2.14.0-301.0.dev
Merge commit '0cd008082be130eeca8c868bb0a75ee5d07b25e6' into 'dev'
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 00efd4c..3dcb6c7 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
@@ -5,8 +5,12 @@
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
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/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
@@ -38,16 +42,17 @@
return;
}
- Future<void> insertAtOffset(AstNode targetNode) async {
+ Future<void> insertAtOffset(Expression targetNode) async {
+ var finder = _ConstRangeFinder();
+ targetNode.accept(finder);
await builder.addDartFileEdit(file, (builder) {
builder.addSimpleInsertion(targetNode.offset, 'const ');
+ for (var range in finder.ranges) {
+ builder.addDeletion(range);
+ }
});
}
- // todo(pq):consider removing nested `const` declarations
- // made unnecessary by outer ones in List, Set literal and
- // instance creations.
-
if (targetNode is ListLiteral) {
await insertAtOffset(targetNode);
return;
@@ -82,3 +87,36 @@
/// Return an instance of this class. Used as a tear-off in `FixProcessor`.
static AddConst toLiteral() => AddConst(true, true);
}
+
+class _ConstRangeFinder extends RecursiveAstVisitor<void> {
+ final List<SourceRange> ranges = [];
+
+ @override
+ void visitFunctionExpression(FunctionExpression node) {
+ // Stop visiting when we get to a closure.
+ }
+
+ @override
+ void visitInstanceCreationExpression(InstanceCreationExpression node) {
+ _removeKeyword(node.keyword);
+ super.visitInstanceCreationExpression(node);
+ }
+
+ @override
+ void visitListLiteral(ListLiteral node) {
+ _removeKeyword(node.constKeyword);
+ super.visitListLiteral(node);
+ }
+
+ @override
+ void visitSetOrMapLiteral(SetOrMapLiteral node) {
+ _removeKeyword(node.constKeyword);
+ super.visitSetOrMapLiteral(node);
+ }
+
+ void _removeKeyword(Token? keyword) {
+ if (keyword != null && keyword.type == Keyword.CONST) {
+ ranges.add(range.startStart(keyword, keyword.next!));
+ }
+ }
+}
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 89b7eb7..5dc2905c 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
@@ -177,6 +177,27 @@
}
''');
}
+
+ Future<void> test_withConstList() async {
+ await resolveTestCode('''
+class C {
+ const C(List<int> l);
+}
+void f() {
+ var c = C(const <int>[]);
+ print(c);
+}
+''');
+ await assertHasFix('''
+class C {
+ const C(List<int> l);
+}
+void f() {
+ var c = const C(<int>[]);
+ print(c);
+}
+''');
+ }
}
@reflectiveTest
@@ -272,6 +293,27 @@
''');
}
+ Future<void> test_list_list() async {
+ await resolveTestCode('''
+import 'package:meta/meta.dart';
+
+@immutable
+class C {
+ const C(List<C> children);
+}
+C c = C([C(const [])]);
+''');
+ await assertHasFix('''
+import 'package:meta/meta.dart';
+
+@immutable
+class C {
+ const C(List<C> children);
+}
+C c = C(const [C([])]);
+''');
+ }
+
Future<void> test_map() async {
await resolveTestCode('''
import 'package:meta/meta.dart';
@@ -282,9 +324,7 @@
const C({required this.children});
}
void f() {
- var c = C(children: {
- 1 : const {}
- });
+ var c = C(children: {});
print(c);
}
''');
@@ -297,14 +337,33 @@
const C({required this.children});
}
void f() {
- var c = C(children: const {
- 1 : const {}
- });
+ var c = C(children: const {});
print(c);
}
''');
}
+ Future<void> test_map_map() async {
+ await resolveTestCode('''
+import 'package:meta/meta.dart';
+
+@immutable
+class C {
+ const C(Map<String, C> children);
+}
+C c = C({'c': C(const {})});
+''');
+ await assertHasFix('''
+import 'package:meta/meta.dart';
+
+@immutable
+class C {
+ const C(Map<String, C> children);
+}
+C c = C(const {'c': C({})});
+''');
+ }
+
Future<void> test_set() async {
await resolveTestCode('''
import 'package:meta/meta.dart';
@@ -333,4 +392,25 @@
}
''');
}
+
+ Future<void> test_set_set() async {
+ await resolveTestCode('''
+import 'package:meta/meta.dart';
+
+@immutable
+class C {
+ const C(Set<C> children);
+}
+C c = C({C(const {})});
+''');
+ await assertHasFix('''
+import 'package:meta/meta.dart';
+
+@immutable
+class C {
+ const C(Set<C> children);
+}
+C c = C(const {C({})});
+''');
+ }
}
diff --git a/tools/VERSION b/tools/VERSION
index fc0969a..141cbba 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 300
+PRERELEASE 301
PRERELEASE_PATCH 0
\ No newline at end of file