@@ -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 }
0 commit comments