| 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' as api_e; | 10 import '../../compiler.dart' as api_e; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 static const ElementKind TYPEDEF = | 109 static const ElementKind TYPEDEF = |
| 110 const ElementKind('typedef', ElementCategory.ALIAS); | 110 const ElementKind('typedef', ElementCategory.ALIAS); |
| 111 | 111 |
| 112 static const ElementKind STATEMENT = | 112 static const ElementKind STATEMENT = |
| 113 const ElementKind('statement', ElementCategory.NONE); | 113 const ElementKind('statement', ElementCategory.NONE); |
| 114 static const ElementKind LABEL = | 114 static const ElementKind LABEL = |
| 115 const ElementKind('label', ElementCategory.NONE); | 115 const ElementKind('label', ElementCategory.NONE); |
| 116 static const ElementKind VOID = | 116 static const ElementKind VOID = |
| 117 const ElementKind('void', ElementCategory.NONE); | 117 const ElementKind('void', ElementCategory.NONE); |
| 118 | 118 |
| 119 static const ElementKind AMBIGUOUS = |
| 120 const ElementKind('ambiguous', ElementCategory.NONE); |
| 119 static const ElementKind ERROR = | 121 static const ElementKind ERROR = |
| 120 const ElementKind('error', ElementCategory.NONE); | 122 const ElementKind('error', ElementCategory.NONE); |
| 121 | 123 |
| 122 toString() => id; | 124 toString() => id; |
| 123 } | 125 } |
| 124 | 126 |
| 125 class Element implements Spannable { | 127 class Element implements Spannable { |
| 126 static int elementHashCode = 0; | 128 static int elementHashCode = 0; |
| 127 | 129 |
| 128 final SourceString name; | 130 final SourceString name; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 bool isSetter() => identical(kind, ElementKind.SETTER); | 190 bool isSetter() => identical(kind, ElementKind.SETTER); |
| 189 bool isAccessor() => isGetter() || isSetter(); | 191 bool isAccessor() => isGetter() || isSetter(); |
| 190 bool isForeign() => identical(kind, ElementKind.FOREIGN); | 192 bool isForeign() => identical(kind, ElementKind.FOREIGN); |
| 191 bool isLibrary() => identical(kind, ElementKind.LIBRARY); | 193 bool isLibrary() => identical(kind, ElementKind.LIBRARY); |
| 192 bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0; | 194 bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0; |
| 193 bool isExtendable() => (kind.category & ElementCategory.IS_EXTENDABLE) != 0; | 195 bool isExtendable() => (kind.category & ElementCategory.IS_EXTENDABLE) != 0; |
| 194 | 196 |
| 195 /** See [ErroneousElement] for documentation. */ | 197 /** See [ErroneousElement] for documentation. */ |
| 196 bool isErroneous() => false; | 198 bool isErroneous() => false; |
| 197 | 199 |
| 200 /** See [AmbiguousElement] for documentation. */ |
| 201 bool isAmbiguous() => false; |
| 202 |
| 198 /** | 203 /** |
| 199 * Is [:true:] if this element has a corresponding patch. | 204 * Is [:true:] if this element has a corresponding patch. |
| 200 * | 205 * |
| 201 * If [:true:] this element has a non-null [patch] field. | 206 * If [:true:] this element has a non-null [patch] field. |
| 202 * | 207 * |
| 203 * See [:patch_parser.dart:] for a description of the terminology. | 208 * See [:patch_parser.dart:] for a description of the terminology. |
| 204 */ | 209 */ |
| 205 bool get isPatched => false; | 210 bool get isPatched => false; |
| 206 | 211 |
| 207 /** | 212 /** |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 * Accessing any field or calling any method defined on [ErroneousElement] | 372 * Accessing any field or calling any method defined on [ErroneousElement] |
| 368 * except [isErroneous] will currently throw an exception. (This might | 373 * except [isErroneous] will currently throw an exception. (This might |
| 369 * change when we actually want more information on the erroneous element, | 374 * change when we actually want more information on the erroneous element, |
| 370 * e.g., the name of the element we were trying to resolve.) | 375 * e.g., the name of the element we were trying to resolve.) |
| 371 * | 376 * |
| 372 * Code that cannot not handle an [ErroneousElement] should use | 377 * Code that cannot not handle an [ErroneousElement] should use |
| 373 * [: Element.isInvalid(element) :] | 378 * [: Element.isInvalid(element) :] |
| 374 * to check for unresolvable elements instead of | 379 * to check for unresolvable elements instead of |
| 375 * [: element == null :]. | 380 * [: element == null :]. |
| 376 */ | 381 */ |
| 377 class ErroneousElement extends Element { | 382 class ErroneousElement extends Element implements FunctionElement { |
| 378 final MessageKind messageKind; | 383 final MessageKind messageKind; |
| 379 final List messageArguments; | 384 final List messageArguments; |
| 380 final SourceString targetName; | |
| 381 | 385 |
| 382 ErroneousElement(this.messageKind, this.messageArguments, | 386 ErroneousElement(this.messageKind, this.messageArguments, |
| 383 this.targetName, Element enclosing) | 387 SourceString name, Element enclosing) |
| 384 : super(const SourceString('erroneous element'), | 388 : super(name, ElementKind.ERROR, enclosing); |
| 385 ElementKind.ERROR, enclosing); | |
| 386 | 389 |
| 387 isErroneous() => true; | 390 isErroneous() => true; |
| 388 | 391 |
| 389 unsupported() { | 392 unsupported() { |
| 390 throw 'unsupported operation on erroneous element'; | 393 throw 'unsupported operation on erroneous element'; |
| 391 } | 394 } |
| 392 | 395 |
| 393 SourceString get name => unsupported(); | |
| 394 Link<MetadataAnnotation> get metadata => unsupported(); | 396 Link<MetadataAnnotation> get metadata => unsupported(); |
| 395 | |
| 396 getLibrary() => enclosingElement.getLibrary(); | |
| 397 | |
| 398 String toString() { | |
| 399 String n = targetName.slowToString(); | |
| 400 return '<$n: ${messageKind.message(messageArguments)}>'; | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 class ErroneousFunctionElement extends ErroneousElement | |
| 405 implements FunctionElement { | |
| 406 ErroneousFunctionElement(MessageKind messageKind, List messageArguments, | |
| 407 SourceString targetName, Element enclosing) | |
| 408 : super(messageKind, messageArguments, targetName, enclosing); | |
| 409 | |
| 410 get type => unsupported(); | 397 get type => unsupported(); |
| 411 get cachedNode => unsupported(); | 398 get cachedNode => unsupported(); |
| 412 get functionSignature => unsupported(); | 399 get functionSignature => unsupported(); |
| 413 get patch => unsupported(); | 400 get patch => unsupported(); |
| 414 get origin => unsupported(); | 401 get origin => unsupported(); |
| 415 get defaultImplementation => unsupported(); | 402 get defaultImplementation => unsupported(); |
| 416 bool get isPatched => unsupported(); | 403 bool get isPatched => unsupported(); |
| 417 bool get isPatch => unsupported(); | 404 bool get isPatch => unsupported(); |
| 418 setPatch(patch) => unsupported(); | 405 setPatch(patch) => unsupported(); |
| 419 computeSignature(compiler) => unsupported(); | 406 computeSignature(compiler) => unsupported(); |
| 420 requiredParameterCount(compiler) => unsupported(); | 407 requiredParameterCount(compiler) => unsupported(); |
| 421 optionalParameterCount(compiler) => unsupported(); | 408 optionalParameterCount(compiler) => unsupported(); |
| 422 parameterCount(copmiler) => unsupported(); | 409 parameterCount(copmiler) => unsupported(); |
| 410 |
| 411 get redirectionTarget => this; |
| 412 |
| 413 getLibrary() => enclosingElement.getLibrary(); |
| 414 |
| 415 String toString() { |
| 416 String n = name.slowToString(); |
| 417 return '<$n: ${messageKind.message(messageArguments)}>'; |
| 418 } |
| 419 } |
| 420 |
| 421 /** |
| 422 * An ambiguous element represent multiple elements accessible by the same name. |
| 423 * |
| 424 * Ambiguous elements are created during handling of import/export scopes. If an |
| 425 * ambiguous element is encountered during resolution a warning/error should be |
| 426 * reported. |
| 427 */ |
| 428 class AmbiguousElement extends Element { |
| 429 /** |
| 430 * The message to report on resolving this element. |
| 431 */ |
| 432 final MessageKind messageKind; |
| 433 |
| 434 /** |
| 435 * The message arguments to report on resolving this element. |
| 436 */ |
| 437 final List messageArguments; |
| 438 |
| 439 /** |
| 440 * The first element that this ambiguous element might refer to. |
| 441 */ |
| 442 final Element existingElement; |
| 443 |
| 444 /** |
| 445 * The second element that this ambiguous element might refer to. |
| 446 */ |
| 447 final Element newElement; |
| 448 |
| 449 AmbiguousElement(this.messageKind, this.messageArguments, |
| 450 Element enclosingElement, Element existingElement, Element newElement) |
| 451 : this.existingElement = existingElement, |
| 452 this.newElement = newElement, |
| 453 super(existingElement.name, ElementKind.AMBIGUOUS, enclosingElement); |
| 454 |
| 455 bool isAmbiguous() => true; |
| 423 } | 456 } |
| 424 | 457 |
| 425 class ContainerElement extends Element { | 458 class ContainerElement extends Element { |
| 426 Link<Element> localMembers = const Link<Element>(); | 459 Link<Element> localMembers = const Link<Element>(); |
| 427 | 460 |
| 428 ContainerElement(name, kind, enclosingElement) | 461 ContainerElement(name, kind, enclosingElement) |
| 429 : super(name, kind, enclosingElement); | 462 : super(name, kind, enclosingElement); |
| 430 | 463 |
| 431 void addMember(Element element, DiagnosticListener listener) { | 464 void addMember(Element element, DiagnosticListener listener) { |
| 432 localMembers = localMembers.prepend(element); | 465 localMembers = localMembers.prepend(element); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 /** | 686 /** |
| 654 * Adds [element] to the import scope of this library. | 687 * Adds [element] to the import scope of this library. |
| 655 * | 688 * |
| 656 * If an element by the same name is already in the imported scope, an | 689 * If an element by the same name is already in the imported scope, an |
| 657 * [ErroneousElement] will be put in the imported scope, allowing for the | 690 * [ErroneousElement] will be put in the imported scope, allowing for the |
| 658 * detection of ambiguous uses of imported names. | 691 * detection of ambiguous uses of imported names. |
| 659 */ | 692 */ |
| 660 void addImport(Element element, DiagnosticListener listener) { | 693 void addImport(Element element, DiagnosticListener listener) { |
| 661 Element existing = importScope[element.name]; | 694 Element existing = importScope[element.name]; |
| 662 if (existing != null) { | 695 if (existing != null) { |
| 663 if (!existing.isErroneous()) { | 696 // TODO(johnniwinther): Provide access to the import tags from which |
| 664 // TODO(johnniwinther): Provide access to both the new and existing | 697 // the elements came. |
| 665 // elements. | 698 importScope[element.name] = new AmbiguousElement( |
| 666 importScope[element.name] = new ErroneousElement( | 699 MessageKind.DUPLICATE_IMPORT, [element.name], |
| 667 MessageKind.DUPLICATE_IMPORT, | 700 this, existing, element); |
| 668 [element.name], element.name, this); | |
| 669 } | |
| 670 } else { | 701 } else { |
| 671 importScope[element.name] = element; | 702 importScope[element.name] = element; |
| 672 } | 703 } |
| 673 } | 704 } |
| 674 | 705 |
| 675 /** | 706 /** |
| 676 * Returns [:true:] if the export scope has already been computed for this | 707 * Returns [:true:] if the export scope has already been computed for this |
| 677 * library. | 708 * library. |
| 678 */ | 709 */ |
| 679 bool get exportsHandled => slotForExports != null; | 710 bool get exportsHandled => slotForExports != null; |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1094 /** | 1125 /** |
| 1095 * A function declaration that should be parsed instead of the current one. | 1126 * A function declaration that should be parsed instead of the current one. |
| 1096 * The patch should be parsed as if it was in the current scope. Its | 1127 * The patch should be parsed as if it was in the current scope. Its |
| 1097 * signature must match this function's signature. | 1128 * signature must match this function's signature. |
| 1098 */ | 1129 */ |
| 1099 // TODO(lrn): Consider using [defaultImplementation] to store the patch. | 1130 // TODO(lrn): Consider using [defaultImplementation] to store the patch. |
| 1100 FunctionElement patch = null; | 1131 FunctionElement patch = null; |
| 1101 FunctionElement origin = null; | 1132 FunctionElement origin = null; |
| 1102 | 1133 |
| 1103 /** | 1134 /** |
| 1104 * If this is an interface constructor, [defaultImplementation] will | 1135 * If this is a redirecting factory, [defaultImplementation] will be |
| 1105 * changed by the resolver to point to the default | 1136 * changed by the resolver to point to the redirection target. If |
| 1106 * implementation. Otherwise, [:defaultImplementation === this:]. | 1137 * this is an interface constructor, [defaultImplementation] will be |
| 1138 * changed by the resolver to point to the default implementation. |
| 1139 * Otherwise, [:defaultImplementation === this:]. |
| 1107 */ | 1140 */ |
| 1141 // TODO(ahe): Rename this field to redirectionTarget and remove |
| 1142 // mention of interface constructors above. |
| 1108 FunctionElement defaultImplementation; | 1143 FunctionElement defaultImplementation; |
| 1109 | 1144 |
| 1110 FunctionElement(SourceString name, | 1145 FunctionElement(SourceString name, |
| 1111 ElementKind kind, | 1146 ElementKind kind, |
| 1112 Modifiers modifiers, | 1147 Modifiers modifiers, |
| 1113 Element enclosing) | 1148 Element enclosing) |
| 1114 : this.tooMuchOverloading(name, null, kind, modifiers, enclosing, null); | 1149 : this.tooMuchOverloading(name, null, kind, modifiers, enclosing, null); |
| 1115 | 1150 |
| 1116 FunctionElement.node(SourceString name, | 1151 FunctionElement.node(SourceString name, |
| 1117 FunctionExpression node, | 1152 FunctionExpression node, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1134 Element enclosing, | 1169 Element enclosing, |
| 1135 FunctionSignature this.functionSignature) | 1170 FunctionSignature this.functionSignature) |
| 1136 : super(name, kind, enclosing) { | 1171 : super(name, kind, enclosing) { |
| 1137 assert(modifiers != null); | 1172 assert(modifiers != null); |
| 1138 defaultImplementation = this; | 1173 defaultImplementation = this; |
| 1139 } | 1174 } |
| 1140 | 1175 |
| 1141 bool get isPatched => patch != null; | 1176 bool get isPatched => patch != null; |
| 1142 bool get isPatch => origin != null; | 1177 bool get isPatch => origin != null; |
| 1143 | 1178 |
| 1179 FunctionElement get redirectionTarget { |
| 1180 if (this == defaultImplementation) return this; |
| 1181 Element target = defaultImplementation; |
| 1182 Set<Element> seen = new Set<Element>(); |
| 1183 seen.add(target); |
| 1184 while (!target.isErroneous() && target != target.defaultImplementation) { |
| 1185 target = target.defaultImplementation; |
| 1186 if (seen.contains(target)) { |
| 1187 // TODO(ahe): This is expedient for now, but it should be |
| 1188 // checked by the resolver. Keeping http://dartbug.com/3970 |
| 1189 // open to track this. |
| 1190 throw new SpannableAssertionFailure( |
| 1191 target, 'redirecting factory leads to cycle'); |
| 1192 } |
| 1193 } |
| 1194 return target; |
| 1195 } |
| 1196 |
| 1144 /** | 1197 /** |
| 1145 * Applies a patch function to this function. The patch function's body | 1198 * Applies a patch function to this function. The patch function's body |
| 1146 * is used as replacement when parsing this function's body. | 1199 * is used as replacement when parsing this function's body. |
| 1147 * This method must not be called after the function has been parsed, | 1200 * This method must not be called after the function has been parsed, |
| 1148 * and it must be called at most once. | 1201 * and it must be called at most once. |
| 1149 */ | 1202 */ |
| 1150 void setPatch(FunctionElement patchElement) { | 1203 void setPatch(FunctionElement patchElement) { |
| 1151 // Sanity checks. The caller must check these things before calling. | 1204 // Sanity checks. The caller must check these things before calling. |
| 1152 assert(patch == null); | 1205 assert(patch == null); |
| 1153 this.patch = patchElement; | 1206 this.patch = patchElement; |
| (...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1956 | 2009 |
| 1957 MetadataAnnotation ensureResolved(Compiler compiler) { | 2010 MetadataAnnotation ensureResolved(Compiler compiler) { |
| 1958 if (resolutionState == STATE_NOT_STARTED) { | 2011 if (resolutionState == STATE_NOT_STARTED) { |
| 1959 compiler.resolver.resolveMetadataAnnotation(this); | 2012 compiler.resolver.resolveMetadataAnnotation(this); |
| 1960 } | 2013 } |
| 1961 return this; | 2014 return this; |
| 1962 } | 2015 } |
| 1963 | 2016 |
| 1964 String toString() => 'MetadataAnnotation($value, $resolutionState)'; | 2017 String toString() => 'MetadataAnnotation($value, $resolutionState)'; |
| 1965 } | 2018 } |
| OLD | NEW |