[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],
+ );
}
}