Chromium Code Reviews| 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 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |