Version 2.16.0-139.0.dev

Merge commit '69f2bae9d52895ebdf35176acbb55065a2ac15db' into 'dev'
diff --git a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
index 9984e82..c7a1de2 100644
--- a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
+++ b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
@@ -25,6 +25,12 @@
   ClassElement? _enclosingClass;
   ExecutableElement? _enclosingExec;
 
+  /// Non-null when the visitor is inside an [IsExpression]'s type.
+  IsExpression? _enclosingIsExpression;
+
+  /// Non-null when the visitor is inside a [VariableDeclarationList]'s type.
+  VariableDeclarationList? _enclosingVariableDeclaration;
+
   GatherUsedLocalElementsVisitor(this._enclosingLibrary);
 
   @override
@@ -114,6 +120,18 @@
   }
 
   @override
+  void visitIsExpression(IsExpression node) {
+    var enclosingIsExpressionOld = _enclosingIsExpression;
+    node.expression.accept(this);
+    try {
+      _enclosingIsExpression = node;
+      node.type.accept(this);
+    } finally {
+      _enclosingIsExpression = enclosingIsExpressionOld;
+    }
+  }
+
+  @override
   void visitMethodDeclaration(MethodDeclaration node) {
     var enclosingExecOld = _enclosingExec;
     try {
@@ -178,21 +196,22 @@
         usedElements.addElement(element);
       }
     } else {
-      _useIdentifierElement(node, node.readElement);
-      _useIdentifierElement(node, node.writeElement);
-      _useIdentifierElement(node, node.staticElement);
       var parent = node.parent!;
-      // If [node] is a method tear-off, assume all parameters are used.
+      _useIdentifierElement(node, node.readElement, parent: parent);
+      _useIdentifierElement(node, node.writeElement, parent: parent);
+      _useIdentifierElement(node, node.staticElement, parent: parent);
+      var grandparent = parent.parent;
+      // If [node] is a tear-off, assume all parameters are used.
       var functionReferenceIsCall =
           (element is ExecutableElement && parent is MethodInvocation) ||
               // named constructor
               (element is ConstructorElement &&
                   parent is ConstructorName &&
-                  parent.parent is InstanceCreationExpression) ||
+                  grandparent is InstanceCreationExpression) ||
               // unnamed constructor
               (element is ClassElement &&
-                  parent.parent is ConstructorName &&
-                  parent.parent!.parent is InstanceCreationExpression);
+                  grandparent is ConstructorName &&
+                  grandparent.parent is InstanceCreationExpression);
       if (element is ExecutableElement &&
           isIdentifierRead &&
           !functionReferenceIsCall) {
@@ -224,6 +243,19 @@
     }
   }
 
+  @override
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    node.metadata.accept(this);
+    var enclosingVariableDeclarationOld = _enclosingVariableDeclaration;
+    try {
+      _enclosingVariableDeclaration = node;
+      node.type?.accept(this);
+    } finally {
+      _enclosingVariableDeclaration = enclosingVariableDeclarationOld;
+    }
+    node.variables.accept(this);
+  }
+
   /// Add [element] as a used member and, if [element] is a setter, add its
   /// corresponding getter as a used member.
   void _addMemberAndCorrespondingGetter(Element element) {
@@ -236,7 +268,11 @@
   }
 
   /// Marks the [element] of [node] as used in the library.
-  void _useIdentifierElement(Identifier node, Element? element) {
+  void _useIdentifierElement(
+    Identifier node,
+    Element? element, {
+    required AstNode parent,
+  }) {
     if (element == null) {
       return;
     }
@@ -252,17 +288,17 @@
       return;
     }
     // Ignore places where the element is not actually used.
-    if (node.parent is NamedType) {
+    if (parent is NamedType) {
       if (element is ClassElement) {
-        AstNode parent2 = node.parent!.parent!;
-        if (parent2 is IsExpression) {
-          return;
-        }
-        if (parent2 is VariableDeclarationList) {
+        var enclosingVariableDeclaration = _enclosingVariableDeclaration;
+        if (enclosingVariableDeclaration != null) {
           // If it's a field's type, it still counts as used.
-          if (parent2.parent is! FieldDeclaration) {
+          if (enclosingVariableDeclaration.parent is! FieldDeclaration) {
             return;
           }
+        } else if (_enclosingIsExpression != null) {
+          // An interface type found in an `is` expression is not used.
+          return;
         }
       }
     }
diff --git a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
index c377ca0..b9104c2 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
@@ -1700,6 +1700,78 @@
 
 @reflectiveTest
 class UnusedElementWithNullSafetyTest extends PubPackageResolutionTest {
+  test_class_isUsed_isExpression_expression() async {
+    await assertNoErrorsInCode('''
+class _A {}
+void f(Object p) {
+  if (_A() is int) {
+  }
+}
+''');
+  }
+
+  test_class_notUsed_isExpression_typeArgument() async {
+    await assertErrorsInCode(r'''
+class _A {}
+void f(Object p) {
+  if (p is List<_A>) {
+  }
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
+  test_class_notUsed_isExpression_typeInFunctionType() async {
+    await assertErrorsInCode(r'''
+class _A {}
+void f(Object p) {
+  if (p is void Function(_A)) {
+  }
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
+  test_class_notUsed_isExpression_typeInTypeParameter() async {
+    await assertErrorsInCode(r'''
+class _A {}
+void f(Object p) {
+  if (p is void Function<T extends _A>()) {
+  }
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
+  test_class_notUsed_variableDeclaration() async {
+    await assertErrorsInCode('''
+class _A {}
+void f() {
+  _A? v;
+  print(v);
+}
+print(x) {}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
+  test_class_notUsed_variableDeclaration_typeArgument() async {
+    await assertErrorsInCode('''
+class _A {}
+main() {
+  List<_A>? v;
+  print(v);
+}
+print(x) {}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 6, 2),
+    ]);
+  }
+
   test_optionalParameter_isUsed_genericConstructor() async {
     await assertNoErrorsInCode('''
 class C<T> {
diff --git a/tools/VERSION b/tools/VERSION
index 9a1c513..1fea6fb 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 138
+PRERELEASE 139
 PRERELEASE_PATCH 0
\ No newline at end of file