Skip to content

Commit 3f53542

Browse files
pqCommit Queue
authored and
Commit Queue
committed
[wildcards] update UNUSED_LOCAL_VARIABLE for wildcards
Updates `UNUSED_LOCAL_VARIABLE` to flag `__`s when the wildcard variables feature is enabled. Fixes: #55719 The implementation is quick so I'm very open to feedback. Also, I'm not sure how exhaustively we want/need to test. Coverage is incomplete and I'm not sure it needs to be *but* for sure if there are interesting cases missed, please do let me know! Change-Id: I4d95d5b94141fa033b3c426ac4b5a721a12fc107 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/366403 Reviewed-by: Kallen Tu <[email protected]> Commit-Queue: Phil Quitslund <[email protected]>
1 parent 88f5c43 commit 3f53542

File tree

2 files changed

+133
-8
lines changed

2 files changed

+133
-8
lines changed

pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'dart:collection';
66
import 'dart:math' as math;
77

8+
import 'package:analyzer/dart/analysis/features.dart';
89
import 'package:analyzer/dart/ast/token.dart';
910
import 'package:analyzer/dart/ast/visitor.dart';
1011
import 'package:analyzer/dart/element/element.dart';
@@ -485,14 +486,19 @@ class UnusedLocalElementsVerifier extends RecursiveAstVisitor<void> {
485486
/// The URI of the library being verified.
486487
final Uri _libraryUri;
487488

489+
/// Whether the `wildcard_variables` feature is enabled.
490+
final bool _wildCardVariablesEnabled;
491+
488492
/// The current set of pattern variable elements, used to track whether _all_
489493
/// within a [PatternVariableDeclaration] are used.
490494
List<BindPatternVariableElement>? _patternVariableElements;
491495

492496
/// Create a new instance of the [UnusedLocalElementsVerifier].
493497
UnusedLocalElementsVerifier(this._errorListener, this._usedElements,
494498
this._inheritanceManager, LibraryElement library)
495-
: _libraryUri = library.source.uri;
499+
: _libraryUri = library.source.uri,
500+
_wildCardVariablesEnabled =
501+
library.featureSet.isEnabled(Feature.wildcard_variables);
496502

497503
@override
498504
void visitCatchClauseParameter(CatchClauseParameter node) {
@@ -662,7 +668,7 @@ class UnusedLocalElementsVerifier extends RecursiveAstVisitor<void> {
662668
if (isUsed) {
663669
return;
664670
}
665-
if (!_isNamedUnderscore(element)) {
671+
if (!_isNamedWildcard(element)) {
666672
elementsToReport.add(element);
667673
}
668674
}
@@ -749,16 +755,19 @@ class UnusedLocalElementsVerifier extends RecursiveAstVisitor<void> {
749755
return correspondingParameter;
750756
}
751757

752-
/// Returns whether the name of [element] consists only of underscore
753-
/// characters.
754-
bool _isNamedUnderscore(LocalVariableElement element) {
758+
/// Returns whether the name of [element] should be treated as a wildcard.
759+
bool _isNamedWildcard(LocalVariableElement element) {
755760
String name = element.name;
756-
for (int index = name.length - 1; index >= 0; --index) {
761+
var length = name.length;
762+
if (length > 1 && _wildCardVariablesEnabled) return false;
763+
764+
for (int index = length - 1; index >= 0; --index) {
757765
if (name.codeUnitAt(index) != 0x5F) {
758766
// 0x5F => '_'
759767
return false;
760768
}
761769
}
770+
762771
return true;
763772
}
764773

@@ -1010,7 +1019,7 @@ class UnusedLocalElementsVerifier extends RecursiveAstVisitor<void> {
10101019
}
10111020

10121021
void _visitLocalVariableElement(LocalVariableElement element) {
1013-
if (!_isUsedElement(element) && !_isNamedUnderscore(element)) {
1022+
if (!_isUsedElement(element) && !_isNamedWildcard(element)) {
10141023
ErrorCode errorCode;
10151024
if (_usedElements.isCatchException(element)) {
10161025
errorCode = WarningCode.UNUSED_CATCH_CLAUSE;

pkg/analyzer/test/src/diagnostics/unused_local_variable_test.dart

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:analyzer/dart/analysis/features.dart';
56
import 'package:analyzer/src/error/codes.dart';
67
import 'package:test_reflective_loader/test_reflective_loader.dart';
78

@@ -10,6 +11,7 @@ import '../dart/resolution/context_collection_resolution.dart';
1011
main() {
1112
defineReflectiveSuite(() {
1213
defineReflectiveTests(UnusedLocalVariableTest);
14+
defineReflectiveTests(UnusedLocalVariableWildCardVariablesTest);
1315
});
1416
}
1517

@@ -128,7 +130,7 @@ void f(Object? x) {
128130
''');
129131
}
130132

131-
test_inFor_underscore_ignored() async {
133+
test_inFor_underscores() async {
132134
await assertNoErrorsInCode(r'''
133135
main() {
134136
for (var _ in [1,2,3]) {
@@ -502,3 +504,117 @@ main() {
502504
''');
503505
}
504506
}
507+
508+
@reflectiveTest
509+
class UnusedLocalVariableWildCardVariablesTest extends UnusedLocalVariableTest {
510+
@override
511+
List<String> get experiments => [
512+
...super.experiments,
513+
Feature.wildcard_variables.enableString,
514+
];
515+
516+
@override
517+
test_inFor_underscores() async {
518+
await assertErrorsInCode(r'''
519+
main() {
520+
for (var _ in [1,2,3]) {
521+
for (var __ in [4,5,6]) {
522+
// do something
523+
}
524+
}
525+
}
526+
''', [
527+
error(WarningCode.UNUSED_LOCAL_VARIABLE, 49, 2),
528+
]);
529+
}
530+
531+
test_localVariable_forElement_underscores() async {
532+
await assertErrorsInCode(r'''
533+
main() {
534+
[
535+
for (var __ in [1, 2, 3]) 1
536+
];
537+
}
538+
''', [
539+
error(WarningCode.UNUSED_LOCAL_VARIABLE, 30, 2),
540+
]);
541+
}
542+
543+
test_localVariable_underscores() async {
544+
await assertErrorsInCode(r'''
545+
main() {
546+
var __ = 0;
547+
var ___ = 0;
548+
}
549+
''', [
550+
error(WarningCode.UNUSED_LOCAL_VARIABLE, 15, 2),
551+
error(WarningCode.UNUSED_LOCAL_VARIABLE, 29, 3),
552+
]);
553+
}
554+
555+
test_localVariable_wildcard() async {
556+
await assertNoErrorsInCode(r'''
557+
main() {
558+
var _ = 0;
559+
}
560+
''');
561+
}
562+
563+
test_localVariableListPattern_underscores() async {
564+
await assertErrorsInCode(r'''
565+
main() {
566+
var [__] = [1];
567+
}
568+
''', [
569+
error(WarningCode.UNUSED_LOCAL_VARIABLE, 16, 2),
570+
]);
571+
}
572+
573+
test_localVariableListPattern_wildcard() async {
574+
await assertNoErrorsInCode(r'''
575+
main() {
576+
var [_] = [1];
577+
}
578+
''');
579+
}
580+
581+
test_localVariablePattern_underscores() async {
582+
await assertErrorsInCode(r'''
583+
main() {
584+
var (__) = (1);
585+
}
586+
''', [
587+
error(WarningCode.UNUSED_LOCAL_VARIABLE, 16, 2),
588+
]);
589+
}
590+
591+
test_localVariablePattern_wildcard() async {
592+
await assertNoErrorsInCode(r'''
593+
main() {
594+
var (_) = (1);
595+
}
596+
''');
597+
}
598+
599+
test_localVariableSwitchListPattern_underscores() async {
600+
await assertErrorsInCode(r'''
601+
void f(Object o) {
602+
switch(o) {
603+
case [var __] : {}
604+
}
605+
}
606+
''', [
607+
error(WarningCode.UNUSED_LOCAL_VARIABLE, 47, 2),
608+
]);
609+
}
610+
611+
test_localVariableSwitchListPattern_wildcard() async {
612+
await assertNoErrorsInCode(r'''
613+
void f(Object o) {
614+
switch(o) {
615+
case [var _] : {}
616+
}
617+
}
618+
''');
619+
}
620+
}

0 commit comments

Comments
 (0)