Skip to content

Commit a446cd9

Browse files
pqCommit Queue
authored and
Commit Queue
committed
update DEAD_CODE analysis for local wildcard functions
See: #55680 Change-Id: Ib65be42206c6bd66ddaaf54224490870acf4a2bd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/368941 Auto-Submit: Phil Quitslund <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Phil Quitslund <[email protected]>
1 parent 1b9cc28 commit a446cd9

File tree

4 files changed

+64
-6
lines changed

4 files changed

+64
-6
lines changed

pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ class LibraryAnalyzer {
437437

438438
UnicodeTextVerifier(errorReporter).verify(unit, unitAnalysis.file.content);
439439

440-
unit.accept(DeadCodeVerifier(errorReporter));
440+
unit.accept(DeadCodeVerifier(errorReporter, _libraryElement));
441441

442442
unit.accept(
443443
BestPracticesVerifier(

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

Lines changed: 25 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/dart/ast/ast.dart';
67
import 'package:analyzer/dart/ast/token.dart';
78
import 'package:analyzer/dart/ast/visitor.dart';
@@ -31,7 +32,12 @@ class DeadCodeVerifier extends RecursiveAstVisitor<void> {
3132
/// The object used to track the usage of labels within a given label scope.
3233
_LabelTracker? _labelTracker;
3334

34-
DeadCodeVerifier(this._errorReporter);
35+
/// Whether the `wildcard_variables` feature is enabled.
36+
final bool _wildCardVariablesEnabled;
37+
38+
DeadCodeVerifier(this._errorReporter, LibraryElement library)
39+
: _wildCardVariablesEnabled =
40+
library.featureSet.isEnabled(Feature.wildcard_variables);
3541

3642
@override
3743
void visitBreakStatement(BreakStatement node) {
@@ -58,6 +64,19 @@ class DeadCodeVerifier extends RecursiveAstVisitor<void> {
5864
super.visitExportDirective(node);
5965
}
6066

67+
@override
68+
void visitFunctionDeclaration(FunctionDeclaration node) {
69+
var element = node.declaredElement;
70+
// TODO(pq): ask the FunctionElement once implemented
71+
if (_wildCardVariablesEnabled &&
72+
element is FunctionElement &&
73+
element.isLocal &&
74+
element.name == '_') {
75+
_errorReporter.atNode(node, WarningCode.DEAD_CODE);
76+
}
77+
super.visitFunctionDeclaration(node);
78+
}
79+
6180
@override
6281
void visitImportDirective(ImportDirective node) {
6382
var importElement = node.element;
@@ -545,6 +564,11 @@ class _LabelTracker {
545564
}
546565
}
547566

567+
extension on FunctionElement {
568+
bool get isLocal =>
569+
enclosingElement is FunctionElement || enclosingElement is MethodElement;
570+
}
571+
548572
extension DoStatementExtension on DoStatement {
549573
bool get hasBreakStatement {
550574
var visitor = _BreakDoStatementVisitor(this);

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import '../dart/resolution/context_collection_resolution.dart';
1010
main() {
1111
defineReflectiveSuite(() {
1212
defineReflectiveTests(DeadCodeTest);
13+
defineReflectiveTests(DeadCodeWildcardVariablesTest);
1314
defineReflectiveTests(DeadCodeTest_Language219);
1415
});
1516
}
@@ -137,6 +138,17 @@ void f(int a) {
137138
]);
138139
}
139140

141+
test_localFunction_wildcard() async {
142+
await assertErrorsInCode(r'''
143+
void f() {
144+
_(){}
145+
}
146+
''', [
147+
// No dead code.
148+
error(WarningCode.UNUSED_ELEMENT, 13, 1),
149+
]);
150+
}
151+
140152
test_objectPattern_neverTypedGetter() async {
141153
await assertErrorsInCode(r'''
142154
class A {
@@ -1744,3 +1756,19 @@ Iterable<int> f() sync* {
17441756
]);
17451757
}
17461758
}
1759+
1760+
// TODO(pq): inline this test once we've sorted out how we want to use language overrides for experiment testing
1761+
@reflectiveTest
1762+
class DeadCodeWildcardVariablesTest extends DeadCodeTest
1763+
with WithWildCardVariablesMixin {
1764+
@override
1765+
test_localFunction_wildcard() async {
1766+
await assertErrorsInCode(r'''
1767+
void f() {
1768+
_(){}
1769+
}
1770+
''', [
1771+
error(WarningCode.DEAD_CODE, 13, 5),
1772+
]);
1773+
}
1774+
}

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2929,21 +2929,27 @@ class UnusedElementWildCardVariablesTest extends UnusedElementTest
29292929
with WithWildCardVariablesMixin {
29302930
@override
29312931
test_localFunction_inFunction_wildcard() async {
2932-
await assertNoErrorsInCode(r'''
2932+
await assertErrorsInCode(r'''
29332933
m() {
29342934
_(){}
29352935
}
2936-
''');
2936+
''', [
2937+
// Code is dead but not unused.
2938+
error(WarningCode.DEAD_CODE, 8, 5),
2939+
]);
29372940
}
29382941

29392942
@override
29402943
test_localFunction_inMethod_wildcard() async {
2941-
await assertNoErrorsInCode(r'''
2944+
await assertErrorsInCode(r'''
29422945
class C {
29432946
m() {
29442947
_(){}
29452948
}
29462949
}
2947-
''');
2950+
''', [
2951+
// Code is dead but not unused.
2952+
error(WarningCode.DEAD_CODE, 22, 5),
2953+
]);
29482954
}
29492955
}

0 commit comments

Comments
 (0)