Parts. Move the element to imports map to tracking, fix heap usage.

Change-Id: I9debc9fe1633db3ee3c7d6001a4599746672052d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384442
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index c668cc1..7ab6862 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -137,7 +137,10 @@
 
 class ImportsTrackingOfPrefix {
   final PrefixScope scope;
-  final Map<Element, List<LibraryImportElementImpl>> elementImports;
+
+  /// Key: an element.
+  /// Value: the imports that provide the element.
+  final Map<Element, List<LibraryImportElementImpl>> _elementImports = {};
 
   /// Key: an import.
   /// Value: used elements imported from the import.
@@ -159,8 +162,9 @@
 
   ImportsTrackingOfPrefix({
     required this.scope,
-    required this.elementImports,
-  });
+  }) {
+    _buildElementToImportsMap();
+  }
 
   /// The elements that are used from [import].
   Set<Element> elementsOf(LibraryImportElementImpl import) {
@@ -218,14 +222,14 @@
     }
 
     // SAFETY: if we have `element`, it is from a local import.
-    var imports = elementImports[element]!;
+    var imports = _elementImports[element]!;
     for (var import in imports) {
       (importToUsedElements[import] ??= {}).add(element);
     }
   }
 
   void notifyExtensionUsed(ExtensionElement element) {
-    var imports = elementImports[element];
+    var imports = _elementImports[element];
     if (imports != null) {
       for (var import in imports) {
         (importToUsedElements[import] ??= {}).add(element);
@@ -242,6 +246,21 @@
   void notifyPrefixUsedInCommentReference() {
     hasPrefixUsedInCommentReference = true;
   }
+
+  void _buildElementToImportsMap() {
+    for (var import in scope._importElements) {
+      var importedLibrary = import.importedLibrary!;
+      var elementFactory = importedLibrary.session.elementFactory;
+      var combinators = import.combinators.build();
+      for (var exportedReference in importedLibrary.exportedReferences) {
+        var reference = exportedReference.reference;
+        if (combinators.allows(reference.name)) {
+          var element = elementFactory.elementOfReference(reference)!;
+          (_elementImports[element] ??= []).add(import);
+        }
+      }
+    }
+  }
 }
 
 /// The scope defined by an instance element.
@@ -482,7 +501,6 @@
   final PrefixScope? parent;
 
   final List<LibraryImportElementImpl> _importElements = [];
-  final Map<Element, List<LibraryImportElementImpl>> _elementImports = {};
 
   final Map<String, Element> _getters = {};
   final Map<String, Element> _setters = {};
@@ -512,7 +530,6 @@
           if (combinators.allows(reference.name)) {
             var element = elementFactory.elementOfReference(reference)!;
             if (_shouldAdd(importedLibrary, element)) {
-              (_elementImports[element] ??= []).add(import);
               _add(
                 element,
                 importedLibrary.isFromDeprecatedExport(exportedReference),
@@ -534,7 +551,6 @@
   ImportsTrackingOfPrefix importsTrackingInit() {
     return _importsTracking = ImportsTrackingOfPrefix(
       scope: this,
-      elementImports: _elementImports,
     );
   }