| 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 #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 Loading... |
| 107 toString() => id; | 107 toString() => id; |
| 108 } | 108 } |
| 109 | 109 |
| 110 class Element implements Spannable { | 110 class Element implements 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 => Modifiers.EMPTY; | 120 Modifiers get modifiers => Modifiers.EMPTY; |
| 121 | 121 |
| 122 Node parseNode(DiagnosticListener listener) { | 122 Node parseNode(DiagnosticListener listener) { |
| 123 listener.cancel("Internal Error: $this.parseNode", token: position()); | 123 listener.internalErrorOnElement(this, 'not implemented'); |
| 124 } | 124 } |
| 125 | 125 |
| 126 DartType computeType(Compiler compiler) { | 126 DartType computeType(Compiler compiler) { |
| 127 compiler.internalError("$this.computeType.", token: position()); | 127 compiler.internalError("$this.computeType.", token: position()); |
| 128 } | 128 } |
| 129 | 129 |
| 130 void addMetadata(MetadataAnnotation annotation) { | 130 void addMetadata(MetadataAnnotation annotation) { |
| 131 assert(annotation.annotatedElement === null); | 131 assert(annotation.annotatedElement === null); |
| 132 annotation.annotatedElement = this; | 132 annotation.annotatedElement = this; |
| 133 metadata = metadata.prepend(annotation); | 133 metadata = metadata.prepend(annotation); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 | 182 |
| 183 /** | 183 /** |
| 184 * Is [:true:] if this element is a patch. | 184 * Is [:true:] if this element is a patch. |
| 185 * | 185 * |
| 186 * If [:true:] this element has a non-null [origin] field. | 186 * If [:true:] this element has a non-null [origin] field. |
| 187 * | 187 * |
| 188 * See [:patch_parser.dart:] for a description of the terminology. | 188 * See [:patch_parser.dart:] for a description of the terminology. |
| 189 */ | 189 */ |
| 190 bool get isPatch => false; | 190 bool get isPatch => false; |
| 191 | 191 |
| 192 | |
| 193 /** | 192 /** |
| 194 * Is [:true:] if this element defines the implementation for the entity of | 193 * Is [:true:] if this element defines the implementation for the entity of |
| 195 * this element. | 194 * this element. |
| 196 * | 195 * |
| 197 * See [:patch_parser.dart:] for a description of the terminology. | 196 * See [:patch_parser.dart:] for a description of the terminology. |
| 198 */ | 197 */ |
| 199 bool get isImplementation => implementation === this; | 198 bool get isImplementation => !isPatched; |
| 200 | 199 |
| 201 /** | 200 /** |
| 202 * Is [:true:] if this element introduces the entity of this element. | 201 * Is [:true:] if this element introduces the entity of this element. |
| 203 * | 202 * |
| 204 * See [:patch_parser.dart:] for a description of the terminology. | 203 * See [:patch_parser.dart:] for a description of the terminology. |
| 205 */ | 204 */ |
| 206 bool get isDeclaration => declaration === this; | 205 bool get isDeclaration => !isPatch; |
| 207 | 206 |
| 208 /** | 207 /** |
| 209 * Returns the element which defines the implementation for the entity of this | 208 * Returns the element which defines the implementation for the entity of this |
| 210 * element. | 209 * element. |
| 211 * | 210 * |
| 212 * See [:patch_parser.dart:] for a description of the terminology. | 211 * See [:patch_parser.dart:] for a description of the terminology. |
| 213 */ | 212 */ |
| 214 Element get implementation => this; | 213 Element get implementation => isPatched ? patch : this; |
| 215 | 214 |
| 216 /** | 215 /** |
| 217 * Returns the element which introduces the entity of this element. | 216 * Returns the element which introduces the entity of this element. |
| 218 * | 217 * |
| 219 * See [:patch_parser.dart:] for a description of the terminology. | 218 * See [:patch_parser.dart:] for a description of the terminology. |
| 220 */ | 219 */ |
| 221 Element get declaration => this; | 220 Element get declaration => isPatch ? origin : this; |
| 222 | 221 |
| 223 // TODO(johnniwinther): This breaks for libraries (for which enclosing | 222 // TODO(johnniwinther): This breaks for libraries (for which enclosing |
| 224 // elements are null) and is invalid for top level variable declarations for | 223 // elements are null) and is invalid for top level variable declarations for |
| 225 // which the enclosing element is a VariableDeclarations and not a compilation | 224 // which the enclosing element is a VariableDeclarations and not a compilation |
| 226 // unit. | 225 // unit. |
| 227 bool isTopLevel() { | 226 bool isTopLevel() { |
| 228 return enclosingElement !== null && enclosingElement.isCompilationUnit(); | 227 return enclosingElement !== null && enclosingElement.isCompilationUnit(); |
| 229 } | 228 } |
| 230 | 229 |
| 231 bool isAssignable() { | 230 bool isAssignable() { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 253 while (element !== null && !element.isCompilationUnit()) { | 252 while (element !== null && !element.isCompilationUnit()) { |
| 254 if (element is CompilationUnitOverrideElement) { | 253 if (element is CompilationUnitOverrideElement) { |
| 255 CompilationUnitOverrideElement override = element; | 254 CompilationUnitOverrideElement override = element; |
| 256 return override.compilationUnit; | 255 return override.compilationUnit; |
| 257 } | 256 } |
| 258 if (element.isLibrary()) { | 257 if (element.isLibrary()) { |
| 259 LibraryElement library = element; | 258 LibraryElement library = element; |
| 260 return library.entryCompilationUnit; | 259 return library.entryCompilationUnit; |
| 261 } | 260 } |
| 262 element = element.enclosingElement; | 261 element = element.enclosingElement; |
| 263 if (element is FunctionElement) { | |
| 264 FunctionElement function = element; | |
| 265 if (function.isPatched) { | |
| 266 element = function.patch; | |
| 267 } | |
| 268 } | |
| 269 } | 262 } |
| 270 return element; | 263 return element; |
| 271 } | 264 } |
| 272 | 265 |
| 273 LibraryElement getLibrary() { | 266 LibraryElement getLibrary() => enclosingElement.getLibrary(); |
| 267 |
| 268 LibraryElement getImplementationLibrary() { |
| 274 Element element = this; | 269 Element element = this; |
| 275 while (element.kind !== ElementKind.LIBRARY) { | 270 while (element.kind !== ElementKind.LIBRARY) { |
| 276 element = element.enclosingElement; | 271 element = element.enclosingElement; |
| 277 } | 272 } |
| 278 return element; | 273 return element; |
| 279 } | 274 } |
| 280 | 275 |
| 281 LibraryElement getImplementationLibrary() => getLibrary(); | |
| 282 | |
| 283 ClassElement getEnclosingClass() { | 276 ClassElement getEnclosingClass() { |
| 284 for (Element e = this; e !== null; e = e.enclosingElement) { | 277 for (Element e = this; e !== null; e = e.enclosingElement) { |
| 285 if (e.isClass()) return e; | 278 if (e.isClass()) return e; |
| 286 } | 279 } |
| 287 return null; | 280 return null; |
| 288 } | 281 } |
| 289 | 282 |
| 290 Element getEnclosingClassOrCompilationUnit() { | 283 Element getEnclosingClassOrCompilationUnit() { |
| 291 for (Element e = this; e !== null; e = e.enclosingElement) { | 284 for (Element e = this; e !== null; e = e.enclosingElement) { |
| 292 if (e.isClass() || e.isCompilationUnit()) return e; | 285 if (e.isClass() || e.isCompilationUnit()) return e; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 308 return e; | 301 return e; |
| 309 } | 302 } |
| 310 } | 303 } |
| 311 return null; | 304 return null; |
| 312 } | 305 } |
| 313 | 306 |
| 314 /** | 307 /** |
| 315 * Creates the scope for this element. The scope of the | 308 * Creates the scope for this element. The scope of the |
| 316 * enclosing element will be the parent scope. | 309 * enclosing element will be the parent scope. |
| 317 */ | 310 */ |
| 318 Scope buildScope() => buildEnclosingScope(); | 311 // TODO(johnniwinther): Clean up scope generation. Possibly generation scopes |
| 312 // externally. |
| 313 Scope buildScope({bool patchScope: false}) => |
| 314 buildEnclosingScope(patchScope: patchScope); |
| 319 | 315 |
| 320 /** | 316 /** |
| 321 * Creates the scope for the enclosing element. | 317 * Creates the scope for the enclosing element. |
| 322 */ | 318 */ |
| 323 Scope buildEnclosingScope() => enclosingElement.buildScope(); | 319 // TODO(johnniwinther): Remove buildEnclosingScope as part of scope clean-up. |
| 320 Scope buildEnclosingScope({bool patchScope: false}) => |
| 321 enclosingElement.buildScope(patchScope: patchScope); |
| 324 | 322 |
| 325 String toString() { | 323 String toString() { |
| 326 // TODO(johnniwinther): Test for nullness of name, or make non-nullness an | 324 // TODO(johnniwinther): Test for nullness of name, or make non-nullness an |
| 327 // invariant for all element types? | 325 // invariant for all element types? |
| 328 var nameText = name !== null ? name.slowToString() : '?'; | 326 var nameText = name !== null ? name.slowToString() : '?'; |
| 329 if (enclosingElement !== null && !isTopLevel()) { | 327 if (enclosingElement !== null && !isTopLevel()) { |
| 330 String holderName = enclosingElement.name !== null | 328 String holderName = enclosingElement.name !== null |
| 331 ? enclosingElement.name.slowToString() | 329 ? enclosingElement.name.slowToString() |
| 332 : '${enclosingElement.kind}?'; | 330 : '${enclosingElement.kind}?'; |
| 333 return '$kind($holderName#${nameText})'; | 331 return '$kind($holderName#${nameText})'; |
| 334 } else { | 332 } else { |
| 335 return '$kind(${nameText})'; | 333 return '$kind(${nameText})'; |
| 336 } | 334 } |
| 337 } | 335 } |
| 338 | 336 |
| 339 bool _isNative = false; | 337 bool _isNative = false; |
| 340 void setNative() { _isNative = true; } | 338 void setNative() { _isNative = true; } |
| 341 bool isNative() => _isNative; | 339 bool isNative() => _isNative; |
| 342 | 340 |
| 343 FunctionElement asFunctionElement() => null; | 341 FunctionElement asFunctionElement() => null; |
| 344 | 342 |
| 343 static bool isInvalid(Element e) => e == null || e.isErroneous(); |
| 345 Element cloneTo(Element enclosing, DiagnosticListener listener) { | 344 Element cloneTo(Element enclosing, DiagnosticListener listener) { |
| 346 listener.cancel("Unimplemented cloneTo", element: this); | 345 listener.cancel("Unimplemented cloneTo", element: this); |
| 347 } | 346 } |
| 348 } | 347 } |
| 349 | 348 |
| 350 /** | 349 /** |
| 351 * Represents an unresolvable or duplicated element. | 350 * Represents an unresolvable or duplicated element. |
| 352 * | 351 * |
| 353 * An [ErroneousElement] is used instead of [null] to provide additional | 352 * An [ErroneousElement] is used instead of [null] to provide additional |
| 354 * information about the error that caused the element to be unresolvable | 353 * information about the error that caused the element to be unresolvable |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 Element existing = localScope.putIfAbsent(element.name, () => element); | 436 Element existing = localScope.putIfAbsent(element.name, () => element); |
| 438 if (existing !== element) { | 437 if (existing !== element) { |
| 439 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. | 438 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. |
| 440 listener.cancel('duplicate definition', token: element.position()); | 439 listener.cancel('duplicate definition', token: element.position()); |
| 441 listener.cancel('existing definition', token: existing.position()); | 440 listener.cancel('existing definition', token: existing.position()); |
| 442 } | 441 } |
| 443 } | 442 } |
| 444 } | 443 } |
| 445 | 444 |
| 446 Element localLookup(SourceString elementName) { | 445 Element localLookup(SourceString elementName) { |
| 447 return localScope[elementName]; | 446 Element result = localScope[elementName]; |
| 447 if (result == null && isPatch) { |
| 448 result = origin.localScope[elementName]; |
| 449 } |
| 450 return result; |
| 448 } | 451 } |
| 449 | 452 |
| 450 /** | 453 /** |
| 451 * Adds a definition for an [accessor] (getter or setter) to a container. | 454 * 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 | 455 * The definition binds to an abstract field that can hold both a getter |
| 453 * and a setter. | 456 * and a setter. |
| 454 * | 457 * |
| 455 * The abstract field is added once, for the first getter or setter, and | 458 * The abstract field is added once, for the first getter or setter, and |
| 456 * reused if the other one is also added. | 459 * reused if the other one is also added. |
| 457 * The abstract field should not be treated as a proper member of the | 460 * The abstract field should not be treated as a proper member of the |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 super(new SourceString(script.name), | 513 super(new SourceString(script.name), |
| 511 ElementKind.COMPILATION_UNIT, | 514 ElementKind.COMPILATION_UNIT, |
| 512 library) { | 515 library) { |
| 513 library.addCompilationUnit(this); | 516 library.addCompilationUnit(this); |
| 514 } | 517 } |
| 515 | 518 |
| 516 void addMember(Element element, DiagnosticListener listener) { | 519 void addMember(Element element, DiagnosticListener listener) { |
| 517 // Keep a list of top level members. | 520 // Keep a list of top level members. |
| 518 super.addMember(element, listener); | 521 super.addMember(element, listener); |
| 519 // Provide the member to the library to build scope. | 522 // Provide the member to the library to build scope. |
| 520 getLibrary().addMember(element, listener); | 523 if (enclosingElement.isPatch) { |
| 524 getImplementationLibrary().addMember(element, listener); |
| 525 } else { |
| 526 getLibrary().addMember(element, listener); |
| 527 } |
| 521 } | 528 } |
| 522 } | 529 } |
| 523 | 530 |
| 524 class CompilationUnitOverrideElement extends Element { | 531 class CompilationUnitOverrideElement extends Element { |
| 525 final CompilationUnitElement compilationUnit; | 532 final CompilationUnitElement compilationUnit; |
| 526 | 533 |
| 527 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit, | 534 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit, |
| 528 Element enclosing) | 535 Element enclosing) |
| 529 : this.compilationUnit = compilationUnit, | 536 : this.compilationUnit = compilationUnit, |
| 530 super(compilationUnit.name, | 537 super(compilationUnit.name, |
| 531 ElementKind.COMPILATION_UNIT_OVERRIDE, | 538 ElementKind.COMPILATION_UNIT_OVERRIDE, |
| 532 enclosing); | 539 enclosing); |
| 533 } | 540 } |
| 534 | 541 |
| 535 class LibraryElement extends ScopeContainerElement { | 542 class LibraryElement extends ScopeContainerElement { |
| 536 final Uri uri; | 543 final Uri uri; |
| 537 CompilationUnitElement entryCompilationUnit; | 544 CompilationUnitElement entryCompilationUnit; |
| 538 Link<CompilationUnitElement> compilationUnits = | 545 Link<CompilationUnitElement> compilationUnits = |
| 539 const EmptyLink<CompilationUnitElement>(); | 546 const EmptyLink<CompilationUnitElement>(); |
| 540 Link<LibraryTag> tags = const EmptyLink<LibraryTag>(); | 547 Link<LibraryTag> tags = const EmptyLink<LibraryTag>(); |
| 541 LibraryTag libraryTag; | 548 LibraryTag libraryTag; |
| 542 bool canUseNative = false; | 549 bool canUseNative = false; |
| 550 |
| 551 /** |
| 552 * If this library is patched, [patch] points to the patch library. |
| 553 * |
| 554 * See [:patch_parser.dart:] for a description of the terminology. |
| 555 */ |
| 543 LibraryElement patch = null; | 556 LibraryElement patch = null; |
| 544 | 557 |
| 545 /** | 558 /** |
| 559 * If this is a patch library, [origin] points to the origin library. |
| 560 * |
| 561 * See [:patch_parser.dart:] for a description of the terminology. |
| 562 */ |
| 563 final LibraryElement origin; |
| 564 |
| 565 /** |
| 546 * Map for elements imported through import declarations. | 566 * Map for elements imported through import declarations. |
| 547 * | 567 * |
| 548 * Addition to the map is performed by [addImport]. Lookup is done trough | 568 * Addition to the map is performed by [addImport]. Lookup is done trough |
| 549 * [find]. | 569 * [find]. |
| 550 */ | 570 */ |
| 551 final Map<SourceString, Element> importScope; | 571 final Map<SourceString, Element> importScope; |
| 552 | 572 |
| 553 LibraryElement(Script script, [Uri uri]) | 573 LibraryElement(Script script, [Uri uri, LibraryElement this.origin]) |
| 554 : this.uri = ((uri === null) ? script.uri : uri), | 574 : this.uri = ((uri === null) ? script.uri : uri), |
| 555 importScope = new Map<SourceString, Element>(), | 575 importScope = new Map<SourceString, Element>(), |
| 556 super(new SourceString(script.name), ElementKind.LIBRARY, null) { | 576 super(new SourceString(script.name), ElementKind.LIBRARY, null) { |
| 557 entryCompilationUnit = new CompilationUnitElement(script, this); | 577 entryCompilationUnit = new CompilationUnitElement(script, this); |
| 578 if (isPatch) { |
| 579 origin.patch = this; |
| 580 } |
| 558 } | 581 } |
| 559 | 582 |
| 583 bool get isPatched => patch !== null; |
| 584 bool get isPatch => origin !== null; |
| 560 | 585 |
| 561 bool get isPatched => patch !== null; | 586 LibraryElement get declaration => super.declaration; |
| 587 LibraryElement get implementation => super.implementation; |
| 562 | 588 |
| 563 void addCompilationUnit(CompilationUnitElement element) { | 589 void addCompilationUnit(CompilationUnitElement element) { |
| 564 compilationUnits = compilationUnits.prepend(element); | 590 compilationUnits = compilationUnits.prepend(element); |
| 565 } | 591 } |
| 566 | 592 |
| 567 void addTag(LibraryTag tag, DiagnosticListener listener) { | 593 void addTag(LibraryTag tag, DiagnosticListener listener) { |
| 568 tags = tags.prepend(tag); | 594 tags = tags.prepend(tag); |
| 569 } | 595 } |
| 570 | 596 |
| 571 /** | 597 /** |
| 572 * Adds [element] to the import scope of this library. | 598 * Adds [element] to the import scope of this library. |
| 573 * | 599 * |
| 574 * If an element by the same name is already in the imported scope, an | 600 * If an element by the same name is already in the imported scope, an |
| 575 * [ErroneousElement] will be put in the imported scope, allowing for the | 601 * [ErroneousElement] will be put in the imported scope, allowing for the |
| 576 * detection of ambiguous uses of imported names. | 602 * detection of ambiguous uses of imported names. |
| 577 */ | 603 */ |
| 578 void addImport(Element element, DiagnosticListener listener) { | 604 void addImport(Element element, DiagnosticListener listener) { |
| 579 Element existing = importScope.putIfAbsent(element.name, () => element); | 605 Element existing = importScope.putIfAbsent(element.name, () => element); |
| 580 if (existing !== element && existing !== null) { | 606 if (existing !== element && existing !== null) { |
| 581 if (!existing.isErroneous()) { | 607 if (!existing.isErroneous()) { |
| 582 // TODO(johnniwinther): Provide access to both the new and existing | 608 // TODO(johnniwinther): Provide access to both the new and existing |
| 583 // elements. | 609 // elements. |
| 584 importScope[element.name] = new ErroneousElement( | 610 importScope[element.name] = new ErroneousElement( |
| 585 MessageKind.DUPLICATE_IMPORT, | 611 MessageKind.DUPLICATE_IMPORT, |
| 586 [element.name], element.name, this); | 612 [element.name], element.name, this); |
| 587 } | 613 } |
| 588 } | 614 } |
| 589 } | 615 } |
| 590 | 616 |
| 617 LibraryElement getLibrary() => isPatch ? origin : this; |
| 591 | 618 |
| 592 /** | 619 /** |
| 593 * Look up a top-level element in this library. The element could | 620 * Look up a top-level element in this library. The element could |
| 594 * potentially have been imported from another library. Returns | 621 * potentially have been imported from another library. Returns |
| 595 * null if no such element exist and an [ErroneousElement] if multiple | 622 * null if no such element exist and an [ErroneousElement] if multiple |
| 596 * elements have been imported. | 623 * elements have been imported. |
| 597 */ | 624 */ |
| 598 Element find(SourceString elementName) { | 625 Element find(SourceString elementName) { |
| 599 Element result = localScope[elementName]; | 626 Element result = localScope[elementName]; |
| 600 if (result === null) { | 627 if (result === null) { |
| 601 result = importScope[elementName]; | 628 result = importScope[elementName]; |
| 602 } | 629 } |
| 603 return result; | 630 return result; |
| 604 } | 631 } |
| 605 | 632 |
| 606 /** Look up a top-level element in this library, but only look for | 633 /** Look up a top-level element in this library, but only look for |
| 607 * non-imported elements. Returns null if no such element exist. */ | 634 * non-imported elements. Returns null if no such element exist. */ |
| 608 Element findLocal(SourceString elementName) { | 635 Element findLocal(SourceString elementName) { |
| 636 // TODO(johnniwinther): How to handle injected elements in the patch |
| 637 // library? |
| 609 Element result = localScope[elementName]; | 638 Element result = localScope[elementName]; |
| 610 if (result === null || result.getLibrary() != this) return null; | 639 if (result === null || result.getLibrary() != this) return null; |
| 611 return result; | 640 return result; |
| 612 } | 641 } |
| 613 | 642 |
| 614 void forEachExport(f(Element element)) { | 643 void forEachExport(f(Element element)) { |
| 615 localScope.forEach((_, Element e) { | 644 localScope.forEach((_, Element e) { |
| 616 if (this === e.getLibrary() | 645 if (this === e.getLibrary() |
| 617 && e.kind !== ElementKind.PREFIX | 646 && e.kind !== ElementKind.PREFIX |
| 618 && e.kind !== ElementKind.FOREIGN | 647 && e.kind !== ElementKind.FOREIGN |
| 619 && !e.name.isPrivate()) { | 648 && !e.name.isPrivate()) { |
| 620 f(e); | 649 f(e); |
| 621 } | 650 } |
| 622 }); | 651 }); |
| 623 } | 652 } |
| 624 | 653 |
| 654 void forEachLocalMember(f(Element element)) { |
| 655 if (isPatch) { |
| 656 // Patch libraries traverse both origin and injected members. |
| 657 origin.localMembers.forEach(f); |
| 658 |
| 659 void filterPatch(Element element) { |
| 660 if (!element.isPatch) { |
| 661 // Do not traverse the patch members. |
| 662 f(element); |
| 663 } |
| 664 } |
| 665 localMembers.forEach(filterPatch); |
| 666 } else { |
| 667 localMembers.forEach(f); |
| 668 } |
| 669 } |
| 670 |
| 625 bool hasLibraryName() => libraryTag !== null; | 671 bool hasLibraryName() => libraryTag !== null; |
| 626 | 672 |
| 627 /** | 673 /** |
| 628 * Returns the library name (as defined by the #library tag) or for script | 674 * Returns the library name (as defined by the #library tag) or for script |
| 629 * (which have no #library tag) the script file name. The latter case is used | 675 * (which have no #library tag) the script file name. The latter case is used |
| 630 * to private 'library name' for scripts to use for instance in dartdoc. | 676 * to private 'library name' for scripts to use for instance in dartdoc. |
| 631 */ | 677 */ |
| 632 String getLibraryOrScriptName() { | 678 String getLibraryOrScriptName() { |
| 633 if (libraryTag !== null) { | 679 if (libraryTag !== null) { |
| 634 return libraryTag.argument.dartString.slowToString(); | 680 return libraryTag.argument.dartString.slowToString(); |
| 635 } else { | 681 } else { |
| 636 // Use the file name as script name. | 682 // Use the file name as script name. |
| 637 String path = uri.path; | 683 String path = uri.path; |
| 638 return path.substring(path.lastIndexOf('/') + 1); | 684 return path.substring(path.lastIndexOf('/') + 1); |
| 639 } | 685 } |
| 640 } | 686 } |
| 641 | 687 |
| 642 Scope buildEnclosingScope() => new TopScope(this); | 688 // TODO(johnniwinther): Rewrite to avoid the optional argument. |
| 689 Scope buildEnclosingScope({bool patchScope: false}) { |
| 690 if (origin !== null) { |
| 691 return new PatchLibraryScope(origin, this); |
| 692 } if (patchScope && patch !== null) { |
| 693 return new PatchLibraryScope(this, patch); |
| 694 } else { |
| 695 return new TopScope(this); |
| 696 } |
| 697 } |
| 643 | 698 |
| 644 bool get isPlatformLibrary => uri.scheme == "dart"; | 699 bool get isPlatformLibrary => uri.scheme == "dart"; |
| 700 |
| 701 String toString() { |
| 702 if (origin !== null) { |
| 703 return 'patch library(${getLibraryOrScriptName()})'; |
| 704 } else if (patch !== null) { |
| 705 return 'origin library(${getLibraryOrScriptName()})'; |
| 706 } else { |
| 707 return 'library(${getLibraryOrScriptName()})'; |
| 708 } |
| 709 } |
| 645 } | 710 } |
| 646 | 711 |
| 647 class PrefixElement extends Element { | 712 class PrefixElement extends Element { |
| 648 Map<SourceString, Element> imported; | 713 Map<SourceString, Element> imported; |
| 649 Token firstPosition; | 714 Token firstPosition; |
| 650 | 715 |
| 651 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) | 716 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) |
| 652 : imported = new Map<SourceString, Element>(), | 717 : imported = new Map<SourceString, Element>(), |
| 653 super(prefix, ElementKind.PREFIX, enclosing); | 718 super(prefix, ElementKind.PREFIX, enclosing); |
| 654 | 719 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 Typedef node = parseNode(compiler); | 754 Typedef node = parseNode(compiler); |
| 690 Link<DartType> parameters = | 755 Link<DartType> parameters = |
| 691 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); | 756 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); |
| 692 cachedType = new TypedefType(this, parameters); | 757 cachedType = new TypedefType(this, parameters); |
| 693 compiler.resolveTypedef(this); | 758 compiler.resolveTypedef(this); |
| 694 return cachedType; | 759 return cachedType; |
| 695 } | 760 } |
| 696 | 761 |
| 697 Link<DartType> get typeVariables => cachedType.typeArguments; | 762 Link<DartType> get typeVariables => cachedType.typeArguments; |
| 698 | 763 |
| 699 Scope buildScope() => | 764 // TODO(johnniwinther): Rewrite to avoid the optional argument. |
| 700 new TypeDeclarationScope(enclosingElement.buildScope(), this); | 765 Scope buildScope({bool patchScope: false}) { |
| 766 return new TypeDeclarationScope( |
| 767 enclosingElement.buildScope(patchScope: patchScope), this); |
| 768 } |
| 701 | 769 |
| 702 TypedefElement cloneTo(Element enclosing, DiagnosticListener listener) { | 770 TypedefElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 703 TypedefElement result = new TypedefElement(name, enclosing); | 771 TypedefElement result = new TypedefElement(name, enclosing); |
| 704 return result; | 772 return result; |
| 705 } | 773 } |
| 706 } | 774 } |
| 707 | 775 |
| 708 class VariableElement extends Element { | 776 class VariableElement extends Element { |
| 709 final VariableListElement variables; | 777 final VariableListElement variables; |
| 710 Expression cachedNode; // The send or the identifier in the variables list. | 778 Expression cachedNode; // The send or the identifier in the variables list. |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 } else { | 919 } else { |
| 852 result = new VariableListElement(kind, modifiers, enclosing); | 920 result = new VariableListElement(kind, modifiers, enclosing); |
| 853 } | 921 } |
| 854 return result; | 922 return result; |
| 855 } | 923 } |
| 856 | 924 |
| 857 bool isInstanceMember() { | 925 bool isInstanceMember() { |
| 858 return isMember() && !modifiers.isStatic(); | 926 return isMember() && !modifiers.isStatic(); |
| 859 } | 927 } |
| 860 | 928 |
| 861 Scope buildScope() { | 929 // TODO(johnniwinther): Rewrite to avoid the optional argument. |
| 862 Scope result = new VariableScope(enclosingElement.buildScope(), this); | 930 Scope buildScope({bool patchScope: false}) { |
| 931 Scope result = new VariableScope( |
| 932 enclosingElement.buildScope(patchScope: patchScope), this); |
| 863 if (enclosingElement.isClass()) { | 933 if (enclosingElement.isClass()) { |
| 864 ClassScope clsScope = result.parent; | 934 Scope clsScope = result.parent; |
| 865 clsScope.inStaticContext = !isInstanceMember(); | 935 clsScope.inStaticContext = !isInstanceMember(); |
| 866 } | 936 } |
| 867 return result; | 937 return result; |
| 868 } | 938 } |
| 869 } | 939 } |
| 870 | 940 |
| 871 class ForeignElement extends Element { | 941 class ForeignElement extends Element { |
| 872 ForeignElement(SourceString name, ContainerElement enclosingElement) | 942 ForeignElement(SourceString name, ContainerElement enclosingElement) |
| 873 : super(name, ElementKind.FOREIGN, enclosingElement); | 943 : super(name, ElementKind.FOREIGN, enclosingElement); |
| 874 | 944 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 | 1075 |
| 1006 FunctionSignature functionSignature; | 1076 FunctionSignature functionSignature; |
| 1007 | 1077 |
| 1008 /** | 1078 /** |
| 1009 * A function declaration that should be parsed instead of the current one. | 1079 * A function declaration that should be parsed instead of the current one. |
| 1010 * The patch should be parsed as if it was in the current scope. Its | 1080 * The patch should be parsed as if it was in the current scope. Its |
| 1011 * signature must match this function's signature. | 1081 * signature must match this function's signature. |
| 1012 */ | 1082 */ |
| 1013 // TODO(lrn): Consider using [defaultImplementation] to store the patch. | 1083 // TODO(lrn): Consider using [defaultImplementation] to store the patch. |
| 1014 FunctionElement patch = null; | 1084 FunctionElement patch = null; |
| 1085 FunctionElement origin = null; |
| 1015 | 1086 |
| 1016 /** | 1087 /** |
| 1017 * If this is an interface constructor, [defaultImplementation] will | 1088 * If this is an interface constructor, [defaultImplementation] will |
| 1018 * changed by the resolver to point to the default | 1089 * changed by the resolver to point to the default |
| 1019 * implementation. Otherwise, [:defaultImplementation === this:]. | 1090 * implementation. Otherwise, [:defaultImplementation === this:]. |
| 1020 */ | 1091 */ |
| 1021 FunctionElement defaultImplementation; | 1092 FunctionElement defaultImplementation; |
| 1022 | 1093 |
| 1023 FunctionElement(SourceString name, | 1094 FunctionElement(SourceString name, |
| 1024 ElementKind kind, | 1095 ElementKind kind, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1045 ElementKind kind, | 1116 ElementKind kind, |
| 1046 Modifiers this.modifiers, | 1117 Modifiers this.modifiers, |
| 1047 Element enclosing, | 1118 Element enclosing, |
| 1048 FunctionSignature this.functionSignature) | 1119 FunctionSignature this.functionSignature) |
| 1049 : super(name, kind, enclosing) { | 1120 : super(name, kind, enclosing) { |
| 1050 assert(modifiers !== null); | 1121 assert(modifiers !== null); |
| 1051 defaultImplementation = this; | 1122 defaultImplementation = this; |
| 1052 } | 1123 } |
| 1053 | 1124 |
| 1054 bool get isPatched => patch !== null; | 1125 bool get isPatched => patch !== null; |
| 1126 bool get isPatch => origin !== null; |
| 1055 | 1127 |
| 1056 /** | 1128 /** |
| 1057 * Applies a patch function to this function. The patch function's body | 1129 * Applies a patch function to this function. The patch function's body |
| 1058 * is used as replacement when parsing this function's body. | 1130 * is used as replacement when parsing this function's body. |
| 1059 * This method must not be called after the function has been parsed, | 1131 * This method must not be called after the function has been parsed, |
| 1060 * and it must be called at most once. | 1132 * and it must be called at most once. |
| 1061 */ | 1133 */ |
| 1062 void setPatch(FunctionElement patchElement) { | 1134 void setPatch(FunctionElement patchElement) { |
| 1063 // Sanity checks. The caller must check these things before calling. | 1135 // Sanity checks. The caller must check these things before calling. |
| 1064 assert(patch === null); | 1136 assert(patch === null); |
| 1065 assert(cachedNode === null); | |
| 1066 this.patch = patchElement; | 1137 this.patch = patchElement; |
| 1067 cachedNode = patchElement.cachedNode; | |
| 1068 } | 1138 } |
| 1069 | 1139 |
| 1070 bool isInstanceMember() { | 1140 bool isInstanceMember() { |
| 1071 return isMember() | 1141 return isMember() |
| 1072 && !isConstructor() | 1142 && !isConstructor() |
| 1073 && !modifiers.isStatic(); | 1143 && !modifiers.isStatic(); |
| 1074 } | 1144 } |
| 1075 | 1145 |
| 1076 FunctionSignature computeSignature(Compiler compiler) { | 1146 FunctionSignature computeSignature(Compiler compiler) { |
| 1077 if (functionSignature !== null) return functionSignature; | 1147 if (functionSignature !== null) return functionSignature; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1094 } | 1164 } |
| 1095 | 1165 |
| 1096 FunctionType computeType(Compiler compiler) { | 1166 FunctionType computeType(Compiler compiler) { |
| 1097 if (type != null) return type; | 1167 if (type != null) return type; |
| 1098 type = compiler.computeFunctionType(declaration, | 1168 type = compiler.computeFunctionType(declaration, |
| 1099 computeSignature(compiler)); | 1169 computeSignature(compiler)); |
| 1100 return type; | 1170 return type; |
| 1101 } | 1171 } |
| 1102 | 1172 |
| 1103 Node parseNode(DiagnosticListener listener) { | 1173 Node parseNode(DiagnosticListener listener) { |
| 1104 if (cachedNode !== null) return cachedNode; | |
| 1105 if (patch === null) { | 1174 if (patch === null) { |
| 1106 if (modifiers.isExternal()) { | 1175 if (modifiers.isExternal()) { |
| 1107 listener.cancel("Compiling external function with no implementation.", | 1176 listener.cancel("Compiling external function with no implementation.", |
| 1108 element: this); | 1177 element: this); |
| 1109 } | 1178 } |
| 1110 return null; | |
| 1111 } | 1179 } |
| 1112 cachedNode = patch.parseNode(listener); | |
| 1113 return cachedNode; | 1180 return cachedNode; |
| 1114 } | 1181 } |
| 1115 | 1182 |
| 1116 Token position() => cachedNode.getBeginToken(); | 1183 Token position() => cachedNode.getBeginToken(); |
| 1117 | 1184 |
| 1118 FunctionElement asFunctionElement() => this; | 1185 FunctionElement asFunctionElement() => this; |
| 1119 | 1186 |
| 1120 String toString() { | 1187 String toString() { |
| 1121 if (isPatch) { | 1188 if (isPatch) { |
| 1122 return 'patch ${super.toString()}'; | 1189 return 'patch ${super.toString()}'; |
| 1123 } else if (isPatched) { | 1190 } else if (isPatched) { |
| 1124 return 'origin ${super.toString()}'; | 1191 return 'origin ${super.toString()}'; |
| 1125 } else { | 1192 } else { |
| 1126 return super.toString(); | 1193 return super.toString(); |
| 1127 } | 1194 } |
| 1128 } | 1195 } |
| 1129 | 1196 |
| 1130 Scope buildScope() { | 1197 // TODO(johnniwinther): Rewrite to avoid the optional argument. |
| 1131 Scope result = | 1198 Scope buildScope({bool patchScope: false}) { |
| 1132 new MethodScope(enclosingElement.buildScope(), this); | 1199 Scope result = new MethodScope( |
| 1200 enclosingElement.buildScope(patchScope: patchScope), this); |
| 1133 if (enclosingElement.isClass()) { | 1201 if (enclosingElement.isClass()) { |
| 1134 ClassScope clsScope = result.parent; | 1202 Scope clsScope = result.parent; |
| 1135 clsScope.inStaticContext = !isInstanceMember() && !isConstructor(); | 1203 clsScope.inStaticContext = !isInstanceMember() && !isConstructor(); |
| 1136 } | 1204 } |
| 1137 return result; | 1205 return result; |
| 1138 } | 1206 } |
| 1139 } | 1207 } |
| 1140 | 1208 |
| 1141 class ConstructorBodyElement extends FunctionElement { | 1209 class ConstructorBodyElement extends FunctionElement { |
| 1142 FunctionElement constructor; | 1210 FunctionElement constructor; |
| 1143 | 1211 |
| 1144 ConstructorBodyElement(FunctionElement constructor) | 1212 ConstructorBodyElement(FunctionElement constructor) |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1248 int resolutionState; | 1316 int resolutionState; |
| 1249 | 1317 |
| 1250 // backendMembers are members that have been added by the backend to simplify | 1318 // backendMembers are members that have been added by the backend to simplify |
| 1251 // compilation. They don't have any user-side counter-part. | 1319 // compilation. They don't have any user-side counter-part. |
| 1252 Link<Element> backendMembers = const EmptyLink<Element>(); | 1320 Link<Element> backendMembers = const EmptyLink<Element>(); |
| 1253 | 1321 |
| 1254 Link<DartType> allSupertypes; | 1322 Link<DartType> allSupertypes; |
| 1255 | 1323 |
| 1256 // Lazily applied patch of class members. | 1324 // Lazily applied patch of class members. |
| 1257 ClassElement patch = null; | 1325 ClassElement patch = null; |
| 1326 ClassElement origin = null; |
| 1258 | 1327 |
| 1259 ClassElement(SourceString name, Element enclosing, this.id, int initialState) | 1328 ClassElement(SourceString name, Element enclosing, this.id, int initialState) |
| 1260 : supertypeLoadState = initialState, | 1329 : supertypeLoadState = initialState, |
| 1261 resolutionState = initialState, | 1330 resolutionState = initialState, |
| 1262 super(name, ElementKind.CLASS, enclosing); | 1331 super(name, ElementKind.CLASS, enclosing); |
| 1263 | 1332 |
| 1264 InterfaceType computeType(compiler) { | 1333 InterfaceType computeType(compiler) { |
| 1265 if (type == null) { | 1334 if (type == null) { |
| 1266 ClassNode node = parseNode(compiler); | 1335 if (origin === null) { |
| 1267 Link<DartType> parameters = | 1336 ClassNode node = parseNode(compiler); |
| 1268 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); | 1337 Link<DartType> parameters = |
| 1269 type = new InterfaceType(this, parameters); | 1338 TypeDeclarationElement.createTypeVariables(this, |
| 1339 node.typeParameters); |
| 1340 type = new InterfaceType(this, parameters); |
| 1341 } else { |
| 1342 type = origin.computeType(compiler); |
| 1343 } |
| 1270 } | 1344 } |
| 1271 return type; | 1345 return type; |
| 1272 } | 1346 } |
| 1273 | 1347 |
| 1274 bool get isPatched => patch != null; | 1348 bool get isPatched => patch != null; |
| 1349 bool get isPatch => origin != null; |
| 1350 |
| 1351 ClassElement get declaration => super.declaration; |
| 1352 ClassElement get implementation => super.implementation; |
| 1275 | 1353 |
| 1276 /** | 1354 /** |
| 1277 * Return [:true:] if this element is the [:Object:] class for the [compiler]. | 1355 * Return [:true:] if this element is the [:Object:] class for the [compiler]. |
| 1278 */ | 1356 */ |
| 1279 bool isObject(Compiler compiler) => | 1357 bool isObject(Compiler compiler) => |
| 1280 declaration === compiler.objectClass; | 1358 declaration === compiler.objectClass; |
| 1281 | 1359 |
| 1282 Link<DartType> get typeVariables => type.arguments; | 1360 Link<DartType> get typeVariables => type.arguments; |
| 1283 | 1361 |
| 1284 ClassElement ensureResolved(Compiler compiler) { | 1362 ClassElement ensureResolved(Compiler compiler) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1303 Element lookupSuperMember(SourceString memberName) { | 1381 Element lookupSuperMember(SourceString memberName) { |
| 1304 return lookupSuperMemberInLibrary(memberName, getLibrary()); | 1382 return lookupSuperMemberInLibrary(memberName, getLibrary()); |
| 1305 } | 1383 } |
| 1306 | 1384 |
| 1307 /** | 1385 /** |
| 1308 * Lookup super members for the class that is accessible in [library]. | 1386 * Lookup super members for the class that is accessible in [library]. |
| 1309 * This will ignore constructors. | 1387 * This will ignore constructors. |
| 1310 */ | 1388 */ |
| 1311 Element lookupSuperMemberInLibrary(SourceString memberName, | 1389 Element lookupSuperMemberInLibrary(SourceString memberName, |
| 1312 LibraryElement library) { | 1390 LibraryElement library) { |
| 1391 bool includeInjectedMembers = isPatch; |
| 1313 bool isPrivate = memberName.isPrivate(); | 1392 bool isPrivate = memberName.isPrivate(); |
| 1314 for (ClassElement s = superclass; s != null; s = s.superclass) { | 1393 for (ClassElement s = superclass; s != null; s = s.superclass) { |
| 1315 // Private members from a different library are not visible. | 1394 // Private members from a different library are not visible. |
| 1316 if (isPrivate && library !== s.getLibrary()) continue; | 1395 if (isPrivate && library !== s.getLibrary()) continue; |
| 1396 s = includeInjectedMembers ? s.implementation : s; |
| 1317 Element e = s.lookupLocalMember(memberName); | 1397 Element e = s.lookupLocalMember(memberName); |
| 1318 if (e === null) continue; | 1398 if (e === null) continue; |
| 1319 // Static members are not inherited. | 1399 // Static members are not inherited. |
| 1320 if (e.modifiers.isStatic()) continue; | 1400 if (e.modifiers.isStatic()) continue; |
| 1321 return e; | 1401 return e; |
| 1322 } | 1402 } |
| 1323 if (isInterface()) { | 1403 if (isInterface()) { |
| 1324 return lookupSuperInterfaceMember(memberName, getLibrary()); | 1404 return lookupSuperInterfaceMember(memberName, getLibrary()); |
| 1325 } | 1405 } |
| 1326 return null; | 1406 return null; |
| 1327 } | 1407 } |
| 1328 | 1408 |
| 1329 Element lookupSuperInterfaceMember(SourceString memberName, | 1409 Element lookupSuperInterfaceMember(SourceString memberName, |
| 1330 LibraryElement fromLibrary) { | 1410 LibraryElement fromLibrary) { |
| 1411 bool includeInjectedMembers = isPatch; |
| 1331 bool isPrivate = memberName.isPrivate(); | 1412 bool isPrivate = memberName.isPrivate(); |
| 1332 for (InterfaceType t in interfaces) { | 1413 for (InterfaceType t in interfaces) { |
| 1333 ClassElement cls = t.element; | 1414 ClassElement cls = t.element; |
| 1415 cls = includeInjectedMembers ? cls.implementation : cls; |
| 1334 Element e = cls.lookupLocalMember(memberName); | 1416 Element e = cls.lookupLocalMember(memberName); |
| 1335 if (e === null) continue; | 1417 if (e === null) continue; |
| 1336 // Private members from a different library are not visible. | 1418 // Private members from a different library are not visible. |
| 1337 if (isPrivate && fromLibrary !== e.getLibrary()) continue; | 1419 if (isPrivate && fromLibrary !== e.getLibrary()) continue; |
| 1338 // Static members are not inherited. | 1420 // Static members are not inherited. |
| 1339 if (e.modifiers.isStatic()) continue; | 1421 if (e.modifiers.isStatic()) continue; |
| 1340 return e; | 1422 return e; |
| 1341 } | 1423 } |
| 1342 return null; | 1424 return null; |
| 1343 } | 1425 } |
| 1344 | 1426 |
| 1345 /** | 1427 /** |
| 1346 * Find the first member in the class chain with the given [selector]. | 1428 * Find the first member in the class chain with the given [selector]. |
| 1347 * | 1429 * |
| 1348 * This method is NOT to be used for resolving | 1430 * This method is NOT to be used for resolving |
| 1349 * unqualified sends because it does not implement the scoping | 1431 * unqualified sends because it does not implement the scoping |
| 1350 * rules, where library scope comes before superclass scope. | 1432 * rules, where library scope comes before superclass scope. |
| 1433 * |
| 1434 * When called on the implementation element both members declared in the |
| 1435 * origin and the patch class are returned. |
| 1351 */ | 1436 */ |
| 1352 Element lookupSelector(Selector selector) { | 1437 Element lookupSelector(Selector selector) { |
| 1353 SourceString memberName = selector.name; | 1438 SourceString memberName = selector.name; |
| 1354 LibraryElement library = selector.library; | 1439 LibraryElement library = selector.library; |
| 1355 Element localMember = lookupLocalMember(memberName); | 1440 Element localMember = lookupLocalMember(memberName); |
| 1356 if (localMember != null && | 1441 if (localMember != null && |
| 1357 (!memberName.isPrivate() || getLibrary() == library)) { | 1442 (!memberName.isPrivate() || getLibrary() == library)) { |
| 1358 return localMember; | 1443 return localMember; |
| 1359 } | 1444 } |
| 1360 return lookupSuperMemberInLibrary(memberName, library); | 1445 return lookupSuperMemberInLibrary(memberName, library); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1423 // Search in scope to be sure we search patched constructors. | 1508 // Search in scope to be sure we search patched constructors. |
| 1424 for (var element in localScope.getValues()) { | 1509 for (var element in localScope.getValues()) { |
| 1425 if (element.isConstructor()) return true; | 1510 if (element.isConstructor()) return true; |
| 1426 } | 1511 } |
| 1427 return false; | 1512 return false; |
| 1428 } | 1513 } |
| 1429 | 1514 |
| 1430 Link<Element> get constructors { | 1515 Link<Element> get constructors { |
| 1431 // TODO(ajohnsen): See if we can avoid this method at some point. | 1516 // TODO(ajohnsen): See if we can avoid this method at some point. |
| 1432 Link<Element> result = const EmptyLink<Element>(); | 1517 Link<Element> result = const EmptyLink<Element>(); |
| 1433 for (Element member in localMembers) { | 1518 // TODO(johnniwinther): Should we include injected constructors? |
| 1519 forEachMember((_, Element member) { |
| 1434 if (member.isConstructor()) result = result.prepend(member); | 1520 if (member.isConstructor()) result = result.prepend(member); |
| 1435 } | 1521 }); |
| 1436 return result; | 1522 return result; |
| 1437 } | 1523 } |
| 1438 | 1524 |
| 1439 /** | 1525 /** |
| 1440 * Returns the super class, if any. | 1526 * Returns the super class, if any. |
| 1441 * | 1527 * |
| 1442 * The returned element may not be resolved yet. | 1528 * The returned element may not be resolved yet. |
| 1443 */ | 1529 */ |
| 1444 ClassElement get superclass { | 1530 ClassElement get superclass { |
| 1445 assert(supertypeLoadState == STATE_DONE); | 1531 assert(supertypeLoadState == STATE_DONE); |
| 1446 return supertype === null ? null : supertype.element; | 1532 return supertype === null ? null : supertype.element; |
| 1447 } | 1533 } |
| 1448 | 1534 |
| 1449 /** | 1535 /** |
| 1450 * Runs through all members of this class. | 1536 * Runs through all members of this class. |
| 1451 * | 1537 * |
| 1452 * The enclosing class is passed to the callback. This is useful when | 1538 * The enclosing class is passed to the callback. This is useful when |
| 1453 * [includeSuperMembers] is [:true:]. | 1539 * [includeSuperMembers] is [:true:]. |
| 1540 * |
| 1541 * When called on an implementation element both the members in the origin |
| 1542 * and patch class are included. |
| 1454 */ | 1543 */ |
| 1544 // TODO(johnniwinther): Clean up lookup to get rid of the include predicates. |
| 1455 void forEachMember([void f(ClassElement enclosingClass, Element member), | 1545 void forEachMember([void f(ClassElement enclosingClass, Element member), |
| 1456 includeBackendMembers = false, | 1546 includeBackendMembers = false, |
| 1457 includeSuperMembers = false]) { | 1547 includeSuperMembers = false]) { |
| 1548 bool includeInjectedMembers = isPatch; |
| 1458 Set<ClassElement> seen = new Set<ClassElement>(); | 1549 Set<ClassElement> seen = new Set<ClassElement>(); |
| 1459 ClassElement classElement = this; | 1550 ClassElement classElement = declaration; |
| 1460 do { | 1551 do { |
| 1461 if (seen.contains(classElement)) return; | 1552 if (seen.contains(classElement)) return; |
| 1462 seen.add(classElement); | 1553 seen.add(classElement); |
| 1463 | 1554 |
| 1464 // Iterate through the members in textual order, which requires | 1555 // Iterate through the members in textual order, which requires |
| 1465 // to reverse the data structure [localMembers] we created. | 1556 // to reverse the data structure [localMembers] we created. |
| 1466 // Textual order may be important for certain operations, for | 1557 // Textual order may be important for certain operations, for |
| 1467 // example when emitting the initializers of fields. | 1558 // example when emitting the initializers of fields. |
| 1468 for (Element element in classElement.localMembers.reverse()) { | 1559 for (Element element in classElement.localMembers.reverse()) { |
| 1469 f(classElement, element); | 1560 f(classElement, element); |
| 1470 } | 1561 } |
| 1471 if (includeBackendMembers) { | 1562 if (includeBackendMembers) { |
| 1472 for (Element element in classElement.backendMembers) { | 1563 for (Element element in classElement.backendMembers) { |
| 1473 f(classElement, element); | 1564 f(classElement, element); |
| 1474 } | 1565 } |
| 1475 } | 1566 } |
| 1567 if (includeInjectedMembers) { |
| 1568 if (classElement.patch != null) { |
| 1569 for (Element element in classElement.patch.localMembers.reverse()) { |
| 1570 if (!element.isPatch) { |
| 1571 f(classElement, element); |
| 1572 } |
| 1573 } |
| 1574 } |
| 1575 } |
| 1476 classElement = includeSuperMembers ? classElement.superclass : null; | 1576 classElement = includeSuperMembers ? classElement.superclass : null; |
| 1477 } while(classElement !== null); | 1577 } while(classElement !== null); |
| 1478 } | 1578 } |
| 1479 | 1579 |
| 1480 /** | 1580 /** |
| 1481 * Runs through all instance-field members of this class. | 1581 * Runs through all instance-field members of this class. |
| 1482 * | 1582 * |
| 1483 * The enclosing class is passed to the callback. This is useful when | 1583 * The enclosing class is passed to the callback. This is useful when |
| 1484 * [includeSuperMembers] is [:true:]. | 1584 * [includeSuperMembers] is [:true:]. |
| 1485 * | 1585 * |
| 1486 * When [includeBackendMembers] and [includeSuperMembers] are both [:true:] | 1586 * When [includeBackendMembers] and [includeSuperMembers] are both [:true:] |
| 1487 * then the fields are visited in the same order as they need to be given | 1587 * then the fields are visited in the same order as they need to be given |
| 1488 * to the JavaScript constructor. | 1588 * to the JavaScript constructor. |
| 1589 * |
| 1590 * When called on the implementation element both the fields declared in the |
| 1591 * origin and in the patch are included. |
| 1489 */ | 1592 */ |
| 1490 void forEachInstanceField([void f(ClassElement enclosingClass, Element field), | 1593 void forEachInstanceField([void f(ClassElement enclosingClass, Element field), |
| 1491 includeBackendMembers = false, | 1594 includeBackendMembers = false, |
| 1492 includeSuperMembers = false]) { | 1595 includeSuperMembers = false]) { |
| 1493 // Filters so that [f] is only invoked with instance fields. | 1596 // Filters so that [f] is only invoked with instance fields. |
| 1494 void fieldFilter(ClassElement enclosingClass, Element member) { | 1597 void fieldFilter(ClassElement enclosingClass, Element member) { |
| 1495 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { | 1598 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { |
| 1496 f(enclosingClass, member); | 1599 f(enclosingClass, member); |
| 1497 } | 1600 } |
| 1498 } | 1601 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1521 for (ClassElement s = this; s != null; s = s.superclass) { | 1624 for (ClassElement s = this; s != null; s = s.superclass) { |
| 1522 if (s === cls) return true; | 1625 if (s === cls) return true; |
| 1523 } | 1626 } |
| 1524 return false; | 1627 return false; |
| 1525 } | 1628 } |
| 1526 | 1629 |
| 1527 bool isInterface() => false; | 1630 bool isInterface() => false; |
| 1528 bool isNative() => nativeName != null; | 1631 bool isNative() => nativeName != null; |
| 1529 int hashCode() => id; | 1632 int hashCode() => id; |
| 1530 | 1633 |
| 1531 Scope buildScope() => | 1634 // TODO(johnniwinther): Rewrite to avoid the optional argument. |
| 1532 new ClassScope(enclosingElement.buildScope(), this); | 1635 Scope buildScope({bool patchScope: false}) { |
| 1636 if (origin !== null) { |
| 1637 return new PatchClassScope( |
| 1638 enclosingElement.buildScope(patchScope: patchScope), origin, this); |
| 1639 } else if (patchScope && patch !== null) { |
| 1640 return new PatchClassScope( |
| 1641 enclosingElement.buildScope(patchScope: patchScope), this, patch); |
| 1642 } else { |
| 1643 return new ClassScope( |
| 1644 enclosingElement.buildScope(patchScope: patchScope), this); |
| 1645 } |
| 1646 } |
| 1647 |
| 1648 Scope buildLocalScope() { |
| 1649 if (origin !== null) { |
| 1650 return new LocalPatchClassScope(origin, this); |
| 1651 } else { |
| 1652 return new LocalClassScope(this); |
| 1653 } |
| 1654 } |
| 1533 | 1655 |
| 1534 ClassElement cloneTo(Element enclosing, DiagnosticListener listener) { | 1656 ClassElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 1535 listener.internalErrorOnElement(this, 'unsupported operation'); | 1657 listener.internalErrorOnElement(this, 'unsupported operation'); |
| 1536 } | 1658 } |
| 1537 | 1659 |
| 1538 Link<DartType> get allSupertypesAndSelf { | 1660 Link<DartType> get allSupertypesAndSelf { |
| 1539 return allSupertypes.prepend(new InterfaceType(this)); | 1661 return allSupertypes.prepend(new InterfaceType(this)); |
| 1540 } | 1662 } |
| 1663 |
| 1664 String toString() { |
| 1665 if (origin !== null) { |
| 1666 return 'patch ${super.toString()}'; |
| 1667 } else if (patch !== null) { |
| 1668 return 'origin ${super.toString()}'; |
| 1669 } else { |
| 1670 return super.toString(); |
| 1671 } |
| 1672 } |
| 1541 } | 1673 } |
| 1542 | 1674 |
| 1543 class Elements { | 1675 class Elements { |
| 1544 static bool isUnresolved(Element e) => e == null || e.isErroneous(); | 1676 static bool isUnresolved(Element e) => e == null || e.isErroneous(); |
| 1545 static bool isErroneousElement(Element e) => e != null && e.isErroneous(); | 1677 static bool isErroneousElement(Element e) => e != null && e.isErroneous(); |
| 1546 | 1678 |
| 1547 static bool isLocal(Element element) { | 1679 static bool isLocal(Element element) { |
| 1548 return !Elements.isUnresolved(element) | 1680 return !Elements.isUnresolved(element) |
| 1549 && !element.isInstanceMember() | 1681 && !element.isInstanceMember() |
| 1550 && !isStaticOrTopLevelField(element) | 1682 && !isStaticOrTopLevelField(element) |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1832 | 1964 |
| 1833 MetadataAnnotation ensureResolved(Compiler compiler) { | 1965 MetadataAnnotation ensureResolved(Compiler compiler) { |
| 1834 if (resolutionState == STATE_NOT_STARTED) { | 1966 if (resolutionState == STATE_NOT_STARTED) { |
| 1835 compiler.resolver.resolveMetadataAnnotation(this); | 1967 compiler.resolver.resolveMetadataAnnotation(this); |
| 1836 } | 1968 } |
| 1837 return this; | 1969 return this; |
| 1838 } | 1970 } |
| 1839 | 1971 |
| 1840 String toString() => 'MetadataAnnotation($value, $resolutionState)'; | 1972 String toString() => 'MetadataAnnotation($value, $resolutionState)'; |
| 1841 } | 1973 } |
| OLD | NEW |