cache doNotStore state

Change-Id: I74a0e6a9bb3bae23bd3e30b492481761407657ba
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/165147
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 05b73cc..d94a231 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -48,6 +48,10 @@
   /// is deprecated.
   bool _inDeprecatedMember;
 
+  /// A flag indicating whether a surrounding member is annotated as
+  /// `@doNotStore`.
+  bool _inDoNotStoreMember;
+
   /// The error reporter by which errors will be reported.
   final ErrorReporter _errorReporter;
 
@@ -101,6 +105,7 @@
             _errorReporter, _currentLibrary, workspacePackage),
         _workspacePackage = workspacePackage {
     _inDeprecatedMember = _currentLibrary.hasDeprecated;
+    _inDoNotStoreMember = _currentLibrary.hasDoNotStore;
 
     _linterContext = LinterContextImpl(
       null /* allUnits */,
@@ -305,9 +310,13 @@
     _invalidAccessVerifier._enclosingClass = element;
 
     bool wasInDeprecatedMember = _inDeprecatedMember;
+    bool wasInDoNotStoreMember = _inDoNotStoreMember;
     if (element != null && element.hasDeprecated) {
       _inDeprecatedMember = true;
     }
+    if (element != null && element.hasDoNotStore) {
+      _inDoNotStoreMember = true;
+    }
 
     try {
       // Commented out until we decide that we want this hint in the analyzer
@@ -319,6 +328,7 @@
       _enclosingClass = null;
       _invalidAccessVerifier._enclosingClass = null;
       _inDeprecatedMember = wasInDeprecatedMember;
+      _inDoNotStoreMember = wasInDoNotStoreMember;
     }
   }
 
@@ -433,10 +443,14 @@
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     bool wasInDeprecatedMember = _inDeprecatedMember;
+    bool wasInDoNotStoreMember = _inDoNotStoreMember;
     ExecutableElement element = node.declaredElement;
     if (element != null && element.hasDeprecated) {
       _inDeprecatedMember = true;
     }
+    if (element != null && element.hasDoNotStore) {
+      _inDoNotStoreMember = true;
+    }
     try {
       _checkForMissingReturn(
           node.returnType, node.functionExpression.body, element, node);
@@ -450,6 +464,7 @@
       super.visitFunctionDeclaration(node);
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
+      _inDoNotStoreMember = wasInDoNotStoreMember;
     }
   }
 
@@ -549,6 +564,7 @@
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
     bool wasInDeprecatedMember = _inDeprecatedMember;
+    bool wasInDoNotStoreMember = _inDoNotStoreMember;
     ExecutableElement element = node.declaredElement;
     Element enclosingElement = element?.enclosingElement;
 
@@ -572,6 +588,9 @@
     if (element != null && element.hasDeprecated) {
       _inDeprecatedMember = true;
     }
+    if (element != null && element.hasDoNotStore) {
+      _inDoNotStoreMember = true;
+    }
     try {
       // This was determined to not be a good hint, see: dartbug.com/16029
       //checkForOverridingPrivateMember(node);
@@ -598,6 +617,7 @@
       super.visitMethodDeclaration(node);
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
+      _inDoNotStoreMember = wasInDoNotStoreMember;
     }
   }
 
@@ -1359,17 +1379,18 @@
   }
 
   void _checkForReturnOfDoNotStore(Expression expression) {
+    if (_inDoNotStoreMember) {
+      return;
+    }
     var element = _getElement(expression);
     if (element != null && element.hasOrInheritsDoNotStore) {
-      var parent = expression.thisOrAncestorMatching(
+      Declaration parent = expression.thisOrAncestorMatching(
           (e) => e is FunctionDeclaration || e is MethodDeclaration);
-      if (parent is Declaration && !parent.declaredElement.hasDoNotStore) {
-        _errorReporter.reportErrorForNode(
-          HintCode.RETURN_OF_DO_NOT_STORE,
-          expression,
-          [element.name, parent.declaredElement.displayName],
-        );
-      }
+      _errorReporter.reportErrorForNode(
+        HintCode.RETURN_OF_DO_NOT_STORE,
+        expression,
+        [element.name, parent.declaredElement.displayName],
+      );
     }
   }