[analyzer] Remove the [ImportedElement] class

When running analyzer on flutter and it's transitive sources, it
consumes around 480 MB of memory.

The [ImportedElement] class is an intermediatey wrapper around an
[Element] and a boolean that is mostly false.

This CL removes the [ImportedElement] class and stores the boolean
side-information alongside the element in [PrefixScope] and
[PrefixScopeLookupResult].

This saves around 15.5 MB of memory.

TEST=ci

Change-Id: I94692a9709c70decd90c604bbdc85f5b308b3006
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/256029
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index 2c89119..d1d6cb0 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -85,20 +85,6 @@
   }
 }
 
-class ImportedElement {
-  final Element element;
-
-  /// This flag is set to `true` if [element] is available using import
-  /// directives where every imported library re-exports the element, and
-  /// every such `export` directive is marked as deprecated.
-  final bool isFromDeprecatedExport;
-
-  ImportedElement({
-    required this.element,
-    required this.isFromDeprecatedExport,
-  });
-}
-
 /// The scope defined by an interface element.
 class InterfaceScope extends EnclosedScope {
   InterfaceScope(super.parent, InterfaceElement element) {
@@ -158,8 +144,10 @@
 
 class PrefixScope implements Scope {
   final LibraryOrAugmentationElementImpl _container;
-  final Map<String, ImportedElement> _getters = {};
-  final Map<String, ImportedElement> _setters = {};
+  final Map<String, Element> _getters = {};
+  final Map<String, Element> _setters = {};
+  Set<String>? _settersFromDeprecatedExport;
+  Set<String>? _gettersFromDeprecatedExport;
   final Set<ExtensionElement> _extensions = {};
   LibraryElement? _deferredLibrary;
 
@@ -176,12 +164,8 @@
             final reference = exportedReference.reference;
             if (combinators.allows(reference.name)) {
               final element = elementFactory.elementOfReference(reference)!;
-              final importedElement = ImportedElement(
-                element: element,
-                isFromDeprecatedExport:
-                    _isFromDeprecatedExport(importedLibrary, exportedReference),
-              );
-              _add(importedElement);
+              _add(element,
+                  _isFromDeprecatedExport(importedLibrary, exportedReference));
             }
           }
           if (import.prefix is DeferredImportElementPrefix) {
@@ -199,48 +183,56 @@
       return ScopeLookupResultImpl(deferredLibrary.loadLibraryFunction, null);
     }
 
-    var getter = _getters[id];
-    var setter = _setters[id];
-    return PrefixScopeLookupResult(getter, setter);
+    return PrefixScopeLookupResult(
+        _getters[id],
+        _setters[id],
+        _gettersFromDeprecatedExport?.contains(id) ?? false,
+        _settersFromDeprecatedExport?.contains(id) ?? false);
   }
 
-  void _add(ImportedElement imported) {
-    final element = imported.element;
+  void _add(Element element, bool isFromDeprecatedExport) {
     if (element is PropertyAccessorElement && element.isSetter) {
-      _addTo(map: _setters, incoming: imported);
+      _addTo(element, isFromDeprecatedExport, isSetter: true);
     } else {
-      _addTo(map: _getters, incoming: imported);
+      _addTo(element, isFromDeprecatedExport, isSetter: false);
       if (element is ExtensionElement) {
         _extensions.add(element);
       }
     }
   }
 
-  void _addTo({
-    required Map<String, ImportedElement> map,
-    required ImportedElement incoming,
-  }) {
-    final id = incoming.element.displayName;
+  void _addTo(Element element, bool isDeprecatedExport,
+      {required bool isSetter}) {
+    final map = isSetter ? _setters : _getters;
+    final id = element.displayName;
     final existing = map[id];
 
     if (existing == null) {
-      map[id] = incoming;
+      map[id] = element;
+      if (isDeprecatedExport) {
+        if (isSetter) {
+          (_settersFromDeprecatedExport ??= {}).add(id);
+        } else {
+          (_gettersFromDeprecatedExport ??= {}).add(id);
+        }
+      }
       return;
     }
 
-    if (existing.element == incoming.element) {
-      map[id] = ImportedElement(
-        element: incoming.element,
-        isFromDeprecatedExport:
-            existing.isFromDeprecatedExport && incoming.isFromDeprecatedExport,
-      );
+    final deprecatedSet =
+        isSetter ? _settersFromDeprecatedExport : _gettersFromDeprecatedExport;
+    final wasFromDeprecatedExport = deprecatedSet?.contains(id) ?? false;
+    if (existing == element) {
+      if (wasFromDeprecatedExport && !isDeprecatedExport) {
+        deprecatedSet!.remove(id);
+      }
       return;
     }
 
-    map[id] = ImportedElement(
-      element: _merge(existing.element, incoming.element),
-      isFromDeprecatedExport: false,
-    );
+    map[id] = _merge(existing, element);
+    if (wasFromDeprecatedExport) {
+      deprecatedSet!.remove(id);
+    }
   }
 
   Element _merge(Element existing, Element other) {
@@ -305,20 +297,35 @@
   }
 }
 
-class PrefixScopeLookupResult implements ScopeLookupResult {
-  final ImportedElement? importedGetter;
-  final ImportedElement? importedSetter;
+class PrefixScopeLookupResult extends ScopeLookupResultImpl {
+  static const int getterIsFromDeprecatedExportBit = 1 << 0;
+  static const int setterIsFromDeprecatedExportBit = 1 << 1;
+
+  final int _deprecatedBits;
 
   PrefixScopeLookupResult(
-    this.importedGetter,
-    this.importedSetter,
-  );
+    super.importedGetter,
+    super.importedSetter,
+    bool getterIsFromDeprecatedExport,
+    bool setterIsFromDeprecatedExport,
+  ) : _deprecatedBits = (getterIsFromDeprecatedExport
+                ? getterIsFromDeprecatedExportBit
+                : 0) |
+            (setterIsFromDeprecatedExport
+                ? setterIsFromDeprecatedExportBit
+                : 0);
 
-  @override
-  Element? get getter => importedGetter?.element;
+  /// This flag is set to `true` if [getter] is available using import
+  /// directives where every imported library re-exports the element, and
+  /// every such `export` directive is marked as deprecated.
+  bool get getterIsFromDeprecatedExport =>
+      (_deprecatedBits & getterIsFromDeprecatedExportBit) != 0;
 
-  @override
-  Element? get setter => importedSetter?.element;
+  /// This flag is set to `true` if [setter] is available using import
+  /// directives where every imported library re-exports the element, and
+  /// every such `export` directive is marked as deprecated.
+  bool get setterIsFromDeprecatedExport =>
+      (_deprecatedBits & setterIsFromDeprecatedExportBit) != 0;
 }
 
 class ScopeLookupResultImpl implements ScopeLookupResult {
diff --git a/pkg/analyzer/lib/src/generated/scope_helpers.dart b/pkg/analyzer/lib/src/generated/scope_helpers.dart
index a49da26..8d2feb2 100644
--- a/pkg/analyzer/lib/src/generated/scope_helpers.dart
+++ b/pkg/analyzer/lib/src/generated/scope_helpers.dart
@@ -39,10 +39,10 @@
     required ScopeLookupResult scopeLookupResult,
     required SimpleIdentifier node,
   }) {
-    if (scopeLookupResult is PrefixScopeLookupResult) {
+    if (scopeLookupResult is PrefixScopeLookupResult &&
+        scopeLookupResult.getterIsFromDeprecatedExport) {
       _reportDeprecatedExportUse(
         node: node,
-        imported: scopeLookupResult.importedGetter,
       );
     }
   }
@@ -51,24 +51,19 @@
     required ScopeLookupResult scopeLookupResult,
     required SimpleIdentifier node,
   }) {
-    if (scopeLookupResult is PrefixScopeLookupResult) {
+    if (scopeLookupResult is PrefixScopeLookupResult &&
+        scopeLookupResult.setterIsFromDeprecatedExport) {
       _reportDeprecatedExportUse(
         node: node,
-        imported: scopeLookupResult.importedSetter,
       );
     }
   }
 
-  void _reportDeprecatedExportUse({
-    required SimpleIdentifier node,
-    required final ImportedElement? imported,
-  }) {
-    if (imported != null && imported.isFromDeprecatedExport) {
-      errorReporter.reportErrorForNode(
-        HintCode.DEPRECATED_EXPORT_USE,
-        node,
-        [node.name],
-      );
-    }
+  void _reportDeprecatedExportUse({required SimpleIdentifier node}) {
+    errorReporter.reportErrorForNode(
+      HintCode.DEPRECATED_EXPORT_USE,
+      node,
+      [node.name],
+    );
   }
 }