Chromium Code Reviews| 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 DartBackend extends Backend { | 5 class DartBackend extends Backend { |
| 6 final List<CompilerTask> tasks; | 6 final List<CompilerTask> tasks; |
| 7 final UnparseValidator unparseValidator; | 7 final UnparseValidator unparseValidator; |
| 8 | 8 |
| 9 Map<Element, TreeElements> get resolvedElements() => | 9 Map<Element, TreeElements> get resolvedElements() => |
| 10 compiler.enqueuer.resolution.resolvedElements; | 10 compiler.enqueuer.resolution.resolvedElements; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 final LIBS_TO_IGNORE = [ | 38 final LIBS_TO_IGNORE = [ |
| 39 compiler.jsHelperLibrary, | 39 compiler.jsHelperLibrary, |
| 40 compiler.interceptorsLibrary, | 40 compiler.interceptorsLibrary, |
| 41 ]; | 41 ]; |
| 42 bool shouldOutput(Element element) => | 42 bool shouldOutput(Element element) => |
| 43 element.kind !== ElementKind.VOID && | 43 element.kind !== ElementKind.VOID && |
| 44 LIBS_TO_IGNORE.indexOf(element.getLibrary()) == -1 && | 44 LIBS_TO_IGNORE.indexOf(element.getLibrary()) == -1 && |
| 45 !isDartCoreLib(compiler, element.getLibrary()) && | 45 !isDartCoreLib(compiler, element.getLibrary()) && |
| 46 element is !AbstractFieldElement; | 46 element is !AbstractFieldElement; |
| 47 | 47 |
| 48 // TODO(smok): Refactor this traverse/collect mess. | 48 final emptyTreeElements = new TreeElementMapping(); |
| 49 Set<TypedefElement> typedefs = new Set<TypedefElement>(); | 49 |
| 50 Set<ClassElement> classes = new Set<ClassElement>(); | 50 Set<Element> topLevelElements = new Set<Element>(); |
| 51 Set<Element> elements = new Set<Element>(); | 51 Map<ClassElement, Set<Element>> classes = |
| 52 Map<ClassElement, Set<Element>> resolvedClassMembers = | |
| 53 new Map<ClassElement, Set<Element>>(); | 52 new Map<ClassElement, Set<Element>>(); |
| 53 | |
| 54 PlaceholderCollector collector = new PlaceholderCollector(compiler); | 54 PlaceholderCollector collector = new PlaceholderCollector(compiler); |
| 55 var newTypedefElementCallback, newClassElementCallback; | |
| 56 | |
| 57 processElement(element, treeElements) { | |
|
Roman
2012/08/16 14:23:54
How about refactoring all this stuff to a separate
Anton Muhin
2012/08/16 14:30:44
That sounds really interesting, thanks a lot, let
| |
| 58 collector.collect(element, treeElements); | |
| 59 new ReferencedElementCollector( | |
| 60 compiler, | |
| 61 element, treeElements, | |
| 62 newTypedefElementCallback, newClassElementCallback).collect(); | |
| 63 } | |
| 64 | |
| 65 addTopLevel(element, treeElements) { | |
| 66 if (topLevelElements.contains(element)) return; | |
| 67 topLevelElements.add(element); | |
| 68 processElement(element, treeElements); | |
| 69 } | |
| 70 addClass(classElement) { | |
| 71 if (classes.containsKey(classElement)) return; | |
| 72 classes[classElement] = new Set<Element>(); | |
| 73 processElement(classElement, emptyTreeElements); | |
| 74 } | |
| 75 | |
| 76 newTypedefElementCallback = (TypedefElement element) { | |
| 77 if (!shouldOutput(element)) return; | |
| 78 addTopLevel(element, emptyTreeElements); | |
| 79 }; | |
| 80 newClassElementCallback = (ClassElement classElement) { | |
| 81 if (!shouldOutput(classElement)) return; | |
| 82 addClass(classElement); | |
| 83 }; | |
| 84 | |
| 55 resolvedElements.forEach((element, treeElements) { | 85 resolvedElements.forEach((element, treeElements) { |
| 56 if (!shouldOutput(element)) return; | 86 if (!shouldOutput(element)) return; |
| 87 | |
| 57 if (element.isMember()) { | 88 if (element.isMember()) { |
| 58 ClassElement enclosingClass = element.getEnclosingClass(); | 89 ClassElement enclosingClass = element.getEnclosingClass(); |
| 59 assert(enclosingClass.isClass()); | 90 assert(enclosingClass.isClass()); |
| 60 assert(enclosingClass.isTopLevel()); | 91 assert(enclosingClass.isTopLevel()); |
| 61 resolvedClassMembers | 92 assert(shouldOutput(enclosingClass)); |
| 62 .putIfAbsent(enclosingClass, () => new Set<Element>()) | 93 addClass(enclosingClass); |
| 63 .add(element); | 94 classes[enclosingClass].add(element); |
| 64 return; | 95 processElement(element, treeElements); |
| 96 } else { | |
| 97 if (!element.isTopLevel()) { | |
| 98 compiler.cancel(reason: 'Cannot process $element', element: element); | |
| 99 } | |
| 100 addTopLevel(element, treeElements); | |
| 65 } | 101 } |
| 66 if (!element.isTopLevel()) { | |
| 67 compiler.cancel(reason: 'Cannot process $element', element: element); | |
| 68 } | |
| 69 | |
| 70 elements.add(element); | |
| 71 }); | 102 }); |
| 72 resolvedElements.forEach((element, treeElements) { | |
| 73 if (!shouldOutput(element)) return; | |
| 74 collector.collect(element, treeElements); | |
| 75 new ReferencedElementCollector( | |
| 76 compiler, element, treeElements, typedefs, classes) | |
| 77 .collect(); | |
| 78 }); | |
| 79 | |
| 80 final emptyTreeElements = new TreeElementMapping(); | |
| 81 collectElement(element) { collector.collect(element, emptyTreeElements); } | |
| 82 typedefs.forEach(collectElement); | |
| 83 classes.forEach(collectElement); | |
| 84 resolvedClassMembers.getKeys().forEach(collectElement); | |
| 85 | 103 |
| 86 Map<Node, String> renames = new Map<Node, String>(); | 104 Map<Node, String> renames = new Map<Node, String>(); |
| 87 Map<LibraryElement, String> imports = new Map<LibraryElement, String>(); | 105 Map<LibraryElement, String> imports = new Map<LibraryElement, String>(); |
| 88 renamePlaceholders(compiler, collector, renames, imports); | 106 renamePlaceholders(compiler, collector, renames, imports); |
| 89 | 107 |
| 90 Emitter emitter = new Emitter(compiler, renames); | 108 Emitter emitter = new Emitter(compiler, renames); |
| 91 emitter.outputImports(imports); | 109 emitter.outputImports(imports); |
| 92 elements.forEach(emitter.outputElement); | 110 topLevelElements.forEach(emitter.outputElement); |
| 93 typedefs.forEach(emitter.outputElement); | 111 classes.forEach(emitter.outputClass); |
| 94 final emptySet = new Set<Element>(); | |
| 95 classes.forEach((classElement) { | |
| 96 if (!shouldOutput(classElement)) return; | |
| 97 if (resolvedClassMembers.containsKey(classElement)) return; | |
| 98 emitter.outputClass(classElement, emptySet); | |
| 99 }); | |
| 100 | 112 |
| 101 // Now output resolved classes with inner elements we met before. | |
| 102 resolvedClassMembers.forEach(emitter.outputClass); | |
| 103 compiler.assembledCode = emitter.toString(); | 113 compiler.assembledCode = emitter.toString(); |
| 104 } | 114 } |
| 105 | 115 |
| 106 log(String message) => compiler.log('[DartBackend] $message'); | 116 log(String message) => compiler.log('[DartBackend] $message'); |
| 107 } | 117 } |
| 108 | 118 |
| 109 /** | 119 /** |
| 110 * Checks if [:libraryElement:] is a core lib, that is a library | 120 * Checks if [:libraryElement:] is a core lib, that is a library |
| 111 * provided by the implementation like dart:core, dart:coreimpl, etc. | 121 * provided by the implementation like dart:core, dart:coreimpl, etc. |
| 112 */ | 122 */ |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 123 /** | 133 /** |
| 124 * Some elements are not recorded by resolver now, | 134 * Some elements are not recorded by resolver now, |
| 125 * for example, typedefs or classes which are only | 135 * for example, typedefs or classes which are only |
| 126 * used in signatures, as/is operators or in super clauses | 136 * used in signatures, as/is operators or in super clauses |
| 127 * (just to name a few). Retraverse AST to pick those up. | 137 * (just to name a few). Retraverse AST to pick those up. |
| 128 */ | 138 */ |
| 129 class ReferencedElementCollector extends AbstractVisitor { | 139 class ReferencedElementCollector extends AbstractVisitor { |
| 130 final Compiler compiler; | 140 final Compiler compiler; |
| 131 final Element rootElement; | 141 final Element rootElement; |
| 132 final TreeElements treeElements; | 142 final TreeElements treeElements; |
| 133 final Set<TypedefElement> typedefs; | 143 final newTypedefElementCallback; |
| 134 final Set<ClassElement> classes; | 144 final newClassElementCallback; |
| 135 | 145 |
| 136 ReferencedElementCollector( | 146 ReferencedElementCollector( |
| 137 this.compiler, | 147 this.compiler, |
| 138 this.rootElement, this.treeElements, | 148 this.rootElement, this.treeElements, |
| 139 this.typedefs, this.classes); | 149 this.newTypedefElementCallback, this.newClassElementCallback); |
| 140 | |
| 141 void collectElement(Element element) { | |
| 142 new ReferencedElementCollector( | |
| 143 compiler, element, new TreeElementMapping(), typedefs, classes) | |
| 144 .collect(); | |
| 145 } | |
| 146 | 150 |
| 147 visitClassNode(ClassNode node) { | 151 visitClassNode(ClassNode node) { |
| 148 super.visitClassNode(node); | 152 super.visitClassNode(node); |
| 149 // Temporary hack which should go away once interfaces | 153 // Temporary hack which should go away once interfaces |
| 150 // and default clauses are out. | 154 // and default clauses are out. |
| 151 if (node.defaultClause !== null) { | 155 if (node.defaultClause !== null) { |
| 152 // Resolver cannot resolve parameterized default clauses. | 156 // Resolver cannot resolve parameterized default clauses. |
| 153 TypeAnnotation evilCousine = new TypeAnnotation( | 157 TypeAnnotation evilCousine = new TypeAnnotation( |
| 154 node.defaultClause.typeName, null); | 158 node.defaultClause.typeName, null); |
| 155 evilCousine.accept(this); | 159 evilCousine.accept(this); |
| 156 } | 160 } |
| 157 } | 161 } |
| 158 | 162 |
| 159 visitNode(Node node) { node.visitChildren(this); } | 163 visitNode(Node node) { node.visitChildren(this); } |
| 160 | 164 |
| 161 visitTypeAnnotation(TypeAnnotation typeAnnotation) { | 165 visitTypeAnnotation(TypeAnnotation typeAnnotation) { |
| 162 final type = compiler.resolveTypeAnnotation(rootElement, typeAnnotation); | 166 final type = compiler.resolveTypeAnnotation(rootElement, typeAnnotation); |
| 163 Element typeElement = type.element; | 167 Element typeElement = type.element; |
| 164 if (typeElement.isTypedef() && !typedefs.contains(typeElement)) { | 168 if (typeElement.isTypedef()) newTypedefElementCallback(typeElement); |
| 165 typedefs.add(typeElement); | 169 if (typeElement.isClass()) newClassElementCallback(typeElement); |
| 166 collectElement(typeElement); | |
| 167 } | |
| 168 if (typeElement.isClass() && !classes.contains(typeElement)) { | |
| 169 classes.add(typeElement); | |
| 170 collectElement(typeElement); | |
| 171 } | |
| 172 typeAnnotation.visitChildren(this); | 170 typeAnnotation.visitChildren(this); |
| 173 } | 171 } |
| 174 | 172 |
| 175 void collect() { | 173 void collect() { |
| 176 compiler.withCurrentElement(rootElement, () { | 174 compiler.withCurrentElement(rootElement, () { |
| 177 rootElement.parseNode(compiler).accept(this); | 175 rootElement.parseNode(compiler).accept(this); |
| 178 }); | 176 }); |
| 179 } | 177 } |
| 180 } | 178 } |
| OLD | NEW |