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 interface TreeElements { | 5 interface TreeElements { |
6 Element operator[](Node node); | 6 Element operator[](Node node); |
7 Selector getSelector(Send send); | 7 Selector getSelector(Send send); |
8 Type getType(TypeAnnotation annotation); | 8 Type getType(TypeAnnotation annotation); |
9 } | 9 } |
10 | 10 |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 visitor.warning(node, kind, arguments); | 422 visitor.warning(node, kind, arguments); |
423 } | 423 } |
424 | 424 |
425 bool isFieldInitializer(SendSet node) { | 425 bool isFieldInitializer(SendSet node) { |
426 if (node.selector.asIdentifier() == null) return false; | 426 if (node.selector.asIdentifier() == null) return false; |
427 if (node.receiver == null) return true; | 427 if (node.receiver == null) return true; |
428 if (node.receiver.asIdentifier() == null) return false; | 428 if (node.receiver.asIdentifier() == null) return false; |
429 return node.receiver.asIdentifier().isThis(); | 429 return node.receiver.asIdentifier().isThis(); |
430 } | 430 } |
431 | 431 |
| 432 void checkForDuplicateInitializers(SourceString name, Node init) { |
| 433 if (initialized.containsKey(name)) { |
| 434 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); |
| 435 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]); |
| 436 } |
| 437 initialized[name] = init; |
| 438 } |
| 439 |
432 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { | 440 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { |
433 // init is of the form [this.]field = value. | 441 // init is of the form [this.]field = value. |
434 final Node selector = init.selector; | 442 final Node selector = init.selector; |
435 final SourceString name = selector.asIdentifier().source; | 443 final SourceString name = selector.asIdentifier().source; |
436 // Lookup target field. | 444 // Lookup target field. |
437 Element target; | 445 Element target; |
438 if (isFieldInitializer(init)) { | 446 if (isFieldInitializer(init)) { |
439 final ClassElement classElement = constructor.getEnclosingClass(); | 447 final ClassElement classElement = constructor.getEnclosingClass(); |
440 target = classElement.lookupLocalMember(name); | 448 target = classElement.lookupLocalMember(name); |
441 if (target === null) { | 449 if (target === null) { |
442 error(selector, MessageKind.CANNOT_RESOLVE, [name]); | 450 error(selector, MessageKind.CANNOT_RESOLVE, [name]); |
443 } else if (target.kind != ElementKind.FIELD) { | 451 } else if (target.kind != ElementKind.FIELD) { |
444 error(selector, MessageKind.NOT_A_FIELD, [name]); | 452 error(selector, MessageKind.NOT_A_FIELD, [name]); |
445 } else if (!target.isInstanceMember()) { | 453 } else if (!target.isInstanceMember()) { |
446 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); | 454 error(selector, MessageKind.INIT_STATIC_FIELD, [name]); |
447 } | 455 } |
448 } else { | 456 } else { |
449 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); | 457 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); |
450 } | 458 } |
451 visitor.useElement(init, target); | 459 visitor.useElement(init, target); |
452 // Check for duplicate initializers. | 460 checkForDuplicateInitializers(name, init); |
453 if (initialized.containsKey(name)) { | |
454 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); | |
455 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]); | |
456 } | |
457 initialized[name] = init; | |
458 // Resolve initializing value. | 461 // Resolve initializing value. |
459 visitor.visitInStaticContext(init.arguments.head); | 462 visitor.visitInStaticContext(init.arguments.head); |
460 } | 463 } |
461 | 464 |
462 Element resolveSuperOrThisForSend(FunctionElement constructor, | 465 Element resolveSuperOrThisForSend(FunctionElement constructor, |
463 FunctionExpression functionNode, | 466 FunctionExpression functionNode, |
464 Send call) { | 467 Send call) { |
465 // Resolve the selector and the arguments. | 468 // Resolve the selector and the arguments. |
466 ResolverTask resolver = visitor.compiler.resolver; | 469 ResolverTask resolver = visitor.compiler.resolver; |
467 visitor.inStaticContext(() { | 470 visitor.inStaticContext(() { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 } | 548 } |
546 return null; | 549 return null; |
547 } | 550 } |
548 | 551 |
549 /** | 552 /** |
550 * Resolve all initializers of this constructor. In the case of a redirecting | 553 * Resolve all initializers of this constructor. In the case of a redirecting |
551 * constructor, the resolved constructor's function element is returned. | 554 * constructor, the resolved constructor's function element is returned. |
552 */ | 555 */ |
553 FunctionElement resolveInitializers(FunctionElement constructor, | 556 FunctionElement resolveInitializers(FunctionElement constructor, |
554 FunctionExpression functionNode) { | 557 FunctionExpression functionNode) { |
| 558 // Keep track of all "this.param" parameters specified for constructor so |
| 559 // that we can ensure that fields are initialized only once. |
| 560 FunctionSignature functionParameters = |
| 561 constructor.computeSignature(visitor.compiler); |
| 562 functionParameters.forEachParameter((Element element) { |
| 563 if (element.kind === ElementKind.FIELD_PARAMETER) { |
| 564 checkForDuplicateInitializers(element.name, |
| 565 element.parseNode(visitor.compiler)); |
| 566 } |
| 567 }); |
| 568 |
555 if (functionNode.initializers === null) { | 569 if (functionNode.initializers === null) { |
556 initializers = const EmptyLink<Node>(); | 570 initializers = const EmptyLink<Node>(); |
557 } else { | 571 } else { |
558 initializers = functionNode.initializers.nodes; | 572 initializers = functionNode.initializers.nodes; |
559 } | 573 } |
560 FunctionElement result; | 574 FunctionElement result; |
561 bool resolvedSuper = false; | 575 bool resolvedSuper = false; |
562 for (Link<Node> link = initializers; | 576 for (Link<Node> link = initializers; |
563 !link.isEmpty(); | 577 !link.isEmpty(); |
564 link = link.tail) { | 578 link = link.tail) { |
(...skipping 1893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2458 TopScope(LibraryElement library) : super(null, library); | 2472 TopScope(LibraryElement library) : super(null, library); |
2459 Element lookup(SourceString name) { | 2473 Element lookup(SourceString name) { |
2460 return library.find(name); | 2474 return library.find(name); |
2461 } | 2475 } |
2462 | 2476 |
2463 Element add(Element newElement) { | 2477 Element add(Element newElement) { |
2464 throw "Cannot add an element in the top scope"; | 2478 throw "Cannot add an element in the top scope"; |
2465 } | 2479 } |
2466 String toString() => '$element'; | 2480 String toString() => '$element'; |
2467 } | 2481 } |
OLD | NEW |