OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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.modelx; | 5 library elements.modelx; |
6 | 6 |
7 import 'elements.dart'; | 7 import 'elements.dart'; |
| 8 import '../helpers/helpers.dart'; |
8 import '../tree/tree.dart'; | 9 import '../tree/tree.dart'; |
9 import '../util/util.dart'; | 10 import '../util/util.dart'; |
10 import '../resolution/resolution.dart'; | 11 import '../resolution/resolution.dart'; |
11 import '../resolution/class_members.dart' show ClassMemberMixin; | 12 import '../resolution/class_members.dart' show ClassMemberMixin; |
12 | 13 |
13 import '../dart2jslib.dart' show invariant, | 14 import '../dart2jslib.dart' show invariant, |
14 InterfaceType, | 15 InterfaceType, |
15 DartType, | 16 DartType, |
16 TypeVariableType, | 17 TypeVariableType, |
17 TypedefType, | 18 TypedefType, |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 | 104 |
104 /** See [ErroneousElement] for documentation. */ | 105 /** See [ErroneousElement] for documentation. */ |
105 bool isErroneous() => false; | 106 bool isErroneous() => false; |
106 | 107 |
107 /** See [AmbiguousElement] for documentation. */ | 108 /** See [AmbiguousElement] for documentation. */ |
108 bool isAmbiguous() => false; | 109 bool isAmbiguous() => false; |
109 | 110 |
110 /** See [WarnOnUseElement] for documentation. */ | 111 /** See [WarnOnUseElement] for documentation. */ |
111 bool isWarnOnUse() => false; | 112 bool isWarnOnUse() => false; |
112 | 113 |
113 /** | |
114 * Is [:true:] if this element has a corresponding patch. | |
115 * | |
116 * If [:true:] this element has a non-null [patch] field. | |
117 * | |
118 * See [:patch_parser.dart:] for a description of the terminology. | |
119 */ | |
120 bool get isPatched => false; | 114 bool get isPatched => false; |
121 | 115 |
122 /** | |
123 * Is [:true:] if this element is a patch. | |
124 * | |
125 * If [:true:] this element has a non-null [origin] field. | |
126 * | |
127 * See [:patch_parser.dart:] for a description of the terminology. | |
128 */ | |
129 bool get isPatch => false; | 116 bool get isPatch => false; |
130 | 117 |
131 /** | 118 bool get isImplementation => true; |
132 * Is [:true:] if this element defines the implementation for the entity of | |
133 * this element. | |
134 * | |
135 * See [:patch_parser.dart:] for a description of the terminology. | |
136 */ | |
137 bool get isImplementation => !isPatched; | |
138 | 119 |
139 /** | 120 bool get isDeclaration => true; |
140 * Is [:true:] if this element introduces the entity of this element. | |
141 * | |
142 * See [:patch_parser.dart:] for a description of the terminology. | |
143 */ | |
144 bool get isDeclaration => !isPatch; | |
145 | 121 |
146 bool get isSynthesized => false; | 122 Element get implementation => this; |
147 | 123 |
148 bool get isForwardingConstructor => false; | 124 Element get declaration => this; |
149 | |
150 bool get isMixinApplication => false; | |
151 | |
152 /** | |
153 * Returns the element which defines the implementation for the entity of this | |
154 * element. | |
155 * | |
156 * See [:patch_parser.dart:] for a description of the terminology. | |
157 */ | |
158 Element get implementation => isPatched ? patch : this; | |
159 | |
160 /** | |
161 * Returns the element which introduces the entity of this element. | |
162 * | |
163 * See [:patch_parser.dart:] for a description of the terminology. | |
164 */ | |
165 Element get declaration => isPatch ? origin : this; | |
166 | 125 |
167 Element get patch { | 126 Element get patch { |
168 throw new UnsupportedError('patch is not supported on $this'); | 127 throw new UnsupportedError('patch is not supported on $this'); |
169 } | 128 } |
170 | 129 |
171 Element get origin { | 130 Element get origin { |
172 throw new UnsupportedError('origin is not supported on $this'); | 131 throw new UnsupportedError('origin is not supported on $this'); |
173 } | 132 } |
174 | 133 |
| 134 bool get isSynthesized => false; |
| 135 |
| 136 bool get isForwardingConstructor => false; |
| 137 |
| 138 bool get isMixinApplication => false; |
| 139 |
175 // TODO(johnniwinther): This breaks for libraries (for which enclosing | 140 // TODO(johnniwinther): This breaks for libraries (for which enclosing |
176 // elements are null) and is invalid for top level variable declarations for | 141 // elements are null) and is invalid for top level variable declarations for |
177 // which the enclosing element is a VariableDeclarations and not a compilation | 142 // which the enclosing element is a VariableDeclarations and not a compilation |
178 // unit. | 143 // unit. |
179 bool isTopLevel() { | 144 bool isTopLevel() { |
180 return enclosingElement != null && enclosingElement.isCompilationUnit(); | 145 return enclosingElement != null && enclosingElement.isCompilationUnit(); |
181 } | 146 } |
182 | 147 |
183 bool isAssignable() { | 148 bool isAssignable() { |
184 if (modifiers.isFinalOrConst()) return false; | 149 if (modifiers.isFinalOrConst()) return false; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 get type => unsupported(); | 308 get type => unsupported(); |
344 get cachedNode => unsupported(); | 309 get cachedNode => unsupported(); |
345 get functionSignature => unsupported(); | 310 get functionSignature => unsupported(); |
346 get patch => null; | 311 get patch => null; |
347 get origin => this; | 312 get origin => this; |
348 get defaultImplementation => unsupported(); | 313 get defaultImplementation => unsupported(); |
349 get nestedClosures => unsupported(); | 314 get nestedClosures => unsupported(); |
350 | 315 |
351 bool get isRedirectingFactory => unsupported(); | 316 bool get isRedirectingFactory => unsupported(); |
352 | 317 |
353 setPatch(patch) => unsupported(); | |
354 computeSignature(compiler) => unsupported(); | 318 computeSignature(compiler) => unsupported(); |
355 requiredParameterCount(compiler) => unsupported(); | |
356 optionalParameterCount(compiler) => unsupported(); | |
357 parameterCount(compiler) => unsupported(); | |
358 | 319 |
359 // TODO(kasperl): These seem unnecessary. | 320 // TODO(kasperl): These seem unnecessary. |
360 set patch(value) => unsupported(); | |
361 set origin(value) => unsupported(); | |
362 set defaultImplementation(value) => unsupported(); | 321 set defaultImplementation(value) => unsupported(); |
363 | 322 |
364 get redirectionTarget => this; | 323 get redirectionTarget => this; |
365 | 324 |
366 getLibrary() => enclosingElement.getLibrary(); | 325 getLibrary() => enclosingElement.getLibrary(); |
367 | 326 |
368 computeTargetType(InterfaceType newType) => unsupported(); | 327 computeTargetType(InterfaceType newType) => unsupported(); |
369 | 328 |
370 String get message => '${messageKind.message(messageArguments)}'; | 329 String get message => '${messageKind.message(messageArguments)}'; |
371 | 330 |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
762 importScope[name] = ambiguousElement; | 721 importScope[name] = ambiguousElement; |
763 importers.registerImport(ambiguousElement, import); | 722 importers.registerImport(ambiguousElement, import); |
764 importers.registerImport(ambiguousElement, existingImport); | 723 importers.registerImport(ambiguousElement, existingImport); |
765 } | 724 } |
766 } | 725 } |
767 } | 726 } |
768 | 727 |
769 Element operator [](String name) => importScope[name]; | 728 Element operator [](String name) => importScope[name]; |
770 } | 729 } |
771 | 730 |
772 class LibraryElementX extends ElementX with AnalyzableElement | 731 class LibraryElementX |
| 732 extends ElementX with AnalyzableElement, PatchMixin<LibraryElementX> |
773 implements LibraryElement { | 733 implements LibraryElement { |
774 final Uri canonicalUri; | 734 final Uri canonicalUri; |
775 CompilationUnitElement entryCompilationUnit; | 735 CompilationUnitElement entryCompilationUnit; |
776 Link<CompilationUnitElement> compilationUnits = | 736 Link<CompilationUnitElement> compilationUnits = |
777 const Link<CompilationUnitElement>(); | 737 const Link<CompilationUnitElement>(); |
778 Link<LibraryTag> tags = const Link<LibraryTag>(); | 738 Link<LibraryTag> tags = const Link<LibraryTag>(); |
779 LibraryName libraryTag; | 739 LibraryName libraryTag; |
780 bool canUseNative = false; | 740 bool canUseNative = false; |
781 Link<Element> localMembers = const Link<Element>(); | 741 Link<Element> localMembers = const Link<Element>(); |
782 final ScopeX localScope = new ScopeX(); | 742 final ScopeX localScope = new ScopeX(); |
783 final ImportScope importScope = new ImportScope(); | 743 final ImportScope importScope = new ImportScope(); |
784 | 744 |
785 /** | |
786 * If this library is patched, [patch] points to the patch library. | |
787 * | |
788 * See [:patch_parser.dart:] for a description of the terminology. | |
789 */ | |
790 LibraryElementX patch = null; | |
791 | |
792 /** | |
793 * If this is a patch library, [origin] points to the origin library. | |
794 * | |
795 * See [:patch_parser.dart:] for a description of the terminology. | |
796 */ | |
797 final LibraryElementX origin; | |
798 | |
799 /// A mapping from an imported element to the "import" tag. | 745 /// A mapping from an imported element to the "import" tag. |
800 final Importers importers = new Importers(); | 746 final Importers importers = new Importers(); |
801 | 747 |
802 /** | 748 /** |
803 * Link for elements exported either through export declarations or through | 749 * Link for elements exported either through export declarations or through |
804 * declaration. This field should not be accessed directly but instead through | 750 * declaration. This field should not be accessed directly but instead through |
805 * the [exports] getter. | 751 * the [exports] getter. |
806 * | 752 * |
807 * [LibraryDependencyHandler] sets this field through [setExports] when the | 753 * [LibraryDependencyHandler] sets this field through [setExports] when the |
808 * library is loaded. | 754 * library is loaded. |
809 */ | 755 */ |
810 Link<Element> slotForExports; | 756 Link<Element> slotForExports; |
811 | 757 |
812 final Map<LibraryDependency, LibraryElement> tagMapping = | 758 final Map<LibraryDependency, LibraryElement> tagMapping = |
813 new Map<LibraryDependency, LibraryElement>(); | 759 new Map<LibraryDependency, LibraryElement>(); |
814 | 760 |
815 LibraryElementX(Script script, [Uri canonicalUri, LibraryElement this.origin]) | 761 LibraryElementX(Script script, |
| 762 [Uri canonicalUri, LibraryElementX origin]) |
816 : this.canonicalUri = | 763 : this.canonicalUri = |
817 ((canonicalUri == null) ? script.readableUri : canonicalUri), | 764 ((canonicalUri == null) ? script.readableUri : canonicalUri), |
818 super(script.name, ElementKind.LIBRARY, null) { | 765 super(script.name, ElementKind.LIBRARY, null) { |
819 entryCompilationUnit = new CompilationUnitElementX(script, this); | 766 entryCompilationUnit = new CompilationUnitElementX(script, this); |
820 if (isPatch) { | 767 if (origin != null) { |
821 origin.patch = this; | 768 origin.applyPatch(this); |
822 } | 769 } |
823 } | 770 } |
824 | 771 |
825 bool get isPatched => patch != null; | |
826 bool get isPatch => origin != null; | |
827 | |
828 LibraryElement get declaration => super.declaration; | |
829 LibraryElement get implementation => super.implementation; | |
830 | |
831 Link<MetadataAnnotation> get metadata { | 772 Link<MetadataAnnotation> get metadata { |
832 return (libraryTag == null) ? super.metadata : libraryTag.metadata; | 773 return (libraryTag == null) ? super.metadata : libraryTag.metadata; |
833 } | 774 } |
834 | 775 |
835 set metadata(value) { | 776 set metadata(value) { |
836 // The metadata is stored on [libraryTag]. | 777 // The metadata is stored on [libraryTag]. |
837 throw new SpannableAssertionFailure(this, 'Cannot set metadata on Library'); | 778 throw new SpannableAssertionFailure(this, 'Cannot set metadata on Library'); |
838 } | 779 } |
839 | 780 |
840 CompilationUnitElement getCompilationUnit() => entryCompilationUnit; | 781 CompilationUnitElement getCompilationUnit() => entryCompilationUnit; |
(...skipping 10 matching lines...) Expand all Loading... |
851 assert(tagMapping[tag] == null); | 792 assert(tagMapping[tag] == null); |
852 tagMapping[tag] = library; | 793 tagMapping[tag] = library; |
853 } | 794 } |
854 | 795 |
855 LibraryElement getLibraryFromTag(LibraryDependency tag) => tagMapping[tag]; | 796 LibraryElement getLibraryFromTag(LibraryDependency tag) => tagMapping[tag]; |
856 | 797 |
857 /** | 798 /** |
858 * Adds [element] to the import scope of this library. | 799 * Adds [element] to the import scope of this library. |
859 * | 800 * |
860 * If an element by the same name is already in the imported scope, an | 801 * If an element by the same name is already in the imported scope, an |
861 * [ErroneousElement] will be put in the imported scope, allowing for detectio
n of ambiguous uses of imported names. | 802 * [ErroneousElement] will be put in the imported scope, allowing for |
| 803 * detection of ambiguous uses of imported names. |
862 */ | 804 */ |
863 void addImport(Element element, Import import, DiagnosticListener listener) { | 805 void addImport(Element element, Import import, DiagnosticListener listener) { |
864 importScope.addImport(this, element, import, listener); | 806 importScope.addImport(this, element, import, listener); |
865 } | 807 } |
866 | 808 |
867 void addMember(Element element, DiagnosticListener listener) { | 809 void addMember(Element element, DiagnosticListener listener) { |
868 localMembers = localMembers.prepend(element); | 810 localMembers = localMembers.prepend(element); |
869 addToScope(element, listener); | 811 addToScope(element, listener); |
870 } | 812 } |
871 | 813 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 return 'library(${getLibraryOrScriptName()})'; | 969 return 'library(${getLibraryOrScriptName()})'; |
1028 } | 970 } |
1029 } | 971 } |
1030 | 972 |
1031 int compareTo(LibraryElement other) { | 973 int compareTo(LibraryElement other) { |
1032 if (this == other) return 0; | 974 if (this == other) return 0; |
1033 return getLibraryOrScriptName().compareTo(other.getLibraryOrScriptName()); | 975 return getLibraryOrScriptName().compareTo(other.getLibraryOrScriptName()); |
1034 } | 976 } |
1035 | 977 |
1036 accept(ElementVisitor visitor) => visitor.visitLibraryElement(this); | 978 accept(ElementVisitor visitor) => visitor.visitLibraryElement(this); |
| 979 |
| 980 // TODO(johnniwinther): Remove these when issue 18630 is fixed. |
| 981 LibraryElementX get patch => super.patch; |
| 982 LibraryElementX get origin => super.origin; |
1037 } | 983 } |
1038 | 984 |
1039 class PrefixElementX extends ElementX implements PrefixElement { | 985 class PrefixElementX extends ElementX implements PrefixElement { |
1040 Token firstPosition; | 986 Token firstPosition; |
1041 | 987 |
1042 final ImportScope importScope = new ImportScope(); | 988 final ImportScope importScope = new ImportScope(); |
1043 | 989 |
1044 bool get isDeferred => _deferredImport != null; | 990 bool get isDeferred => _deferredImport != null; |
1045 | 991 |
1046 // Only needed for deferred imports. | 992 // Only needed for deferred imports. |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1277 | 1223 |
1278 accept(ElementVisitor visitor) => visitor.visitFieldParameterElement(this); | 1224 accept(ElementVisitor visitor) => visitor.visitFieldParameterElement(this); |
1279 } | 1225 } |
1280 | 1226 |
1281 /// [Element] for a formal parameter. | 1227 /// [Element] for a formal parameter. |
1282 /// | 1228 /// |
1283 /// A [ParameterElementX] can be patched. A parameter of an external method is | 1229 /// A [ParameterElementX] can be patched. A parameter of an external method is |
1284 /// patched with the corresponding parameter of the patch method. This is done | 1230 /// patched with the corresponding parameter of the patch method. This is done |
1285 /// to ensure that default values on parameters are computed once (on the | 1231 /// to ensure that default values on parameters are computed once (on the |
1286 /// origin parameter) but can be found through both the origin and the patch. | 1232 /// origin parameter) but can be found through both the origin and the patch. |
1287 class ParameterElementX extends ElementX implements ParameterElement { | 1233 class ParameterElementX extends ElementX with PatchMixin<ParameterElement> |
| 1234 implements ParameterElement { |
1288 final VariableDefinitions definitions; | 1235 final VariableDefinitions definitions; |
1289 final Identifier identifier; | 1236 final Identifier identifier; |
1290 final Expression initializer; | 1237 final Expression initializer; |
1291 DartType typeCache; | 1238 DartType typeCache; |
1292 | 1239 |
1293 /** | 1240 /** |
1294 * Function signature for a variable with a function type. The signature is | 1241 * Function signature for a variable with a function type. The signature is |
1295 * kept to provide full information about parameter names through the mirror | 1242 * kept to provide full information about parameter names through the mirror |
1296 * system. | 1243 * system. |
1297 */ | 1244 */ |
(...skipping 29 matching lines...) Expand all Loading... |
1327 assert(invariant(this, typeCache != null, | 1274 assert(invariant(this, typeCache != null, |
1328 message: "Parameter signature has not been set for $this.")); | 1275 message: "Parameter signature has not been set for $this.")); |
1329 return functionSignatureCache; | 1276 return functionSignatureCache; |
1330 } | 1277 } |
1331 | 1278 |
1332 VariableDefinitions get node => definitions; | 1279 VariableDefinitions get node => definitions; |
1333 | 1280 |
1334 FunctionType get functionType => type; | 1281 FunctionType get functionType => type; |
1335 | 1282 |
1336 accept(ElementVisitor visitor) => visitor.visitVariableElement(this); | 1283 accept(ElementVisitor visitor) => visitor.visitVariableElement(this); |
1337 | |
1338 ParameterElementX patch = null; | |
1339 ParameterElementX origin = null; | |
1340 | |
1341 bool get isPatch => origin != null; | |
1342 bool get isPatched => patch != null; | |
1343 } | 1284 } |
1344 | 1285 |
1345 class AbstractFieldElementX extends ElementX implements AbstractFieldElement { | 1286 class AbstractFieldElementX extends ElementX implements AbstractFieldElement { |
1346 FunctionElement getter; | 1287 FunctionElement getter; |
1347 FunctionElement setter; | 1288 FunctionElement setter; |
1348 | 1289 |
1349 AbstractFieldElementX(String name, Element enclosing) | 1290 AbstractFieldElementX(String name, Element enclosing) |
1350 : super(name, ElementKind.ABSTRACT_FIELD, enclosing); | 1291 : super(name, ElementKind.ABSTRACT_FIELD, enclosing); |
1351 | 1292 |
1352 DartType computeType(Compiler compiler) { | 1293 DartType computeType(Compiler compiler) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1479 // optional parameters is not a problem, they simply are never provided | 1420 // optional parameters is not a problem, they simply are never provided |
1480 // by call sites of a call to a method with the other signature. | 1421 // by call sites of a call to a method with the other signature. |
1481 int otherTotalCount = signature.parameterCount; | 1422 int otherTotalCount = signature.parameterCount; |
1482 return requiredParameterCount <= otherTotalCount | 1423 return requiredParameterCount <= otherTotalCount |
1483 && parameterCount >= otherTotalCount; | 1424 && parameterCount >= otherTotalCount; |
1484 } | 1425 } |
1485 return true; | 1426 return true; |
1486 } | 1427 } |
1487 } | 1428 } |
1488 | 1429 |
1489 class FunctionElementX extends ElementX with AnalyzableElement | 1430 class FunctionElementX |
| 1431 extends ElementX with AnalyzableElement, PatchMixin<FunctionElement> |
1490 implements FunctionElement { | 1432 implements FunctionElement { |
1491 FunctionExpression cachedNode; | 1433 FunctionExpression cachedNode; |
1492 DartType typeCache; | 1434 DartType typeCache; |
1493 final Modifiers modifiers; | 1435 final Modifiers modifiers; |
1494 | 1436 |
1495 List<FunctionElement> nestedClosures = new List<FunctionElement>(); | 1437 List<FunctionElement> nestedClosures = new List<FunctionElement>(); |
1496 | 1438 |
1497 FunctionSignature functionSignatureCache; | 1439 FunctionSignature functionSignatureCache; |
1498 | 1440 |
1499 /** | |
1500 * A function declaration that should be parsed instead of the current one. | |
1501 * The patch should be parsed as if it was in the current scope. Its | |
1502 * signature must match this function's signature. | |
1503 */ | |
1504 FunctionElement patch = null; | |
1505 FunctionElement origin = null; | |
1506 | |
1507 final bool _hasNoBody; | 1441 final bool _hasNoBody; |
1508 | 1442 |
1509 AbstractFieldElement abstractField; | 1443 AbstractFieldElement abstractField; |
1510 | 1444 |
1511 /** | 1445 /** |
1512 * If this is a redirecting factory, [defaultImplementation] will be | 1446 * If this is a redirecting factory, [defaultImplementation] will be |
1513 * changed by the resolver to point to the redirection target. | 1447 * changed by the resolver to point to the redirection target. |
1514 * Otherwise, [:identical(defaultImplementation, this):]. | 1448 * Otherwise, [:identical(defaultImplementation, this):]. |
1515 */ | 1449 */ |
1516 // TODO(ahe): Rename this field to redirectionTarget. | 1450 // TODO(ahe): Rename this field to redirectionTarget. |
(...skipping 21 matching lines...) Expand all Loading... |
1538 this.modifiers, | 1472 this.modifiers, |
1539 Element enclosing, | 1473 Element enclosing, |
1540 this.functionSignatureCache, | 1474 this.functionSignatureCache, |
1541 bool hasNoBody) | 1475 bool hasNoBody) |
1542 : super(name, kind, enclosing), | 1476 : super(name, kind, enclosing), |
1543 _hasNoBody = hasNoBody { | 1477 _hasNoBody = hasNoBody { |
1544 assert(modifiers != null); | 1478 assert(modifiers != null); |
1545 defaultImplementation = this; | 1479 defaultImplementation = this; |
1546 } | 1480 } |
1547 | 1481 |
1548 bool get isPatched => patch != null; | |
1549 bool get isPatch => origin != null; | |
1550 | |
1551 bool get isRedirectingFactory => defaultImplementation != this; | 1482 bool get isRedirectingFactory => defaultImplementation != this; |
1552 | 1483 |
1553 /// This field is set by the post process queue when checking for cycles. | 1484 /// This field is set by the post process queue when checking for cycles. |
1554 FunctionElement internalRedirectionTarget; | 1485 FunctionElement internalRedirectionTarget; |
1555 DartType redirectionTargetType; | 1486 DartType redirectionTargetType; |
1556 | 1487 |
1557 set redirectionTarget(FunctionElement constructor) { | 1488 set redirectionTarget(FunctionElement constructor) { |
1558 assert(constructor != null && internalRedirectionTarget == null); | 1489 assert(constructor != null && internalRedirectionTarget == null); |
1559 internalRedirectionTarget = constructor; | 1490 internalRedirectionTarget = constructor; |
1560 } | 1491 } |
1561 | 1492 |
1562 FunctionElement get redirectionTarget { | 1493 FunctionElement get redirectionTarget { |
1563 if (Elements.isErroneousElement(defaultImplementation)) { | 1494 if (Elements.isErroneousElement(defaultImplementation)) { |
1564 return defaultImplementation; | 1495 return defaultImplementation; |
1565 } | 1496 } |
1566 assert(!isRedirectingFactory || internalRedirectionTarget != null); | 1497 assert(!isRedirectingFactory || internalRedirectionTarget != null); |
1567 return isRedirectingFactory ? internalRedirectionTarget : this; | 1498 return isRedirectingFactory ? internalRedirectionTarget : this; |
1568 } | 1499 } |
1569 | 1500 |
1570 InterfaceType computeTargetType(InterfaceType newType) { | 1501 InterfaceType computeTargetType(InterfaceType newType) { |
1571 if (!isRedirectingFactory) return newType; | 1502 if (!isRedirectingFactory) return newType; |
1572 assert(invariant(this, redirectionTargetType != null, | 1503 assert(invariant(this, redirectionTargetType != null, |
1573 message: 'Redirection target type has not yet been computed for ' | 1504 message: 'Redirection target type has not yet been computed for ' |
1574 '$this.')); | 1505 '$this.')); |
1575 return redirectionTargetType.substByContext(newType); | 1506 return redirectionTargetType.substByContext(newType); |
1576 } | 1507 } |
1577 | 1508 |
1578 /** | |
1579 * Applies a patch function to this function. The patch function's body | |
1580 * is used as replacement when parsing this function's body. | |
1581 * This method must not be called after the function has been parsed, | |
1582 * and it must be called at most once. | |
1583 */ | |
1584 void setPatch(FunctionElement patchElement) { | |
1585 // Sanity checks. The caller must check these things before calling. | |
1586 assert(patch == null); | |
1587 this.patch = patchElement; | |
1588 } | |
1589 | |
1590 bool isInstanceMember() { | 1509 bool isInstanceMember() { |
1591 return isMember() | 1510 return isMember() |
1592 && !isConstructor() | 1511 && !isConstructor() |
1593 && !modifiers.isStatic(); | 1512 && !modifiers.isStatic(); |
1594 } | 1513 } |
1595 | 1514 |
1596 FunctionSignature computeSignature(Compiler compiler) { | 1515 FunctionSignature computeSignature(Compiler compiler) { |
1597 if (functionSignatureCache != null) return functionSignatureCache; | 1516 if (functionSignatureCache != null) return functionSignatureCache; |
1598 compiler.withCurrentElement(this, () { | 1517 compiler.withCurrentElement(this, () { |
1599 functionSignatureCache = compiler.resolveSignature(this); | 1518 functionSignatureCache = compiler.resolveSignature(this); |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1904 variableElement.typeCache = variableType; | 1823 variableElement.typeCache = variableType; |
1905 arguments.addLast(variableType); | 1824 arguments.addLast(variableType); |
1906 } | 1825 } |
1907 return arguments.toLink(); | 1826 return arguments.toLink(); |
1908 } | 1827 } |
1909 } | 1828 } |
1910 | 1829 |
1911 abstract class BaseClassElementX extends ElementX | 1830 abstract class BaseClassElementX extends ElementX |
1912 with AnalyzableElement, | 1831 with AnalyzableElement, |
1913 TypeDeclarationElementX<InterfaceType>, | 1832 TypeDeclarationElementX<InterfaceType>, |
| 1833 PatchMixin<ClassElement>, |
1914 ClassMemberMixin | 1834 ClassMemberMixin |
1915 implements ClassElement { | 1835 implements ClassElement { |
1916 final int id; | 1836 final int id; |
1917 | 1837 |
1918 DartType supertype; | 1838 DartType supertype; |
1919 Link<DartType> interfaces; | 1839 Link<DartType> interfaces; |
1920 String nativeTagInfo; | 1840 String nativeTagInfo; |
1921 int supertypeLoadState; | 1841 int supertypeLoadState; |
1922 int resolutionState; | 1842 int resolutionState; |
1923 bool get isResolved => resolutionState == STATE_DONE; | 1843 bool get isResolved => resolutionState == STATE_DONE; |
(...skipping 12 matching lines...) Expand all Loading... |
1936 | 1856 |
1937 BaseClassElementX(String name, | 1857 BaseClassElementX(String name, |
1938 Element enclosing, | 1858 Element enclosing, |
1939 this.id, | 1859 this.id, |
1940 int initialState) | 1860 int initialState) |
1941 : supertypeLoadState = initialState, | 1861 : supertypeLoadState = initialState, |
1942 resolutionState = initialState, | 1862 resolutionState = initialState, |
1943 super(name, ElementKind.CLASS, enclosing); | 1863 super(name, ElementKind.CLASS, enclosing); |
1944 | 1864 |
1945 int get hashCode => id; | 1865 int get hashCode => id; |
1946 ClassElement get patch => super.patch; | |
1947 ClassElement get origin => super.origin; | |
1948 ClassElement get declaration => super.declaration; | |
1949 ClassElement get implementation => super.implementation; | |
1950 | 1866 |
1951 bool get hasBackendMembers => !backendMembers.isEmpty; | 1867 bool get hasBackendMembers => !backendMembers.isEmpty; |
1952 | 1868 |
1953 bool get isUnnamedMixinApplication => false; | 1869 bool get isUnnamedMixinApplication => false; |
1954 | 1870 |
1955 InterfaceType computeType(Compiler compiler) { | 1871 InterfaceType computeType(Compiler compiler) { |
1956 if (thisTypeCache == null) { | 1872 if (thisTypeCache == null) { |
1957 computeThisAndRawType(compiler, computeTypeParameters(compiler)); | 1873 computeThisAndRawType(compiler, computeTypeParameters(compiler)); |
1958 } | 1874 } |
1959 return thisTypeCache; | 1875 return thisTypeCache; |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2290 bool isNative() => nativeTagInfo != null; | 2206 bool isNative() => nativeTagInfo != null; |
2291 void setNative(String name) { | 2207 void setNative(String name) { |
2292 nativeTagInfo = name; | 2208 nativeTagInfo = name; |
2293 } | 2209 } |
2294 | 2210 |
2295 FunctionType get callType { | 2211 FunctionType get callType { |
2296 MemberSignature member = | 2212 MemberSignature member = |
2297 lookupInterfaceMember(const PublicName(Compiler.CALL_OPERATOR_NAME)); | 2213 lookupInterfaceMember(const PublicName(Compiler.CALL_OPERATOR_NAME)); |
2298 return member != null && member.isMethod ? member.type : null; | 2214 return member != null && member.isMethod ? member.type : null; |
2299 } | 2215 } |
| 2216 |
| 2217 // TODO(johnniwinther): Remove these when issue 18630 is fixed. |
| 2218 ClassElement get patch => super.patch; |
| 2219 ClassElement get origin => super.origin; |
2300 } | 2220 } |
2301 | 2221 |
2302 abstract class ClassElementX extends BaseClassElementX { | 2222 abstract class ClassElementX extends BaseClassElementX { |
2303 // Lazily applied patch of class members. | |
2304 ClassElement patch = null; | |
2305 ClassElement origin = null; | |
2306 | |
2307 Link<Element> localMembers = const Link<Element>(); | 2223 Link<Element> localMembers = const Link<Element>(); |
2308 final ScopeX localScope = new ScopeX(); | 2224 final ScopeX localScope = new ScopeX(); |
2309 | 2225 |
2310 ClassElementX(String name, Element enclosing, int id, int initialState) | 2226 ClassElementX(String name, Element enclosing, int id, int initialState) |
2311 : super(name, enclosing, id, initialState); | 2227 : super(name, enclosing, id, initialState); |
2312 | 2228 |
2313 ClassNode parseNode(Compiler compiler); | 2229 ClassNode parseNode(Compiler compiler); |
2314 | 2230 |
2315 bool get isMixinApplication => false; | 2231 bool get isMixinApplication => false; |
2316 bool get isPatched => patch != null; | |
2317 bool get isPatch => origin != null; | |
2318 bool get hasLocalScopeMembers => !localScope.isEmpty; | 2232 bool get hasLocalScopeMembers => !localScope.isEmpty; |
2319 | 2233 |
2320 void addMember(Element element, DiagnosticListener listener) { | 2234 void addMember(Element element, DiagnosticListener listener) { |
2321 localMembers = localMembers.prepend(element); | 2235 localMembers = localMembers.prepend(element); |
2322 addToScope(element, listener); | 2236 addToScope(element, listener); |
2323 } | 2237 } |
2324 | 2238 |
2325 void addToScope(Element element, DiagnosticListener listener) { | 2239 void addToScope(Element element, DiagnosticListener listener) { |
2326 if (element.isField() && element.name == name) { | 2240 if (element.isField() && element.name == name) { |
2327 listener.reportError(element, MessageKind.MEMBER_USES_CLASS_NAME); | 2241 listener.reportError(element, MessageKind.MEMBER_USES_CLASS_NAME); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2386 this.node, this.modifiers) | 2300 this.node, this.modifiers) |
2387 : super(name, enclosing, id, STATE_NOT_STARTED); | 2301 : super(name, enclosing, id, STATE_NOT_STARTED); |
2388 | 2302 |
2389 ClassElement get mixin => mixinType != null ? mixinType.element : null; | 2303 ClassElement get mixin => mixinType != null ? mixinType.element : null; |
2390 | 2304 |
2391 bool get isMixinApplication => true; | 2305 bool get isMixinApplication => true; |
2392 bool get isUnnamedMixinApplication => node is! NamedMixinApplication; | 2306 bool get isUnnamedMixinApplication => node is! NamedMixinApplication; |
2393 bool get hasConstructor => !constructors.isEmpty; | 2307 bool get hasConstructor => !constructors.isEmpty; |
2394 bool get hasLocalScopeMembers => !constructors.isEmpty; | 2308 bool get hasLocalScopeMembers => !constructors.isEmpty; |
2395 | 2309 |
2396 unsupported(message) { | |
2397 throw new UnsupportedError('$message is not supported on $this'); | |
2398 } | |
2399 | |
2400 get patch => null; | 2310 get patch => null; |
2401 get origin => null; | 2311 get origin => null; |
2402 | 2312 |
2403 set patch(value) => unsupported('set patch'); | |
2404 set origin(value) => unsupported('set origin'); | |
2405 | |
2406 Token position() => node.getBeginToken(); | 2313 Token position() => node.getBeginToken(); |
2407 | 2314 |
2408 Node parseNode(DiagnosticListener listener) => node; | 2315 Node parseNode(DiagnosticListener listener) => node; |
2409 | 2316 |
2410 FunctionElement lookupLocalConstructor(String name) { | 2317 FunctionElement lookupLocalConstructor(String name) { |
2411 for (Link<Element> link = constructors; | 2318 for (Link<Element> link = constructors; |
2412 !link.isEmpty; | 2319 !link.isEmpty; |
2413 link = link.tail) { | 2320 link = link.tail) { |
2414 if (link.head.name == name) return link.head; | 2321 if (link.head.name == name) return link.head; |
2415 } | 2322 } |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2619 | 2526 |
2620 ParameterMetadataAnnotation(Metadata this.metadata); | 2527 ParameterMetadataAnnotation(Metadata this.metadata); |
2621 | 2528 |
2622 Node parseNode(DiagnosticListener listener) => metadata.expression; | 2529 Node parseNode(DiagnosticListener listener) => metadata.expression; |
2623 | 2530 |
2624 Token get beginToken => metadata.getBeginToken(); | 2531 Token get beginToken => metadata.getBeginToken(); |
2625 | 2532 |
2626 Token get endToken => metadata.getEndToken(); | 2533 Token get endToken => metadata.getEndToken(); |
2627 } | 2534 } |
2628 | 2535 |
| 2536 /// Mixin for the implementation of patched elements. |
| 2537 /// |
| 2538 /// See [:patch_parser.dart:] for a description of the terminology. |
| 2539 abstract class PatchMixin<E extends Element> implements Element { |
| 2540 // TODO(johnniwinther): Use type variables when issue 18630 is fixed. |
| 2541 Element/*E*/ patch = null; |
| 2542 Element/*E*/ origin = null; |
| 2543 |
| 2544 bool get isPatch => origin != null; |
| 2545 bool get isPatched => patch != null; |
| 2546 |
| 2547 bool get isImplementation => !isPatched; |
| 2548 bool get isDeclaration => !isPatch; |
| 2549 |
| 2550 Element/*E*/ get implementation => isPatched ? patch : this; |
| 2551 Element/*E*/ get declaration => isPatch ? origin : this; |
| 2552 |
| 2553 /// Applies a patch to this element. This method must be called at most once. |
| 2554 void applyPatch(PatchMixin<E> patch) { |
| 2555 assert(invariant(this, this.patch == null, |
| 2556 message: "Element is patched twice.")); |
| 2557 assert(invariant(this, this.origin == null, |
| 2558 message: "Origin element is a patch.")); |
| 2559 assert(invariant(patch, patch.origin == null, |
| 2560 message: "Element is patched twice.")); |
| 2561 assert(invariant(patch, patch.patch == null, |
| 2562 message: "Patch element is patched.")); |
| 2563 this.patch = patch; |
| 2564 patch.origin = this; |
| 2565 } |
| 2566 } |
OLD | NEW |