| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 class ElementAst { | 5 class ElementAst { |
| 6 final Node ast; | 6 final Node ast; |
| 7 final TreeElements treeElements; | 7 final TreeElements treeElements; |
| 8 | 8 |
| 9 ElementAst(this.ast, this.treeElements); | 9 ElementAst(this.ast, this.treeElements); |
| 10 | 10 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 | 82 |
| 83 class DartBackend extends Backend { | 83 class DartBackend extends Backend { |
| 84 final List<CompilerTask> tasks; | 84 final List<CompilerTask> tasks; |
| 85 final bool cutDeclarationTypes; | 85 final bool cutDeclarationTypes; |
| 86 // TODO(antonm): make available from command-line options. | 86 // TODO(antonm): make available from command-line options. |
| 87 final bool outputAst = false; | 87 final bool outputAst = false; |
| 88 | 88 |
| 89 Map<Element, TreeElements> get resolvedElements => | 89 Map<Element, TreeElements> get resolvedElements => |
| 90 compiler.enqueuer.resolution.resolvedElements; | 90 compiler.enqueuer.resolution.resolvedElements; |
| 91 | 91 |
| 92 /** |
| 93 * Tells whether it is safe to remove type declarations from variables, |
| 94 * functions parameters. It becomes not safe if: |
| 95 * 1) TypeError is used somewhere in the code, |
| 96 * 2) The code has typedefs in right hand side of IS checks, |
| 97 * 3) The code has classes which extend typedefs, have type arguments typedefs |
| 98 * or type variable bounds typedefs. |
| 99 * These restrictions can be less strict. |
| 100 */ |
| 101 bool isSafeToRemoveTypeDeclarations( |
| 102 Map<ClassElement, Set<Element>> classMembers) { |
| 103 Set<DartType> processedTypes = new Set<DartType>(); |
| 104 List<DartType> workQueue = new List<DartType>(); |
| 105 workQueue.addAll( |
| 106 classMembers.getKeys().map((classElement) => classElement.type)); |
| 107 workQueue.addAll(compiler.resolverWorld.isChecks); |
| 108 DartType typeErrorType = |
| 109 compiler.coreLibrary.find(new SourceString('TypeError')).type; |
| 110 if (workQueue.indexOf(typeErrorType) != -1) { |
| 111 return false; |
| 112 } |
| 113 |
| 114 void processTypeArguments(Element classElement, NodeList typeArguments) { |
| 115 if (typeArguments == null) return; |
| 116 for (Node typeArgument in typeArguments.nodes) { |
| 117 if (typeArgument is TypeVariable) { |
| 118 typeArgument = typeArgument.bound; |
| 119 } |
| 120 if (typeArgument == null) continue; |
| 121 assert(typeArgument is TypeAnnotation); |
| 122 DartType argumentType = |
| 123 compiler.resolveTypeAnnotation(classElement, typeArgument); |
| 124 assert(argumentType !== null); |
| 125 workQueue.add(argumentType); |
| 126 } |
| 127 } |
| 128 |
| 129 while (!workQueue.isEmpty()) { |
| 130 DartType type = workQueue.removeLast(); |
| 131 if (processedTypes.contains(type)) continue; |
| 132 processedTypes.add(type); |
| 133 if (type is TypedefType) return false; |
| 134 if (type is InterfaceType) { |
| 135 ClassElement element = type.element; |
| 136 ClassNode node = element.parseNode(compiler); |
| 137 // Check class type args. |
| 138 processTypeArguments(element, node.typeParameters); |
| 139 // Check superclass type args. |
| 140 if (node.superclass !== null) { |
| 141 NodeList typeArguments = node.superclass.typeArguments; |
| 142 processTypeArguments(element, node.superclass.typeArguments); |
| 143 } |
| 144 // Check interfaces type args. |
| 145 for (Node interfaceNode in node.interfaces) { |
| 146 processTypeArguments( |
| 147 element, (interfaceNode as TypeAnnotation).typeArguments); |
| 148 } |
| 149 // Check all supertypes. |
| 150 if (element.allSupertypes !== null) { |
| 151 workQueue.addAll(element.allSupertypes.toList()); |
| 152 } |
| 153 } |
| 154 } |
| 155 return true; |
| 156 } |
| 157 |
| 92 DartBackend(Compiler compiler, this.cutDeclarationTypes) | 158 DartBackend(Compiler compiler, this.cutDeclarationTypes) |
| 93 : tasks = <CompilerTask>[], | 159 : tasks = <CompilerTask>[], |
| 94 super(compiler); | 160 super(compiler); |
| 95 | 161 |
| 96 void enqueueHelpers(Enqueuer world) { | 162 void enqueueHelpers(Enqueuer world) { |
| 97 // Right now resolver doesn't always resolve interfaces needed | 163 // Right now resolver doesn't always resolve interfaces needed |
| 98 // for literals, so force them. TODO(antonm): fix in the resolver. | 164 // for literals, so force them. TODO(antonm): fix in the resolver. |
| 99 final LITERAL_TYPE_NAMES = const [ | 165 final LITERAL_TYPE_NAMES = const [ |
| 100 'Map', 'List', 'num', 'int', 'double', 'bool' | 166 'Map', 'List', 'num', 'int', 'double', 'bool' |
| 101 ]; | 167 ]; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 // Create all necessary placeholders. | 292 // Create all necessary placeholders. |
| 227 PlaceholderCollector collector = | 293 PlaceholderCollector collector = |
| 228 new PlaceholderCollector(compiler, fixedMemberNames, elementAsts); | 294 new PlaceholderCollector(compiler, fixedMemberNames, elementAsts); |
| 229 makePlaceholders(element) { | 295 makePlaceholders(element) { |
| 230 collector.collect(element); | 296 collector.collect(element); |
| 231 if (element is ClassElement) { | 297 if (element is ClassElement) { |
| 232 classMembers[element].forEach(makePlaceholders); | 298 classMembers[element].forEach(makePlaceholders); |
| 233 } | 299 } |
| 234 } | 300 } |
| 235 topLevelElements.forEach(makePlaceholders); | 301 topLevelElements.forEach(makePlaceholders); |
| 236 | |
| 237 // Create renames. | 302 // Create renames. |
| 238 Map<Node, String> renames = new Map<Node, String>(); | 303 Map<Node, String> renames = new Map<Node, String>(); |
| 239 Map<LibraryElement, String> imports = new Map<LibraryElement, String>(); | 304 Map<LibraryElement, String> imports = new Map<LibraryElement, String>(); |
| 305 bool shouldCutDeclarationTypes = cutDeclarationTypes |
| 306 || (compiler.enableMinification |
| 307 && isSafeToRemoveTypeDeclarations(classMembers)); |
| 240 renamePlaceholders( | 308 renamePlaceholders( |
| 241 compiler, collector, renames, imports, | 309 compiler, collector, renames, imports, |
| 242 fixedMemberNames, cutDeclarationTypes); | 310 fixedMemberNames, shouldCutDeclarationTypes); |
| 243 | 311 |
| 244 // Sort elements. | 312 // Sort elements. |
| 245 final sortedTopLevels = sortElements(topLevelElements); | 313 final sortedTopLevels = sortElements(topLevelElements); |
| 246 final sortedClassMembers = new Map<ClassElement, List<Element>>(); | 314 final sortedClassMembers = new Map<ClassElement, List<Element>>(); |
| 247 classMembers.forEach((classElement, members) { | 315 classMembers.forEach((classElement, members) { |
| 248 sortedClassMembers[classElement] = sortElements(members); | 316 sortedClassMembers[classElement] = sortElements(members); |
| 249 }); | 317 }); |
| 250 | 318 |
| 251 if (outputAst) { | 319 if (outputAst) { |
| 252 // TODO(antonm): Ideally XML should be a separate backend. | 320 // TODO(antonm): Ideally XML should be a separate backend. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 } | 415 } |
| 348 | 416 |
| 349 compareElements(e0, e1) { | 417 compareElements(e0, e1) { |
| 350 int result = compareBy((e) => e.getLibrary().uri.toString())(e0, e1); | 418 int result = compareBy((e) => e.getLibrary().uri.toString())(e0, e1); |
| 351 if (result != 0) return result; | 419 if (result != 0) return result; |
| 352 return compareBy((e) => e.position().charOffset)(e0, e1); | 420 return compareBy((e) => e.position().charOffset)(e0, e1); |
| 353 } | 421 } |
| 354 | 422 |
| 355 List<Element> sortElements(Collection<Element> elements) => | 423 List<Element> sortElements(Collection<Element> elements) => |
| 356 sorted(elements, compareElements); | 424 sorted(elements, compareElements); |
| OLD | NEW |