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 visitor.world.registerStaticUse(target); | 460 visitor.world.registerStaticUse(target); |
453 // Check for duplicate initializers. | 461 checkForDuplicateInitializers(name, init); |
454 if (initialized.containsKey(name)) { | |
455 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); | |
456 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]); | |
457 } | |
458 initialized[name] = init; | |
459 // Resolve initializing value. | 462 // Resolve initializing value. |
460 visitor.visitInStaticContext(init.arguments.head); | 463 visitor.visitInStaticContext(init.arguments.head); |
461 } | 464 } |
462 | 465 |
463 Element resolveSuperOrThisForSend(FunctionElement constructor, | 466 Element resolveSuperOrThisForSend(FunctionElement constructor, |
464 FunctionExpression functionNode, | 467 FunctionExpression functionNode, |
465 Send call) { | 468 Send call) { |
466 // Resolve the selector and the arguments. | 469 // Resolve the selector and the arguments. |
467 ResolverTask resolver = visitor.compiler.resolver; | 470 ResolverTask resolver = visitor.compiler.resolver; |
468 visitor.inStaticContext(() { | 471 visitor.inStaticContext(() { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 } | 550 } |
548 return null; | 551 return null; |
549 } | 552 } |
550 | 553 |
551 /** | 554 /** |
552 * Resolve all initializers of this constructor. In the case of a redirecting | 555 * Resolve all initializers of this constructor. In the case of a redirecting |
553 * constructor, the resolved constructor's function element is returned. | 556 * constructor, the resolved constructor's function element is returned. |
554 */ | 557 */ |
555 FunctionElement resolveInitializers(FunctionElement constructor, | 558 FunctionElement resolveInitializers(FunctionElement constructor, |
556 FunctionExpression functionNode) { | 559 FunctionExpression functionNode) { |
| 560 // Keep track of all "this.param" parameters specified for constructor so |
| 561 // that we can ensure that fields are initialized only once. |
| 562 FunctionSignature functionParameters = |
| 563 constructor.computeSignature(visitor.compiler); |
| 564 functionParameters.forEachParameter((Element element) { |
| 565 if (element.kind === ElementKind.FIELD_PARAMETER) { |
| 566 checkForDuplicateInitializers(element.name, |
| 567 element.parseNode(visitor.compiler)); |
| 568 } |
| 569 }); |
| 570 |
557 if (functionNode.initializers === null) { | 571 if (functionNode.initializers === null) { |
558 initializers = const EmptyLink<Node>(); | 572 initializers = const EmptyLink<Node>(); |
559 } else { | 573 } else { |
560 initializers = functionNode.initializers.nodes; | 574 initializers = functionNode.initializers.nodes; |
561 } | 575 } |
562 FunctionElement result; | 576 FunctionElement result; |
563 bool resolvedSuper = false; | 577 bool resolvedSuper = false; |
564 for (Link<Node> link = initializers; | 578 for (Link<Node> link = initializers; |
565 !link.isEmpty(); | 579 !link.isEmpty(); |
566 link = link.tail) { | 580 link = link.tail) { |
(...skipping 1905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2472 TopScope(LibraryElement library) : super(null, library); | 2486 TopScope(LibraryElement library) : super(null, library); |
2473 Element lookup(SourceString name) { | 2487 Element lookup(SourceString name) { |
2474 return library.find(name); | 2488 return library.find(name); |
2475 } | 2489 } |
2476 | 2490 |
2477 Element add(Element newElement) { | 2491 Element add(Element newElement) { |
2478 throw "Cannot add an element in the top scope"; | 2492 throw "Cannot add an element in the top scope"; |
2479 } | 2493 } |
2480 String toString() => '$element'; | 2494 String toString() => '$element'; |
2481 } | 2495 } |
OLD | NEW |