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('../tree/tree.dart'); | 7 #import('../tree/tree.dart'); |
8 #import('../scanner/scannerlib.dart'); | 8 #import('../scanner/scannerlib.dart'); |
9 #import('../leg.dart'); // TODO(karlklose): we only need type. | 9 #import('../leg.dart'); // TODO(karlklose): we only need type. |
10 #import('../util/util.dart'); | 10 #import('../util/util.dart'); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 static final ElementKind VOID = | 95 static final ElementKind VOID = |
96 const ElementKind('void', ElementCategory.NONE); | 96 const ElementKind('void', ElementCategory.NONE); |
97 | 97 |
98 toString() => id; | 98 toString() => id; |
99 } | 99 } |
100 | 100 |
101 class Element implements Hashable { | 101 class Element implements Hashable { |
102 final SourceString name; | 102 final SourceString name; |
103 final ElementKind kind; | 103 final ElementKind kind; |
104 final Element enclosingElement; | 104 final Element enclosingElement; |
| 105 Script scriptOverride = null; |
105 Link<Node> metadata = const EmptyLink<Node>(); | 106 Link<Node> metadata = const EmptyLink<Node>(); |
106 Modifiers get modifiers() => null; | 107 Modifiers get modifiers() => null; |
107 | 108 |
108 Node parseNode(DiagnosticListener listener) { | 109 Node parseNode(DiagnosticListener listener) { |
109 listener.cancel("Internal Error: $this.parseNode", token: position()); | 110 listener.cancel("Internal Error: $this.parseNode", token: position()); |
110 } | 111 } |
111 | 112 |
112 Type computeType(Compiler compiler) { | 113 Type computeType(Compiler compiler) { |
113 compiler.internalError("$this.computeType.", token: position()); | 114 compiler.internalError("$this.computeType.", token: position()); |
114 } | 115 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 | 169 |
169 Element(this.name, this.kind, this.enclosingElement) { | 170 Element(this.name, this.kind, this.enclosingElement) { |
170 assert(getLibrary() !== null); | 171 assert(getLibrary() !== null); |
171 } | 172 } |
172 | 173 |
173 // TODO(kasperl): This is a very bad hash code for the element and | 174 // TODO(kasperl): This is a very bad hash code for the element and |
174 // there's no reason why two elements with the same name should have | 175 // there's no reason why two elements with the same name should have |
175 // the same hash code. Replace this with a simple id in the element? | 176 // the same hash code. Replace this with a simple id in the element? |
176 int hashCode() => name.hashCode(); | 177 int hashCode() => name.hashCode(); |
177 | 178 |
| 179 Script getScript() { |
| 180 if (scriptOverride !== null) return scriptOverride; |
| 181 return getCompilationUnit().script; |
| 182 } |
| 183 |
178 CompilationUnitElement getCompilationUnit() { | 184 CompilationUnitElement getCompilationUnit() { |
179 Element element = this; | 185 Element element = this; |
180 while (element !== null && !element.isCompilationUnit()) { | 186 while (element !== null && !element.isCompilationUnit()) { |
181 element = element.enclosingElement; | 187 element = element.enclosingElement; |
182 } | 188 } |
183 return element; | 189 return element; |
184 } | 190 } |
185 | 191 |
186 LibraryElement getLibrary() { | 192 LibraryElement getLibrary() { |
187 Element element = this; | 193 Element element = this; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 } else { | 229 } else { |
224 return '$kind(${name.slowToString()})'; | 230 return '$kind(${name.slowToString()})'; |
225 } | 231 } |
226 } | 232 } |
227 | 233 |
228 bool _isNative = false; | 234 bool _isNative = false; |
229 void setNative() { _isNative = true; } | 235 void setNative() { _isNative = true; } |
230 bool isNative() => _isNative; | 236 bool isNative() => _isNative; |
231 | 237 |
232 FunctionElement asFunctionElement() => null; | 238 FunctionElement asFunctionElement() => null; |
| 239 |
| 240 Element cloneTo(Element enclosing, DiagnosticListener listener) { |
| 241 listener.cancel("Unimplemented cloneTo", element: this); |
| 242 } |
233 } | 243 } |
234 | 244 |
235 class ContainerElement extends Element { | 245 class ContainerElement extends Element { |
236 ContainerElement(name, kind, enclosingElement) : | 246 ContainerElement(name, kind, enclosingElement) : |
237 super(name, kind, enclosingElement); | 247 super(name, kind, enclosingElement); |
238 | 248 |
239 abstract void addMember(Element element, DiagnosticListener listener); | 249 abstract void addMember(Element element, DiagnosticListener listener); |
240 | 250 |
241 void addGetterOrSetter(Element element, | 251 void addGetterOrSetter(Element element, |
242 Element existing, | 252 Element existing, |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 // Use the file name as script name. | 399 // Use the file name as script name. |
390 var path = script.uri.path; | 400 var path = script.uri.path; |
391 return path.substring(path.lastIndexOf('/') + 1); | 401 return path.substring(path.lastIndexOf('/') + 1); |
392 } | 402 } |
393 } | 403 } |
394 } | 404 } |
395 | 405 |
396 class PrefixElement extends Element { | 406 class PrefixElement extends Element { |
397 Map<SourceString, Element> imported; | 407 Map<SourceString, Element> imported; |
398 Token firstPosition; | 408 Token firstPosition; |
399 final CompilationUnitElement patchSource; | |
400 | 409 |
401 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition, | 410 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) |
402 [this.patchSource]) | 411 : imported = new Map<SourceString, Element>(), |
403 : imported = new Map<SourceString, Element>(), | 412 super(prefix, ElementKind.PREFIX, enclosing); |
404 super(prefix, ElementKind.PREFIX, enclosing); | |
405 | |
406 CompilationUnitElement getCompilationUnit() { | |
407 if (patchSource !== null) return patchSource; | |
408 return super.getCompilationUnit(); | |
409 } | |
410 | 413 |
411 lookupLocalMember(SourceString memberName) => imported[memberName]; | 414 lookupLocalMember(SourceString memberName) => imported[memberName]; |
412 | 415 |
413 Type computeType(Compiler compiler) => compiler.types.dynamicType; | 416 Type computeType(Compiler compiler) => compiler.types.dynamicType; |
414 | 417 |
415 Token position() => firstPosition; | 418 Token position() => firstPosition; |
| 419 |
| 420 PrefixElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 421 PrefixElement result = new PrefixElement(name, enclosing, firstPosition); |
| 422 result.scriptOverride = getScript(); |
| 423 return result; |
| 424 } |
416 } | 425 } |
417 | 426 |
418 class TypedefElement extends Element { | 427 class TypedefElement extends Element { |
419 Type cachedType; | 428 Type cachedType; |
420 Typedef cachedNode; | 429 Typedef cachedNode; |
421 | 430 |
422 TypedefElement(SourceString name, Element enclosing) | 431 TypedefElement(SourceString name, Element enclosing) |
423 : super(name, ElementKind.TYPEDEF, enclosing); | 432 : super(name, ElementKind.TYPEDEF, enclosing); |
424 | 433 |
425 Type computeType(Compiler compiler) { | 434 Type computeType(Compiler compiler) { |
426 if (cachedType !== null) return cachedType; | 435 if (cachedType !== null) return cachedType; |
427 cachedType = compiler.computeFunctionType( | 436 cachedType = compiler.computeFunctionType( |
428 this, compiler.resolveTypedef(this)); | 437 this, compiler.resolveTypedef(this)); |
429 return cachedType; | 438 return cachedType; |
430 } | 439 } |
| 440 |
| 441 TypedefElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 442 TypedefElement result = new TypedefElement(name, enclosing); |
| 443 result.scriptOverride = getScript(); |
| 444 return result; |
| 445 } |
431 } | 446 } |
432 | 447 |
433 class VariableElement extends Element { | 448 class VariableElement extends Element { |
434 final VariableListElement variables; | 449 final VariableListElement variables; |
435 Expression cachedNode; // The send or the identifier in the variables list. | 450 Expression cachedNode; // The send or the identifier in the variables list. |
436 | 451 |
437 Modifiers get modifiers() => variables.modifiers; | 452 Modifiers get modifiers() => variables.modifiers; |
438 | 453 |
439 VariableElement(SourceString name, | 454 VariableElement(SourceString name, |
440 VariableListElement this.variables, | 455 VariableListElement this.variables, |
(...skipping 26 matching lines...) Expand all Loading... |
467 | 482 |
468 Type get type() => variables.type; | 483 Type get type() => variables.type; |
469 | 484 |
470 bool isInstanceMember() { | 485 bool isInstanceMember() { |
471 return isMember() && !modifiers.isStatic(); | 486 return isMember() && !modifiers.isStatic(); |
472 } | 487 } |
473 | 488 |
474 // Note: cachedNode.getBeginToken() will not be correct in all | 489 // Note: cachedNode.getBeginToken() will not be correct in all |
475 // cases, for example, for function typed parameters. | 490 // cases, for example, for function typed parameters. |
476 Token position() => findMyName(variables.position()); | 491 Token position() => findMyName(variables.position()); |
| 492 |
| 493 VariableElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 494 VariableListElement clonedVariables = |
| 495 variables.cloneTo(enclosing, listener); |
| 496 VariableElement result = new VariableElement( |
| 497 name, clonedVariables, kind, enclosing, cachedNode); |
| 498 result.scriptOverride = getScript(); |
| 499 return result; |
| 500 } |
477 } | 501 } |
478 | 502 |
479 /** | 503 /** |
480 * Parameters in constructors that directly initialize fields. For example: | 504 * Parameters in constructors that directly initialize fields. For example: |
481 * [:A(this.field):]. | 505 * [:A(this.field):]. |
482 */ | 506 */ |
483 class FieldParameterElement extends VariableElement { | 507 class FieldParameterElement extends VariableElement { |
484 VariableElement fieldElement; | 508 VariableElement fieldElement; |
485 | 509 |
486 FieldParameterElement(SourceString name, | 510 FieldParameterElement(SourceString name, |
487 this.fieldElement, | 511 this.fieldElement, |
488 VariableListElement variables, | 512 VariableListElement variables, |
489 Element enclosing, | 513 Element enclosing, |
490 Node node) | 514 Node node) |
491 : super(name, variables, ElementKind.FIELD_PARAMETER, enclosing, node); | 515 : super(name, variables, ElementKind.FIELD_PARAMETER, enclosing, node); |
| 516 |
| 517 FieldParameterElement cloneTo(Element enclosing, |
| 518 DiagnosticListener listener) { |
| 519 FieldParameterElement result = |
| 520 new FieldParameterElement(name, fieldElement, |
| 521 variables.cloneTo(enclosing, listener), |
| 522 enclosing, cachedNode); |
| 523 result.scriptOverride = getScript(); |
| 524 return result; |
| 525 } |
492 } | 526 } |
493 | 527 |
494 // This element represents a list of variable or field declaration. | 528 // This element represents a list of variable or field declaration. |
495 // It contains the node, and the type. A [VariableElement] always | 529 // It contains the node, and the type. A [VariableElement] always |
496 // references its [VariableListElement]. It forwards its | 530 // references its [VariableListElement]. It forwards its |
497 // [computeType] and [parseNode] methods to this element. | 531 // [computeType] and [parseNode] methods to this element. |
498 class VariableListElement extends Element { | 532 class VariableListElement extends Element { |
499 VariableDefinitions cachedNode; | 533 VariableDefinitions cachedNode; |
500 Type type; | 534 Type type; |
501 final Modifiers modifiers; | 535 final Modifiers modifiers; |
(...skipping 14 matching lines...) Expand all Loading... |
516 return cachedNode; | 550 return cachedNode; |
517 } | 551 } |
518 | 552 |
519 Type computeType(Compiler compiler) { | 553 Type computeType(Compiler compiler) { |
520 if (type != null) return type; | 554 if (type != null) return type; |
521 type = compiler.resolveTypeAnnotation(this, parseNode(compiler).type); | 555 type = compiler.resolveTypeAnnotation(this, parseNode(compiler).type); |
522 return type; | 556 return type; |
523 } | 557 } |
524 | 558 |
525 Token position() => cachedNode.getBeginToken(); | 559 Token position() => cachedNode.getBeginToken(); |
| 560 |
| 561 VariableListElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 562 VariableListElement result; |
| 563 if (cachedNode !== null) { |
| 564 result = new VariableListElement(cachedNode, kind, enclosing); |
| 565 } else { |
| 566 result = new VariableListElement(kind, modifiers, enclosing); |
| 567 } |
| 568 result.scriptOverride = getScript(); |
| 569 return result; |
| 570 } |
526 } | 571 } |
527 | 572 |
528 class ForeignElement extends Element { | 573 class ForeignElement extends Element { |
529 ForeignElement(SourceString name, ContainerElement enclosingElement) | 574 ForeignElement(SourceString name, ContainerElement enclosingElement) |
530 : super(name, ElementKind.FOREIGN, enclosingElement); | 575 : super(name, ElementKind.FOREIGN, enclosingElement); |
531 | 576 |
532 Type computeType(Compiler compiler) { | 577 Type computeType(Compiler compiler) { |
533 return compiler.types.dynamicType; | 578 return compiler.types.dynamicType; |
534 } | 579 } |
535 | 580 |
536 parseNode(DiagnosticListener listener) { | 581 parseNode(DiagnosticListener listener) { |
537 throw "internal error: ForeignElement has no node"; | 582 throw "internal error: ForeignElement has no node"; |
538 } | 583 } |
| 584 |
| 585 ForeignElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 586 ForeignElement result = new ForeignElement(name, kind, enclosing); |
| 587 result.scriptOverride = getScript(); |
| 588 return result; |
| 589 } |
539 } | 590 } |
540 | 591 |
541 class AbstractFieldElement extends Element { | 592 class AbstractFieldElement extends Element { |
542 FunctionElement getter; | 593 FunctionElement getter; |
543 FunctionElement setter; | 594 FunctionElement setter; |
544 | 595 |
545 AbstractFieldElement(SourceString name, Element enclosing) | 596 AbstractFieldElement(SourceString name, Element enclosing) |
546 : super(name, ElementKind.ABSTRACT_FIELD, enclosing); | 597 : super(name, ElementKind.ABSTRACT_FIELD, enclosing); |
547 | 598 |
548 Type computeType(Compiler compiler) { | 599 Type computeType(Compiler compiler) { |
(...skipping 24 matching lines...) Expand all Loading... |
573 if (getter !== null) { | 624 if (getter !== null) { |
574 return new Modifiers.withFlags( | 625 return new Modifiers.withFlags( |
575 getter.modifiers.nodes, | 626 getter.modifiers.nodes, |
576 getter.modifiers.flags | Modifiers.FLAG_ABSTRACT); | 627 getter.modifiers.flags | Modifiers.FLAG_ABSTRACT); |
577 } else { | 628 } else { |
578 return new Modifiers.withFlags( | 629 return new Modifiers.withFlags( |
579 setter.modifiers.nodes, | 630 setter.modifiers.nodes, |
580 setter.modifiers.flags | Modifiers.FLAG_ABSTRACT); | 631 setter.modifiers.flags | Modifiers.FLAG_ABSTRACT); |
581 } | 632 } |
582 } | 633 } |
| 634 |
| 635 AbstractFieldElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 636 listener.cancel("Cannot clone synthetic AbstractFieldElement", |
| 637 element: this); |
| 638 } |
583 } | 639 } |
584 | 640 |
585 class FunctionSignature { | 641 class FunctionSignature { |
586 Link<Element> requiredParameters; | 642 Link<Element> requiredParameters; |
587 Link<Element> optionalParameters; | 643 Link<Element> optionalParameters; |
588 Type returnType; | 644 Type returnType; |
589 int requiredParameterCount; | 645 int requiredParameterCount; |
590 int optionalParameterCount; | 646 int optionalParameterCount; |
591 FunctionSignature(this.requiredParameters, | 647 FunctionSignature(this.requiredParameters, |
592 this.optionalParameters, | 648 this.optionalParameters, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 FunctionElement.tooMuchOverloading(SourceString name, | 711 FunctionElement.tooMuchOverloading(SourceString name, |
656 FunctionExpression this.cachedNode, | 712 FunctionExpression this.cachedNode, |
657 ElementKind kind, | 713 ElementKind kind, |
658 Modifiers this.modifiers, | 714 Modifiers this.modifiers, |
659 Element enclosing, | 715 Element enclosing, |
660 FunctionSignature this.functionSignature) | 716 FunctionSignature this.functionSignature) |
661 : super(name, kind, enclosing) { | 717 : super(name, kind, enclosing) { |
662 defaultImplementation = this; | 718 defaultImplementation = this; |
663 } | 719 } |
664 | 720 |
665 CompilationUnitElement getCompilationUnit() { | 721 Script getScript() { |
666 if (patch !== null) return patch.getCompilationUnit(); | 722 if (patch !== null) return patch.getScript(); |
667 return super.getCompilationUnit(); | 723 return super.getScript(); |
668 } | 724 } |
669 | 725 |
670 bool get isPatched() => patch !== null; | 726 bool get isPatched() => patch !== null; |
671 | 727 |
672 /** | 728 /** |
673 * Applies a patch function to this function. The patch function's body | 729 * Applies a patch function to this function. The patch function's body |
674 * is used as replacement when parsing this function's body. | 730 * is used as replacement when parsing this function's body. |
675 * This method must not be called after the function has been parsed, | 731 * This method must not be called after the function has been parsed, |
676 * and it must be called at most once. | 732 * and it must be called at most once. |
677 */ | 733 */ |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 } | 781 } |
726 return null; | 782 return null; |
727 } | 783 } |
728 cachedNode = patch.parseNode(listener); | 784 cachedNode = patch.parseNode(listener); |
729 return cachedNode; | 785 return cachedNode; |
730 } | 786 } |
731 | 787 |
732 Token position() => cachedNode.getBeginToken(); | 788 Token position() => cachedNode.getBeginToken(); |
733 | 789 |
734 FunctionElement asFunctionElement() => this; | 790 FunctionElement asFunctionElement() => this; |
| 791 |
| 792 FunctionElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 793 FunctionElement result = new FunctionElement.tooMuchOverloading( |
| 794 name, cachedNode, kind, modifiers, enclosing, functionSignature); |
| 795 result.defaultImplementation = defaultImplementation; |
| 796 result.type = type; |
| 797 result.scriptOverride = getScript(); |
| 798 return result; |
| 799 } |
735 } | 800 } |
736 | 801 |
| 802 |
737 class ConstructorBodyElement extends FunctionElement { | 803 class ConstructorBodyElement extends FunctionElement { |
738 FunctionElement constructor; | 804 FunctionElement constructor; |
739 | 805 |
740 ConstructorBodyElement(FunctionElement constructor) | 806 ConstructorBodyElement(FunctionElement constructor) |
741 : this.constructor = constructor, | 807 : this.constructor = constructor, |
742 super(constructor.name, | 808 super(constructor.name, |
743 ElementKind.GENERATIVE_CONSTRUCTOR_BODY, | 809 ElementKind.GENERATIVE_CONSTRUCTOR_BODY, |
744 null, | 810 null, |
745 constructor.enclosingElement) { | 811 constructor.enclosingElement) { |
746 functionSignature = constructor.functionSignature; | 812 functionSignature = constructor.functionSignature; |
747 } | 813 } |
748 | 814 |
749 bool isInstanceMember() => true; | 815 bool isInstanceMember() => true; |
750 | 816 |
751 FunctionType computeType(Compiler compiler) { | 817 FunctionType computeType(Compiler compiler) { |
752 compiler.reportFatalError('Internal error: $this.computeType', this); | 818 compiler.reportFatalError('Internal error: $this.computeType', this); |
753 } | 819 } |
754 | 820 |
755 Node parseNode(DiagnosticListener listener) { | 821 Node parseNode(DiagnosticListener listener) { |
756 if (cachedNode !== null) return cachedNode; | 822 if (cachedNode !== null) return cachedNode; |
757 cachedNode = constructor.parseNode(listener); | 823 cachedNode = constructor.parseNode(listener); |
758 assert(cachedNode !== null); | 824 assert(cachedNode !== null); |
759 return cachedNode; | 825 return cachedNode; |
760 } | 826 } |
761 | 827 |
762 Token position() => constructor.position(); | 828 Token position() => constructor.position(); |
| 829 |
| 830 ConstructorBodyElement cloneTo(Element enclosing, |
| 831 DiagnosticListener listener) { |
| 832 ConstructorBodyElement result = |
| 833 new ConstructorBodyElement(constructor.cloneTo(enclosing, listener)); |
| 834 result.scriptOverride = getScript(); |
| 835 return result; |
| 836 } |
763 } | 837 } |
764 | 838 |
765 class SynthesizedConstructorElement extends FunctionElement { | 839 class SynthesizedConstructorElement extends FunctionElement { |
766 SynthesizedConstructorElement(Element enclosing) | 840 SynthesizedConstructorElement(Element enclosing) |
767 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, | 841 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, |
768 null, enclosing); | 842 null, enclosing); |
769 | 843 |
770 Token position() => enclosingElement.position(); | 844 Token position() => enclosingElement.position(); |
| 845 |
| 846 SynthesizedConstructorElement cloneTo(Element enclosing, |
| 847 DiagnosticListener listener) { |
| 848 return new SynthesizedConstructorElement(enclosing); |
| 849 } |
771 } | 850 } |
772 | 851 |
773 class VoidElement extends Element { | 852 class VoidElement extends Element { |
774 VoidElement(Element enclosing) | 853 VoidElement(Element enclosing) |
775 : super(const SourceString('void'), ElementKind.VOID, enclosing); | 854 : super(const SourceString('void'), ElementKind.VOID, enclosing); |
776 Type computeType(compiler) => compiler.types.voidType; | 855 Type computeType(compiler) => compiler.types.voidType; |
777 Node parseNode(_) { | 856 Node parseNode(_) { |
778 throw 'internal error: parseNode on void'; | 857 throw 'internal error: parseNode on void'; |
779 } | 858 } |
780 bool impliesType() => true; | 859 bool impliesType() => true; |
781 } | 860 } |
782 | 861 |
783 class ClassElement extends ContainerElement { | 862 class ClassElement extends ContainerElement { |
784 final int id; | 863 final int id; |
785 Type type; | 864 Type type; |
786 Type supertype; | 865 Type supertype; |
787 Type defaultClass; | 866 Type defaultClass; |
788 Link<Element> members = const EmptyLink<Element>(); | 867 Link<Element> members = const EmptyLink<Element>(); |
789 Map<SourceString, Element> localMembers; | 868 Map<SourceString, Element> localMembers; |
790 Map<SourceString, Element> constructors; | 869 Map<SourceString, Element> constructors; |
791 Link<Type> interfaces = const EmptyLink<Type>(); | 870 Link<Type> interfaces = const EmptyLink<Type>(); |
792 LinkedHashMap<SourceString, TypeVariableElement> typeParameters; | 871 LinkedHashMap<SourceString, TypeVariableElement> typeParameters; |
| 872 SourceString nativeName; |
793 bool isResolved = false; | 873 bool isResolved = false; |
794 bool isBeingResolved = false; | 874 bool isBeingResolved = false; |
795 // backendMembers are members that have been added by the backend to simplify | 875 // backendMembers are members that have been added by the backend to simplify |
796 // compilation. They don't have any user-side counter-part. | 876 // compilation. They don't have any user-side counter-part. |
797 Link<Element> backendMembers = const EmptyLink<Element>(); | 877 Link<Element> backendMembers = const EmptyLink<Element>(); |
798 | 878 |
799 Link<Type> allSupertypes; | 879 Link<Type> allSupertypes; |
800 ClassElement patch = null; | |
801 | 880 |
802 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) | 881 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) |
803 : localMembers = new Map<SourceString, Element>(), | 882 : localMembers = new Map<SourceString, Element>(), |
804 constructors = new Map<SourceString, Element>(), | 883 constructors = new Map<SourceString, Element>(), |
805 typeParameters = new LinkedHashMap<SourceString, TypeVariableElement>(), | 884 typeParameters = new LinkedHashMap<SourceString, TypeVariableElement>(), |
806 super(name, ElementKind.CLASS, enclosing); | 885 super(name, ElementKind.CLASS, enclosing); |
807 | 886 |
808 void addMember(Element element, DiagnosticListener listener) { | 887 void addMember(Element element, DiagnosticListener listener) { |
809 members = members.prepend(element); | 888 members = members.prepend(element); |
810 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || | 889 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
961 */ | 1040 */ |
962 bool isSubclassOf(ClassElement cls) { | 1041 bool isSubclassOf(ClassElement cls) { |
963 for (ClassElement s = this; s != null; s = s.superclass) { | 1042 for (ClassElement s = this; s != null; s = s.superclass) { |
964 if (s === cls) return true; | 1043 if (s === cls) return true; |
965 } | 1044 } |
966 return false; | 1045 return false; |
967 } | 1046 } |
968 | 1047 |
969 bool isInterface() => false; | 1048 bool isInterface() => false; |
970 bool isNative() => nativeName != null; | 1049 bool isNative() => nativeName != null; |
971 SourceString nativeName; | |
972 int hashCode() => id; | 1050 int hashCode() => id; |
| 1051 |
| 1052 void cloneMembersTo(Element target, DiagnosticListener listener) { |
| 1053 target.type = type; |
| 1054 target.supertype = supertype; |
| 1055 target.defaultClass = defaultClass; |
| 1056 target.interfaces = interfaces; |
| 1057 target.typeParameters = |
| 1058 new LinkedHashMap<SourceString, TypeVariableElement>(); |
| 1059 typeParameters.forEach((SourceString name, TypeVariableElement type) { |
| 1060 target.typeParameters[name] = type.cloneTo(target, listener); |
| 1061 }); |
| 1062 target.nativeName = nativeName; |
| 1063 target.isResolved = isResolved; |
| 1064 target.isBeingResolved = isBeingResolved; |
| 1065 target.allSupertypes = allSupertypes; |
| 1066 if (!backendMembers.isEmpty()) { |
| 1067 listener.cancel("Cloning backend-modified class.", element: this); |
| 1068 } |
| 1069 |
| 1070 Link<Element> elementList = this.members; |
| 1071 while (!elementList.isEmpty()) { |
| 1072 target.addMember(elementList.head.cloneTo(target, listener), listener); |
| 1073 elementList = elementList.tail; |
| 1074 } |
| 1075 } |
| 1076 |
| 1077 ClassElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 1078 // TODO(lrn): Is copying id acceptable? |
| 1079 ClassElement result = new ClassElement(name, enclosing, id); |
| 1080 cloneMembersTo(result, listener); |
| 1081 result.scriptOverride = getScript(); |
| 1082 return result; |
| 1083 } |
973 } | 1084 } |
974 | 1085 |
975 class Elements { | 1086 class Elements { |
976 static bool isLocal(Element element) { | 1087 static bool isLocal(Element element) { |
977 return ((element !== null) | 1088 return ((element !== null) |
978 && !element.isInstanceMember() | 1089 && !element.isInstanceMember() |
979 && !isStaticOrTopLevelField(element) | 1090 && !isStaticOrTopLevelField(element) |
980 && !isStaticOrTopLevelFunction(element) | 1091 && !isStaticOrTopLevelFunction(element) |
981 && (element.kind === ElementKind.VARIABLE || | 1092 && (element.kind === ElementKind.VARIABLE || |
982 element.kind === ElementKind.PARAMETER || | 1093 element.kind === ElementKind.PARAMETER || |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1083 || (element == coreLibrary.find(const SourceString('Pattern'))); | 1194 || (element == coreLibrary.find(const SourceString('Pattern'))); |
1084 } | 1195 } |
1085 | 1196 |
1086 static bool isListSupertype(Element element, Compiler compiler) { | 1197 static bool isListSupertype(Element element, Compiler compiler) { |
1087 LibraryElement coreLibrary = compiler.coreLibrary; | 1198 LibraryElement coreLibrary = compiler.coreLibrary; |
1088 return (element == coreLibrary.find(const SourceString('Collection'))) | 1199 return (element == coreLibrary.find(const SourceString('Collection'))) |
1089 || (element == coreLibrary.find(const SourceString('Iterable'))); | 1200 || (element == coreLibrary.find(const SourceString('Iterable'))); |
1090 } | 1201 } |
1091 } | 1202 } |
1092 | 1203 |
1093 | |
1094 class LabelElement extends Element { | 1204 class LabelElement extends Element { |
1095 // We store the original label here so it can be returned by [parseNode]. | 1205 // We store the original label here so it can be returned by [parseNode]. |
1096 final Label label; | 1206 final Label label; |
1097 final String labelName; | 1207 final String labelName; |
1098 final TargetElement target; | 1208 final TargetElement target; |
1099 bool isBreakTarget = false; | 1209 bool isBreakTarget = false; |
1100 bool isContinueTarget = false; | 1210 bool isContinueTarget = false; |
1101 LabelElement(Label label, this.labelName, this.target, | 1211 LabelElement(Label label, this.labelName, this.target, |
1102 Element enclosingElement) | 1212 Element enclosingElement) |
1103 : this.label = label, | 1213 : this.label = label, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 class TypeVariableElement extends Element { | 1260 class TypeVariableElement extends Element { |
1151 final Node node; | 1261 final Node node; |
1152 Type bound; | 1262 Type bound; |
1153 Type type; | 1263 Type type; |
1154 TypeVariableElement(name, Element enclosing, this.node, this.type, | 1264 TypeVariableElement(name, Element enclosing, this.node, this.type, |
1155 [this.bound]) | 1265 [this.bound]) |
1156 : super(name, ElementKind.TYPE_VARIABLE, enclosing); | 1266 : super(name, ElementKind.TYPE_VARIABLE, enclosing); |
1157 Type computeType(compiler) => type; | 1267 Type computeType(compiler) => type; |
1158 Node parseNode(compiler) => node; | 1268 Node parseNode(compiler) => node; |
1159 toString() => "${enclosingElement.toString()}.${name.slowToString()}"; | 1269 toString() => "${enclosingElement.toString()}.${name.slowToString()}"; |
| 1270 |
| 1271 TypeVariableElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 1272 TypeVariableElement result = |
| 1273 new TypeVariableElement(name, enclosing, node, type, bound); |
| 1274 result.scriptOverride = getScript(); |
| 1275 return result; |
| 1276 } |
1160 } | 1277 } |
OLD | NEW |