Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Unified Diff: pkg/analyzer2dart/lib/src/tree_shaker.dart

Issue 2037123002: Cleanup: remove package "analyzer2dart". (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer2dart/lib/src/semantic_visitor.dart ('k') | pkg/analyzer2dart/lib/src/util.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer2dart/lib/src/tree_shaker.dart
diff --git a/pkg/analyzer2dart/lib/src/tree_shaker.dart b/pkg/analyzer2dart/lib/src/tree_shaker.dart
deleted file mode 100644
index 6b9eaa67a95bd3ca3f7220eed3c28eff85fbe011..0000000000000000000000000000000000000000
--- a/pkg/analyzer2dart/lib/src/tree_shaker.dart
+++ /dev/null
@@ -1,418 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library analyzer2dart.treeShaker;
-
-import 'dart:collection';
-
-import 'package:analyzer/analyzer.dart';
-import 'package:analyzer/src/generated/element.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:compiler/src/universe/universe.dart';
-
-import 'closed_world.dart';
-import 'util.dart';
-import 'semantic_visitor.dart';
-import 'identifier_semantics.dart';
-
-/**
- * The result of performing local reachability analysis on a method.
- */
-class MethodAnalysis {
- /**
- * The AST for the method.
- */
- final Declaration declaration;
-
- /**
- * The functions statically called by the method.
- */
- final List<ExecutableElement> calls = <ExecutableElement>[];
-
- /**
- * The fields and top-level variables statically accessed by the method.
- */
- // TODO(johnniwinther): Should we split this into reads and writes?
- final List<PropertyInducingElement> accesses = <PropertyInducingElement>[];
-
- /**
- * The selectors used by the method to perform dynamic invocation.
- */
- final List<Selector> invokes = <Selector>[];
-
- /**
- * The classes that are instantiated by the method.
- */
- // TODO(johnniwinther,paulberry): Register instantiated types.
- // TODO(johnniwinther,paulberry): Register checked types from is/as checks,
- // catch clauses and (checked) type annotations.
- final List<ClassElement> instantiates = <ClassElement>[];
-
- MethodAnalysis(this.declaration);
-}
-
-/**
- * The result of performing local reachability analysis on a class.
- *
- * TODO(paulberry): Do we need to do any other analysis of classes? (For
- * example, detect annotations that are relevant to mirrors, detect that a
- * class might be used for custom HTML elements, or collect inherited and
- * mixed-in classes).
- */
-class ClassAnalysis {
- /**
- * The AST for the class.
- */
- final ClassDeclaration declaration;
-
- ClassAnalysis(this.declaration);
-}
-
-/**
- * This class is responsible for performing local analysis of the source code
- * to provide the information needed to do tree shaking.
- */
-class LocalReachabilityComputer {
- /**
- * Perform local reachability analysis of [method].
- */
- MethodAnalysis analyzeMethod(ExecutableElement method) {
- Declaration declaration = method.node;
- MethodAnalysis analysis = new MethodAnalysis(declaration);
- if (declaration != null) {
- declaration.accept(new TreeShakingVisitor(analysis));
- } else if (method is ConstructorElement) {
- // This constructor has no associated declaration in the AST. Either it
- // is a default constructor for an ordinary class, or it's a synthetic
- // constructor associated with a mixin. For now we assume it's a default
- // constructor, in which case all we need to do is record the class as
- // being instantiated by this method. TODO(paulberry): handle the
- // mixin case.
- ClassElement instantiatedClass = method.enclosingElement;
- analysis.instantiates.add(instantiatedClass);
- if (instantiatedClass.supertype != null) {
- ClassElement superClass = instantiatedClass.supertype.element;
- ConstructorElement superConstructor = superClass.unnamedConstructor;
- if (superConstructor != null) {
- // TODO(johnniwinther): Register instantiated type and selector.
- analysis.calls.add(superConstructor);
- }
- }
- } else {
- // This is an executable element with no associated declaration in the
- // AST, and it's not a constructor. TODO(paulberry): can this ever
- // happen?
- throw new UnimplementedError();
- }
- return analysis;
- }
-
- /**
- * Perform local reachability analysis of [classElement].
- */
- ClassAnalysis analyzeClass(ClassElement classElement) {
- return new ClassAnalysis(classElement.node);
- }
-
- /**
- * Determine which members of [classElement] are matched by the given
- * [selector].
- *
- * [methods] is populated with all the class methods which are matched by the
- * selector, [accessors] with all the getters and setters which are matched
- * by the selector, and [fields] with all the fields which are matched by the
- * selector.
- */
- void getMatchingClassMembers(ClassElement classElement, Selector selector,
- List<MethodElement> methods, List<PropertyAccessorElement> accessors,
- List<PropertyInducingElement> fields) {
- // TODO(paulberry): should we walk through superclasses and mixins as well
- // here? Or would it be better to make [TreeShaker] responsible for those
- // relationships (since they are non-local)? Consider making use of
- // InheritanceManager to do this.
- for (MethodElement method in classElement.methods) {
- // TODO(paulberry): account for arity and named arguments when matching
- // the selector against the method.
- if (selector.name == method.name) {
- methods.add(method);
- }
- }
- if (selector.kind == SelectorKind.GETTER) {
- for (PropertyAccessorElement accessor in classElement.accessors) {
- if (accessor.isGetter && selector.name == accessor.name) {
- if (accessor.isSynthetic) {
- // This accessor is implied by the corresponding field declaration.
- fields.add(accessor.variable);
- } else {
- accessors.add(accessor);
- }
- }
- }
- } else if (selector.kind == SelectorKind.SETTER) {
- // accessor.name uses the convention that setter names end in '='.
- String selectorNameWithEquals = '${selector.name}=';
- for (PropertyAccessorElement accessor in classElement.accessors) {
- if (accessor.isSetter && selectorNameWithEquals == accessor.name) {
- if (accessor.isSynthetic) {
- // This accessor is implied by the corresponding field declaration.
- // TODO(paulberry): should we distinguish reads and writes?
- fields.add(accessor.variable);
- } else {
- accessors.add(accessor);
- }
- }
- }
- }
- }
-}
-
-/**
- * This class is responsible for driving the tree shaking process, and
- * and performing the global inferences necessary to determine which methods
- * in the source program are reachable. It makes use of
- * [LocalReachabilityComputer] to do local analysis of individual classes and
- * methods.
- */
-class TreeShaker {
- List<Element> _queue = <Element>[];
- Set<Element> _alreadyEnqueued = new HashSet<Element>();
- ClosedWorld _world;
- Set<Selector> _selectors = new HashSet<Selector>();
- final LocalReachabilityComputer _localComputer =
- new LocalReachabilityComputer();
-
- TreeShaker(TypeProvider typeProvider, FunctionElement mainFunction)
- : _world = new ClosedWorld(typeProvider, mainFunction);
-
- void _addElement(Element element) {
- if (_alreadyEnqueued.add(element)) {
- _queue.add(element);
- }
- }
-
- void _addSelector(Selector selector) {
- if (_selectors.add(selector)) {
- // New selector, so match it against all class methods.
- _world.instantiatedClasses.forEach((ClassElement element, AstNode node) {
- _matchClassToSelector(element, selector);
- });
- }
- }
-
- void _matchClassToSelector(ClassElement classElement, Selector selector) {
- List<MethodElement> methods = <MethodElement>[];
- List<PropertyAccessorElement> accessors = <PropertyAccessorElement>[];
- List<PropertyInducingElement> fields = <PropertyInducingElement>[];
- _localComputer.getMatchingClassMembers(
- classElement,
- selector,
- methods,
- accessors,
- fields);
- methods.forEach(_addElement);
- accessors.forEach(_addElement);
- fields.forEach(_addElement);
- }
-
- ClosedWorld shake() {
- _addElement(_world.mainFunction);
- while (_queue.isNotEmpty) {
- Element element = _queue.removeLast();
- if (element is ExecutableElement) {
- MethodAnalysis analysis = _localComputer.analyzeMethod(element);
- _world.executableElements[element] = analysis.declaration;
- analysis.calls.forEach(_addElement);
- analysis.invokes.forEach(_addSelector);
- analysis.instantiates.forEach(_addElement);
- analysis.accesses.forEach(_addElement);
- } else if (element is ClassElement) {
- ClassAnalysis analysis = _localComputer.analyzeClass(element);
- _world.instantiatedClasses[element] = analysis.declaration;
- for (Selector selector in _selectors) {
- _matchClassToSelector(element, selector);
- }
- } else if (element is FieldElement) {
- VariableDeclaration declaration = element.node;
- _world.fields[element] = declaration;
- } else if (element is TopLevelVariableElement) {
- VariableDeclaration declaration = element.node;
- _world.variables[element] = declaration;
- } else {
- throw new Exception(
- 'Unexpected element type while tree shaking: '
- '$element (${element.runtimeType})');
- }
- }
- return _world;
- }
-}
-
-class TreeShakingVisitor extends SemanticVisitor {
- final MethodAnalysis analysis;
-
- TreeShakingVisitor(this.analysis);
-
- Source get currentSource => analysis.declaration.element.source;
-
- @override
- void visitInstanceCreationExpression(InstanceCreationExpression node) {
- ConstructorElement staticElement = node.staticElement;
- if (staticElement != null) {
- analysis.calls.add(staticElement);
- } else {
- // TODO(paulberry): deal with this situation. This can happen, for
- // example, in the case "main() => new Unresolved();" (which is a
- // warning, not an error).
- }
- super.visitInstanceCreationExpression(node);
- }
-
- @override
- void visitDynamicInvocation(MethodInvocation node,
- AccessSemantics semantics) {
- analysis.invokes.add(createSelectorFromMethodInvocation(
- node.argumentList, node.methodName.name));
- }
-
- @override
- void visitLocalFunctionInvocation(MethodInvocation node,
- AccessSemantics semantics) {
- // Locals don't need to be tree shaken.
- }
-
- @override
- void visitLocalVariableInvocation(MethodInvocation node,
- AccessSemantics semantics) {
- // Locals don't need to be tree shaken.
- }
-
- @override
- void visitParameterInvocation(MethodInvocation node,
- AccessSemantics semantics) {
- // Locals don't need to be tree shaken.
- }
-
- @override
- void visitStaticFieldInvocation(MethodInvocation node,
- AccessSemantics semantics) {
- // Invocation of a static field.
- analysis.accesses.add(semantics.element);
- analysis.invokes.add(createSelectorFromMethodInvocation(
- node.argumentList, 'call'));
- }
-
- @override
- void visitStaticMethodInvocation(MethodInvocation node,
- AccessSemantics semantics) {
- analysis.calls.add(semantics.element);
- }
-
- @override
- void visitStaticPropertyInvocation(MethodInvocation node,
- AccessSemantics semantics) {
- // Invocation of a property. TODO(paulberry): handle this.
- super.visitStaticPropertyInvocation(node, semantics);
- }
-
- void handleDynamicAccess(AccessSemantics semantics) {
- if (semantics.isRead) {
- analysis.invokes.add(
- new Selector.getter(semantics.identifier.name, null));
- }
- if (semantics.isWrite) {
- // Selector.setter constructor uses the convention that setter names
- // don't end in '='.
- analysis.invokes.add(
- new Selector.setter(semantics.identifier.name, null));
- }
- }
-
- @override
- void visitDynamicAccess(AstNode node, AccessSemantics semantics) {
- handleDynamicAccess(semantics);
- }
-
- @override
- void visitLocalFunctionAccess(AstNode node, AccessSemantics semantics) {
- // Locals don't need to be tree shaken.
- }
-
- @override
- void visitLocalVariableAccess(AstNode node, AccessSemantics semantics) {
- // Locals don't need to be tree shaken.
- }
-
- @override
- void visitParameterAccess(AstNode node, AccessSemantics semantics) {
- // Locals don't need to be tree shaken.
- }
-
- @override
- void visitStaticFieldAccess(AstNode node, AccessSemantics semantics) {
- analysis.accesses.add(semantics.element);
- }
-
- @override
- void visitStaticMethodAccess(AstNode node, AccessSemantics semantics) {
- // Method tear-off. TODO(paulberry): implement.
- super.visitStaticMethodAccess(node, semantics);
- }
-
- @override
- void visitStaticPropertyAccess(AstNode node, AccessSemantics semantics) {
- // TODO(paulberry): implement.
- super.visitStaticPropertyAccess(node, semantics);
- }
-
- @override
- void visitConstructorDeclaration(ConstructorDeclaration node) {
- // TODO(paulberry): handle parameter list.
- node.initializers.accept(this);
- node.body.accept(this);
- if (node.factoryKeyword == null) {
- // This is a generative constructor. Figure out if it is redirecting.
- // If it isn't, then the constructor instantiates the class so we need to
- // add the class to analysis.instantiates. (If it is redirecting, then
- // we don't need to, because the redirected-to constructor will take care
- // of that).
- if (node.initializers.length != 1 || node.initializers[0] is! RedirectingConstructorInvocation) {
- ClassElement classElement = node.element.enclosingElement;
- analysis.instantiates.add(node.element.enclosingElement);
- if (!node.initializers.any((i) => i is SuperConstructorInvocation)) {
- if (classElement.supertype != null) {
- ClassElement superClass = classElement.supertype.element;
- ConstructorElement superConstructor = superClass.unnamedConstructor;
- if (superConstructor != null) {
- // TODO(johnniwinther): Register instantiated type and selector.
- analysis.calls.add(superConstructor);
- }
- }
- }
- }
- } else if (node.redirectedConstructor != null) {
- if (node.redirectedConstructor.staticElement == null) {
- // Factory constructor redirects to a non-existent constructor.
- // TODO(paulberry): handle this.
- throw new UnimplementedError();
- } else {
- analysis.calls.add(node.redirectedConstructor.staticElement);
- }
- }
- }
-
- @override
- void
- visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
- // Note: we don't have to worry about node.staticElement being
- // null, because that would have been detected by the analyzer and
- // reported as a compile time error.
- analysis.calls.add(node.staticElement);
- }
-
- @override
- void handleAssignmentExpression(AssignmentExpression node) {
- // Don't special-case assignment expressions.
- }
-}
« no previous file with comments | « pkg/analyzer2dart/lib/src/semantic_visitor.dart ('k') | pkg/analyzer2dart/lib/src/util.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698