Move shouldIgnoreUndefined logic into LibraryElementImpl.

This logic was previously in LibraryScope and ScopeExtension.  It
really isn't related to scopes, though, since all it does is to look
through the library's imports and parts.  (The only use it made of
scopes was to locate the library element).

Separating this code from scopes will facilitate some other changes
I'm working on to streamline the use of scopes in the analyzer.

Change-Id: Ic45e3382628a433a96cc7ecf751b4df5d681b42a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208522
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index f362f93..ae8a8fc 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -15,6 +15,7 @@
 import 'package:analyzer/dart/element/scope.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
@@ -4005,6 +4006,64 @@
     return getTypeFromParts(className, _definingCompilationUnit, _parts);
   }
 
+  /// Indicates whether it is unnecessary to report an undefined identifier
+  /// error for an identifier reference with the given [name] and optional
+  /// [prefix].
+  ///
+  /// This method is intended to reduce spurious errors in circumstances where
+  /// an undefined identifier occurs as the result of a missing (most likely
+  /// code generated) file.  It will only return `true` in a circumstance where
+  /// the current library is guaranteed to have at least one other error (due to
+  /// a missing part or import), so there is no risk that ignoring the undefined
+  /// identifier would cause an invalid program to be treated as valid.
+  bool shouldIgnoreUndefined({
+    required String? prefix,
+    required String name,
+  }) {
+    for (var importElement in imports) {
+      if (importElement.prefix?.name == prefix &&
+          importElement.importedLibrary?.isSynthetic != false) {
+        var showCombinators = importElement.combinators
+            .whereType<ShowElementCombinator>()
+            .toList();
+        if (prefix != null && showCombinators.isEmpty) {
+          return true;
+        }
+        for (var combinator in showCombinators) {
+          if (combinator.shownNames.contains(name)) {
+            return true;
+          }
+        }
+      }
+    }
+
+    if (prefix == null && name.startsWith(r'_$')) {
+      for (var partElement in parts) {
+        if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  /// Convenience wrapper around [shouldIgnoreUndefined] that calls it for a
+  /// given (possibly prefixed) identifier [node].
+  bool shouldIgnoreUndefinedIdentifier(Identifier node) {
+    if (node is PrefixedIdentifier) {
+      return shouldIgnoreUndefined(
+        prefix: node.prefix.name,
+        name: node.identifier.name,
+      );
+    }
+
+    return shouldIgnoreUndefined(
+      prefix: null,
+      name: (node as SimpleIdentifier).name,
+    );
+  }
+
   @override
   T toLegacyElementIfOptOut<T extends Element>(T element) {
     if (isNonNullableByDefault) return element;
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index 1f15606..4df2190 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/scope.dart';
-import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart' as impl;
 
@@ -104,38 +103,6 @@
     _element.units.forEach(_addUnitElements);
   }
 
-  bool shouldIgnoreUndefined({
-    required String? prefix,
-    required String name,
-  }) {
-    for (var importElement in _element.imports) {
-      if (importElement.prefix?.name == prefix &&
-          importElement.importedLibrary?.isSynthetic != false) {
-        var showCombinators = importElement.combinators
-            .whereType<ShowElementCombinator>()
-            .toList();
-        if (prefix != null && showCombinators.isEmpty) {
-          return true;
-        }
-        for (var combinator in showCombinators) {
-          if (combinator.shownNames.contains(name)) {
-            return true;
-          }
-        }
-      }
-    }
-
-    if (prefix == null && name.startsWith(r'_$')) {
-      for (var partElement in _element.parts) {
-        if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
-          return true;
-        }
-      }
-    }
-
-    return false;
-  }
-
   void _addExtension(ExtensionElement element) {
     _addGetter(element);
     if (!extensions.contains(element)) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 7485e6e..9de1a34 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -10,12 +10,12 @@
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/migratable_ast_info_provider.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -42,7 +42,7 @@
   final InheritanceManager3 _inheritance;
 
   /// The element for the library containing the compilation unit being visited.
-  final LibraryElement _definingLibrary;
+  final LibraryElementImpl _definingLibrary;
 
   /// The URI of [_definingLibrary].
   final Uri _definingLibraryUri;
@@ -271,7 +271,7 @@
   }) {
     _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
 
-    if (nameScope.shouldIgnoreUndefined2(prefix: prefix, name: name)) {
+    if (_definingLibrary.shouldIgnoreUndefined(prefix: prefix, name: name)) {
       return;
     }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index e2d5336..10c9f96 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -13,7 +13,6 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/resolution_result.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/assignment_verifier.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -590,7 +589,7 @@
 
     if (hasRead && readElement == null || hasWrite && writeElement == null) {
       if (!forAnnotation &&
-          !_resolver.nameScope.shouldIgnoreUndefined2(
+          !_resolver.definingLibrary.shouldIgnoreUndefined(
             prefix: target.name,
             name: identifier.name,
           )) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 6a03d38..f08fb8d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -56,6 +56,7 @@
 /// 3. Resolve all [TypeName]s - set elements and types.
 /// 4. Resolve all [GenericFunctionType]s - set their types.
 class ResolutionVisitor extends RecursiveAstVisitor<void> {
+  LibraryElementImpl _libraryElement;
   final TypeProvider _typeProvider;
   final CompilationUnitElementImpl _unitElement;
   final bool _isNonNullableByDefault;
@@ -102,13 +103,14 @@
     );
 
     var typeNameResolver = TypeNameResolver(
-      libraryElement.typeSystem,
+      libraryElement,
       typeProvider,
       isNonNullableByDefault,
       errorReporter,
     );
 
     return ResolutionVisitor._(
+      libraryElement,
       typeProvider,
       unitElement,
       isNonNullableByDefault,
@@ -122,6 +124,7 @@
   }
 
   ResolutionVisitor._(
+    this._libraryElement,
     this._typeProvider,
     this._unitElement,
     this._isNonNullableByDefault,
@@ -1211,7 +1214,7 @@
     // If the type is not an InterfaceType, then visitTypeName() sets the type
     // to be a DynamicTypeImpl
     Identifier name = typeName.name;
-    if (!_nameScope.shouldIgnoreUndefined(name)) {
+    if (!_libraryElement.shouldIgnoreUndefinedIdentifier(name)) {
       _errorReporter.reportErrorForNode(errorCode, name, [name.name]);
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 95850f3..845c8e1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -352,35 +352,6 @@
 }
 
 extension ScopeExtension on Scope {
-  /// Return `true` if the fact that the given [node] is not defined should be
-  /// ignored (from the perspective of error reporting).
-  bool shouldIgnoreUndefined(Identifier node) {
-    if (node is PrefixedIdentifier) {
-      return shouldIgnoreUndefined2(
-        prefix: node.prefix.name,
-        name: node.identifier.name,
-      );
-    }
-
-    return shouldIgnoreUndefined2(
-      prefix: null,
-      name: (node as SimpleIdentifier).name,
-    );
-  }
-
-  /// Return `true` if the fact that the identifier with the given [prefix]
-  /// (might be `null`) and [name] is not defined should be ignored (from the
-  /// perspective of error reporting).
-  bool shouldIgnoreUndefined2({
-    required String? prefix,
-    required String name,
-  }) {
-    return _enclosingLibraryScope.shouldIgnoreUndefined(
-      prefix: prefix,
-      name: name,
-    );
-  }
-
   List<ExtensionElement> get extensions {
     return _enclosingLibraryScope.extensions;
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
index a3e5943..4c872f9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -14,7 +14,6 @@
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
@@ -203,7 +202,8 @@
           CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT,
           node,
         );
-      } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
+      } else if (!_resolver.definingLibrary
+          .shouldIgnoreUndefinedIdentifier(node)) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
           node,
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
index 4acea06..3f3c167 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
@@ -16,7 +16,6 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
 import 'package:analyzer/src/error/codes.dart';
 
@@ -24,6 +23,7 @@
 ///
 /// The client must set [nameScope] before calling [resolveTypeName].
 class TypeNameResolver {
+  final LibraryElementImpl _libraryElement;
   final TypeSystemImpl typeSystem;
   final DartType dynamicType;
   final bool isNonNullableByDefault;
@@ -56,9 +56,10 @@
   /// If [resolveTypeName] reported an error, this flag is set to `true`.
   bool hasErrorReported = false;
 
-  TypeNameResolver(this.typeSystem, TypeProvider typeProvider,
+  TypeNameResolver(this._libraryElement, TypeProvider typeProvider,
       this.isNonNullableByDefault, this.errorReporter)
-      : dynamicType = typeProvider.dynamicType;
+      : typeSystem = _libraryElement.typeSystem,
+        dynamicType = typeProvider.dynamicType;
 
   bool get _genericMetadataIsEnabled =>
       enclosingClass!.library.featureSet.isEnabled(Feature.generic_metadata);
@@ -285,7 +286,7 @@
   void _resolveToElement(TypeNameImpl node, Element? element) {
     if (element == null) {
       node.type = dynamicType;
-      if (!nameScope.shouldIgnoreUndefined(node.name)) {
+      if (!_libraryElement.shouldIgnoreUndefinedIdentifier(node.name)) {
         _ErrorHelper(errorReporter).reportNullOrNonTypeElement(node, null);
       }
       return;
diff --git a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
index ee009b4..e781de9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -37,7 +37,7 @@
       TypeSystemImpl typeSystem, TypeProviderImpl typeProvider,
       {MigratableAstInfoProvider migratableAstInfoProvider =
           const MigratableAstInfoProvider()}) {
-    var library = resolver.definingLibrary as LibraryElementImpl;
+    var library = resolver.definingLibrary;
     var analysisOptions = library.context.analysisOptions;
     var analysisOptionsImpl = analysisOptions as AnalysisOptionsImpl;
     return TypedLiteralResolver._(
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index cc5fc13..2a378e11 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -498,7 +498,8 @@
     var declaration = node.thisOrAncestorOfType<ClassDeclaration>();
     var superclassName = declaration?.extendsClause?.superclass.name;
     if (superclassName != null &&
-        _resolver.nameScope.shouldIgnoreUndefined(superclassName)) {
+        _resolver.definingLibrary
+            .shouldIgnoreUndefinedIdentifier(superclassName)) {
       return;
     }
     var argumentList = node.argumentList;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 9bdf31e..09b83ed 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -268,7 +268,7 @@
   /// breaking change).
   ResolverVisitor(
       InheritanceManager3 inheritanceManager,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       Source source,
       TypeProvider typeProvider,
       AnalysisErrorListener errorListener,
@@ -279,7 +279,7 @@
             inheritanceManager,
             definingLibrary,
             source,
-            definingLibrary.typeSystem as TypeSystemImpl,
+            definingLibrary.typeSystem,
             typeProvider,
             errorListener,
             featureSet ??
@@ -291,7 +291,7 @@
 
   ResolverVisitor._(
       this.inheritance,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       Source source,
       this.typeSystem,
       TypeProvider typeProvider,
@@ -2303,7 +2303,7 @@
 
   ResolverVisitorForMigration(
       InheritanceManager3 inheritanceManager,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       Source source,
       TypeProvider typeProvider,
       AnalysisErrorListener errorListener,
@@ -2373,7 +2373,7 @@
   static const _nameScopeProperty = 'nameScope';
 
   /// The element for the library containing the compilation unit being visited.
-  final LibraryElement definingLibrary;
+  final LibraryElementImpl definingLibrary;
 
   /// The source representing the compilation unit being visited.
   final Source source;
@@ -3164,7 +3164,7 @@
   /// [nameScope] is the scope used to resolve identifiers in the node that will
   /// first be visited.  If `null` or unspecified, a new [LibraryScope] will be
   /// created based on [definingLibrary] and [typeProvider].
-  VariableResolverVisitor(LibraryElement definingLibrary, Source source,
+  VariableResolverVisitor(LibraryElementImpl definingLibrary, Source source,
       TypeProvider typeProvider, AnalysisErrorListener errorListener,
       {Scope? nameScope})
       : super(definingLibrary, source, typeProvider as TypeProviderImpl,
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 8a70226..bcfdef6 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -141,7 +141,7 @@
       TypeProvider typeProvider,
       TypeSystemImpl typeSystem,
       Variables? variables,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       NullabilityMigrationListener? listener,
       CompilationUnit? unit,
       bool? warnOnWeakCode,
@@ -170,7 +170,7 @@
       this._typeSystem,
       this._variables,
       this.source,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       this.listener,
       this.unit,
       this.migrationResolutionHooks,
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index f22569b..867f72a 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -146,7 +147,7 @@
         result.typeProvider,
         library.typeSystem as TypeSystemImpl,
         _variables,
-        library,
+        library as LibraryElementImpl,
         _permissive! ? listener : null,
         unit,
         warnOnWeakCode,
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index a9026b2..74fa1a8 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/element_type_provider.dart';
@@ -3886,7 +3887,7 @@
         typeProvider,
         typeSystem,
         variables,
-        definingLibrary,
+        definingLibrary as LibraryElementImpl,
         null,
         scope.thisOrAncestorOfType<CompilationUnit>(),
         warnOnWeakCode,