Skip to content

Commit 3de6f28

Browse files
FMorschelCommit Queue
authored andcommitted
[linter, DAS] Adds simplify_variable_pattern lint and fix
Fixes: #60518 Change-Id: Id02cc06a68c14bda578058e34050947253a888ee Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/450421 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Auto-Submit: Felipe Morschel <git@fmorschel.dev> Reviewed-by: Samuel Rawlins <srawlins@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
1 parent 2a7b2fa commit 3de6f28

File tree

18 files changed

+532
-0
lines changed

18 files changed

+532
-0
lines changed

pkg/analysis_server/lib/src/services/correction/assist.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,11 @@ abstract final class DartAssistKind {
402402
DartAssistKindPriority.priority,
403403
'Remove type annotation',
404404
);
405+
static const removeUnnecessaryName = AssistKind(
406+
'dart.assist.remove.unnecessaryName',
407+
DartAssistKindPriority.default_,
408+
'Remove unnecessary name from pattern',
409+
);
405410
static const replaceConditionalWithIfElse = AssistKind(
406411
'dart.assist.convert.conditionalToIfElse',
407412
DartAssistKindPriority.default_,

pkg/analysis_server/lib/src/services/correction/assist_internal.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import 'package:analysis_server/src/services/correction/dart/join_variable_decla
6969
import 'package:analysis_server/src/services/correction/dart/remove_async.dart';
7070
import 'package:analysis_server/src/services/correction/dart/remove_digit_separators.dart';
7171
import 'package:analysis_server/src/services/correction/dart/remove_type_annotation.dart';
72+
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_name.dart';
7273
import 'package:analysis_server/src/services/correction/dart/replace_conditional_with_if_else.dart';
7374
import 'package:analysis_server/src/services/correction/dart/replace_if_else_with_conditional.dart';
7475
import 'package:analysis_server/src/services/correction/dart/replace_with_var.dart';
@@ -150,6 +151,7 @@ const Set<ProducerGenerator> _builtInGenerators = {
150151
JoinIfWithOuter.new,
151152
JoinVariableDeclaration.new,
152153
RemoveAsync.new,
154+
RemoveUnnecessaryName.new,
153155
RemoveDigitSeparators.new,
154156
RemoveTypeAnnotation.other,
155157
ReplaceConditionalWithIfElse.new,
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analysis_server/src/services/correction/assist.dart';
6+
import 'package:analysis_server/src/services/correction/fix.dart';
7+
import 'package:analysis_server_plugin/edit/dart/correction_producer.dart';
8+
import 'package:analyzer/dart/ast/ast.dart';
9+
import 'package:analyzer/dart/ast/token.dart';
10+
import 'package:analyzer_plugin/utilities/assist/assist.dart';
11+
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
12+
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
13+
import 'package:analyzer_plugin/utilities/range_factory.dart';
14+
15+
class RemoveUnnecessaryName extends ResolvedCorrectionProducer {
16+
RemoveUnnecessaryName({required super.context});
17+
18+
@override
19+
CorrectionApplicability get applicability =>
20+
CorrectionApplicability.automatically;
21+
22+
@override
23+
AssistKind get assistKind => DartAssistKind.removeUnnecessaryName;
24+
25+
@override
26+
FixKind get fixKind => DartFixKind.removeUnnecessaryName;
27+
28+
@override
29+
FixKind? get multiFixKind => DartFixKind.removeUnnecessaryNameMulti;
30+
31+
@override
32+
Future<void> compute(ChangeBuilder builder) async {
33+
var node = this.node;
34+
if (node.parent case PatternField patternField) {
35+
node = patternField;
36+
}
37+
if (node is! PatternField) {
38+
return;
39+
}
40+
41+
var pattern = node.pattern;
42+
if (pattern is! DeclaredVariablePattern) return;
43+
44+
var name = node.name;
45+
if (name?.name case Token(:var isSynthetic, :var lexeme) && var name
46+
when !isSynthetic && pattern.name.lexeme == lexeme) {
47+
await builder.addDartFileEdit(file, (builder) {
48+
builder.addDeletion(range.token(name));
49+
});
50+
}
51+
}
52+
}

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,6 +2385,8 @@ require_trailing_commas:
23852385
status: hasFix
23862386
secure_pubspec_urls:
23872387
status: noFix
2388+
simplify_variable_pattern:
2389+
status: hasFix
23882390
sized_box_for_whitespace:
23892391
status: hasFix
23902392
sized_box_shrink_expand:

pkg/analysis_server/lib/src/services/correction/fix.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,6 +1660,16 @@ abstract final class DartFixKind {
16601660
DartFixKindPriority.inFile,
16611661
'Remove all unnecessary casts in file',
16621662
);
1663+
static const removeUnnecessaryName = FixKind(
1664+
'dart.fix.remove.unnecessaryName',
1665+
DartFixKindPriority.standard,
1666+
'Remove unnecessary name from pattern',
1667+
);
1668+
static const removeUnnecessaryNameMulti = FixKind(
1669+
'dart.fix.remove.unnecessaryName.multi',
1670+
DartFixKindPriority.inFile,
1671+
'Remove unnecessary names from patterns in file',
1672+
);
16631673
static const removeUnnecessaryFinal = FixKind(
16641674
'dart.fix.remove.unnecessaryFinal',
16651675
DartFixKindPriority.standard,

pkg/analysis_server/lib/src/services/correction/fix_internal.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_
186186
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_final.dart';
187187
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_late.dart';
188188
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_library_directive.dart';
189+
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_name.dart';
189190
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_new.dart';
190191
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_parentheses.dart';
191192
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_raw_string.dart';
@@ -412,6 +413,7 @@ final _builtInLintGenerators = <DiagnosticCode, List<ProducerGenerator>>{
412413
],
413414
diag.preferVoidToNull: [ReplaceNullWithVoid.new],
414415
diag.requireTrailingCommas: [AddTrailingComma.new],
416+
diag.simplifyVariablePattern: [RemoveUnnecessaryName.new],
415417
diag.sizedBoxForWhitespace: [ReplaceContainerWithSizedBox.new],
416418
diag.slashForDocComments: [ConvertDocumentationIntoLine.new],
417419
diag.sortChildPropertiesLast: [SortChildPropertyLast.new],
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analysis_server/src/services/correction/assist.dart';
6+
import 'package:analyzer_plugin/utilities/assist/assist.dart';
7+
import 'package:test_reflective_loader/test_reflective_loader.dart';
8+
9+
import 'assist_processor.dart';
10+
11+
void main() {
12+
defineReflectiveSuite(() {
13+
defineReflectiveTests(RemoveUnnecessaryNameTest);
14+
});
15+
}
16+
17+
@reflectiveTest
18+
class RemoveUnnecessaryNameTest extends AssistProcessorTest {
19+
@override
20+
AssistKind get kind => DartAssistKind.removeUnnecessaryName;
21+
22+
Future<void> test_objectDestructuring() async {
23+
await resolveTestCode('''
24+
void f(int value) {
25+
var int(isEven: is^Even) = value;
26+
print(isEven);
27+
}
28+
''');
29+
await assertHasAssist('''
30+
void f(int value) {
31+
var int(: is^Even) = value;
32+
print(isEven);
33+
}
34+
''');
35+
}
36+
37+
Future<void> test_objectPatternField_explicit() async {
38+
await resolveTestCode('''
39+
void f(Object o) {
40+
if (o case int(isEv^en:var isEven) when isEven) {}
41+
}
42+
''');
43+
await assertHasAssist('''
44+
void f(Object o) {
45+
if (o case int(:var isEven) when isEven) {}
46+
}
47+
''');
48+
}
49+
50+
Future<void> test_objectPatternField_otherName() async {
51+
await resolveTestCode('''
52+
void f(Object o) {
53+
if (o case int(isEv^en:var other) when other) {}
54+
}
55+
''');
56+
await assertNoAssist();
57+
}
58+
59+
Future<void> test_recordDestructuring() async {
60+
await resolveTestCode('''
61+
void f((int, {String name}) record) {
62+
var (x, name: na^me) = record;
63+
print(name);
64+
}
65+
''');
66+
await assertHasAssist('''
67+
void f((int, {String name}) record) {
68+
var (x, : name) = record;
69+
print(name);
70+
}
71+
''');
72+
}
73+
74+
Future<void> test_recordPatternField_explicit() async {
75+
await resolveTestCode('''
76+
void f(({bool isEven,}) o) {
77+
if (o case (isEv^en:var isEven) when isEven) {}
78+
}
79+
''');
80+
await assertHasAssist('''
81+
void f(({bool isEven,}) o) {
82+
if (o case (:var isEven) when isEven) {}
83+
}
84+
''');
85+
}
86+
}

pkg/analysis_server/test/src/services/correction/assist/test_all.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ import 'join_variable_declaration_test.dart' as join_variable_declaration;
9494
import 'remove_async_test.dart' as remove_async;
9595
import 'remove_digit_separators_test.dart' as remove_digit_separators;
9696
import 'remove_type_annotation_test.dart' as remove_type_annotation;
97+
import 'remove_unnecessary_name_test.dart' as remove_unnecessary_name;
9798
import 'replace_conditional_with_if_else_test.dart'
9899
as replace_conditional_with_if_else;
99100
import 'replace_if_else_with_conditional_test.dart'
@@ -191,6 +192,7 @@ void main() {
191192
join_variable_declaration.main();
192193
remove_async.main();
193194
remove_digit_separators.main();
195+
remove_unnecessary_name.main();
194196
remove_type_annotation.main();
195197
replace_conditional_with_if_else.main();
196198
replace_if_else_with_conditional.main();
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analysis_server/src/services/correction/fix.dart';
6+
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
7+
import 'package:linter/src/lint_names.dart';
8+
import 'package:test_reflective_loader/test_reflective_loader.dart';
9+
10+
import 'fix_processor.dart';
11+
12+
void main() {
13+
defineReflectiveSuite(() {
14+
defineReflectiveTests(RemoveUnnecessaryNameBulkTest);
15+
defineReflectiveTests(RemoveUnnecessaryNameTest);
16+
});
17+
}
18+
19+
@reflectiveTest
20+
class RemoveUnnecessaryNameBulkTest extends BulkFixProcessorTest {
21+
@override
22+
String get lintCode => LintNames.simplify_variable_pattern;
23+
24+
Future<void> test_singleFile() async {
25+
await parseTestCode('''
26+
void f(Object o) {
27+
if (o case int(isEven:var isEven) when isEven) {}
28+
if (o case int(isOdd:var isOdd) when isOdd) {}
29+
}
30+
''');
31+
await assertHasFix('''
32+
void f(Object o) {
33+
if (o case int(:var isEven) when isEven) {}
34+
if (o case int(:var isOdd) when isOdd) {}
35+
}
36+
''');
37+
}
38+
}
39+
40+
@reflectiveTest
41+
class RemoveUnnecessaryNameTest extends FixProcessorLintTest {
42+
@override
43+
FixKind get kind => DartFixKind.removeUnnecessaryName;
44+
45+
@override
46+
String get lintCode => LintNames.simplify_variable_pattern;
47+
48+
Future<void> test_patternField_explicit() async {
49+
await resolveTestCode('''
50+
void f(Object o) {
51+
if (o case int(isEven:var isEven) when isEven) {}
52+
}
53+
''');
54+
await assertHasFix('''
55+
void f(Object o) {
56+
if (o case int(:var isEven) when isEven) {}
57+
}
58+
''');
59+
}
60+
61+
Future<void> test_recordDestructuring() async {
62+
await resolveTestCode('''
63+
void f((int, {String name}) record) {
64+
var (x, name: name) = record;
65+
print(name);
66+
}
67+
''');
68+
await assertHasFix('''
69+
void f((int, {String name}) record) {
70+
var (x, : name) = record;
71+
print(name);
72+
}
73+
''');
74+
}
75+
}

pkg/analysis_server/test/src/services/correction/fix/test_all.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ import 'remove_unnecessary_final_test.dart' as remove_unnecessary_final;
239239
import 'remove_unnecessary_late_test.dart' as remove_unnecessary_late;
240240
import 'remove_unnecessary_library_directive_test.dart'
241241
as remove_unnecessary_library_directive;
242+
import 'remove_unnecessary_name_test.dart' as remove_unnecessary_name;
242243
import 'remove_unnecessary_new_test.dart' as remove_unnecessary_new;
243244
import 'remove_unnecessary_parentheses_test.dart'
244245
as remove_unnecessary_parentheses;
@@ -528,6 +529,7 @@ void main() {
528529
remove_unnecessary_final.main();
529530
remove_unnecessary_late.main();
530531
remove_unnecessary_library_directive.main();
532+
remove_unnecessary_name.main();
531533
remove_unnecessary_new.main();
532534
remove_unnecessary_parentheses.main();
533535
remove_unnecessary_raw_string.main();

0 commit comments

Comments
 (0)