Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 class SendVisitor extends ResolvedVisitor { | |
| 6 final PlaceholderCollector collector; | |
| 7 | |
| 8 SendVisitor(this.collector, TreeElements elements) : super(elements); | |
| 9 | |
| 10 visitSuperSend(Send node) {} | |
| 11 visitOperatorSend(Send node) {} | |
| 12 visitClosureSend(Send node) {} | |
| 13 visitForeignSend(Send node) {} | |
| 14 | |
| 15 String visitDynamicSend(Send node) => tryRenamePrivateId(node); | |
|
Anton Muhin
2012/08/09 06:34:52
nit: this method doesn't return String any more, p
Roman
2012/08/09 07:34:03
Done. I don't know why, probably returning nothing
| |
| 16 | |
| 17 String tryRenamePrivateId(Send node) { | |
|
Anton Muhin
2012/08/09 06:34:52
ditto for return type.
Roman
2012/08/09 07:34:03
Done.
| |
| 18 Node selector = node.selector; | |
| 19 assert(selector !== null); | |
| 20 if (selector.source.isPrivate()) { | |
| 21 collector.makePrivateIdentifier(selector); | |
| 22 } | |
| 23 } | |
| 24 | |
| 25 visitGetterSend(Send node) { | |
| 26 final element = elements[node]; | |
| 27 // element === null means dynamic property access. | |
| 28 // We don't want to rename non top-level element access. | |
| 29 if (element === null || !element.isTopLevel()) { | |
| 30 tryRenamePrivateId(node); | |
| 31 return; | |
| 32 } | |
| 33 // Unqualified <class> in static invocation, why it's not a type annotation? | |
| 34 // Another option would be to process in visitStaticSend, NB: | |
| 35 // those elements are not top-level. | |
| 36 // OR: unqualified top level. | |
| 37 collector.makeElementPlaceholder(node.selector, element); | |
| 38 if (node.receiver !== null) { | |
| 39 // <lib prefix>.<top level>. | |
| 40 collector.makeNullPlaceholder(node.receiver); // Cut library prefix. | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 visitStaticSend(Send node) { | |
| 45 final element = elements[node]; | |
| 46 if (!element.isTopLevel()) return; | |
| 47 // Another ugly case: <lib prefix>.<top level> is represented as | |
| 48 // receiver: lib prefix, selector: top level. | |
| 49 collector.makeElementPlaceholder(node.selector, element); | |
| 50 if (node.receiver !== null) { | |
| 51 assert(elements[node.receiver].isPrefix()); | |
| 52 // Hack: putting null into map overrides receiver of original node. | |
| 53 collector.makeNullPlaceholder(node.receiver); | |
| 54 } | |
| 55 } | |
| 56 } | |
| 57 | |
| 58 class PlaceholderCollector extends AbstractVisitor { | |
| 59 final Compiler compiler; | |
| 60 final Map<Node, Placeholder> placeholders; | |
| 61 Element currentElement; | |
| 62 TreeElements treeElements; | |
| 63 | |
| 64 PlaceholderCollector(this.compiler) : | |
| 65 placeholders = new Map<Node, Placeholder>(); | |
| 66 | |
| 67 void collectFunctionDeclarationPlaceholder( | |
| 68 FunctionElement element, Node node) { | |
| 69 if (element.isGenerativeConstructor() || element.isFactoryConstructor()) { | |
| 70 // Two complicated cases for class/interface renaming: | |
| 71 // 1) class which implements constructors of other interfaces, but not | |
| 72 // implements interfaces themselves: | |
| 73 // 0.dart: class C { I(); } | |
| 74 // 1.dart and 2.dart: interface I default C { I(); } | |
| 75 // now we have to duplicate our I() constructor in C class with | |
| 76 // proper names. | |
| 77 // 2) (even worse for us): | |
| 78 // 0.dart: class C { C(); } | |
| 79 // 1.dart: interface C default p0.C { C(); } | |
| 80 // the second case is just a bug now. | |
| 81 final enclosingClass = element.getEnclosingClass(); | |
| 82 Node nameNode = node.name; | |
| 83 if (nameNode is Send) nameNode = nameNode.receiver; | |
| 84 // For cases like class C implements I { I(); } | |
| 85 if (nameNode.token.slowToString() == enclosingClass.name.slowToString()) { | |
| 86 makeTypePlaceholder(nameNode, enclosingClass.type); | |
| 87 } | |
| 88 } else if (element.isTopLevel()) { | |
| 89 makeElementPlaceholder(node.name, element); | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 void collect(Element element, TreeElements elements) { | |
| 94 // Skip AbstractFieldElement, it has no node. | |
| 95 // Instead getters and setters should be processed explicitly. | |
| 96 if (element is AbstractFieldElement) return; | |
| 97 if (element.isField()) { | |
| 98 currentElement = element; | |
| 99 // TODO(smok): In the future make sure we don't process same | |
| 100 // variable list element twice, better merge this with emitter logic. | |
| 101 element = element.variables; | |
| 102 } | |
| 103 currentElement = element; | |
| 104 treeElements = elements; | |
| 105 Node elementNode = element.parseNode(compiler); | |
| 106 if (element is FunctionElement) { | |
| 107 collectFunctionDeclarationPlaceholder(element, elementNode); | |
| 108 } | |
| 109 elementNode.accept(this); | |
| 110 } | |
| 111 | |
| 112 Type resolveType(TypeAnnotation typeAnnotation) { | |
| 113 if (treeElements === null) return null; | |
| 114 var result = treeElements.getType(typeAnnotation); | |
| 115 // TODO: Have better type resolution. | |
| 116 if (result === null) { | |
| 117 result = compiler.resolveTypeAnnotation(currentElement, typeAnnotation); | |
| 118 } | |
| 119 return result; | |
| 120 } | |
| 121 | |
| 122 void makeTypePlaceholder(Node node, Type type) { | |
| 123 makeElementPlaceholder(node, type.element); | |
| 124 } | |
| 125 | |
| 126 void makeNullPlaceholder(Node node) { | |
| 127 placeholders[node] = new NullPlaceholder(); | |
| 128 } | |
| 129 | |
| 130 void makeElementPlaceholder(Node node, Element element) { | |
| 131 assert(element !== null); | |
| 132 placeholders[node] = new ElementPlaceholder(element); | |
| 133 } | |
| 134 | |
| 135 void makePrivateIdentifier(Identifier node) { | |
| 136 assert(node !== null); | |
| 137 placeholders[node] = | |
| 138 new PrivatePlaceholder(currentElement.getLibrary(), node); | |
| 139 } | |
| 140 | |
| 141 void internalError(String reason, [Node node]) { | |
| 142 compiler.cancel(reason: reason, node: node); | |
| 143 } | |
| 144 | |
| 145 visit(Node node) => (node === null) ? null : node.accept(this); | |
| 146 | |
| 147 visitNode(Node node) { node.visitChildren(this); } // We must go deeper. | |
| 148 | |
| 149 visitClassNode(ClassNode node) { | |
| 150 internalError('Should never meet ClassNode', node); | |
| 151 } | |
| 152 | |
| 153 void visitIdentifier(Identifier node) { | |
| 154 if (node.source.isPrivate()) { | |
| 155 makePrivateIdentifier(node); | |
| 156 } | |
| 157 } | |
| 158 | |
| 159 visitSend(Send send) { | |
| 160 new SendVisitor(this, treeElements).visitSend(send); | |
| 161 super.visitSend(send); | |
| 162 } | |
| 163 | |
| 164 visitTypeAnnotation(TypeAnnotation node) { | |
| 165 final type = compiler.resolveTypeAnnotation(currentElement, node); | |
| 166 if (type is !InterfaceType) return null; | |
| 167 var target = node.typeName; | |
| 168 if (node.typeName is Send) { | |
| 169 final element = treeElements[node]; | |
| 170 if (element !== null) { | |
| 171 final send = node.typeName.asSend(); | |
| 172 final hasPrefix = element.lookupConstructor( | |
| 173 send.receiver.source, send.selector.source) === null; | |
| 174 if (!hasPrefix) target = send.receiver; | |
| 175 } | |
| 176 } | |
| 177 makeTypePlaceholder(target, type); | |
| 178 visit(node.typeArguments); | |
|
Anton Muhin
2012/08/09 06:34:52
super.visit?
Roman
2012/08/09 07:34:03
I can't! If I use super.visit, we will get into id
| |
| 179 } | |
| 180 } | |
| OLD | NEW |