| 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 #library('elements'); | 5 #library('elements'); |
| 6 | 6 |
| 7 #import('dart:uri'); | 7 #import('dart:uri'); |
| 8 | 8 |
| 9 // TODO(ahe): Rename prefix to 'api' when VM bug is fixed. | 9 // TODO(ahe): Rename prefix to 'api' when VM bug is fixed. |
| 10 #import('../../compiler.dart', prefix: 'api_e'); | 10 #import('../../compiler.dart', prefix: 'api_e'); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 static const ElementKind TYPEDEF = | 97 static const ElementKind TYPEDEF = |
| 98 const ElementKind('typedef', ElementCategory.ALIAS); | 98 const ElementKind('typedef', ElementCategory.ALIAS); |
| 99 | 99 |
| 100 static const ElementKind STATEMENT = | 100 static const ElementKind STATEMENT = |
| 101 const ElementKind('statement', ElementCategory.NONE); | 101 const ElementKind('statement', ElementCategory.NONE); |
| 102 static const ElementKind LABEL = | 102 static const ElementKind LABEL = |
| 103 const ElementKind('label', ElementCategory.NONE); | 103 const ElementKind('label', ElementCategory.NONE); |
| 104 static const ElementKind VOID = | 104 static const ElementKind VOID = |
| 105 const ElementKind('void', ElementCategory.NONE); | 105 const ElementKind('void', ElementCategory.NONE); |
| 106 | 106 |
| 107 static const ElementKind ERROR = |
| 108 const ElementKind('error', ElementCategory.NONE); |
| 109 |
| 107 toString() => id; | 110 toString() => id; |
| 108 } | 111 } |
| 109 | 112 |
| 110 class Element implements Spannable { | 113 class Element implements Spannable { |
| 111 final SourceString name; | 114 final SourceString name; |
| 112 final ElementKind kind; | 115 final ElementKind kind; |
| 113 final Element enclosingElement; | 116 final Element enclosingElement; |
| 114 Link<MetadataAnnotation> metadata = const EmptyLink<MetadataAnnotation>(); | 117 Link<MetadataAnnotation> metadata = const EmptyLink<MetadataAnnotation>(); |
| 115 | 118 |
| 116 Element(this.name, this.kind, this.enclosingElement) { | 119 Element(this.name, this.kind, this.enclosingElement) { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 * to check for unresolvable elements instead of | 354 * to check for unresolvable elements instead of |
| 352 * [: element == null :]. | 355 * [: element == null :]. |
| 353 */ | 356 */ |
| 354 class ErroneousElement extends Element { | 357 class ErroneousElement extends Element { |
| 355 final MessageKind messageKind; | 358 final MessageKind messageKind; |
| 356 final List messageArguments; | 359 final List messageArguments; |
| 357 final SourceString targetName; | 360 final SourceString targetName; |
| 358 | 361 |
| 359 ErroneousElement(this.messageKind, this.messageArguments, | 362 ErroneousElement(this.messageKind, this.messageArguments, |
| 360 this.targetName, Element enclosing) | 363 this.targetName, Element enclosing) |
| 361 : super(const SourceString('erroneous element'), null, enclosing); | 364 : super(const SourceString('erroneous element'), |
| 365 ElementKind.ERROR, enclosing); |
| 362 | 366 |
| 363 isErroneous() => true; | 367 isErroneous() => true; |
| 364 | 368 |
| 365 unsupported() { | 369 unsupported() { |
| 366 throw 'unsupported operation on erroneous element'; | 370 throw 'unsupported operation on erroneous element'; |
| 367 } | 371 } |
| 368 | 372 |
| 369 SourceString get name => unsupported(); | 373 SourceString get name => unsupported(); |
| 370 ElementKind get kind => unsupported(); | |
| 371 Link<MetadataAnnotation> get metadata => unsupported(); | 374 Link<MetadataAnnotation> get metadata => unsupported(); |
| 372 | 375 |
| 373 getLibrary() => enclosingElement.getLibrary(); | 376 getLibrary() => enclosingElement.getLibrary(); |
| 374 } | 377 } |
| 375 | 378 |
| 376 class ErroneousFunctionElement extends ErroneousElement | 379 class ErroneousFunctionElement extends ErroneousElement |
| 377 implements FunctionElement { | 380 implements FunctionElement { |
| 378 ErroneousFunctionElement(MessageKind messageKind, List messageArguments, | 381 ErroneousFunctionElement(MessageKind messageKind, List messageArguments, |
| 379 SourceString targetName, Element enclosing) | 382 SourceString targetName, Element enclosing) |
| 380 : super(messageKind, messageArguments, targetName, enclosing); | 383 : super(messageKind, messageArguments, targetName, enclosing); |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 final LibraryElement origin; | 581 final LibraryElement origin; |
| 579 | 582 |
| 580 /** | 583 /** |
| 581 * Map for elements imported through import declarations. | 584 * Map for elements imported through import declarations. |
| 582 * | 585 * |
| 583 * Addition to the map is performed by [addImport]. Lookup is done trough | 586 * Addition to the map is performed by [addImport]. Lookup is done trough |
| 584 * [find]. | 587 * [find]. |
| 585 */ | 588 */ |
| 586 final Map<SourceString, Element> importScope; | 589 final Map<SourceString, Element> importScope; |
| 587 | 590 |
| 591 /** |
| 592 * Link for elements exported either through export declarations or through |
| 593 * declaration. This field should not be accessed directly but instead through |
| 594 * the [exports] getter. |
| 595 * |
| 596 * [LibraryDependencyHandler] sets this field through [setExports] when the |
| 597 * library is loaded. |
| 598 */ |
| 599 Link<Element> slotForExports; |
| 600 |
| 588 LibraryElement(Script script, [Uri uri, LibraryElement this.origin]) | 601 LibraryElement(Script script, [Uri uri, LibraryElement this.origin]) |
| 589 : this.uri = ((uri === null) ? script.uri : uri), | 602 : this.uri = ((uri === null) ? script.uri : uri), |
| 590 importScope = new Map<SourceString, Element>(), | 603 importScope = new Map<SourceString, Element>(), |
| 591 super(new SourceString(script.name), ElementKind.LIBRARY, null) { | 604 super(new SourceString(script.name), ElementKind.LIBRARY, null) { |
| 592 entryCompilationUnit = new CompilationUnitElement(script, this); | 605 entryCompilationUnit = new CompilationUnitElement(script, this); |
| 593 if (isPatch) { | 606 if (isPatch) { |
| 594 origin.patch = this; | 607 origin.patch = this; |
| 595 } | 608 } |
| 596 } | 609 } |
| 597 | 610 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 610 } | 623 } |
| 611 | 624 |
| 612 /** | 625 /** |
| 613 * Adds [element] to the import scope of this library. | 626 * Adds [element] to the import scope of this library. |
| 614 * | 627 * |
| 615 * If an element by the same name is already in the imported scope, an | 628 * If an element by the same name is already in the imported scope, an |
| 616 * [ErroneousElement] will be put in the imported scope, allowing for the | 629 * [ErroneousElement] will be put in the imported scope, allowing for the |
| 617 * detection of ambiguous uses of imported names. | 630 * detection of ambiguous uses of imported names. |
| 618 */ | 631 */ |
| 619 void addImport(Element element, DiagnosticListener listener) { | 632 void addImport(Element element, DiagnosticListener listener) { |
| 620 Element existing = importScope.putIfAbsent(element.name, () => element); | 633 Element existing = importScope[element.name]; |
| 621 if (existing !== element && existing !== null) { | 634 if (existing !== null) { |
| 622 if (!existing.isErroneous()) { | 635 if (!existing.isErroneous()) { |
| 623 // TODO(johnniwinther): Provide access to both the new and existing | 636 // TODO(johnniwinther): Provide access to both the new and existing |
| 624 // elements. | 637 // elements. |
| 625 importScope[element.name] = new ErroneousElement( | 638 importScope[element.name] = new ErroneousElement( |
| 626 MessageKind.DUPLICATE_IMPORT, | 639 MessageKind.DUPLICATE_IMPORT, |
| 627 [element.name], element.name, this); | 640 [element.name], element.name, this); |
| 628 } | 641 } |
| 642 } else { |
| 643 importScope[element.name] = element; |
| 629 } | 644 } |
| 630 } | 645 } |
| 631 | 646 |
| 647 /** |
| 648 * Returns [:true:] if the export scope has already been computed for this |
| 649 * library. |
| 650 */ |
| 651 bool get exportsHandled => slotForExports !== null; |
| 652 |
| 653 Link<Element> get exports { |
| 654 assert(invariant(this, exportsHandled, |
| 655 message: 'Exports not handled on $this')); |
| 656 return slotForExports; |
| 657 } |
| 658 |
| 659 /** |
| 660 * Sets the export scope of this library. This method can only be called once. |
| 661 */ |
| 662 void setExports(Iterable<Element> exportedElements) { |
| 663 assert(invariant(this, !exportsHandled, |
| 664 message: 'Exports already set to $slotForExports on $this')); |
| 665 assert(invariant(this, exportedElements !== null)); |
| 666 var builder = new LinkBuilder<Element>(); |
| 667 for (Element export in exportedElements) { |
| 668 builder.addLast(export); |
| 669 } |
| 670 slotForExports = builder.toLink(); |
| 671 } |
| 672 |
| 632 LibraryElement getLibrary() => isPatch ? origin : this; | 673 LibraryElement getLibrary() => isPatch ? origin : this; |
| 633 | 674 |
| 634 /** | 675 /** |
| 635 * Look up a top-level element in this library. The element could | 676 * Look up a top-level element in this library. The element could |
| 636 * potentially have been imported from another library. Returns | 677 * potentially have been imported from another library. Returns |
| 637 * null if no such element exist and an [ErroneousElement] if multiple | 678 * null if no such element exist and an [ErroneousElement] if multiple |
| 638 * elements have been imported. | 679 * elements have been imported. |
| 639 */ | 680 */ |
| 640 Element find(SourceString elementName) { | 681 Element find(SourceString elementName) { |
| 641 Element result = localScope[elementName]; | 682 Element result = localScope[elementName]; |
| 642 if (result === null) { | 683 if (result === null) { |
| 643 result = importScope[elementName]; | 684 result = importScope[elementName]; |
| 644 } | 685 } |
| 645 return result; | 686 return result; |
| 646 } | 687 } |
| 647 | 688 |
| 648 /** Look up a top-level element in this library, but only look for | 689 /** Look up a top-level element in this library, but only look for |
| 649 * non-imported elements. Returns null if no such element exist. */ | 690 * non-imported elements. Returns null if no such element exist. */ |
| 650 Element findLocal(SourceString elementName) { | 691 Element findLocal(SourceString elementName) { |
| 651 // TODO(johnniwinther): How to handle injected elements in the patch | 692 // TODO(johnniwinther): How to handle injected elements in the patch |
| 652 // library? | 693 // library? |
| 653 Element result = localScope[elementName]; | 694 Element result = localScope[elementName]; |
| 654 if (result === null || result.getLibrary() != this) return null; | 695 if (result === null || result.getLibrary() != this) return null; |
| 655 return result; | 696 return result; |
| 656 } | 697 } |
| 657 | 698 |
| 658 void forEachExport(f(Element element)) { | 699 void forEachExport(f(Element element)) { |
| 659 localScope.forEach((_, Element e) { | 700 exports.forEach((Element e) => f(e)); |
| 660 if (this === e.getLibrary() | |
| 661 && e.kind !== ElementKind.PREFIX | |
| 662 && e.kind !== ElementKind.FOREIGN | |
| 663 && !e.name.isPrivate()) { | |
| 664 f(e); | |
| 665 } | |
| 666 }); | |
| 667 } | 701 } |
| 668 | 702 |
| 669 void forEachLocalMember(f(Element element)) { | 703 void forEachLocalMember(f(Element element)) { |
| 670 if (isPatch) { | 704 if (isPatch) { |
| 671 // Patch libraries traverse both origin and injected members. | 705 // Patch libraries traverse both origin and injected members. |
| 672 origin.localMembers.forEach(f); | 706 origin.localMembers.forEach(f); |
| 673 | 707 |
| 674 void filterPatch(Element element) { | 708 void filterPatch(Element element) { |
| 675 if (!element.isPatch) { | 709 if (!element.isPatch) { |
| 676 // Do not traverse the patch members. | 710 // Do not traverse the patch members. |
| (...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1913 | 1947 |
| 1914 MetadataAnnotation ensureResolved(Compiler compiler) { | 1948 MetadataAnnotation ensureResolved(Compiler compiler) { |
| 1915 if (resolutionState == STATE_NOT_STARTED) { | 1949 if (resolutionState == STATE_NOT_STARTED) { |
| 1916 compiler.resolver.resolveMetadataAnnotation(this); | 1950 compiler.resolver.resolveMetadataAnnotation(this); |
| 1917 } | 1951 } |
| 1918 return this; | 1952 return this; |
| 1919 } | 1953 } |
| 1920 | 1954 |
| 1921 String toString() => 'MetadataAnnotation($value, $resolutionState)'; | 1955 String toString() => 'MetadataAnnotation($value, $resolutionState)'; |
| 1922 } | 1956 } |
| OLD | NEW |