| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analyzer2dart.treeShaker; | 5 library analyzer2dart.treeShaker; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/analyzer.dart'; | 9 import 'package:analyzer/analyzer.dart'; |
| 10 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
| 11 import 'package:compiler/implementation/universe/universe.dart'; | 11 import 'package:compiler/implementation/universe/universe.dart'; |
| 12 | 12 |
| 13 import 'closed_world.dart'; | 13 import 'closed_world.dart'; |
| 14 | 14 |
| 15 class TreeShaker { | 15 class TreeShaker { |
| 16 List<Element> _queue = <Element>[]; | 16 List<Element> _queue = <Element>[]; |
| 17 Set<Element> _alreadyEnqueued = new HashSet<Element>(); | 17 Set<Element> _alreadyEnqueued = new HashSet<Element>(); |
| 18 ClosedWorld _world = new ClosedWorld(); | 18 ClosedWorld _world; |
| 19 Set<Selector> _selectors = new HashSet<Selector>(); | 19 Set<Selector> _selectors = new HashSet<Selector>(); |
| 20 | 20 |
| 21 TreeShaker(FunctionElement mainFunction) |
| 22 : _world = new ClosedWorld(mainFunction) { |
| 23 addElement(mainFunction); |
| 24 } |
| 25 |
| 21 void addElement(Element element) { | 26 void addElement(Element element) { |
| 22 if (_alreadyEnqueued.add(element)) { | 27 if (_alreadyEnqueued.add(element)) { |
| 23 _queue.add(element); | 28 _queue.add(element); |
| 24 } | 29 } |
| 25 } | 30 } |
| 26 | 31 |
| 27 void addSelector(Selector selector) { | 32 void addSelector(Selector selector) { |
| 28 if (_selectors.add(selector)) { | 33 if (_selectors.add(selector)) { |
| 29 // New selector, so match it against all class methods. | 34 // New selector, so match it against all class methods. |
| 30 _world.instantiatedClasses.forEach((ClassElement element, AstNode node) { | 35 _world.instantiatedClasses.forEach((ClassElement element, AstNode node) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 _world.fields[element] = declaration; | 94 _world.fields[element] = declaration; |
| 90 } else { | 95 } else { |
| 91 throw new Exception('Unexpected element type while tree shaking'); | 96 throw new Exception('Unexpected element type while tree shaking'); |
| 92 } | 97 } |
| 93 } | 98 } |
| 94 print('Tree shaking done'); | 99 print('Tree shaking done'); |
| 95 return _world; | 100 return _world; |
| 96 } | 101 } |
| 97 } | 102 } |
| 98 | 103 |
| 104 Selector createSelectorFromMethodInvocation(MethodInvocation node) { |
| 105 int arity = 0; |
| 106 List<String> namedArguments = <String>[]; |
| 107 for (var x in node.argumentList.arguments) { |
| 108 if (x is NamedExpression) { |
| 109 namedArguments.add(x.name.label.name); |
| 110 } else { |
| 111 arity++; |
| 112 } |
| 113 } |
| 114 return new Selector.call(node.methodName.name, null, arity, namedArguments); |
| 115 } |
| 116 |
| 99 class TreeShakingVisitor extends RecursiveAstVisitor { | 117 class TreeShakingVisitor extends RecursiveAstVisitor { |
| 100 final TreeShaker treeShaker; | 118 final TreeShaker treeShaker; |
| 101 | 119 |
| 102 TreeShakingVisitor(this.treeShaker); | 120 TreeShakingVisitor(this.treeShaker); |
| 103 | 121 |
| 104 /** | 122 /** |
| 105 * Handle a true method call (a MethodInvocation that represents a call to | 123 * Handle a true method call (a MethodInvocation that represents a call to |
| 106 * a non-static method). | 124 * a non-static method). |
| 107 */ | 125 */ |
| 108 void handleMethodCall(MethodInvocation node) { | 126 void handleMethodCall(MethodInvocation node) { |
| 109 int arity = 0; | 127 treeShaker.addSelector(createSelectorFromMethodInvocation(node)); |
| 110 List<String> namedArguments = <String>[]; | |
| 111 for (var x in node.argumentList.arguments) { | |
| 112 if (x is NamedExpression) { | |
| 113 namedArguments.add(x.name.label.name); | |
| 114 } else { | |
| 115 arity++; | |
| 116 } | |
| 117 } | |
| 118 treeShaker.addSelector( | |
| 119 new Selector.call(node.methodName.name, null, arity, namedArguments)); | |
| 120 } | 128 } |
| 121 | 129 |
| 122 @override | 130 @override |
| 123 void visitFunctionDeclaration(FunctionDeclaration node) { | 131 void visitFunctionDeclaration(FunctionDeclaration node) { |
| 124 super.visitFunctionDeclaration(node); | 132 super.visitFunctionDeclaration(node); |
| 125 } | 133 } |
| 126 | 134 |
| 127 @override | 135 @override |
| 128 void visitInstanceCreationExpression(InstanceCreationExpression node) { | 136 void visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 129 ConstructorElement staticElement = node.staticElement; | 137 ConstructorElement staticElement = node.staticElement; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 // main() { | 250 // main() { |
| 243 // new A().g; | 251 // new A().g; |
| 244 // } | 252 // } |
| 245 // TODO(paulberry): do setters go through this path as well? | 253 // TODO(paulberry): do setters go through this path as well? |
| 246 // TODO(paulberry): handle cases where the property access is represented | 254 // TODO(paulberry): handle cases where the property access is represented |
| 247 // as a PrefixedIdentifier. | 255 // as a PrefixedIdentifier. |
| 248 super.visitPropertyAccess(node); | 256 super.visitPropertyAccess(node); |
| 249 treeShaker.addSelector(new Selector.getter(node.propertyName.name, null)); | 257 treeShaker.addSelector(new Selector.getter(node.propertyName.name, null)); |
| 250 } | 258 } |
| 251 } | 259 } |
| OLD | NEW |