Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: lib/compiler/implementation/elements/elements.dart

Issue 10905305: Patch refactoring. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 #import('../tree/tree.dart'); 9 #import('../tree/tree.dart');
10 #import('../scanner/scannerlib.dart'); 10 #import('../scanner/scannerlib.dart');
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 toString() => id; 107 toString() => id;
108 } 108 }
109 109
110 class Element implements Hashable, Spannable { 110 class Element implements Hashable, Spannable {
111 final SourceString name; 111 final SourceString name;
112 final ElementKind kind; 112 final ElementKind kind;
113 final Element enclosingElement; 113 final Element enclosingElement;
114 Link<MetadataAnnotation> metadata = const EmptyLink<MetadataAnnotation>(); 114 Link<MetadataAnnotation> metadata = const EmptyLink<MetadataAnnotation>();
115 115
116 Element(this.name, this.kind, this.enclosingElement) { 116 Element(this.name, this.kind, this.enclosingElement) {
117 assert(getLibrary() !== null); 117 assert(isErroneous() || getImplementationLibrary() !== null);
118 } 118 }
119 119
120 Modifiers get modifiers => null; 120 Modifiers get modifiers => null;
121 121
122 Node parseNode(DiagnosticListener listener) { 122 Node parseNode(DiagnosticListener listener) {
123 listener.cancel("Internal Error: $this.parseNode", token: position()); 123 listener.cancel("Internal Error: $this.parseNode not "
124 "implemented on ${super.toString()}", token: position());
124 } 125 }
125 126
126 DartType computeType(Compiler compiler) { 127 DartType computeType(Compiler compiler) {
127 compiler.internalError("$this.computeType.", token: position()); 128 compiler.internalError("$this.computeType.", token: position());
128 } 129 }
129 130
130 void addMetadata(MetadataAnnotation annotation) { 131 void addMetadata(MetadataAnnotation annotation) {
131 assert(annotation.annotatedElement === null); 132 assert(annotation.annotatedElement === null);
132 annotation.annotatedElement = this; 133 annotation.annotatedElement = this;
133 metadata = metadata.prepend(annotation); 134 metadata = metadata.prepend(annotation);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 183
183 /** 184 /**
184 * Is [:true:] if this element is a patch. 185 * Is [:true:] if this element is a patch.
185 * 186 *
186 * If [:true:] this element has a non-null [origin] field. 187 * If [:true:] this element has a non-null [origin] field.
187 * 188 *
188 * See [:patch_parser.dart:] for a description of the terminology. 189 * See [:patch_parser.dart:] for a description of the terminology.
189 */ 190 */
190 bool get isPatch => false; 191 bool get isPatch => false;
191 192
192
193 /** 193 /**
194 * Is [:true:] if this element defines the implementation for the entity of 194 * Is [:true:] if this element defines the implementation for the entity of
195 * this element. 195 * this element.
196 * 196 *
197 * See [:patch_parser.dart:] for a description of the terminology. 197 * See [:patch_parser.dart:] for a description of the terminology.
198 */ 198 */
199 bool get isImplementation => implementation === this; 199 bool get isImplementation => !isPatched;
200 200
201 /** 201 /**
202 * Is [:true:] if this element introduces the entity of this element. 202 * Is [:true:] if this element introduces the entity of this element.
203 * 203 *
204 * See [:patch_parser.dart:] for a description of the terminology. 204 * See [:patch_parser.dart:] for a description of the terminology.
205 */ 205 */
206 bool get isDeclaration => declaration === this; 206 bool get isDeclaration => !isPatch;
207 207
208 /** 208 /**
209 * Returns the element which defines the implementation for the entity of this 209 * Returns the element which defines the implementation for the entity of this
210 * element. 210 * element.
211 * 211 *
212 * See [:patch_parser.dart:] for a description of the terminology. 212 * See [:patch_parser.dart:] for a description of the terminology.
213 */ 213 */
214 Element get implementation => this; 214 Element get implementation => isPatched ? patch : this;
215 215
216 /** 216 /**
217 * Returns the element which introduces the entity of this element. 217 * Returns the element which introduces the entity of this element.
218 * 218 *
219 * See [:patch_parser.dart:] for a description of the terminology. 219 * See [:patch_parser.dart:] for a description of the terminology.
220 */ 220 */
221 Element get declaration => this; 221 Element get declaration => isPatch ? origin : this;
222 222
223 // TODO(johnniwinther): This breaks for libraries (for which enclosing 223 // TODO(johnniwinther): This breaks for libraries (for which enclosing
224 // elements are null) and is invalid for top level variable declarations for 224 // elements are null) and is invalid for top level variable declarations for
225 // which the enclosing element is a VariableDeclarations and not a compilation 225 // which the enclosing element is a VariableDeclarations and not a compilation
226 // unit. 226 // unit.
227 bool isTopLevel() { 227 bool isTopLevel() {
228 return enclosingElement !== null && enclosingElement.isCompilationUnit(); 228 return enclosingElement !== null && enclosingElement.isCompilationUnit();
229 } 229 }
230 230
231 bool isAssignable() { 231 bool isAssignable() {
(...skipping 21 matching lines...) Expand all
253 while (element !== null && !element.isCompilationUnit()) { 253 while (element !== null && !element.isCompilationUnit()) {
254 if (element is CompilationUnitOverrideElement) { 254 if (element is CompilationUnitOverrideElement) {
255 CompilationUnitOverrideElement override = element; 255 CompilationUnitOverrideElement override = element;
256 return override.compilationUnit; 256 return override.compilationUnit;
257 } 257 }
258 if (element.isLibrary()) { 258 if (element.isLibrary()) {
259 LibraryElement library = element; 259 LibraryElement library = element;
260 return library.entryCompilationUnit; 260 return library.entryCompilationUnit;
261 } 261 }
262 element = element.enclosingElement; 262 element = element.enclosingElement;
263 if (element is FunctionElement) {
264 FunctionElement function = element;
265 if (function.isPatched) {
266 element = function.patch;
267 }
268 }
269 } 263 }
270 return element; 264 return element;
271 } 265 }
272 266
273 LibraryElement getLibrary() { 267 LibraryElement getLibrary() => enclosingElement.getLibrary();
268
269 LibraryElement getImplementationLibrary() {
274 Element element = this; 270 Element element = this;
275 while (element.kind !== ElementKind.LIBRARY) { 271 while (element.kind !== ElementKind.LIBRARY) {
276 element = element.enclosingElement; 272 element = element.enclosingElement;
277 } 273 }
278 return element; 274 return element;
279 } 275 }
280 276
281 LibraryElement getImplementationLibrary() => getLibrary();
282
283 ClassElement getEnclosingClass() { 277 ClassElement getEnclosingClass() {
284 for (Element e = this; e !== null; e = e.enclosingElement) { 278 for (Element e = this; e !== null; e = e.enclosingElement) {
285 if (e.isClass()) return e; 279 if (e.isClass()) return e;
286 } 280 }
287 return null; 281 return null;
288 } 282 }
289 283
290 Element getEnclosingClassOrCompilationUnit() { 284 Element getEnclosingClassOrCompilationUnit() {
291 for (Element e = this; e !== null; e = e.enclosingElement) { 285 for (Element e = this; e !== null; e = e.enclosingElement) {
292 if (e.isClass() || e.isCompilationUnit()) return e; 286 if (e.isClass() || e.isCompilationUnit()) return e;
(...skipping 15 matching lines...) Expand all
308 return e; 302 return e;
309 } 303 }
310 } 304 }
311 return null; 305 return null;
312 } 306 }
313 307
314 /** 308 /**
315 * Creates the scope for this element. The scope of the 309 * Creates the scope for this element. The scope of the
316 * enclosing element will be the parent scope. 310 * enclosing element will be the parent scope.
317 */ 311 */
318 Scope buildScope() => buildEnclosingScope(); 312 Scope buildScope([bool patchScope = false]) =>
ahe 2012/09/24 12:30:18 I don't like this optional argument. I think you w
ahe 2012/09/24 12:30:18 Use {}
Johnni Winther 2012/09/25 09:01:07 Done.
Johnni Winther 2012/09/25 09:01:07 Done.
313 buildEnclosingScope(patchScope);
319 314
320 /** 315 /**
321 * Creates the scope for the enclosing element. 316 * Creates the scope for the enclosing element.
322 */ 317 */
323 Scope buildEnclosingScope() => enclosingElement.buildScope(); 318 Scope buildEnclosingScope([bool patchScope = false]) =>
ahe 2012/09/24 12:30:18 Ditto.
ahe 2012/09/24 12:30:18 Use {}
Johnni Winther 2012/09/25 09:01:07 Done.
Johnni Winther 2012/09/25 09:01:07 Done.
319 enclosingElement.buildScope(patchScope);
324 320
325 String toString() { 321 String toString() {
326 // TODO(johnniwinther): Test for nullness of name, or make non-nullness an 322 // TODO(johnniwinther): Test for nullness of name, or make non-nullness an
327 // invariant for all element types? 323 // invariant for all element types?
328 var nameText = name !== null ? name.slowToString() : '?'; 324 var nameText = name !== null ? name.slowToString() : '?';
329 if (enclosingElement !== null && !isTopLevel()) { 325 if (enclosingElement !== null && !isTopLevel()) {
330 String holderName = enclosingElement.name !== null 326 String holderName = enclosingElement.name !== null
331 ? enclosingElement.name.slowToString() 327 ? enclosingElement.name.slowToString()
332 : '${enclosingElement.kind}?'; 328 : '${enclosingElement.kind}?';
333 return '$kind($holderName#${nameText})'; 329 return '$kind($holderName#${nameText})';
334 } else { 330 } else {
335 return '$kind(${nameText})'; 331 return '$kind(${nameText})';
336 } 332 }
337 } 333 }
338 334
339 bool _isNative = false; 335 bool _isNative = false;
340 void setNative() { _isNative = true; } 336 void setNative() { _isNative = true; }
341 bool isNative() => _isNative; 337 bool isNative() => _isNative;
342 338
343 FunctionElement asFunctionElement() => null; 339 FunctionElement asFunctionElement() => null;
344 340
341 static bool isInvalid(Element e) => e == null || e.isErroneous();
345 Element cloneTo(Element enclosing, DiagnosticListener listener) { 342 Element cloneTo(Element enclosing, DiagnosticListener listener) {
346 listener.cancel("Unimplemented cloneTo", element: this); 343 listener.cancel("Unimplemented cloneTo", element: this);
347 } 344 }
348 } 345 }
349 346
350 /** 347 /**
351 * Represents an unresolvable or duplicated element. 348 * Represents an unresolvable or duplicated element.
352 * 349 *
353 * An [ErroneousElement] is used instead of [null] to provide additional 350 * An [ErroneousElement] is used instead of [null] to provide additional
354 * information about the error that caused the element to be unresolvable 351 * information about the error that caused the element to be unresolvable
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 Element existing = localScope.putIfAbsent(element.name, () => element); 434 Element existing = localScope.putIfAbsent(element.name, () => element);
438 if (existing !== element) { 435 if (existing !== element) {
439 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. 436 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext.
440 listener.cancel('duplicate definition', token: element.position()); 437 listener.cancel('duplicate definition', token: element.position());
441 listener.cancel('existing definition', token: existing.position()); 438 listener.cancel('existing definition', token: existing.position());
442 } 439 }
443 } 440 }
444 } 441 }
445 442
446 Element localLookup(SourceString elementName) { 443 Element localLookup(SourceString elementName) {
447 return localScope[elementName]; 444 Element result = localScope[elementName];
445 if (result == null && isPatch) {
446 result = origin.localScope[elementName];
447 }
448 return result;
448 } 449 }
449 450
450 /** 451 /**
451 * Adds a definition for an [accessor] (getter or setter) to a container. 452 * Adds a definition for an [accessor] (getter or setter) to a container.
452 * The definition binds to an abstract field that can hold both a getter 453 * The definition binds to an abstract field that can hold both a getter
453 * and a setter. 454 * and a setter.
454 * 455 *
455 * The abstract field is added once, for the first getter or setter, and 456 * The abstract field is added once, for the first getter or setter, and
456 * reused if the other one is also added. 457 * reused if the other one is also added.
457 * The abstract field should not be treated as a proper member of the 458 * The abstract field should not be treated as a proper member of the
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 CompilationUnitElement(Script script, Element enclosing) 509 CompilationUnitElement(Script script, Element enclosing)
509 : this.script = script, 510 : this.script = script,
510 super(new SourceString(script.name), 511 super(new SourceString(script.name),
511 ElementKind.COMPILATION_UNIT, 512 ElementKind.COMPILATION_UNIT,
512 enclosing); 513 enclosing);
513 514
514 void addMember(Element element, DiagnosticListener listener) { 515 void addMember(Element element, DiagnosticListener listener) {
515 // Keep a list of top level members. 516 // Keep a list of top level members.
516 super.addMember(element, listener); 517 super.addMember(element, listener);
517 // Provide the member to the library to build scope. 518 // Provide the member to the library to build scope.
518 getLibrary().addMember(element, listener); 519 if (enclosingElement.isPatch) {
520 getImplementationLibrary().addMember(element, listener);
521 } else {
522 getLibrary().addMember(element, listener);
523 }
519 } 524 }
520 } 525 }
521 526
522 class CompilationUnitOverrideElement extends Element { 527 class CompilationUnitOverrideElement extends Element {
523 final CompilationUnitElement compilationUnit; 528 final CompilationUnitElement compilationUnit;
524 529
525 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit, 530 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit,
526 Element enclosing) 531 Element enclosing)
527 : this.compilationUnit = compilationUnit, 532 : this.compilationUnit = compilationUnit,
528 super(compilationUnit.name, 533 super(compilationUnit.name,
529 ElementKind.COMPILATION_UNIT_OVERRIDE, 534 ElementKind.COMPILATION_UNIT_OVERRIDE,
530 enclosing); 535 enclosing);
531 } 536 }
532 537
533 class LibraryElement extends ScopeContainerElement { 538 class LibraryElement extends ScopeContainerElement {
534 final Uri uri; 539 final Uri uri;
535 CompilationUnitElement entryCompilationUnit; 540 CompilationUnitElement entryCompilationUnit;
536 Link<CompilationUnitElement> compilationUnits = 541 Link<CompilationUnitElement> compilationUnits =
537 const EmptyLink<CompilationUnitElement>(); 542 const EmptyLink<CompilationUnitElement>();
538 Link<LibraryTag> tags = const EmptyLink<LibraryTag>(); 543 Link<LibraryTag> tags = const EmptyLink<LibraryTag>();
539 LibraryTag libraryTag; 544 LibraryTag libraryTag;
540 bool canUseNative = false; 545 bool canUseNative = false;
541 LibraryElement patch = null; 546 LibraryElement patch = null;
547 final LibraryElement origin;
542 548
543 /** 549 /**
544 * Map for elements imported through import declarations. 550 * Map for elements imported through import declarations.
545 * 551 *
546 * Addition to the map is performed by [addImport]. Lookup is done trough 552 * Addition to the map is performed by [addImport]. Lookup is done trough
547 * [find]. 553 * [find].
548 */ 554 */
549 final Map<SourceString, Element> importScope; 555 final Map<SourceString, Element> importScope;
550 556
551 LibraryElement(Script script, [Uri uri]) 557 LibraryElement(Script script, [Uri uri, LibraryElement this.origin])
552 : this.uri = ((uri === null) ? script.uri : uri), 558 : this.uri = ((uri === null) ? script.uri : uri),
553 importScope = new Map<SourceString, Element>(), 559 importScope = new Map<SourceString, Element>(),
554 super(new SourceString(script.name), ElementKind.LIBRARY, null) { 560 super(new SourceString(script.name), ElementKind.LIBRARY, null) {
555 entryCompilationUnit = new CompilationUnitElement(script, this); 561 entryCompilationUnit = new CompilationUnitElement(script, this);
562 if (isPatch) {
563 origin.patch = this;
564 }
556 } 565 }
557 566
558
559 bool get isPatched => patch !== null; 567 bool get isPatched => patch !== null;
568 bool get isPatch => origin !== null;
560 569
561 void addCompilationUnit(CompilationUnitElement element) { 570 void addCompilationUnit(CompilationUnitElement element) {
562 compilationUnits = compilationUnits.prepend(element); 571 compilationUnits = compilationUnits.prepend(element);
563 } 572 }
564 573
565 void addTag(LibraryTag tag, DiagnosticListener listener) { 574 void addTag(LibraryTag tag, DiagnosticListener listener) {
566 tags = tags.prepend(tag); 575 tags = tags.prepend(tag);
567 } 576 }
568 577
569 /** 578 /**
570 * Adds [element] to the import scope of this library. 579 * Adds [element] to the import scope of this library.
571 * 580 *
572 * If an element by the same name is already in the imported scope, an 581 * If an element by the same name is already in the imported scope, an
573 * [ErroneousElement] will be put in the imported scope, allowing for the 582 * [ErroneousElement] will be put in the imported scope, allowing for the
574 * detection of ambiguous uses of imported names. 583 * detection of ambiguous uses of imported names.
575 */ 584 */
576 void addImport(Element element, DiagnosticListener listener) { 585 void addImport(Element element, DiagnosticListener listener) {
577 Element existing = importScope.putIfAbsent(element.name, () => element); 586 Element existing = importScope.putIfAbsent(element.name, () => element);
578 if (existing !== element && existing !== null) { 587 if (existing !== element && existing !== null) {
579 if (!existing.isErroneous()) { 588 if (!existing.isErroneous()) {
580 // TODO(johnniwinther): Provide access to both the new and existing 589 // TODO(johnniwinther): Provide access to both the new and existing
581 // elements. 590 // elements.
582 importScope[element.name] = new ErroneousElement( 591 importScope[element.name] = new ErroneousElement(
583 MessageKind.DUPLICATE_IMPORT, 592 MessageKind.DUPLICATE_IMPORT,
584 [element.name], element.name, this); 593 [element.name], element.name, this);
585 } 594 }
586 } 595 }
587 } 596 }
588 597
598 LibraryElement getLibrary() => isPatch ? origin : this;
589 599
590 /** 600 /**
591 * Look up a top-level element in this library. The element could 601 * Look up a top-level element in this library. The element could
592 * potentially have been imported from another library. Returns 602 * potentially have been imported from another library. Returns
593 * null if no such element exist and an [ErroneousElement] if multiple 603 * null if no such element exist and an [ErroneousElement] if multiple
594 * elements have been imported. 604 * elements have been imported.
595 */ 605 */
596 Element find(SourceString elementName) { 606 Element find(SourceString elementName) {
597 Element result = localScope[elementName]; 607 Element result = localScope[elementName];
598 if (result === null) { 608 if (result === null) {
599 result = importScope[elementName]; 609 result = importScope[elementName];
600 } 610 }
601 return result; 611 return result;
602 } 612 }
603 613
604 /** Look up a top-level element in this library, but only look for 614 /** Look up a top-level element in this library, but only look for
605 * non-imported elements. Returns null if no such element exist. */ 615 * non-imported elements. Returns null if no such element exist. */
606 Element findLocal(SourceString elementName) { 616 Element findLocal(SourceString elementName) {
617 // TODO(johnniwinther): How to handle injected elements in the patch
618 // library?
607 Element result = localScope[elementName]; 619 Element result = localScope[elementName];
608 if (result === null || result.getLibrary() != this) return null; 620 if (result === null || result.getLibrary() != this) return null;
609 return result; 621 return result;
610 } 622 }
611 623
612 void forEachExport(f(Element element)) { 624 void forEachExport(f(Element element)) {
613 localScope.forEach((_, Element e) { 625 localScope.forEach((_, Element e) {
614 if (this === e.getLibrary() 626 if (this === e.getLibrary()
615 && e.kind !== ElementKind.PREFIX 627 && e.kind !== ElementKind.PREFIX
616 && e.kind !== ElementKind.FOREIGN 628 && e.kind !== ElementKind.FOREIGN
617 && !e.name.isPrivate()) { 629 && !e.name.isPrivate()) {
618 f(e); 630 f(e);
619 } 631 }
620 }); 632 });
621 } 633 }
622 634
635 void forEachLocalMember(f(Element element),
636 [includeInjectedMembers = false]) {
ahe 2012/09/24 12:30:18 Could we get rid of includeInjectedMembers by usin
Johnni Winther 2012/09/25 09:01:07 Done.
637 localMembers.forEach(f);
638 if (includeInjectedMembers && patch != null) {
639 void filterPatch(Element element) {
640 if (!element.isPatch) {
641 f(element);
642 }
643 }
644 patch.forEachLocalMember(filterPatch);
645 }
646 }
647
623 bool hasLibraryName() => libraryTag !== null; 648 bool hasLibraryName() => libraryTag !== null;
624 649
625 /** 650 /**
626 * Returns the library name (as defined by the #library tag) or for script 651 * Returns the library name (as defined by the #library tag) or for script
627 * (which have no #library tag) the script file name. The latter case is used 652 * (which have no #library tag) the script file name. The latter case is used
628 * to private 'library name' for scripts to use for instance in dartdoc. 653 * to private 'library name' for scripts to use for instance in dartdoc.
629 */ 654 */
630 String getLibraryOrScriptName() { 655 String getLibraryOrScriptName() {
631 if (libraryTag !== null) { 656 if (libraryTag !== null) {
632 return libraryTag.argument.dartString.slowToString(); 657 return libraryTag.argument.dartString.slowToString();
633 } else { 658 } else {
634 // Use the file name as script name. 659 // Use the file name as script name.
635 String path = uri.path; 660 String path = uri.path;
636 return path.substring(path.lastIndexOf('/') + 1); 661 return path.substring(path.lastIndexOf('/') + 1);
637 } 662 }
638 } 663 }
639 664
640 Scope buildEnclosingScope() => new TopScope(this); 665 Scope buildEnclosingScope([bool patchScope = false]) {
666 if (origin !== null) {
667 return new PatchLibraryScope(origin, this);
668 } if (patchScope && patch !== null) {
669 return new PatchLibraryScope(this, patch);
670 } else {
671 return new TopScope(this);
672 }
673 }
641 674
642 bool get isPlatformLibrary => uri.scheme == "dart"; 675 bool get isPlatformLibrary => uri.scheme == "dart";
676
677 String toString() {
678 if (origin !== null) {
679 return 'patch library(${getLibraryOrScriptName()})';
680 } else if (patch !== null) {
681 return 'origin library(${getLibraryOrScriptName()})';
682 } else {
683 return 'library(${getLibraryOrScriptName()})';
684 }
685 }
643 } 686 }
644 687
645 class PrefixElement extends Element { 688 class PrefixElement extends Element {
646 Map<SourceString, Element> imported; 689 Map<SourceString, Element> imported;
647 Token firstPosition; 690 Token firstPosition;
648 691
649 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) 692 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition)
650 : imported = new Map<SourceString, Element>(), 693 : imported = new Map<SourceString, Element>(),
651 super(prefix, ElementKind.PREFIX, enclosing); 694 super(prefix, ElementKind.PREFIX, enclosing);
652 695
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 Typedef node = parseNode(compiler); 730 Typedef node = parseNode(compiler);
688 Link<DartType> parameters = 731 Link<DartType> parameters =
689 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); 732 TypeDeclarationElement.createTypeVariables(this, node.typeParameters);
690 cachedType = new TypedefType(this, parameters); 733 cachedType = new TypedefType(this, parameters);
691 compiler.resolveTypedef(this); 734 compiler.resolveTypedef(this);
692 return cachedType; 735 return cachedType;
693 } 736 }
694 737
695 Link<DartType> get typeVariables => cachedType.typeArguments; 738 Link<DartType> get typeVariables => cachedType.typeArguments;
696 739
697 Scope buildScope() =>
698 new TypeDeclarationScope(enclosingElement.buildScope(), this);
699 740
741 Scope buildScope([bool patchScope = false]) =>
742 new TypeDeclarationScope(enclosingElement.buildScope(patchScope), this);
700 TypedefElement cloneTo(Element enclosing, DiagnosticListener listener) { 743 TypedefElement cloneTo(Element enclosing, DiagnosticListener listener) {
701 TypedefElement result = new TypedefElement(name, enclosing); 744 TypedefElement result = new TypedefElement(name, enclosing);
702 return result; 745 return result;
703 } 746 }
704 } 747 }
705 748
706 class VariableElement extends Element { 749 class VariableElement extends Element {
707 final VariableListElement variables; 750 final VariableListElement variables;
708 Expression cachedNode; // The send or the identifier in the variables list. 751 Expression cachedNode; // The send or the identifier in the variables list.
709 752
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 } else { 890 } else {
848 result = new VariableListElement(kind, modifiers, enclosing); 891 result = new VariableListElement(kind, modifiers, enclosing);
849 } 892 }
850 return result; 893 return result;
851 } 894 }
852 895
853 bool isInstanceMember() { 896 bool isInstanceMember() {
854 return isMember() && !modifiers.isStatic(); 897 return isMember() && !modifiers.isStatic();
855 } 898 }
856 899
857 Scope buildScope() { 900 Scope buildScope([bool patchScope = false]) {
858 Scope result = new VariableScope(enclosingElement.buildScope(), this); 901 Scope result = new VariableScope(enclosingElement.buildScope(patchScope), th is);
859 if (enclosingElement.isClass()) { 902 if (enclosingElement.isClass()) {
860 ClassScope clsScope = result.parent; 903 Scope clsScope = result.parent;
861 clsScope.inStaticContext = !isInstanceMember(); 904 clsScope.inStaticContext = !isInstanceMember();
862 } 905 }
863 return result; 906 return result;
864 } 907 }
865 } 908 }
866 909
867 class ForeignElement extends Element { 910 class ForeignElement extends Element {
868 ForeignElement(SourceString name, ContainerElement enclosingElement) 911 ForeignElement(SourceString name, ContainerElement enclosingElement)
869 : super(name, ElementKind.FOREIGN, enclosingElement); 912 : super(name, ElementKind.FOREIGN, enclosingElement);
870 913
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
981 1024
982 FunctionSignature functionSignature; 1025 FunctionSignature functionSignature;
983 1026
984 /** 1027 /**
985 * A function declaration that should be parsed instead of the current one. 1028 * A function declaration that should be parsed instead of the current one.
986 * The patch should be parsed as if it was in the current scope. Its 1029 * The patch should be parsed as if it was in the current scope. Its
987 * signature must match this function's signature. 1030 * signature must match this function's signature.
988 */ 1031 */
989 // TODO(lrn): Consider using [defaultImplementation] to store the patch. 1032 // TODO(lrn): Consider using [defaultImplementation] to store the patch.
990 FunctionElement patch = null; 1033 FunctionElement patch = null;
1034 FunctionElement origin = null;
991 1035
992 /** 1036 /**
993 * If this is an interface constructor, [defaultImplementation] will 1037 * If this is an interface constructor, [defaultImplementation] will
994 * changed by the resolver to point to the default 1038 * changed by the resolver to point to the default
995 * implementation. Otherwise, [:defaultImplementation === this:]. 1039 * implementation. Otherwise, [:defaultImplementation === this:].
996 */ 1040 */
997 FunctionElement defaultImplementation; 1041 FunctionElement defaultImplementation;
998 1042
999 FunctionElement(SourceString name, 1043 FunctionElement(SourceString name,
1000 ElementKind kind, 1044 ElementKind kind,
(...skipping 19 matching lines...) Expand all
1020 FunctionExpression this.cachedNode, 1064 FunctionExpression this.cachedNode,
1021 ElementKind kind, 1065 ElementKind kind,
1022 Modifiers this.modifiers, 1066 Modifiers this.modifiers,
1023 Element enclosing, 1067 Element enclosing,
1024 FunctionSignature this.functionSignature) 1068 FunctionSignature this.functionSignature)
1025 : super(name, kind, enclosing) { 1069 : super(name, kind, enclosing) {
1026 defaultImplementation = this; 1070 defaultImplementation = this;
1027 } 1071 }
1028 1072
1029 bool get isPatched => patch !== null; 1073 bool get isPatched => patch !== null;
1074 bool get isPatch => origin !== null;
1030 1075
1031 /** 1076 /**
1032 * Applies a patch function to this function. The patch function's body 1077 * Applies a patch function to this function. The patch function's body
1033 * is used as replacement when parsing this function's body. 1078 * is used as replacement when parsing this function's body.
1034 * This method must not be called after the function has been parsed, 1079 * This method must not be called after the function has been parsed,
1035 * and it must be called at most once. 1080 * and it must be called at most once.
1036 */ 1081 */
1037 void setPatch(FunctionElement patchElement) { 1082 void setPatch(FunctionElement patchElement) {
1038 // Sanity checks. The caller must check these things before calling. 1083 // Sanity checks. The caller must check these things before calling.
1039 assert(patch === null); 1084 assert(patch === null);
1040 assert(cachedNode === null);
1041 this.patch = patchElement; 1085 this.patch = patchElement;
1042 cachedNode = patchElement.cachedNode;
1043 } 1086 }
1044 1087
1045 bool isInstanceMember() { 1088 bool isInstanceMember() {
1046 return isMember() 1089 return isMember()
1047 && !isConstructor() 1090 && !isConstructor()
1048 && !modifiers.isStatic(); 1091 && !modifiers.isStatic();
1049 } 1092 }
1050 1093
1051 FunctionSignature computeSignature(Compiler compiler) { 1094 FunctionSignature computeSignature(Compiler compiler) {
1052 if (functionSignature !== null) return functionSignature; 1095 if (functionSignature !== null) return functionSignature;
(...skipping 16 matching lines...) Expand all
1069 } 1112 }
1070 1113
1071 FunctionType computeType(Compiler compiler) { 1114 FunctionType computeType(Compiler compiler) {
1072 if (type != null) return type; 1115 if (type != null) return type;
1073 type = compiler.computeFunctionType(declaration, 1116 type = compiler.computeFunctionType(declaration,
1074 computeSignature(compiler)); 1117 computeSignature(compiler));
1075 return type; 1118 return type;
1076 } 1119 }
1077 1120
1078 Node parseNode(DiagnosticListener listener) { 1121 Node parseNode(DiagnosticListener listener) {
1079 if (cachedNode !== null) return cachedNode;
1080 if (patch === null) { 1122 if (patch === null) {
1081 if (modifiers != null && modifiers.isExternal()) { 1123 if (modifiers != null && modifiers.isExternal()) {
1082 listener.cancel("Compiling external function with no implementation.", 1124 listener.cancel("Compiling external function with no implementation.",
1083 element: this); 1125 element: this);
1084 } 1126 }
1085 return null;
1086 } 1127 }
1087 cachedNode = patch.parseNode(listener);
1088 return cachedNode; 1128 return cachedNode;
1089 } 1129 }
1090 1130
1091 Token position() => cachedNode.getBeginToken(); 1131 Token position() => cachedNode.getBeginToken();
1092 1132
1093 FunctionElement asFunctionElement() => this; 1133 FunctionElement asFunctionElement() => this;
1094 1134
1095 String toString() { 1135 String toString() {
1096 if (isPatch) { 1136 if (isPatch) {
1097 return 'patch ${super.toString()}'; 1137 return 'patch ${super.toString()}';
1098 } else if (isPatched) { 1138 } else if (isPatched) {
1099 return 'origin ${super.toString()}'; 1139 return 'origin ${super.toString()}';
1100 } else { 1140 } else {
1101 return super.toString(); 1141 return super.toString();
1102 } 1142 }
1103 } 1143 }
1104 1144
1105 Scope buildScope() { 1145 Scope buildScope([bool patchScope = false]) {
1106 Scope result = 1146 Scope result =
1107 new MethodScope(enclosingElement.buildScope(), this); 1147 new MethodScope(enclosingElement.buildScope(patchScope), this);
1108 if (enclosingElement.isClass()) { 1148 if (enclosingElement.isClass()) {
1109 Scope clsScope = result.parent; 1149 Scope clsScope = result.parent;
1110 clsScope.inStaticContext = !isInstanceMember() && !isConstructor(); 1150 clsScope.inStaticContext = !isInstanceMember() && !isConstructor();
1111 } 1151 }
1112 return result; 1152 return result;
1113 } 1153 }
1114 } 1154 }
1115 1155
1116 class ConstructorBodyElement extends FunctionElement { 1156 class ConstructorBodyElement extends FunctionElement {
1117 FunctionElement constructor; 1157 FunctionElement constructor;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 int resolutionState; 1263 int resolutionState;
1224 1264
1225 // backendMembers are members that have been added by the backend to simplify 1265 // backendMembers are members that have been added by the backend to simplify
1226 // compilation. They don't have any user-side counter-part. 1266 // compilation. They don't have any user-side counter-part.
1227 Link<Element> backendMembers = const EmptyLink<Element>(); 1267 Link<Element> backendMembers = const EmptyLink<Element>();
1228 1268
1229 Link<DartType> allSupertypes; 1269 Link<DartType> allSupertypes;
1230 1270
1231 // Lazily applied patch of class members. 1271 // Lazily applied patch of class members.
1232 ClassElement patch = null; 1272 ClassElement patch = null;
1273 ClassElement origin = null;
1233 1274
1234 ClassElement(SourceString name, Element enclosing, this.id, int initialState) 1275 ClassElement(SourceString name, Element enclosing, this.id, int initialState)
1235 : supertypeLoadState = initialState, 1276 : supertypeLoadState = initialState,
1236 resolutionState = initialState, 1277 resolutionState = initialState,
1237 super(name, ElementKind.CLASS, enclosing); 1278 super(name, ElementKind.CLASS, enclosing);
1238 1279
1239 InterfaceType computeType(compiler) { 1280 InterfaceType computeType(compiler) {
1240 if (type == null) { 1281 if (type == null) {
1241 ClassNode node = parseNode(compiler); 1282 if (origin !== null) {
1242 Link<DartType> parameters = 1283 type = origin.computeType(compiler);
1243 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); 1284 } else {
1244 type = new InterfaceType(this, parameters); 1285 ClassNode node = parseNode(compiler);
1286 Link<DartType> parameters =
1287 TypeDeclarationElement.createTypeVariables(this, node.typeParameters );
1288 type = new InterfaceType(this, parameters);
1289 }
1245 } 1290 }
1246 return type; 1291 return type;
1247 } 1292 }
1248 1293
1249 bool get isPatched => patch != null; 1294 bool get isPatched => patch != null;
1295 bool get isPatch => origin != null;
1250 1296
1251 /** 1297 /**
1252 * Return [:true:] if this element is the [:Object:] class for the [compiler]. 1298 * Return [:true:] if this element is the [:Object:] class for the [compiler].
1253 */ 1299 */
1254 bool isObject(Compiler compiler) => 1300 bool isObject(Compiler compiler) =>
1255 declaration === compiler.objectClass; 1301 declaration === compiler.objectClass;
1256 1302
1257 Link<DartType> get typeVariables => type.arguments; 1303 Link<DartType> get typeVariables => type.arguments;
1258 1304
1259 ClassElement ensureResolved(Compiler compiler) { 1305 ClassElement ensureResolved(Compiler compiler) {
1260 if (resolutionState == STATE_NOT_STARTED) { 1306 if (resolutionState == STATE_NOT_STARTED) {
1261 compiler.resolver.resolveClass(this); 1307 if (origin !== null) {
ahe 2012/09/24 12:30:18 I think this code should have been added to resolv
Johnni Winther 2012/09/25 09:01:07 Done.
1308 resolutionState = STATE_STARTED;
1309 origin.ensureResolved(compiler);
1310 computeType(compiler);
1311 supertype = origin.supertype;
1312 defaultClass = origin.defaultClass;
1313 interfaces = origin.interfaces;
1314 allSupertypes = origin.allSupertypes;
1315 // Stepwise assignment to ensure invariant.
1316 supertypeLoadState = STATE_STARTED;
1317 supertypeLoadState = STATE_DONE;
1318 resolutionState = STATE_DONE;
1319 // TODO(johnniwinther): Check matching type variables and
1320 // empty extends/implements clauses.
1321 } else {
1322 compiler.resolver.resolveClass(this);
1323 if (patch !== null) {
1324 patch.ensureResolved(compiler);
1325 }
1326 }
1262 } 1327 }
1263 return this; 1328 return this;
1264 } 1329 }
1265 1330
1266 /** 1331 /**
1267 * Lookup local members in the class. This will ignore constructors. 1332 * Lookup local members in the class. This will ignore constructors.
1268 */ 1333 */
1269 Element lookupLocalMember(SourceString memberName) { 1334 Element lookupLocalMember(SourceString memberName,
1335 [bool includeInjectedMembers = false]) {
ahe 2012/09/24 12:30:18 Get rid of includeInjectedMembers?
Johnni Winther 2012/09/25 09:01:07 Done.
1270 var result = localLookup(memberName); 1336 var result = localLookup(memberName);
1271 if (result !== null && result.isConstructor()) return null; 1337 if (result !== null && result.isConstructor()) return null;
1338 if (result == null && patch != null && includeInjectedMembers) {
1339 result = patch.localLookup(memberName);
1340 }
1272 return result; 1341 return result;
1273 } 1342 }
1274 1343
1275 /** 1344 /**
1276 * Lookup super members for the class. This will ignore constructors. 1345 * Lookup super members for the class. This will ignore constructors.
1277 */ 1346 */
1278 Element lookupSuperMember(SourceString memberName) { 1347 Element lookupSuperMember(SourceString memberName) {
1279 return lookupSuperMemberInLibrary(memberName, getLibrary()); 1348 return lookupSuperMemberInLibrary(memberName, getLibrary());
1280 } 1349 }
1281 1350
1282 /** 1351 /**
1283 * Lookup super members for the class that is accessible in [library]. 1352 * Lookup super members for the class that is accessible in [library].
1284 * This will ignore constructors. 1353 * This will ignore constructors.
1285 */ 1354 */
1286 Element lookupSuperMemberInLibrary(SourceString memberName, 1355 Element lookupSuperMemberInLibrary(SourceString memberName,
1287 LibraryElement library) { 1356 LibraryElement library,
1357 [includeInjectedMembers = false]) {
1288 bool isPrivate = memberName.isPrivate(); 1358 bool isPrivate = memberName.isPrivate();
1289 for (ClassElement s = superclass; s != null; s = s.superclass) { 1359 for (ClassElement s = superclass; s != null; s = s.superclass) {
1290 // Private members from a different library are not visible. 1360 // Private members from a different library are not visible.
1291 if (isPrivate && library !== s.getLibrary()) continue; 1361 if (isPrivate && library !== s.getLibrary()) continue;
1292 Element e = s.lookupLocalMember(memberName); 1362 Element e = s.lookupLocalMember(memberName,
1363 includeInjectedMembers: includeInjectedMembers);
1293 if (e === null) continue; 1364 if (e === null) continue;
1294 // Static members are not inherited. 1365 // Static members are not inherited.
1295 if (e.modifiers.isStatic()) continue; 1366 if (e.modifiers.isStatic()) continue;
1296 return e; 1367 return e;
1297 } 1368 }
1298 if (isInterface()) { 1369 if (isInterface()) {
1299 return lookupSuperInterfaceMember(memberName, getLibrary()); 1370 return lookupSuperInterfaceMember(memberName, getLibrary(),
1371 includeInjectedMembers: includeInjectedMembers);
1300 } 1372 }
1301 return null; 1373 return null;
1302 } 1374 }
1303 1375
1304 Element lookupSuperInterfaceMember(SourceString memberName, 1376 Element lookupSuperInterfaceMember(SourceString memberName,
1305 LibraryElement fromLibrary) { 1377 LibraryElement fromLibrary,
1378 [includeInjectedMembers = false]) {
1306 bool isPrivate = memberName.isPrivate(); 1379 bool isPrivate = memberName.isPrivate();
1307 for (InterfaceType t in interfaces) { 1380 for (InterfaceType t in interfaces) {
1308 ClassElement cls = t.element; 1381 ClassElement cls = t.element;
1309 Element e = cls.lookupLocalMember(memberName); 1382 Element e = cls.lookupLocalMember(memberName,
1383 includeInjectedMembers: includeInjectedMembers);
1310 if (e === null) continue; 1384 if (e === null) continue;
1311 // Private members from a different library are not visible. 1385 // Private members from a different library are not visible.
1312 if (isPrivate && fromLibrary !== e.getLibrary()) continue; 1386 if (isPrivate && fromLibrary !== e.getLibrary()) continue;
1313 // Static members are not inherited. 1387 // Static members are not inherited.
1314 if (e.modifiers.isStatic()) continue; 1388 if (e.modifiers.isStatic()) continue;
1315 return e; 1389 return e;
1316 } 1390 }
1317 return null; 1391 return null;
1318 } 1392 }
1319 1393
1320 /** 1394 /**
1321 * Find the first member in the class chain with the given [selector]. 1395 * Find the first member in the class chain with the given [selector].
1322 * 1396 *
1323 * This method is NOT to be used for resolving 1397 * This method is NOT to be used for resolving
1324 * unqualified sends because it does not implement the scoping 1398 * unqualified sends because it does not implement the scoping
1325 * rules, where library scope comes before superclass scope. 1399 * rules, where library scope comes before superclass scope.
1326 */ 1400 */
1327 Element lookupSelector(Selector selector) { 1401 Element lookupSelector(Selector selector) {
1328 SourceString memberName = selector.name; 1402 SourceString memberName = selector.name;
1329 LibraryElement library = selector.library; 1403 LibraryElement library = selector.library;
1330 Element localMember = lookupLocalMember(memberName); 1404 Element localMember = lookupLocalMember(memberName,
1405 includeInjectedMembers: true);
1331 if (localMember != null && 1406 if (localMember != null &&
1332 (!memberName.isPrivate() || getLibrary() == library)) { 1407 (!memberName.isPrivate() || getLibrary() == library)) {
1333 return localMember; 1408 return localMember;
1334 } 1409 }
1335 return lookupSuperMemberInLibrary(memberName, library); 1410 return lookupSuperMemberInLibrary(memberName, library,
1411 includeInjectedMembers: true);
1336 } 1412 }
1337 1413
1338 /** 1414 /**
1339 * Find the first member in the class chain with the given 1415 * Find the first member in the class chain with the given
1340 * [memberName]. This method is NOT to be used for resolving 1416 * [memberName]. This method is NOT to be used for resolving
1341 * unqualified sends because it does not implement the scoping 1417 * unqualified sends because it does not implement the scoping
1342 * rules, where library scope comes before superclass scope. 1418 * rules, where library scope comes before superclass scope.
1343 */ 1419 */
1344 Element lookupMember(SourceString memberName) { 1420 Element lookupMember(SourceString memberName) {
1345 Element localMember = lookupLocalMember(memberName); 1421 Element localMember = lookupLocalMember(memberName);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1398 // Search in scope to be sure we search patched constructors. 1474 // Search in scope to be sure we search patched constructors.
1399 for (var element in localScope.getValues()) { 1475 for (var element in localScope.getValues()) {
1400 if (element.isConstructor()) return true; 1476 if (element.isConstructor()) return true;
1401 } 1477 }
1402 return false; 1478 return false;
1403 } 1479 }
1404 1480
1405 Link<Element> get constructors { 1481 Link<Element> get constructors {
1406 // TODO(ajohnsen): See if we can avoid this method at some point. 1482 // TODO(ajohnsen): See if we can avoid this method at some point.
1407 Link<Element> result = const EmptyLink<Element>(); 1483 Link<Element> result = const EmptyLink<Element>();
1408 for (Element member in localMembers) { 1484 // TODO(johnniwinther): Should we include injected constructors?
1485 forEachMember((_, Element member) {
1409 if (member.isConstructor()) result = result.prepend(member); 1486 if (member.isConstructor()) result = result.prepend(member);
1410 } 1487 });
1411 return result; 1488 return result;
1412 } 1489 }
1413 1490
1414 /** 1491 /**
1415 * Returns the super class, if any. 1492 * Returns the super class, if any.
1416 * 1493 *
1417 * The returned element may not be resolved yet. 1494 * The returned element may not be resolved yet.
1418 */ 1495 */
1419 ClassElement get superclass { 1496 ClassElement get superclass {
1420 assert(supertypeLoadState == STATE_DONE); 1497 assert(supertypeLoadState == STATE_DONE);
1421 return supertype === null ? null : supertype.element; 1498 return supertype === null ? null : supertype.element;
1422 } 1499 }
1423 1500
1424 /** 1501 /**
1425 * Runs through all members of this class. 1502 * Runs through all members of this class.
1426 * 1503 *
1427 * The enclosing class is passed to the callback. This is useful when 1504 * The enclosing class is passed to the callback. This is useful when
1428 * [includeSuperMembers] is [:true:]. 1505 * [includeSuperMembers] is [:true:].
1506 *
1507 * When [includeInjectedMembers] is [:true:] the members declared in patch
1508 * classes are also included in the members for origin classes.
1429 */ 1509 */
1510 // TODO(johnniwinther): Normalize member reporting for origin/patch classes:
1511 // A call on a patch class such return the same as an origin class with
1512 // [includeInjectedMembers] set to [:true:].
1430 void forEachMember([void f(ClassElement enclosingClass, Element member), 1513 void forEachMember([void f(ClassElement enclosingClass, Element member),
1431 includeBackendMembers = false, 1514 includeBackendMembers = false,
1432 includeSuperMembers = false]) { 1515 includeSuperMembers = false,
1516 includeInjectedMembers = false]) {
1433 Set<ClassElement> seen = new Set<ClassElement>(); 1517 Set<ClassElement> seen = new Set<ClassElement>();
1434 ClassElement classElement = this; 1518 ClassElement classElement = this;
1435 do { 1519 do {
1436 if (seen.contains(classElement)) return; 1520 if (seen.contains(classElement)) return;
1437 seen.add(classElement); 1521 seen.add(classElement);
1438 1522
1439 // Iterate through the members in textual order, which requires 1523 // Iterate through the members in textual order, which requires
1440 // to reverse the data structure [localMembers] we created. 1524 // to reverse the data structure [localMembers] we created.
1441 // Textual order may be important for certain operations, for 1525 // Textual order may be important for certain operations, for
1442 // example when emitting the initializers of fields. 1526 // example when emitting the initializers of fields.
1443 for (Element element in classElement.localMembers.reverse()) { 1527 for (Element element in classElement.localMembers.reverse()) {
1444 f(classElement, element); 1528 f(classElement, element);
1445 } 1529 }
1446 if (includeBackendMembers) { 1530 if (includeBackendMembers) {
1447 for (Element element in classElement.backendMembers) { 1531 for (Element element in classElement.backendMembers) {
1448 f(classElement, element); 1532 f(classElement, element);
1449 } 1533 }
1450 } 1534 }
1535 if (includeInjectedMembers) {
1536 if (classElement.patch != null) {
1537 void filterPatchMembers(patchClass, patchMember) {
1538 if (!patchMember.isPatch) {
1539 f(classElement, patchMember);
1540 }
1541 }
1542 classElement.patch.forEachMember(
1543 includeBackendMembers: includeBackendMembers,
1544 includeSuperMembers: false,
1545 includeInjectedMembers: false,
1546 f: filterPatchMembers);
1547 }
1548 }
1451 classElement = includeSuperMembers ? classElement.superclass : null; 1549 classElement = includeSuperMembers ? classElement.superclass : null;
1452 } while(classElement !== null); 1550 } while(classElement !== null);
1453 } 1551 }
1454 1552
1455 /** 1553 /**
1456 * Runs through all instance-field members of this class. 1554 * Runs through all instance-field members of this class.
1457 * 1555 *
1458 * The enclosing class is passed to the callback. This is useful when 1556 * The enclosing class is passed to the callback. This is useful when
1459 * [includeSuperMembers] is [:true:]. 1557 * [includeSuperMembers] is [:true:].
1460 * 1558 *
1461 * When [includeBackendMembers] and [includeSuperMembers] are both [:true:] 1559 * When [includeBackendMembers] and [includeSuperMembers] are both [:true:]
1462 * then the fields are visited in the same order as they need to be given 1560 * then the fields are visited in the same order as they need to be given
1463 * to the JavaScript constructor. 1561 * to the JavaScript constructor.
1562 *
1563 * When [includeInjectedMembers] is [:true:] the fields declared in patch
1564 * classes are also included in the fields for origin classes.
1464 */ 1565 */
1465 void forEachInstanceField([void f(ClassElement enclosingClass, Element field), 1566 void forEachInstanceField([void f(ClassElement enclosingClass, Element field),
1466 includeBackendMembers = false, 1567 includeBackendMembers = false,
1467 includeSuperMembers = false]) { 1568 includeSuperMembers = false,
1569 includeInjectedMembers = false]) {
1468 // Filters so that [f] is only invoked with instance fields. 1570 // Filters so that [f] is only invoked with instance fields.
1469 void fieldFilter(ClassElement enclosingClass, Element member) { 1571 void fieldFilter(ClassElement enclosingClass, Element member) {
1470 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { 1572 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) {
1471 f(enclosingClass, member); 1573 f(enclosingClass, member);
1472 } 1574 }
1473 } 1575 }
1474 1576
1475 forEachMember(fieldFilter, includeBackendMembers, includeSuperMembers); 1577 forEachMember(fieldFilter, includeBackendMembers,
1578 includeSuperMembers, includeInjectedMembers);
1476 } 1579 }
1477 1580
1478 bool implementsInterface(ClassElement intrface) { 1581 bool implementsInterface(ClassElement intrface) {
1479 for (DartType implementedInterfaceType in allSupertypes) { 1582 for (DartType implementedInterfaceType in allSupertypes) {
1480 ClassElement implementedInterface = implementedInterfaceType.element; 1583 ClassElement implementedInterface = implementedInterfaceType.element;
1481 if (implementedInterface === intrface) { 1584 if (implementedInterface === intrface) {
1482 return true; 1585 return true;
1483 } 1586 }
1484 } 1587 }
1485 return false; 1588 return false;
(...skipping 10 matching lines...) Expand all
1496 for (ClassElement s = this; s != null; s = s.superclass) { 1599 for (ClassElement s = this; s != null; s = s.superclass) {
1497 if (s === cls) return true; 1600 if (s === cls) return true;
1498 } 1601 }
1499 return false; 1602 return false;
1500 } 1603 }
1501 1604
1502 bool isInterface() => false; 1605 bool isInterface() => false;
1503 bool isNative() => nativeName != null; 1606 bool isNative() => nativeName != null;
1504 int hashCode() => id; 1607 int hashCode() => id;
1505 1608
1506 Scope buildScope() => 1609 Scope buildScope([bool patchScope = false]) {
1507 new ClassScope(enclosingElement.buildScope(), this); 1610 if (origin !== null) {
1611 return new PatchClassScope(enclosingElement.buildScope(patchScope),
1612 origin, this);
1613 } else if (patchScope && patch !== null) {
1614 return new PatchClassScope(enclosingElement.buildScope(patchScope),
1615 this, patch);
1616 } else {
1617 return new ClassScope(enclosingElement.buildScope(patchScope), this);
1618 }
1619 }
1620
1621 Scope buildLocalScope() {
1622 if (origin !== null) {
1623 return new LocalPatchClassScope(origin, this);
1624 } else {
1625 return new LocalClassScope(this);
1626 }
1627 }
1508 1628
1509 ClassElement cloneTo(Element enclosing, DiagnosticListener listener) { 1629 ClassElement cloneTo(Element enclosing, DiagnosticListener listener) {
1510 listener.internalErrorOnElement(this, 'unsupported operation'); 1630 listener.internalErrorOnElement(this, 'unsupported operation');
1511 } 1631 }
1512 1632
1513 Link<DartType> get allSupertypesAndSelf { 1633 Link<DartType> get allSupertypesAndSelf {
1514 return allSupertypes.prepend(new InterfaceType(this)); 1634 return allSupertypes.prepend(new InterfaceType(this));
1515 } 1635 }
1636
1637 String toString() {
1638 if (origin !== null) {
1639 return 'patch ${super.toString()}';
1640 } else if (patch !== null) {
1641 return 'origin ${super.toString()}';
1642 } else {
1643 return super.toString();
1644 }
1645 }
1516 } 1646 }
1517 1647
1518 class Elements { 1648 class Elements {
1519 static bool isUnresolved(Element e) => e == null || e.isErroneous(); 1649 static bool isUnresolved(Element e) => e == null || e.isErroneous();
1520 static bool isErroneousElement(Element e) => e != null && e.isErroneous(); 1650 static bool isErroneousElement(Element e) => e != null && e.isErroneous();
1521 1651
1522 static bool isLocal(Element element) { 1652 static bool isLocal(Element element) {
1523 return !Elements.isUnresolved(element) 1653 return !Elements.isUnresolved(element)
1524 && !element.isInstanceMember() 1654 && !element.isInstanceMember()
1525 && !isStaticOrTopLevelField(element) 1655 && !isStaticOrTopLevelField(element)
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
1790 1920
1791 MetadataAnnotation ensureResolved(Compiler compiler) { 1921 MetadataAnnotation ensureResolved(Compiler compiler) {
1792 if (resolutionState == STATE_NOT_STARTED) { 1922 if (resolutionState == STATE_NOT_STARTED) {
1793 compiler.resolver.resolveMetadataAnnotation(this); 1923 compiler.resolver.resolveMetadataAnnotation(this);
1794 } 1924 }
1795 return this; 1925 return this;
1796 } 1926 }
1797 1927
1798 String toString() => 'MetadataAnnotation($value, $resolutionState)'; 1928 String toString() => 'MetadataAnnotation($value, $resolutionState)';
1799 } 1929 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698