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<String> { | |
| 6 final Usager usager; | |
| 7 | |
| 8 SendVisitor(this.usager, TreeElements elements) : super(elements); | |
| 9 | |
| 10 R visitSuperSend(Send node) => node.visitChildren(usager); | |
| 11 R visitOperatorSend(Send node) => node.visitChildren(usager); | |
| 12 R visitClosureSend(Send node) => node.visitChildren(usager); | |
| 13 R visitDynamicSend(Send node) => node.visitChildren(usager); | |
| 14 R visitForeignSend(Send node) => node.visitChildren(usager); | |
| 15 | |
| 16 R visitGetterSend(Send node) { | |
| 17 final element = elements[node]; | |
| 18 if (element !== null && element.isTopLevel()) { | |
|
Anton Muhin
2012/08/07 12:32:11
maybe use early return: if (element === null || el
Roman
2012/08/07 15:44:03
Done.
| |
| 19 if (node.receiver !== null) { | |
| 20 // Library reference prefix. Omit it. | |
|
Anton Muhin
2012/08/07 12:32:11
please, add an assert, that receiver resolves to p
Roman
2012/08/07 15:44:03
Done.
| |
| 21 usager.useNull(node.receiver); | |
| 22 } | |
| 23 usager.useElement(node.selector, element); | |
| 24 usager.visit(node.argumentsNode); | |
|
Anton Muhin
2012/08/07 12:32:11
I am not quite happy we duplicate visitChildren he
Roman
2012/08/07 15:44:03
Changed to visitChildren, it should not matter muc
| |
| 25 } else { | |
| 26 node.visitChildren(usager); | |
| 27 } | |
| 28 } | |
| 29 | |
| 30 R visitStaticSend(Send node) { | |
|
Anton Muhin
2012/08/07 12:32:11
isn't that too complicated?
e.g. shouldn't we ren
Roman
2012/08/07 15:44:03
I will use magic from your CL to make it better.
| |
| 31 final element = elements[node]; | |
| 32 if (element.isTopLevel()) { | |
| 33 if (node.receiver !== null) { | |
| 34 // Library reference prefix. Omit it. | |
| 35 usager.useNull(node.receiver); | |
| 36 } | |
| 37 usager.useMethod(node.selector, element); | |
| 38 usager.visit(node.argumentsNode); | |
| 39 } else if ( | |
| 40 (element.isGenerativeConstructor() || element.isFactoryConstructor()) | |
| 41 // Don't want to rename redirects to :this(args) or super calls. | |
| 42 && !Initializers.isConstructorRedirect(node) | |
| 43 && !Initializers.isSuperConstructorCall(node)) { | |
| 44 final FunctionElement constructor = element.asFunctionElement(); | |
| 45 final Send nameAsSend = constructor.cachedNode.name.asSend(); | |
| 46 if (nameAsSend !== null) { | |
| 47 // Named constructor or factory call. | |
| 48 if (node.selector is TypeAnnotation) { | |
| 49 // Simple A.fromFoo(); | |
| 50 assert(node.selector.typeName is Send); | |
| 51 assert(node.selector.typeName.receiver is Identifier); | |
| 52 assert(node.selector.typeName.selector is Identifier); | |
| 53 usager.useType(node.selector.typeName.receiver, | |
| 54 usager.resolveType(node.selector)); | |
| 55 usager.useConstructorName( | |
| 56 node.selector.typeName.selector, constructor); | |
| 57 } else { | |
| 58 // lib.A.fromFoo() or A<T>.fromFoo() | |
| 59 // or lib.A.fromFoo() or lib.A<T>.fromFoo(); | |
| 60 assert(node.selector is Send); | |
| 61 assert(node.selector.selector is Identifier); | |
| 62 assert(node.selector.receiver is TypeAnnotation); | |
| 63 usager.useType(node.selector.receiver.typeName, | |
| 64 usager.resolveType(node.selector.receiver)); | |
| 65 usager.useConstructorName(node.selector.selector, constructor); | |
| 66 usager.visit(node.selector.receiver.typeArguments); | |
| 67 } | |
| 68 } else { | |
| 69 // Ordinary constructor call. | |
| 70 assert(node.selector is TypeAnnotation); | |
| 71 usager.useType( | |
| 72 node.selector.typeName, usager.resolveType(node.selector)); | |
| 73 usager.visit(node.selector.typeArguments); | |
| 74 } | |
| 75 } else { | |
| 76 // Fallback to default processing. | |
| 77 node.visitChildren(usager); | |
| 78 } | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 class Usager implements Visitor { | |
| 83 final Compiler compiler; | |
| 84 final Map<Node, Usage> usages; | |
| 85 Element currentElement; | |
| 86 TreeElements treeElements; | |
| 87 | |
| 88 Usager(this.compiler) : usages = new Map<Node, Usage>(); | |
| 89 | |
| 90 /** | |
| 91 * Checks if [:libraryElement:] is a core lib, that is a library | |
| 92 * provided by the implementation like dart:core, dart:coreimpl, etc. | |
| 93 */ | |
| 94 bool isDartCoreLib(Compiler compiler, LibraryElement libraryElement) { | |
| 95 final libraries = compiler.libraries; | |
| 96 for (final uri in libraries.getKeys()) { | |
| 97 if (libraryElement === libraries[uri]) { | |
| 98 if (uri.startsWith('dart:')) return true; | |
| 99 } | |
| 100 } | |
| 101 return false; | |
| 102 } | |
| 103 | |
| 104 void process(Element element, TreeElements elements) { | |
| 105 currentElement = element; | |
| 106 treeElements = elements; | |
| 107 Node elementNode = element.parseNode(compiler); | |
| 108 elementNode.accept(this); | |
| 109 } | |
| 110 | |
| 111 Type resolveType(TypeAnnotation typeAnnotation) { | |
| 112 if (treeElements === null) return null; | |
| 113 var result = treeElements.getType(typeAnnotation); | |
| 114 if (result == null) { | |
|
Anton Muhin
2012/08/07 12:32:11
nit: === null
Roman
2012/08/07 15:44:03
Done.
| |
| 115 result = compiler.resolveTypeAnnotation(currentElement, typeAnnotation); | |
| 116 } | |
| 117 return result; | |
| 118 } | |
| 119 | |
| 120 void useType(Node node, Type type) { | |
| 121 assert(type !== null); | |
| 122 usages[node] = new TypeUsage(type); | |
| 123 } | |
| 124 void useConstructorName(Identifier node, FunctionElement constructor) { | |
| 125 assert(constructor !== null); | |
| 126 usages[node] = new ConstructorNameUsage(constructor); | |
| 127 } | |
| 128 void useMethod(Node node, Element method) { | |
| 129 assert(method !== null); | |
| 130 assert(method is FunctionElement || method is VariableElement); | |
| 131 usages[node] = new MethodUsage(method); | |
| 132 } | |
| 133 void useNull(Node node) { | |
| 134 usages[node] = new NullUsage(); | |
| 135 } | |
| 136 void useElement(Node node, Element element) { | |
| 137 assert(element !== null); | |
| 138 usages[node] = new ElementUsage(element); | |
| 139 } | |
| 140 | |
| 141 void internalError(String reason, [Node node]) { | |
| 142 compiler.cancel(reason: reason, node: node); | |
| 143 } | |
| 144 | |
| 145 R visit(Node node) => (node == null) ? null : node.accept(this); | |
|
Anton Muhin
2012/08/07 12:32:11
nit: === null
Roman
2012/08/07 15:44:03
Done.
| |
| 146 | |
| 147 R visitBlock(Block node) { | |
|
Anton Muhin
2012/08/07 12:32:11
arrow syntax, your variant returns null.
Anton Muhin
2012/08/07 12:32:11
cannot you reuse AbstractVisitor?
| |
| 148 node.visitChildren(this); | |
| 149 } | |
| 150 R visitBreakStatement(BreakStatement node) { | |
| 151 node.visitChildren(this); | |
| 152 } | |
| 153 R visitCascade(Cascade node) { | |
| 154 node.visitChildren(this); | |
| 155 } | |
| 156 R visitCascadeReceiver(CascadeReceiver node) { | |
| 157 node.visitChildren(this); | |
| 158 } | |
| 159 R visitCaseMatch(CaseMatch node) { | |
| 160 node.visitChildren(this); | |
| 161 } | |
| 162 R visitCatchBlock(CatchBlock node) { | |
| 163 node.visitChildren(this); | |
| 164 } | |
| 165 R visitClassNode(ClassNode node) { | |
| 166 internalError('Should never meet ClassNode', node); | |
| 167 } | |
| 168 R visitConditional(Conditional node) { | |
| 169 node.visitChildren(this); | |
| 170 } | |
| 171 R visitContinueStatement(ContinueStatement node) { | |
| 172 node.visitChildren(this); | |
| 173 } | |
| 174 R visitDoWhile(DoWhile node) { | |
| 175 node.visitChildren(this); | |
| 176 } | |
| 177 R visitEmptyStatement(EmptyStatement node) { | |
| 178 node.visitChildren(this); | |
| 179 } | |
| 180 R visitExpressionStatement(ExpressionStatement node) { | |
| 181 node.visitChildren(this); | |
| 182 } | |
| 183 R visitFor(For node) { | |
| 184 node.visitChildren(this); | |
| 185 } | |
| 186 R visitForIn(ForIn node) { | |
| 187 node.visitChildren(this); | |
| 188 } | |
| 189 R visitFunctionDeclaration(FunctionDeclaration node) { | |
| 190 node.visitChildren(this); | |
| 191 } | |
| 192 R visitFunctionExpression(FunctionExpression node) { | |
| 193 node.visitChildren(this); | |
| 194 } | |
| 195 R visitIdentifier(Identifier node) { | |
| 196 if (currentElement.isGenerativeConstructor() | |
| 197 || currentElement.isFactoryConstructor()) { | |
| 198 // Two complicated cases for class/interface renaming: | |
| 199 // 1) class which implements constructors of other interfaces, but not | |
| 200 // implements interfaces themselves: | |
| 201 // 0.dart: class C { I(); } | |
| 202 // 1.dart and 2.dart: interface I default C { I(); } | |
| 203 // now we have to duplicate our I() constructor in C class with | |
| 204 // proper names. | |
| 205 // 2) (even worse for us): | |
| 206 // 0.dart: class C { C(); } | |
| 207 // 1.dart: interface C default p0.C { C(); } | |
| 208 // the second case is just a bug now. | |
| 209 final ClassElement enclosingClass = currentElement.getEnclosingClass(); | |
| 210 if (node.token.slowToString() == enclosingClass.name.slowToString()) { | |
| 211 // TODO: distinguish the case of constructor vs. nested named closure | |
| 212 // (see function_syntax_test). | |
| 213 // TODO: fix the bugs above and turn if into the assert. | |
| 214 useType(node, enclosingClass.type); | |
| 215 } | |
| 216 } else if (currentElement.isFunction() | |
| 217 && currentElement.cachedNode.name == node) { | |
| 218 useMethod(node, currentElement); | |
| 219 } | |
| 220 } | |
| 221 R visitIf(If node) { | |
| 222 node.visitChildren(this); | |
| 223 } | |
| 224 R visitLabel(Label node) { | |
| 225 node.visitChildren(this); | |
| 226 } | |
| 227 R visitLabeledStatement(LabeledStatement node) { | |
| 228 node.visitChildren(this); | |
| 229 } | |
| 230 R visitLiteralBool(LiteralBool node) { | |
| 231 node.visitChildren(this); | |
| 232 } | |
| 233 R visitLiteralDouble(LiteralDouble node) { | |
| 234 node.visitChildren(this); | |
| 235 } | |
| 236 R visitLiteralInt(LiteralInt node) { | |
| 237 node.visitChildren(this); | |
| 238 } | |
| 239 R visitLiteralList(LiteralList node) { | |
| 240 node.visitChildren(this); | |
| 241 } | |
| 242 R visitLiteralMap(LiteralMap node) { | |
| 243 node.visitChildren(this); | |
| 244 } | |
| 245 R visitLiteralMapEntry(LiteralMapEntry node) { | |
| 246 node.visitChildren(this); | |
| 247 } | |
| 248 R visitLiteralNull(LiteralNull node) { | |
| 249 node.visitChildren(this); | |
| 250 } | |
| 251 R visitLiteralString(LiteralString node) { | |
| 252 node.visitChildren(this); | |
| 253 } | |
| 254 R visitModifiers(Modifiers node) { | |
| 255 node.visitChildren(this); | |
| 256 } | |
| 257 R visitNamedArgument(NamedArgument node) { | |
| 258 node.visitChildren(this); | |
| 259 } | |
| 260 R visitNewExpression(NewExpression node) { | |
| 261 node.visitChildren(this); | |
| 262 } | |
| 263 R visitNodeList(NodeList node) { | |
| 264 node.visitChildren(this); | |
| 265 } | |
| 266 R visitOperator(Operator node) { | |
| 267 node.visitChildren(this); | |
| 268 } | |
| 269 R visitParenthesizedExpression(ParenthesizedExpression node) { | |
| 270 node.visitChildren(this); | |
| 271 } | |
| 272 R visitReturn(Return node) { | |
| 273 node.visitChildren(this); | |
| 274 } | |
| 275 R visitScriptTag(ScriptTag node) { | |
| 276 node.visitChildren(this); | |
| 277 } | |
| 278 R visitSend(Send send) => new SendVisitor(this, treeElements).visitSend(send); | |
| 279 R visitSendSet(SendSet node) { | |
| 280 node.visitChildren(this); | |
| 281 } | |
| 282 R visitStringInterpolation(StringInterpolation node) { | |
| 283 node.visitChildren(this); | |
| 284 } | |
| 285 R visitStringInterpolationPart(StringInterpolationPart node) { | |
| 286 node.visitChildren(this); | |
| 287 } | |
| 288 R visitStringJuxtaposition(StringJuxtaposition node) { | |
| 289 node.visitChildren(this); | |
| 290 } | |
| 291 R visitSwitchCase(SwitchCase node) { | |
| 292 node.visitChildren(this); | |
| 293 } | |
| 294 R visitSwitchStatement(SwitchStatement node) { | |
| 295 node.visitChildren(this); | |
| 296 } | |
| 297 R visitThrow(Throw node) { | |
| 298 node.visitChildren(this); | |
| 299 } | |
| 300 R visitTryStatement(TryStatement node) { | |
| 301 node.visitChildren(this); | |
| 302 } | |
| 303 | |
| 304 R visitTypeAnnotation(TypeAnnotation node) { | |
| 305 Type type = resolveType(node); | |
| 306 useType(node.typeName, type); | |
| 307 visit(node.typeArguments); | |
| 308 } | |
| 309 | |
| 310 R visitTypedef(Typedef node) { | |
| 311 node.visitChildren(this); | |
| 312 } | |
| 313 R visitTypeVariable(TypeVariable node) { | |
| 314 node.visitChildren(this); | |
| 315 } | |
| 316 R visitVariableDefinitions(VariableDefinitions node) { | |
| 317 node.visitChildren(this); | |
| 318 } | |
| 319 R visitWhile(While node) { | |
| 320 node.visitChildren(this); | |
| 321 } | |
| 322 } | |
| OLD | NEW |