| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 TreeElements { | 5 class TreeElements { |
| 6 Map<Node, Element> map; | 6 Map<Node, Element> map; |
| 7 TreeElements() : map = new LinkedHashMap<Node, Element>(); | 7 TreeElements() : map = new LinkedHashMap<Node, Element>(); |
| 8 operator []=(Node node, Element element) => map[node] = element; | 8 operator []=(Node node, Element element) => map[node] = element; |
| 9 operator [](Node node) => map[node]; | 9 operator [](Node node) => map[node]; |
| 10 } | 10 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 } | 35 } |
| 36 | 36 |
| 37 TreeElements resolveMethodElement(FunctionElement element) { | 37 TreeElements resolveMethodElement(FunctionElement element) { |
| 38 FunctionExpression tree = element.parseNode(compiler, compiler); | 38 FunctionExpression tree = element.parseNode(compiler, compiler); |
| 39 // TODO(ahe): Can this be cleaned up to use resolveSignature? | 39 // TODO(ahe): Can this be cleaned up to use resolveSignature? |
| 40 ResolverVisitor visitor = new SignatureResolverVisitor(compiler, element); | 40 ResolverVisitor visitor = new SignatureResolverVisitor(compiler, element); |
| 41 visitor.visit(tree); | 41 visitor.visit(tree); |
| 42 | 42 |
| 43 visitor = new FullResolverVisitor.from(visitor); | 43 visitor = new FullResolverVisitor.from(visitor); |
| 44 if (tree.initializers != null) { | 44 if (tree.initializers != null) { |
| 45 resolveInitializers(element, tree, visitor); | 45 new InitializerResolver(visitor, element).resolveInitializers(tree); |
| 46 } | 46 } |
| 47 visitor.visit(tree.body); | 47 visitor.visit(tree.body); |
| 48 | 48 |
| 49 // Resolve the type annotations encountered in the method. | 49 // Resolve the type annotations encountered in the method. |
| 50 while (!toResolve.isEmpty()) { | 50 while (!toResolve.isEmpty()) { |
| 51 toResolve.removeFirst().resolve(compiler); | 51 toResolve.removeFirst().resolve(compiler); |
| 52 } | 52 } |
| 53 return visitor.mapping; | 53 return visitor.mapping; |
| 54 } | 54 } |
| 55 | 55 |
| 56 TreeElements resolveFieldElement(Element element) { | 56 TreeElements resolveFieldElement(Element element) { |
| 57 Node tree = element.parseNode(compiler, compiler); | 57 Node tree = element.parseNode(compiler, compiler); |
| 58 ResolverVisitor visitor = new FullResolverVisitor(compiler, element); | 58 ResolverVisitor visitor = new FullResolverVisitor(compiler, element); |
| 59 if (tree is SendSet) { | 59 if (tree is SendSet) { |
| 60 SendSet send = tree; | 60 SendSet send = tree; |
| 61 visitor.visit(send.arguments.head); | 61 visitor.visit(send.arguments.head); |
| 62 } | 62 } |
| 63 return visitor.mapping; | 63 return visitor.mapping; |
| 64 } | 64 } |
| 65 | 65 |
| 66 bool isInitializer(SendSet node) { | |
| 67 if (node.selector.asIdentifier() == null) return false; | |
| 68 if (node.receiver == null) return true; | |
| 69 if (node.receiver.asIdentifier() == null) return false; | |
| 70 return node.receiver.asIdentifier().isThis(); | |
| 71 } | |
| 72 | |
| 73 SourceString getInitializerFieldName(SendSet node, onError(node)) { | |
| 74 if (!isInitializer(node)) onError(node); | |
| 75 return node.selector.asIdentifier().source; | |
| 76 } | |
| 77 | |
| 78 void resolveInitializers(Element element, FunctionExpression node, | |
| 79 ResolverVisitor visitor) { | |
| 80 void onError(node) { | |
| 81 visitor.error(node, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); | |
| 82 } | |
| 83 Map<SourceString, Node> initialized = new Map<SourceString, Node>(); | |
| 84 for (Link<Node> link = node.initializers.nodes; | |
| 85 !link.isEmpty(); | |
| 86 link = link.tail) { | |
| 87 if (link.head.asSendSet() != null) { | |
| 88 SendSet init = link.head; | |
| 89 SourceString name = getInitializerFieldName(init, onError); | |
| 90 ClassElement classElement = element.enclosingElement; | |
| 91 Element target = classElement.lookupLocalMember(name); | |
| 92 Node selector = init.selector; | |
| 93 if (target == null) { | |
| 94 visitor.error(selector, MessageKind.CANNOT_RESOLVE, [name]); | |
| 95 } else if (target.kind != ElementKind.FIELD) { | |
| 96 visitor.error(selector, MessageKind.NOT_A_FIELD, [name]); | |
| 97 } else if (!target.isInstanceMember()) { | |
| 98 visitor.error(selector, MessageKind.INIT_STATIC_FIELD, [name]); | |
| 99 } | |
| 100 visitor.useElement(init, target); | |
| 101 if (initialized.containsKey(name)) { | |
| 102 visitor.error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); | |
| 103 visitor.warning(initialized[name], MessageKind.ALREADY_INITIALIZED, | |
| 104 [name]); | |
| 105 } | |
| 106 initialized[name] = init; | |
| 107 Node value = init.arguments.head; | |
| 108 visitor.visitInStaticContext(value); | |
| 109 } else if (link.head.asSend() !== null) { | |
| 110 // TODO(karlklose): super(...), this(...). | |
| 111 compiler.cancel('uniplemented', node:link.head); | |
| 112 } else { | |
| 113 compiler.cancel('internal error: invalid initializer', | |
| 114 node: link.head); | |
| 115 } | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 void resolveType(ClassElement element) { | 66 void resolveType(ClassElement element) { |
| 120 measure(() { | 67 measure(() { |
| 121 ClassNode tree = element.parseNode(compiler, compiler); | 68 ClassNode tree = element.parseNode(compiler, compiler); |
| 122 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler); | 69 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler); |
| 123 visitor.visit(tree); | 70 visitor.visit(tree); |
| 124 }); | 71 }); |
| 125 } | 72 } |
| 126 | 73 |
| 127 void resolveSignature(FunctionElement element) { | 74 void resolveSignature(FunctionElement element) { |
| 128 measure(() { | 75 measure(() { |
| 129 FunctionExpression node = element.parseNode(compiler, compiler); | 76 FunctionExpression node = element.parseNode(compiler, compiler); |
| 130 SignatureResolverVisitor visitor = | 77 SignatureResolverVisitor visitor = |
| 131 new SignatureResolverVisitor(compiler, element); | 78 new SignatureResolverVisitor(compiler, element); |
| 132 visitor.visitFunctionExpression(node); | 79 visitor.visitFunctionExpression(node); |
| 133 }); | 80 }); |
| 134 } | 81 } |
| 135 } | 82 } |
| 136 | 83 |
| 84 |
| 85 class InitializerResolver { |
| 86 final ResolverVisitor visitor; |
| 87 final FunctionElement constructor; |
| 88 final Map<SourceString, Node> initialized; |
| 89 Link<Node> initializers; |
| 90 bool hasSuper; |
| 91 |
| 92 bool isSuperConstructorCall(Send node) { |
| 93 return (node.receiver === null && |
| 94 node.selector.asIdentifier() !== null && |
| 95 node.selector.asIdentifier().isSuper()) || |
| 96 (node.receiver !== null && |
| 97 node.receiver.asIdentifier() !== null && |
| 98 node.receiver.asIdentifier().isSuper() && |
| 99 node.selector.asIdentifier() !== null); |
| 100 } |
| 101 |
| 102 bool isConstructorRedirect(Send node) { |
| 103 return (node.receiver === null && |
| 104 node.selector.asIdentifier() !== null && |
| 105 node.selector.asIdentifier().isThis()) || |
| 106 (node.receiver !== null && |
| 107 node.receiver.asIdentifier() !== null && |
| 108 node.receiver.asIdentifier().isThis() && |
| 109 node.selector.asIdentifier() !== null); |
| 110 } |
| 111 |
| 112 InitializerResolver(this.visitor, this.constructor) |
| 113 : initialized = new Map<SourceString, Node>(), hasSuper = false; |
| 114 |
| 115 error(Node node, MessageKind kind, [arguments = const []]) { |
| 116 visitor.error(node, kind, arguments); |
| 117 } |
| 118 |
| 119 warning(Node node, MessageKind kind, [arguments = const []]) { |
| 120 visitor.warning(node, kind, arguments); |
| 121 } |
| 122 |
| 123 bool isFieldInitializer(SendSet node) { |
| 124 if (node.selector.asIdentifier() == null) return false; |
| 125 if (node.receiver == null) return true; |
| 126 if (node.receiver.asIdentifier() == null) return false; |
| 127 return node.receiver.asIdentifier().isThis(); |
| 128 } |
| 129 |
| 130 void resolveFieldInitializer(SendSet init) { |
| 131 // init is of the form [this.]field = value. |
| 132 final Node selector = init.selector; |
| 133 final SourceString name = selector.asIdentifier().source; |
| 134 // Lookup target field. |
| 135 Element target; |
| 136 if (isFieldInitializer(init)) { |
| 137 final ClassElement classElement = constructor.enclosingElement; |
| 138 target = classElement.lookupLocalMember(name); |
| 139 if (target === null) { |
| 140 error(selector, MessageKind.CANNOT_RESOLVE, [name]); |
| 141 } else if (target.kind != ElementKind.FIELD) { |
| 142 error(selector, MessageKind.NOT_A_FIELD, [name]); |
| 143 } else if (!target.isInstanceMember()) { |
| 144 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); |
| 145 } |
| 146 } else { |
| 147 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); |
| 148 } |
| 149 visitor.useElement(init, target); |
| 150 // Check for duplicate initializers. |
| 151 if (initialized.containsKey(name)) { |
| 152 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); |
| 153 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]); |
| 154 } |
| 155 initialized[name] = init; |
| 156 // Resolve initializing value. |
| 157 visitor.visitInStaticContext(init.arguments.head); |
| 158 } |
| 159 |
| 160 SourceString getConstructorName(Send node) { |
| 161 if (node.receiver !== null) { |
| 162 return node.selector.asIdentifier().source; |
| 163 } else { |
| 164 return const SourceString(''); |
| 165 } |
| 166 } |
| 167 |
| 168 void resolveSuperOrThis(Send call) { |
| 169 noConstructor(e) { |
| 170 if (e !== null) error(call, MessageKind.NO_CONSTRUCTOR, [e.name, e.kind]); |
| 171 } |
| 172 |
| 173 ClassElement lookupTarget = constructor.enclosingElement; |
| 174 bool validTarget = true; |
| 175 if (isSuperConstructorCall(call)) { |
| 176 // Check for invalid initializers. |
| 177 if (hasSuper) { |
| 178 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER); |
| 179 } |
| 180 hasSuper = true; |
| 181 // Calculate correct lookup target and constructor name. |
| 182 if (lookupTarget.name == Types.OBJECT) { |
| 183 error(call, MessageKind.SUPER_INITIALIZER_IN_OBJECT); |
| 184 } else { |
| 185 lookupTarget = lookupTarget.supertype.element; |
| 186 } |
| 187 } else if (isConstructorRedirect(call)) { |
| 188 // Check that there are no other initializers. |
| 189 if (!initializers.tail.isEmpty()) { |
| 190 error(call, MessageKind.REDIRECTING_CTOR_HAS_INITIALIZER); |
| 191 } |
| 192 } else { |
| 193 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED); |
| 194 validTarget = false; |
| 195 } |
| 196 |
| 197 if (validTarget) { |
| 198 final SourceString className = lookupTarget.name; |
| 199 final SourceString constructorName = getConstructorName(call); |
| 200 FunctionElement target = |
| 201 lookupTarget.lookupConstructor(className, constructorName, |
| 202 noConstructor); |
| 203 if (target === null && call.arguments.isEmpty()) { |
| 204 target = lookupTarget.getSynthesizedConstructor(); |
| 205 } |
| 206 if (target === null) { |
| 207 String name = (constructorName === const SourceString('')) |
| 208 ? className.stringValue |
| 209 : "$className.$constructorName"; |
| 210 error(call, MessageKind.CANNOT_RESOLVE_CONSTRUCTOR, [name]); |
| 211 } else { |
| 212 final Compiler compiler = visitor.compiler; |
| 213 // TODO(karlklose): support optional arguments. |
| 214 if (target.parameterCount(compiler) != call.argumentCount()) { |
| 215 error(call, MessageKind.NO_MATCHING_CONSTRUCTOR); |
| 216 } |
| 217 } |
| 218 visitor.useElement(call, target); |
| 219 } |
| 220 // Resolve the arguments of the call. |
| 221 for (Link<Node> arguments = call.arguments; |
| 222 !arguments.isEmpty(); |
| 223 arguments = arguments.tail) { |
| 224 visitor.visitInStaticContext(arguments.head); |
| 225 } |
| 226 } |
| 227 |
| 228 void resolveInitializers(FunctionExpression node) { |
| 229 if (node.initializers === null) return; |
| 230 initializers = node.initializers.nodes; |
| 231 Compiler compiler = visitor.compiler; |
| 232 for (Link<Node> link = initializers; |
| 233 !link.isEmpty(); |
| 234 link = link.tail) { |
| 235 if (link.head.asSendSet() != null) { |
| 236 final SendSet init = link.head.asSendSet(); |
| 237 resolveFieldInitializer(init); |
| 238 } else if (link.head.asSend() !== null) { |
| 239 final Send call = link.head.asSend(); |
| 240 resolveSuperOrThis(call); |
| 241 } else { |
| 242 visitor.compiler.cancel('internal error: invalid initializer', |
| 243 node: link.head); |
| 244 } |
| 245 } |
| 246 } |
| 247 } |
| 248 |
| 249 |
| 137 // TODO(ahe): Frog cannot handle generic types. | 250 // TODO(ahe): Frog cannot handle generic types. |
| 138 class ResolverVisitor extends AbstractVisitor/*<Element>*/ { | 251 class ResolverVisitor extends AbstractVisitor/*<Element>*/ { |
| 139 final Compiler compiler; | 252 final Compiler compiler; |
| 140 final TreeElements mapping; | 253 final TreeElements mapping; |
| 141 final Element enclosingElement; | 254 final Element enclosingElement; |
| 142 bool inInstanceContext; | 255 bool inInstanceContext; |
| 143 Scope context; | 256 Scope context; |
| 144 ClassElement currentClass; | 257 ClassElement currentClass; |
| 145 bool typeRequired = false; | 258 bool typeRequired = false; |
| 146 | 259 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 173 compiler.reportWarning(node, warning); | 286 compiler.reportWarning(node, warning); |
| 174 } | 287 } |
| 175 | 288 |
| 176 cancel(Node node, String message) { | 289 cancel(Node node, String message) { |
| 177 compiler.cancel(message, node: node); | 290 compiler.cancel(message, node: node); |
| 178 } | 291 } |
| 179 | 292 |
| 180 Element lookup(Node node, SourceString name) { | 293 Element lookup(Node node, SourceString name) { |
| 181 Element result = context.lookup(name); | 294 Element result = context.lookup(name); |
| 182 if (!inInstanceContext && result != null && result.isInstanceMember()) { | 295 if (!inInstanceContext && result != null && result.isInstanceMember()) { |
| 183 error(node, MessageKind.NOT_STATIC, [node]); | 296 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); |
| 184 } | 297 } |
| 185 return result; | 298 return result; |
| 186 } | 299 } |
| 187 | 300 |
| 188 visitInStaticContext(Node node) { | 301 visitInStaticContext(Node node) { |
| 189 bool wasInstanceContext = inInstanceContext; | 302 bool wasInstanceContext = inInstanceContext; |
| 190 inInstanceContext = false; | 303 inInstanceContext = false; |
| 191 visit(node); | 304 visit(node); |
| 192 inInstanceContext = wasInstanceContext; | 305 inInstanceContext = wasInstanceContext; |
| 193 } | 306 } |
| 194 | 307 |
| 195 visit(Node node) { | 308 visit(Node node) { |
| 196 if (node == null) return null; | 309 if (node == null) return null; |
| 197 return node.accept(this); | 310 return node.accept(this); |
| 198 } | 311 } |
| 199 | 312 |
| 200 visitIdentifier(Identifier node) { | 313 visitIdentifier(Identifier node) { |
| 201 if (node.isThis()) { | 314 if (node.isThis()) { |
| 202 if (!inInstanceContext) error(node, MessageKind.NO_THIS_IN_STATIC); | 315 if (!inInstanceContext) { |
| 316 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); |
| 317 } |
| 203 return null; | 318 return null; |
| 204 } else if (node.isSuper()) { | 319 } else if (node.isSuper()) { |
| 205 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); | 320 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); |
| 206 return null; | 321 return null; |
| 207 } else { | 322 } else { |
| 208 Element element = lookup(node, node.source); | 323 Element element = lookup(node, node.source); |
| 209 if (element == null) { | 324 if (element == null) { |
| 210 error(node, MessageKind.CANNOT_RESOLVE, [node]); | 325 error(node, MessageKind.CANNOT_RESOLVE, [node]); |
| 211 } | 326 } |
| 212 return useElement(node, element); | 327 return useElement(node, element); |
| 213 } | 328 } |
| 214 } | 329 } |
| 215 | 330 |
| 216 visitTypeAnnotation(TypeAnnotation node) { | 331 visitTypeAnnotation(TypeAnnotation node) { |
| 217 Identifier name = node.typeName.asIdentifier(); | 332 SourceString className; |
| 218 if (name === null) { | 333 if (node.typeName.asSend() !== null) { |
| 219 // TODO(karlklose): In progress. | 334 // In new and const expressions, the type name can be a Send to |
| 220 cancel(node.typeName, "not implemented"); | 335 // denote named constructors or library prefixes. |
| 336 Send send = node.typeName.asSend(); |
| 337 className = send.receiver.asIdentifier().source; |
| 338 } else { |
| 339 className = node.typeName.asIdentifier().source; |
| 221 } | 340 } |
| 222 if (name.source == const SourceString('var')) return null; | 341 if (className == const SourceString('var')) return null; |
| 223 if (name.source == const SourceString('void')) return null; | 342 if (className == const SourceString('void')) return null; |
| 224 Element element = context.lookup(name.source); | 343 Element element = context.lookup(className); |
| 225 if (element === null) { | 344 if (element === null) { |
| 226 if (typeRequired) { | 345 if (typeRequired) { |
| 227 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [name]); | 346 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); |
| 228 } else { | 347 } else { |
| 229 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [name]); | 348 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]); |
| 230 } | 349 } |
| 231 } else if (element.kind !== ElementKind.CLASS) { | 350 } else if (element.kind !== ElementKind.CLASS) { |
| 232 if (typeRequired) { | 351 if (typeRequired) { |
| 233 error(node, MessageKind.NOT_A_TYPE, [name]); | 352 error(node, MessageKind.NOT_A_TYPE, [className]); |
| 234 } else { | 353 } else { |
| 235 warning(node, MessageKind.NOT_A_TYPE, [name]); | 354 warning(node, MessageKind.NOT_A_TYPE, [className]); |
| 236 } | 355 } |
| 237 } else { | 356 } else { |
| 238 ClassElement cls = element; | 357 ClassElement cls = element; |
| 239 compiler.resolver.toResolve.add(element); | 358 compiler.resolver.toResolve.add(element); |
| 240 // TODO(ahe): This should be a Type. | 359 // TODO(ahe): This should be a Type. |
| 241 useElement(node, element); | 360 useElement(node, element); |
| 242 } | 361 } |
| 243 return element; | 362 return element; |
| 244 } | 363 } |
| 245 | 364 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 visitFor(For node) { | 445 visitFor(For node) { |
| 327 Scope scope = new BlockScope(context); | 446 Scope scope = new BlockScope(context); |
| 328 visitIn(node.initializer, scope); | 447 visitIn(node.initializer, scope); |
| 329 visitIn(node.condition, scope); | 448 visitIn(node.condition, scope); |
| 330 visitIn(node.update, scope); | 449 visitIn(node.update, scope); |
| 331 visitIn(node.body, scope); | 450 visitIn(node.body, scope); |
| 332 } | 451 } |
| 333 | 452 |
| 334 visitFunctionExpression(FunctionExpression node) { | 453 visitFunctionExpression(FunctionExpression node) { |
| 335 visit(node.returnType); | 454 visit(node.returnType); |
| 455 SourceString name; |
| 336 if (node.name === null) { | 456 if (node.name === null) { |
| 337 cancel(node, "anonymous functions are not implemented"); | 457 cancel(node, "anonymous functions are not implemented"); |
| 338 } | 458 } |
| 339 if (node.name.asIdentifier() === null) { | 459 name = node.name.asIdentifier().source; |
| 340 cancel(node.name, "named constructors are not implemented"); | |
| 341 } | |
| 342 FunctionElement enclosingElement = new FunctionElement.node( | 460 FunctionElement enclosingElement = new FunctionElement.node( |
| 343 node, ElementKind.FUNCTION, null, context.element); | 461 name, node, ElementKind.FUNCTION, null, context.element); |
| 344 defineElement(node, enclosingElement); | 462 defineElement(node, enclosingElement); |
| 345 context = new MethodScope(context, enclosingElement); | 463 context = new MethodScope(context, enclosingElement); |
| 346 | 464 |
| 347 // TODO(ahe): Can this be cleaned up to use resolveSignature? | 465 // TODO(ahe): Can this be cleaned up to use resolveSignature? |
| 348 ParametersVisitor visitor = new ParametersVisitor(this); | 466 ParametersVisitor visitor = new ParametersVisitor(this); |
| 349 visitor.visit(node.parameters); | 467 visitor.visit(node.parameters); |
| 350 enclosingElement.parameters = visitor.elements.toLink(); | 468 enclosingElement.parameters = visitor.elements.toLink(); |
| 351 | 469 |
| 352 visit(node.body); | 470 visit(node.body); |
| 353 context = context.parent; | 471 context = context.parent; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 | 628 |
| 511 visitParenthesizedExpression(ParenthesizedExpression node) { | 629 visitParenthesizedExpression(ParenthesizedExpression node) { |
| 512 visit(node.expression); | 630 visit(node.expression); |
| 513 } | 631 } |
| 514 | 632 |
| 515 visitNewExpression(NewExpression node) { | 633 visitNewExpression(NewExpression node) { |
| 516 if (node.isConst()) cancel(node, 'const expressions are not implemented'); | 634 if (node.isConst()) cancel(node, 'const expressions are not implemented'); |
| 517 | 635 |
| 518 visit(node.send.argumentsNode); | 636 visit(node.send.argumentsNode); |
| 519 | 637 |
| 638 SourceString constructorName; |
| 639 Node typeName = node.send.selector.asTypeAnnotation().typeName; |
| 640 if (typeName.asSend() !== null) { |
| 641 Identifier receiver = typeName.asSend().receiver.asIdentifier(); |
| 642 Identifier selector = typeName.asSend().selector.asIdentifier(); |
| 643 SourceString className = receiver.source; |
| 644 SourceString name = selector.source; |
| 645 constructorName = new SourceString('$className.$name'); |
| 646 } else { |
| 647 constructorName = typeName.asIdentifier().source; |
| 648 } |
| 520 ClassElement cls = resolveTypeRequired(node.send.selector); | 649 ClassElement cls = resolveTypeRequired(node.send.selector); |
| 521 Element constructor = null; | 650 Element constructor = null; |
| 522 if (cls !== null) { | 651 if (cls !== null) { |
| 523 // TODO(ngeoffray): set constructor-name correctly. | 652 constructor = cls.resolve(compiler).lookupConstructor(constructorName); |
| 524 SourceString name = cls.name; | 653 if (constructorName == cls.name |
| 525 constructor = cls.resolve(compiler).lookupConstructor(name); | |
| 526 if (name == cls.name | |
| 527 && constructor === null | 654 && constructor === null |
| 528 && node.send.argumentsNode.isEmpty()) { | 655 && node.send.argumentsNode.isEmpty()) { |
| 529 constructor = cls.getSynthesizedConstructor(); | 656 constructor = cls.getSynthesizedConstructor(); |
| 530 } | 657 } |
| 531 if (constructor === null) { | 658 if (constructor === null) { |
| 532 error(node, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node]); | 659 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]); |
| 660 } else { |
| 661 FunctionElement function = constructor; |
| 662 // TODO(karlklose): handle optional arguments. |
| 663 if (node.send.argumentCount() != function.parameterCount(compiler)) { |
| 664 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]); |
| 665 } |
| 533 } | 666 } |
| 667 } else { |
| 668 Node selector = node.send.selector; |
| 669 error(selector, MessageKind.CANNOT_RESOLVE_TYPE, [selector]); |
| 534 } | 670 } |
| 535 | |
| 536 useElement(node.send, constructor); | 671 useElement(node.send, constructor); |
| 537 return null; | 672 return null; |
| 538 } | 673 } |
| 539 | 674 |
| 540 ClassElement resolveTypeRequired(Node node) { | 675 ClassElement resolveTypeRequired(Node node) { |
| 541 bool old = typeRequired; | 676 bool old = typeRequired; |
| 542 typeRequired = true; | 677 typeRequired = true; |
| 543 ClassElement cls = visit(node); | 678 ClassElement cls = visit(node); |
| 544 typeRequired = old; | 679 typeRequired = old; |
| 545 return cls; | 680 return cls; |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 class TopScope extends Scope { | 961 class TopScope extends Scope { |
| 827 Universe universe; | 962 Universe universe; |
| 828 | 963 |
| 829 TopScope(Universe this.universe) : super(null, null); | 964 TopScope(Universe this.universe) : super(null, null); |
| 830 Element lookup(SourceString name) => universe.find(name); | 965 Element lookup(SourceString name) => universe.find(name); |
| 831 | 966 |
| 832 Element add(Element element) { | 967 Element add(Element element) { |
| 833 throw "Cannot add an element in the top scope"; | 968 throw "Cannot add an element in the top scope"; |
| 834 } | 969 } |
| 835 } | 970 } |
| OLD | NEW |