| 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 SendVisitor extends ResolvedVisitor { | 5 class SendVisitor extends ResolvedVisitor { |
| 6 final PlaceholderCollector collector; | 6 final PlaceholderCollector collector; |
| 7 | 7 |
| 8 SendVisitor(this.collector, TreeElements elements) : super(elements); | 8 SendVisitor(this.collector, TreeElements elements) : super(elements); |
| 9 | 9 |
| 10 visitSuperSend(Send node) {} | 10 visitSuperSend(Send node) {} |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 // variable list element twice, better merge this with emitter logic. | 144 // variable list element twice, better merge this with emitter logic. |
| 145 currentElement = element.variables; | 145 currentElement = element.variables; |
| 146 elementNode = currentElement.parseNode(compiler); | 146 elementNode = currentElement.parseNode(compiler); |
| 147 collectFieldDeclarationPlaceholders(element, elementNode); | 147 collectFieldDeclarationPlaceholders(element, elementNode); |
| 148 } else if (element is ClassElement || element is TypedefElement) { | 148 } else if (element is ClassElement || element is TypedefElement) { |
| 149 currentElement = element; | 149 currentElement = element; |
| 150 elementNode = currentElement.parseNode(compiler); | 150 elementNode = currentElement.parseNode(compiler); |
| 151 } else { | 151 } else { |
| 152 assert(false); // Unreachable. | 152 assert(false); // Unreachable. |
| 153 } | 153 } |
| 154 elementNode.accept(this); | 154 compiler.withCurrentElement(element, () { |
| 155 elementNode.accept(this); |
| 156 }); |
| 155 } | 157 } |
| 156 | 158 |
| 157 Type resolveType(TypeAnnotation typeAnnotation) { | 159 Type resolveType(TypeAnnotation typeAnnotation) { |
| 158 if (treeElements === null) return null; | 160 if (treeElements === null) return null; |
| 159 var result = treeElements.getType(typeAnnotation); | 161 var result = treeElements.getType(typeAnnotation); |
| 160 // TODO: Have better type resolution. | 162 // TODO: Have better type resolution. |
| 161 if (result === null) { | 163 if (result === null) { |
| 162 result = compiler.resolveTypeAnnotation(currentElement, typeAnnotation); | 164 result = compiler.resolveTypeAnnotation(currentElement, typeAnnotation); |
| 163 } | 165 } |
| 164 return result; | 166 return result; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 180 assert(element !== null); | 182 assert(element !== null); |
| 181 placeholders[node] = new ElementPlaceholder(element); | 183 placeholders[node] = new ElementPlaceholder(element); |
| 182 } | 184 } |
| 183 | 185 |
| 184 void makePrivateIdentifier(Identifier node) { | 186 void makePrivateIdentifier(Identifier node) { |
| 185 assert(node !== null); | 187 assert(node !== null); |
| 186 placeholders[node] = | 188 placeholders[node] = |
| 187 new PrivatePlaceholder(currentElement.getLibrary(), node); | 189 new PrivatePlaceholder(currentElement.getLibrary(), node); |
| 188 } | 190 } |
| 189 | 191 |
| 192 void makeUnresolvedPlaceholder(Node node) { |
| 193 placeholders[node] = const UnresolvedPlaceholder(); |
| 194 } |
| 195 |
| 190 void internalError(String reason, [Node node]) { | 196 void internalError(String reason, [Node node]) { |
| 191 compiler.cancel(reason: reason, node: node); | 197 compiler.cancel(reason: reason, node: node); |
| 192 } | 198 } |
| 193 | 199 |
| 194 visit(Node node) => (node === null) ? null : node.accept(this); | 200 visit(Node node) => (node === null) ? null : node.accept(this); |
| 195 | 201 |
| 196 visitNode(Node node) { node.visitChildren(this); } // We must go deeper. | 202 visitNode(Node node) { node.visitChildren(this); } // We must go deeper. |
| 197 | 203 |
| 198 visitSend(Send send) { | 204 visitSend(Send send) { |
| 199 new SendVisitor(this, treeElements).visitSend(send); | 205 new SendVisitor(this, treeElements).visitSend(send); |
| 200 send.visitChildren(this); | 206 send.visitChildren(this); |
| 201 } | 207 } |
| 202 | 208 |
| 203 visitSendSet(SendSet send) { | 209 visitSendSet(SendSet send) { |
| 204 final element = treeElements[send]; | 210 final element = treeElements[send]; |
| 205 if (element !== null && element.isInstanceMember()) { | 211 if (element !== null && element.isInstanceMember()) { |
| 206 tryMakePrivateIdentifier(send.selector.asIdentifier()); | 212 tryMakePrivateIdentifier(send.selector.asIdentifier()); |
| 207 } | 213 } |
| 208 send.visitChildren(this); | 214 send.visitChildren(this); |
| 209 } | 215 } |
| 210 | 216 |
| 217 static bool isPlainTypeName(TypeAnnotation typeAnnotation) { |
| 218 if (typeAnnotation.typeName is !Identifier) return false; |
| 219 if (typeAnnotation.typeArguments === null) return true; |
| 220 if (typeAnnotation.typeArguments.length === 0) return true; |
| 221 return false; |
| 222 } |
| 223 |
| 224 static bool isDynamicType(TypeAnnotation typeAnnotation) { |
| 225 if (!isPlainTypeName(typeAnnotation)) return false; |
| 226 String name = typeAnnotation.typeName.asIdentifier().source.slowToString(); |
| 227 return name == 'Dynamic'; |
| 228 } |
| 229 |
| 211 visitTypeAnnotation(TypeAnnotation node) { | 230 visitTypeAnnotation(TypeAnnotation node) { |
| 231 // Poor man generic variables resolution. |
| 232 // TODO(antonm): get rid of it once resolver can deal with it. |
| 233 if (isPlainTypeName(node)) { |
| 234 String name = node.typeName.source.slowToString(); |
| 235 if (currentElement is TypedefElement) { |
| 236 TypedefElement typedefElement = currentElement; |
| 237 NodeList typeParameters = typedefElement.cachedNode.typeParameters; |
| 238 if (typeParameters !== null) { |
| 239 for (TypeVariable typeVariable in typeParameters) { |
| 240 Identifier typeVariableName = typeVariable.name; |
| 241 // If names are equal, then it's a variable and sholdn't be renamed. |
| 242 if (typeVariableName.source.slowToString() == name) return; |
| 243 } |
| 244 } |
| 245 } |
| 246 if (currentElement is ClassElement) { |
| 247 ClassElement classElement = currentElement; |
| 248 String name = node.typeName.source.slowToString(); |
| 249 for (TypeVariableType argument in classElement.type.arguments) { |
| 250 // If names are equal, then it's a variable and sholdn't be renamed. |
| 251 if (argument.name.slowToString() == name) return; |
| 252 } |
| 253 } |
| 254 } |
| 212 final type = compiler.resolveTypeAnnotation(currentElement, node); | 255 final type = compiler.resolveTypeAnnotation(currentElement, node); |
| 213 if (type is !InterfaceType) return null; | 256 if (type is !InterfaceType) return null; |
| 214 var target = node.typeName; | 257 var target = node.typeName; |
| 215 if (node.typeName is Send) { | 258 if (node.typeName is Send) { |
| 216 final element = treeElements[node]; | 259 final element = treeElements[node]; |
| 217 if (element !== null) { | 260 if (element !== null) { |
| 218 final send = node.typeName.asSend(); | 261 final send = node.typeName.asSend(); |
| 219 final hasPrefix = element.lookupConstructor( | 262 final hasPrefix = element.lookupConstructor( |
| 220 send.receiver.source, send.selector.source) === null; | 263 send.receiver.source, send.selector.source) === null; |
| 221 if (!hasPrefix) target = send.receiver; | 264 if (!hasPrefix) target = send.receiver; |
| 222 } | 265 } |
| 223 } | 266 } |
| 224 makeTypePlaceholder(target, type); | 267 // TODO(antonm): is there a better way to detect unresolved types? |
| 268 if (type !== compiler.types.dynamicType) { |
| 269 makeTypePlaceholder(target, type); |
| 270 } else { |
| 271 if (!isDynamicType(node)) makeUnresolvedPlaceholder(target); |
| 272 } |
| 225 node.visitChildren(this); | 273 node.visitChildren(this); |
| 226 } | 274 } |
| 227 } | 275 } |
| OLD | NEW |