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); | |
|
Anton Muhin
2012/08/07 16:00:30
why do you need to visit children?
Anton Muhin
2012/08/07 16:00:30
R should be now String
Roman
2012/08/08 06:46:14
Fixed, visiting children now in PlaceholderCollect
Roman
2012/08/08 06:46:14
Actually it should not return anything.
| |
| 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 // element === null means dynamic property access. | |
| 19 if (element === null || !element.isTopLevel()) { | |
| 20 node.visitChildren(usager); | |
| 21 return; | |
|
Anton Muhin
2012/08/07 16:00:30
you promise to return String, but explicitly retur
| |
| 22 } | |
| 23 // Unqualified <class> in static invocation, why it's not a type annotation? | |
| 24 // Another option would be to process in visitStaticSend, NB: | |
| 25 // those elements are not top-level. | |
| 26 // OR: unqualified top level. | |
| 27 usager.useElement(node.selector, element); | |
| 28 if (node.receiver !== null) { | |
| 29 // <lib prefix>.<top level>. | |
| 30 usager.useNull(node.receiver); // Cut library prefix. | |
| 31 } | |
| 32 usager.visit(node.argumentsNode); | |
| 33 } | |
| 34 | |
| 35 R visitStaticSend(Send node) { | |
| 36 final element = elements[node]; | |
| 37 if (!element.isTopLevel()) { | |
| 38 node.visitChildren(usager); | |
| 39 return; | |
| 40 } | |
| 41 // Another ugly case: <lib prefix>.<top level> is represented as | |
| 42 // receiver: lib prefix, selector: top level. | |
| 43 usager.useMethod(node.selector, element); | |
| 44 if (node.receiver !== null) { | |
| 45 assert(elements[node.receiver].isPrefix()); | |
| 46 // Hack: putting null into map overrides receiver of original node. | |
| 47 usager.useNull(node.receiver); | |
| 48 } | |
| 49 usager.visit(node.argumentsNode); | |
| 50 } | |
| 51 } | |
| 52 | |
| 53 class Usager implements Visitor { | |
| 54 final Compiler compiler; | |
| 55 final Map<Node, Usage> usages; | |
| 56 Element currentElement; | |
| 57 TreeElements treeElements; | |
| 58 | |
| 59 Usager(this.compiler) : usages = new Map<Node, Usage>(); | |
| 60 | |
| 61 /** | |
| 62 * Checks if [:libraryElement:] is a core lib, that is a library | |
| 63 * provided by the implementation like dart:core, dart:coreimpl, etc. | |
| 64 */ | |
| 65 bool isDartCoreLib(Compiler compiler, LibraryElement libraryElement) { | |
|
Anton Muhin
2012/08/07 16:00:30
I don't think it should belong to any class.
Roman
2012/08/08 06:46:14
Forgot to remove.
| |
| 66 final libraries = compiler.libraries; | |
| 67 for (final uri in libraries.getKeys()) { | |
| 68 if (libraryElement === libraries[uri]) { | |
| 69 if (uri.startsWith('dart:')) return true; | |
| 70 } | |
| 71 } | |
| 72 return false; | |
| 73 } | |
| 74 | |
| 75 void processConstructorName( | |
| 76 FunctionElement element, FunctionExpression node) { | |
| 77 // Two complicated cases for class/interface renaming: | |
| 78 // 1) class which implements constructors of other interfaces, but not | |
| 79 // implements interfaces themselves: | |
| 80 // 0.dart: class C { I(); } | |
| 81 // 1.dart and 2.dart: interface I default C { I(); } | |
| 82 // now we have to duplicate our I() constructor in C class with | |
| 83 // proper names. | |
| 84 // 2) (even worse for us): | |
| 85 // 0.dart: class C { C(); } | |
| 86 // 1.dart: interface C default p0.C { C(); } | |
| 87 // the second case is just a bug now. | |
| 88 final enclosingClass = currentElement.getEnclosingClass(); | |
| 89 Node nameNode = node.name; | |
| 90 if (nameNode is Send) nameNode = nameNode.receiver; | |
| 91 if (nameNode.token.slowToString() == enclosingClass.name.slowToString()) { | |
|
Anton Muhin
2012/08/07 16:24:08
please, add a comment that this if is needed for c
Roman
2012/08/08 06:46:14
Done.
| |
| 92 useType(nameNode, enclosingClass.type); | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 void process(Element element, TreeElements elements) { | |
| 97 currentElement = element; | |
| 98 treeElements = elements; | |
| 99 Node elementNode = element.parseNode(compiler); | |
| 100 if (element.isGenerativeConstructor() || element.isFactoryConstructor()) { | |
| 101 processConstructorName(element, elementNode); | |
| 102 } | |
| 103 elementNode.accept(this); | |
| 104 } | |
| 105 | |
| 106 Type resolveType(TypeAnnotation typeAnnotation) { | |
| 107 if (treeElements === null) return null; | |
| 108 var result = treeElements.getType(typeAnnotation); | |
|
Anton Muhin
2012/08/07 16:00:30
please, TODO to have better type resolution.
Roman
2012/08/08 06:46:14
Done.
| |
| 109 if (result === null) { | |
| 110 result = compiler.resolveTypeAnnotation(currentElement, typeAnnotation); | |
| 111 } | |
| 112 return result; | |
| 113 } | |
| 114 | |
| 115 void useType(Node node, Type type) { | |
|
Anton Muhin
2012/08/07 16:00:30
as we discussed, use is probably wrong name
Roman
2012/08/08 06:46:14
renamed to placeholderForType
| |
| 116 assert(type !== null); | |
| 117 usages[node] = new TypeUsage(type); | |
| 118 } | |
| 119 void useMethod(Node node, Element method) { | |
| 120 assert(method !== null); | |
| 121 assert(method is FunctionElement || method is VariableElement); | |
| 122 usages[node] = new MethodUsage(method); | |
| 123 } | |
| 124 void useNull(Node node) { | |
| 125 usages[node] = new NullUsage(); | |
| 126 } | |
| 127 void useElement(Node node, Element element) { | |
| 128 assert(element !== null); | |
| 129 usages[node] = new ElementUsage(element); | |
| 130 } | |
| 131 | |
| 132 void internalError(String reason, [Node node]) { | |
| 133 compiler.cancel(reason: reason, node: node); | |
| 134 } | |
| 135 | |
| 136 R visit(Node node) => (node === null) ? null : node.accept(this); | |
| 137 | |
| 138 R visitBlock(Block node) => node.visitChildren(this); | |
| 139 R visitBreakStatement(BreakStatement node) => node.visitChildren(this); | |
| 140 R visitCascade(Cascade node) => node.visitChildren(this); | |
| 141 R visitCascadeReceiver(CascadeReceiver node) => node.visitChildren(this); | |
| 142 R visitCaseMatch(CaseMatch node) => node.visitChildren(this); | |
| 143 R visitCatchBlock(CatchBlock node) => node.visitChildren(this); | |
| 144 R visitClassNode(ClassNode node) { | |
| 145 internalError('Should never meet ClassNode', node); | |
| 146 } | |
| 147 R visitConditional(Conditional node) => node.visitChildren(this); | |
| 148 R visitContinueStatement(ContinueStatement node) => | |
| 149 node.visitChildren(this); | |
| 150 R visitDoWhile(DoWhile node) => node.visitChildren(this); | |
| 151 R visitEmptyStatement(EmptyStatement node) => node.visitChildren(this); | |
| 152 R visitExpressionStatement(ExpressionStatement node) => | |
| 153 node.visitChildren(this); | |
| 154 R visitFor(For node) => node.visitChildren(this); | |
| 155 R visitForIn(ForIn node) => node.visitChildren(this); | |
| 156 R visitFunctionDeclaration(FunctionDeclaration node) => | |
| 157 node.visitChildren(this); | |
| 158 R visitFunctionExpression(FunctionExpression node) => | |
| 159 node.visitChildren(this); | |
| 160 R visitIdentifier(Identifier node) => node.visitChildren(this); | |
| 161 R visitIf(If node) => node.visitChildren(this); | |
| 162 R visitLabel(Label node) => node.visitChildren(this); | |
| 163 R visitLabeledStatement(LabeledStatement node) => node.visitChildren(this); | |
| 164 R visitLiteralBool(LiteralBool node) => node.visitChildren(this); | |
| 165 R visitLiteralDouble(LiteralDouble node) => node.visitChildren(this); | |
| 166 R visitLiteralInt(LiteralInt node) => node.visitChildren(this); | |
| 167 R visitLiteralList(LiteralList node) => node.visitChildren(this); | |
| 168 R visitLiteralMap(LiteralMap node) => node.visitChildren(this); | |
| 169 R visitLiteralMapEntry(LiteralMapEntry node) => node.visitChildren(this); | |
| 170 R visitLiteralNull(LiteralNull node) => node.visitChildren(this); | |
| 171 R visitLiteralString(LiteralString node) => node.visitChildren(this); | |
| 172 R visitModifiers(Modifiers node) => node.visitChildren(this); | |
| 173 R visitNamedArgument(NamedArgument node) => node.visitChildren(this); | |
| 174 R visitNewExpression(NewExpression node) => node.visitChildren(this); | |
| 175 R visitNodeList(NodeList node) => node.visitChildren(this); | |
| 176 R visitOperator(Operator node) => node.visitChildren(this); | |
| 177 R visitParenthesizedExpression(ParenthesizedExpression node) => | |
| 178 node.visitChildren(this); | |
| 179 R visitReturn(Return node) => node.visitChildren(this); | |
| 180 R visitScriptTag(ScriptTag node) => node.visitChildren(this); | |
| 181 | |
| 182 R visitSend(Send send) => new SendVisitor(this, treeElements).visitSend(send); | |
| 183 | |
| 184 R visitSendSet(SendSet node) => node.visitChildren(this); | |
| 185 R visitStringInterpolation(StringInterpolation node) => | |
| 186 node.visitChildren(this); | |
| 187 R visitStringInterpolationPart(StringInterpolationPart node) => | |
| 188 node.visitChildren(this); | |
| 189 R visitStringJuxtaposition(StringJuxtaposition node) => | |
| 190 node.visitChildren(this); | |
| 191 R visitSwitchCase(SwitchCase node) => node.visitChildren(this); | |
| 192 R visitSwitchStatement(SwitchStatement node) => node.visitChildren(this); | |
| 193 R visitThrow(Throw node) => node.visitChildren(this); | |
| 194 R visitTryStatement(TryStatement node) => node.visitChildren(this); | |
| 195 | |
| 196 R visitTypeAnnotation(TypeAnnotation node) { | |
| 197 if (currentElement.isClass()) { | |
| 198 throw 'e'; | |
| 199 } | |
| 200 final type = compiler.resolveTypeAnnotation(currentElement, node); | |
| 201 if (type is !InterfaceType) return null; | |
| 202 var target = node.typeName; | |
| 203 if (node.typeName is Send) { | |
| 204 final element = treeElements[node]; | |
| 205 if (element !== null) { | |
| 206 final send = node.typeName.asSend(); | |
| 207 final isPrefixed = element.lookupConstructor( | |
| 208 send.receiver.source, send.selector.source) === null; | |
| 209 if (!isPrefixed) target = send.receiver; | |
| 210 } | |
| 211 } | |
| 212 useType(target, type); | |
| 213 visit(node.typeArguments); | |
| 214 } | |
| 215 | |
| 216 R visitTypedef(Typedef node) => node.visitChildren(this); | |
| 217 R visitTypeVariable(TypeVariable node) => node.visitChildren(this); | |
| 218 R visitVariableDefinitions(VariableDefinitions node) => | |
| 219 node.visitChildren(this); | |
| 220 R visitWhile(While node) => node.visitChildren(this); | |
| 221 } | |
| OLD | NEW |