dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.06k stars 1.56k forks source link

Running analyzer with empty memory store and resolving all files results in retained `PrefixScopeLookupResult` #49798

Open mkustermann opened 2 years ago

mkustermann commented 2 years ago

When running the analyzer on flutter and it's transitive dependencies twice, once with an empty memory store and the second time with cleared library context but populated memory store we observe

An example retaining path for those PrefixScopeLookupResult objects is:

AnalysisDriver.analysisContext (package:analyzer/src/dart/analysis/driver.dart)
    |-> LibraryContext (package:analyzer/src/dart/analysis/library_context.dart)
        |-> LinkedElementFactory (package:analyzer/src/summary2/linked_element_factory.dart)
            |-> AnalysisSessionImpl (package:analyzer/src/dart/analysis/session.dart)
                |-> ClassHierarchy (package:analyzer/src/dart/element/class_hierarchy.dart)
                    |-> _InternalLinkedHashMap (dart:collection)
                        |-> _List (dart:core)
                            |-> ClassElementImpl (package:analyzer/src/dart/element/element.dart)
                                |-> _GrowableList (dart:core)
                                    |-> _List (dart:core)
                                        |-> ConstFieldElementImpl (package:analyzer/src/dart/element/element.dart)
                                            |-> InstanceCreationExpressionImpl (package:analyzer/src/dart/ast/ast.dart)
                                                |-> ArgumentListImpl (package:analyzer/src/dart/ast/ast.dart)
                                                    |-> NodeListImpl (package:analyzer/src/dart/ast/ast.dart)
                                                        |-> _GrowableList (dart:core)
                                                            |-> _List (dart:core)
                                                                |-> NamedExpressionImpl (package:analyzer/src/dart/ast/ast.dart)
                                                                    |-> LabelImpl (package:analyzer/src/dart/ast/ast.dart)
                                                                        |-> SimpleIdentifierImpl (package:analyzer/src/dart/ast/ast.dart)
                                                                            |-> PrefixScopeLookupResult (package:analyzer/src/dart/element/scope.dart)

It appears the SimpleIdentifierImpl.scopeLookupResult is set during resolution (see resolver.dart):


  @override
  void visitSimpleIdentifier(covariant SimpleIdentifierImpl node) {
    ...
    var scopeLookupResult = nameScope.lookup(node.name);
    node.scopeLookupResult = scopeLookupResult;
    ...
  }

The fact that we don't have those objects when running with cached files in the memory store indicates that maybe the scopeLookupResult needs to be cleared at some point???

/cc @scheglov @bwilkerson

scheglov commented 2 years ago

Yes, we set these scopeLookupResult values while resolving AST, and could clear them after linking the element model (or resolving a unit, although now I wonder if it could be used in lints instead of LinterContext.resolveNameInScope()). But 1MB does not look huge to me, so may be it is not worth efforts.