Don't report DEPRECATED_MEMBER_USE for deprecated mixins, top-level variables, and class fields.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: Ied5fbe5f7427d286a43902719eb153964c8800e0
Reviewed-on: https://dart-review.googlesource.com/c/84545
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 0ae475b..b647c6a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -93,7 +93,7 @@
   /**
    * The version of data format, should be incremented on every format change.
    */
-  static const int DATA_VERSION = 75;
+  static const int DATA_VERSION = 76;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 61fc2a4..7fd6ce9 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -388,6 +388,20 @@
   }
 
   @override
+  Object visitFieldDeclaration(FieldDeclaration node) {
+    bool wasInDeprecatedMember = _inDeprecatedMember;
+    if (_hasDeprecatedAnnotation(node.metadata)) {
+      _inDeprecatedMember = true;
+    }
+
+    try {
+      return super.visitFieldDeclaration(node);
+    } finally {
+      _inDeprecatedMember = wasInDeprecatedMember;
+    }
+  }
+
+  @override
   Object visitFormalParameterList(FormalParameterList node) {
     _checkRequiredParameter(node);
     return super.visitFormalParameterList(node);
@@ -471,11 +485,18 @@
   Object visitMixinDeclaration(MixinDeclaration node) {
     _enclosingClass = node.declaredElement;
     _invalidAccessVerifier._enclosingClass = _enclosingClass;
+
+    bool wasInDeprecatedMember = _inDeprecatedMember;
+    if (_hasDeprecatedAnnotation(node.metadata)) {
+      _inDeprecatedMember = true;
+    }
+
     try {
       return super.visitMixinDeclaration(node);
     } finally {
       _enclosingClass = null;
       _invalidAccessVerifier._enclosingClass = null;
+      _inDeprecatedMember = wasInDeprecatedMember;
     }
   }
 
@@ -518,6 +539,20 @@
   }
 
   @override
+  Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    bool wasInDeprecatedMember = _inDeprecatedMember;
+    if (_hasDeprecatedAnnotation(node.metadata)) {
+      _inDeprecatedMember = true;
+    }
+
+    try {
+      return super.visitTopLevelVariableDeclaration(node);
+    } finally {
+      _inDeprecatedMember = wasInDeprecatedMember;
+    }
+  }
+
+  @override
   Object visitVariableDeclaration(VariableDeclaration node) {
     _checkForInvalidAssignment(node.name, node.initializer);
     return super.visitVariableDeclaration(node);
@@ -1189,6 +1224,15 @@
     return false;
   }
 
+  static bool _hasDeprecatedAnnotation(List<Annotation> annotations) {
+    for (var i = 0; i < annotations.length; i++) {
+      if (annotations[i].elementAnnotation.isDeprecated) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   /// Given a parenthesized expression, this returns the parent (or recursively
   /// grand-parent) of the expression that is a parenthesized expression, but
   /// whose parent is not a parenthesized expression.
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index 2900675e..b6053b6 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -340,6 +340,21 @@
     verify([source]);
   }
 
+  test_deprecatedMemberUse_inDeprecatedField() async {
+    Source source = addSource(r'''
+@deprecated
+class C {}
+
+class X {
+  @deprecated
+  C f;
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   test_deprecatedMemberUse_inDeprecatedFunction() async {
     Source source = addSource(r'''
 @deprecated
@@ -409,6 +424,36 @@
     verify([source]);
   }
 
+  test_deprecatedMemberUse_inDeprecatedMixin() async {
+    Source source = addSource(r'''
+@deprecated
+f() {}
+
+@deprecated
+mixin M {
+  m() {
+    f();
+  }
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  test_deprecatedMemberUse_inDeprecatedTopLevelVariable() async {
+    Source source = addSource(r'''
+@deprecated
+class C {}
+
+@deprecated
+C v;
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   test_divisionOptimization() async {
     Source source = addSource(r'''
 f(int x, int y) {