Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ab50477

Browse files
author
Dart CI
committed
Version 2.16.0-139.0.dev
Merge commit '69f2bae9d52895ebdf35176acbb55065a2ac15db' into 'dev'
2 parents a6cfd1d + 69f2bae commit ab50477

File tree

3 files changed

+124
-16
lines changed

3 files changed

+124
-16
lines changed

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

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor<void> {
2525
ClassElement? _enclosingClass;
2626
ExecutableElement? _enclosingExec;
2727

28+
/// Non-null when the visitor is inside an [IsExpression]'s type.
29+
IsExpression? _enclosingIsExpression;
30+
31+
/// Non-null when the visitor is inside a [VariableDeclarationList]'s type.
32+
VariableDeclarationList? _enclosingVariableDeclaration;
33+
2834
GatherUsedLocalElementsVisitor(this._enclosingLibrary);
2935

3036
@override
@@ -113,6 +119,18 @@ class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor<void> {
113119
super.visitInstanceCreationExpression(node);
114120
}
115121

122+
@override
123+
void visitIsExpression(IsExpression node) {
124+
var enclosingIsExpressionOld = _enclosingIsExpression;
125+
node.expression.accept(this);
126+
try {
127+
_enclosingIsExpression = node;
128+
node.type.accept(this);
129+
} finally {
130+
_enclosingIsExpression = enclosingIsExpressionOld;
131+
}
132+
}
133+
116134
@override
117135
void visitMethodDeclaration(MethodDeclaration node) {
118136
var enclosingExecOld = _enclosingExec;
@@ -178,21 +196,22 @@ class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor<void> {
178196
usedElements.addElement(element);
179197
}
180198
} else {
181-
_useIdentifierElement(node, node.readElement);
182-
_useIdentifierElement(node, node.writeElement);
183-
_useIdentifierElement(node, node.staticElement);
184199
var parent = node.parent!;
185-
// If [node] is a method tear-off, assume all parameters are used.
200+
_useIdentifierElement(node, node.readElement, parent: parent);
201+
_useIdentifierElement(node, node.writeElement, parent: parent);
202+
_useIdentifierElement(node, node.staticElement, parent: parent);
203+
var grandparent = parent.parent;
204+
// If [node] is a tear-off, assume all parameters are used.
186205
var functionReferenceIsCall =
187206
(element is ExecutableElement && parent is MethodInvocation) ||
188207
// named constructor
189208
(element is ConstructorElement &&
190209
parent is ConstructorName &&
191-
parent.parent is InstanceCreationExpression) ||
210+
grandparent is InstanceCreationExpression) ||
192211
// unnamed constructor
193212
(element is ClassElement &&
194-
parent.parent is ConstructorName &&
195-
parent.parent!.parent is InstanceCreationExpression);
213+
grandparent is ConstructorName &&
214+
grandparent.parent is InstanceCreationExpression);
196215
if (element is ExecutableElement &&
197216
isIdentifierRead &&
198217
!functionReferenceIsCall) {
@@ -224,6 +243,19 @@ class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor<void> {
224243
}
225244
}
226245

246+
@override
247+
void visitVariableDeclarationList(VariableDeclarationList node) {
248+
node.metadata.accept(this);
249+
var enclosingVariableDeclarationOld = _enclosingVariableDeclaration;
250+
try {
251+
_enclosingVariableDeclaration = node;
252+
node.type?.accept(this);
253+
} finally {
254+
_enclosingVariableDeclaration = enclosingVariableDeclarationOld;
255+
}
256+
node.variables.accept(this);
257+
}
258+
227259
/// Add [element] as a used member and, if [element] is a setter, add its
228260
/// corresponding getter as a used member.
229261
void _addMemberAndCorrespondingGetter(Element element) {
@@ -236,7 +268,11 @@ class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor<void> {
236268
}
237269

238270
/// Marks the [element] of [node] as used in the library.
239-
void _useIdentifierElement(Identifier node, Element? element) {
271+
void _useIdentifierElement(
272+
Identifier node,
273+
Element? element, {
274+
required AstNode parent,
275+
}) {
240276
if (element == null) {
241277
return;
242278
}
@@ -252,17 +288,17 @@ class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor<void> {
252288
return;
253289
}
254290
// Ignore places where the element is not actually used.
255-
if (node.parent is NamedType) {
291+
if (parent is NamedType) {
256292
if (element is ClassElement) {
257-
AstNode parent2 = node.parent!.parent!;
258-
if (parent2 is IsExpression) {
259-
return;
260-
}
261-
if (parent2 is VariableDeclarationList) {
293+
var enclosingVariableDeclaration = _enclosingVariableDeclaration;
294+
if (enclosingVariableDeclaration != null) {
262295
// If it's a field's type, it still counts as used.
263-
if (parent2.parent is! FieldDeclaration) {
296+
if (enclosingVariableDeclaration.parent is! FieldDeclaration) {
264297
return;
265298
}
299+
} else if (_enclosingIsExpression != null) {
300+
// An interface type found in an `is` expression is not used.
301+
return;
266302
}
267303
}
268304
}

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

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,6 +1700,78 @@ main() {
17001700

17011701
@reflectiveTest
17021702
class UnusedElementWithNullSafetyTest extends PubPackageResolutionTest {
1703+
test_class_isUsed_isExpression_expression() async {
1704+
await assertNoErrorsInCode('''
1705+
class _A {}
1706+
void f(Object p) {
1707+
if (_A() is int) {
1708+
}
1709+
}
1710+
''');
1711+
}
1712+
1713+
test_class_notUsed_isExpression_typeArgument() async {
1714+
await assertErrorsInCode(r'''
1715+
class _A {}
1716+
void f(Object p) {
1717+
if (p is List<_A>) {
1718+
}
1719+
}
1720+
''', [
1721+
error(HintCode.UNUSED_ELEMENT, 6, 2),
1722+
]);
1723+
}
1724+
1725+
test_class_notUsed_isExpression_typeInFunctionType() async {
1726+
await assertErrorsInCode(r'''
1727+
class _A {}
1728+
void f(Object p) {
1729+
if (p is void Function(_A)) {
1730+
}
1731+
}
1732+
''', [
1733+
error(HintCode.UNUSED_ELEMENT, 6, 2),
1734+
]);
1735+
}
1736+
1737+
test_class_notUsed_isExpression_typeInTypeParameter() async {
1738+
await assertErrorsInCode(r'''
1739+
class _A {}
1740+
void f(Object p) {
1741+
if (p is void Function<T extends _A>()) {
1742+
}
1743+
}
1744+
''', [
1745+
error(HintCode.UNUSED_ELEMENT, 6, 2),
1746+
]);
1747+
}
1748+
1749+
test_class_notUsed_variableDeclaration() async {
1750+
await assertErrorsInCode('''
1751+
class _A {}
1752+
void f() {
1753+
_A? v;
1754+
print(v);
1755+
}
1756+
print(x) {}
1757+
''', [
1758+
error(HintCode.UNUSED_ELEMENT, 6, 2),
1759+
]);
1760+
}
1761+
1762+
test_class_notUsed_variableDeclaration_typeArgument() async {
1763+
await assertErrorsInCode('''
1764+
class _A {}
1765+
main() {
1766+
List<_A>? v;
1767+
print(v);
1768+
}
1769+
print(x) {}
1770+
''', [
1771+
error(HintCode.UNUSED_ELEMENT, 6, 2),
1772+
]);
1773+
}
1774+
17031775
test_optionalParameter_isUsed_genericConstructor() async {
17041776
await assertNoErrorsInCode('''
17051777
class C<T> {

tools/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ CHANNEL dev
2727
MAJOR 2
2828
MINOR 16
2929
PATCH 0
30-
PRERELEASE 138
30+
PRERELEASE 139
3131
PRERELEASE_PATCH 0

0 commit comments

Comments
 (0)