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 " |
|
ahe
2012/10/02 13:27:04
listener.internalErrorOnElement('not implemented',
Johnni Winther
2012/10/03 09:22:59
Done.
| |
| 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 12 matching lines...) Expand all Loading... | |
| 244 } | 244 } |
| 245 | 245 |
| 246 // TODO(kasperl): This is a very bad hash code for the element and | 246 // TODO(kasperl): This is a very bad hash code for the element and |
| 247 // there's no reason why two elements with the same name should have | 247 // there's no reason why two elements with the same name should have |
| 248 // the same hash code. Replace this with a simple id in the element? | 248 // the same hash code. Replace this with a simple id in the element? |
| 249 int hashCode() => name === null ? 0 : name.hashCode(); | 249 int hashCode() => name === null ? 0 : name.hashCode(); |
| 250 | 250 |
| 251 CompilationUnitElement getCompilationUnit() { | 251 CompilationUnitElement getCompilationUnit() { |
| 252 Element element = this; | 252 Element element = this; |
| 253 while (element !== null && !element.isCompilationUnit()) { | 253 while (element !== null && !element.isCompilationUnit()) { |
| 254 if (element is CompilationUnitOverrideElement) { | 254 if (element is CompilationUnitOverrideElement) { |
|
ahe
2012/10/02 13:27:04
Why do we still have this?
Johnni Winther
2012/10/03 09:22:59
It'll be removed in an after-patch-refactoring cle
| |
| 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 // TODO(johnniwinther): Clean up scope generation. Possibly generation scopes |
| 313 // externally. | |
| 314 Scope buildScope({bool patchScope: false}) => | |
| 315 buildEnclosingScope(patchScope: patchScope); | |
| 319 | 316 |
| 320 /** | 317 /** |
| 321 * Creates the scope for the enclosing element. | 318 * Creates the scope for the enclosing element. |
| 322 */ | 319 */ |
| 323 Scope buildEnclosingScope() => enclosingElement.buildScope(); | 320 // TODO(johnniwinther): Remove buildEnclosingScope as part of scope clean-up. |
| 321 Scope buildEnclosingScope({bool patchScope: false}) => | |
| 322 enclosingElement.buildScope(patchScope: patchScope); | |
| 324 | 323 |
| 325 String toString() { | 324 String toString() { |
| 326 // TODO(johnniwinther): Test for nullness of name, or make non-nullness an | 325 // TODO(johnniwinther): Test for nullness of name, or make non-nullness an |
| 327 // invariant for all element types? | 326 // invariant for all element types? |
| 328 var nameText = name !== null ? name.slowToString() : '?'; | 327 var nameText = name !== null ? name.slowToString() : '?'; |
| 329 if (enclosingElement !== null && !isTopLevel()) { | 328 if (enclosingElement !== null && !isTopLevel()) { |
| 330 String holderName = enclosingElement.name !== null | 329 String holderName = enclosingElement.name !== null |
| 331 ? enclosingElement.name.slowToString() | 330 ? enclosingElement.name.slowToString() |
| 332 : '${enclosingElement.kind}?'; | 331 : '${enclosingElement.kind}?'; |
| 333 return '$kind($holderName#${nameText})'; | 332 return '$kind($holderName#${nameText})'; |
| 334 } else { | 333 } else { |
| 335 return '$kind(${nameText})'; | 334 return '$kind(${nameText})'; |
| 336 } | 335 } |
| 337 } | 336 } |
| 338 | 337 |
| 339 bool _isNative = false; | 338 bool _isNative = false; |
| 340 void setNative() { _isNative = true; } | 339 void setNative() { _isNative = true; } |
| 341 bool isNative() => _isNative; | 340 bool isNative() => _isNative; |
| 342 | 341 |
| 343 FunctionElement asFunctionElement() => null; | 342 FunctionElement asFunctionElement() => null; |
| 344 | 343 |
| 344 static bool isInvalid(Element e) => e == null || e.isErroneous(); | |
| 345 Element cloneTo(Element enclosing, DiagnosticListener listener) { | 345 Element cloneTo(Element enclosing, DiagnosticListener listener) { |
| 346 listener.cancel("Unimplemented cloneTo", element: this); | 346 listener.cancel("Unimplemented cloneTo", element: this); |
| 347 } | 347 } |
| 348 } | 348 } |
| 349 | 349 |
| 350 /** | 350 /** |
| 351 * Represents an unresolvable or duplicated element. | 351 * Represents an unresolvable or duplicated element. |
| 352 * | 352 * |
| 353 * An [ErroneousElement] is used instead of [null] to provide additional | 353 * An [ErroneousElement] is used instead of [null] to provide additional |
| 354 * information about the error that caused the element to be unresolvable | 354 * 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); | 437 Element existing = localScope.putIfAbsent(element.name, () => element); |
| 438 if (existing !== element) { | 438 if (existing !== element) { |
| 439 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. | 439 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. |
| 440 listener.cancel('duplicate definition', token: element.position()); | 440 listener.cancel('duplicate definition', token: element.position()); |
| 441 listener.cancel('existing definition', token: existing.position()); | 441 listener.cancel('existing definition', token: existing.position()); |
| 442 } | 442 } |
| 443 } | 443 } |
| 444 } | 444 } |
| 445 | 445 |
| 446 Element localLookup(SourceString elementName) { | 446 Element localLookup(SourceString elementName) { |
| 447 return localScope[elementName]; | 447 Element result = localScope[elementName]; |
| 448 if (result == null && isPatch) { | |
| 449 result = origin.localScope[elementName]; | |
| 450 } | |
| 451 return result; | |
| 448 } | 452 } |
| 449 | 453 |
| 450 /** | 454 /** |
| 451 * Adds a definition for an [accessor] (getter or setter) to a container. | 455 * 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 | 456 * The definition binds to an abstract field that can hold both a getter |
| 453 * and a setter. | 457 * and a setter. |
| 454 * | 458 * |
| 455 * The abstract field is added once, for the first getter or setter, and | 459 * The abstract field is added once, for the first getter or setter, and |
| 456 * reused if the other one is also added. | 460 * reused if the other one is also added. |
| 457 * The abstract field should not be treated as a proper member of the | 461 * 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) | 512 CompilationUnitElement(Script script, Element enclosing) |
| 509 : this.script = script, | 513 : this.script = script, |
| 510 super(new SourceString(script.name), | 514 super(new SourceString(script.name), |
| 511 ElementKind.COMPILATION_UNIT, | 515 ElementKind.COMPILATION_UNIT, |
| 512 enclosing); | 516 enclosing); |
| 513 | 517 |
| 514 void addMember(Element element, DiagnosticListener listener) { | 518 void addMember(Element element, DiagnosticListener listener) { |
| 515 // Keep a list of top level members. | 519 // Keep a list of top level members. |
| 516 super.addMember(element, listener); | 520 super.addMember(element, listener); |
| 517 // Provide the member to the library to build scope. | 521 // Provide the member to the library to build scope. |
| 518 getLibrary().addMember(element, listener); | 522 if (enclosingElement.isPatch) { |
| 523 getImplementationLibrary().addMember(element, listener); | |
| 524 } else { | |
| 525 getLibrary().addMember(element, listener); | |
| 526 } | |
| 519 } | 527 } |
| 520 } | 528 } |
| 521 | 529 |
| 522 class CompilationUnitOverrideElement extends Element { | 530 class CompilationUnitOverrideElement extends Element { |
| 523 final CompilationUnitElement compilationUnit; | 531 final CompilationUnitElement compilationUnit; |
| 524 | 532 |
| 525 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit, | 533 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit, |
| 526 Element enclosing) | 534 Element enclosing) |
| 527 : this.compilationUnit = compilationUnit, | 535 : this.compilationUnit = compilationUnit, |
| 528 super(compilationUnit.name, | 536 super(compilationUnit.name, |
| 529 ElementKind.COMPILATION_UNIT_OVERRIDE, | 537 ElementKind.COMPILATION_UNIT_OVERRIDE, |
| 530 enclosing); | 538 enclosing); |
| 531 } | 539 } |
| 532 | 540 |
| 533 class LibraryElement extends ScopeContainerElement { | 541 class LibraryElement extends ScopeContainerElement { |
| 534 final Uri uri; | 542 final Uri uri; |
| 535 CompilationUnitElement entryCompilationUnit; | 543 CompilationUnitElement entryCompilationUnit; |
| 536 Link<CompilationUnitElement> compilationUnits = | 544 Link<CompilationUnitElement> compilationUnits = |
| 537 const EmptyLink<CompilationUnitElement>(); | 545 const EmptyLink<CompilationUnitElement>(); |
| 538 Link<LibraryTag> tags = const EmptyLink<LibraryTag>(); | 546 Link<LibraryTag> tags = const EmptyLink<LibraryTag>(); |
| 539 LibraryTag libraryTag; | 547 LibraryTag libraryTag; |
| 540 bool canUseNative = false; | 548 bool canUseNative = false; |
| 541 LibraryElement patch = null; | 549 LibraryElement patch = null; |
| 550 final LibraryElement origin; | |
|
ahe
2012/10/02 13:27:04
Document this.
Johnni Winther
2012/10/03 09:22:59
Done.
| |
| 542 | 551 |
| 543 /** | 552 /** |
| 544 * Map for elements imported through import declarations. | 553 * Map for elements imported through import declarations. |
| 545 * | 554 * |
| 546 * Addition to the map is performed by [addImport]. Lookup is done trough | 555 * Addition to the map is performed by [addImport]. Lookup is done trough |
| 547 * [find]. | 556 * [find]. |
| 548 */ | 557 */ |
| 549 final Map<SourceString, Element> importScope; | 558 final Map<SourceString, Element> importScope; |
| 550 | 559 |
| 551 LibraryElement(Script script, [Uri uri]) | 560 LibraryElement(Script script, [Uri uri, LibraryElement this.origin]) |
| 552 : this.uri = ((uri === null) ? script.uri : uri), | 561 : this.uri = ((uri === null) ? script.uri : uri), |
| 553 importScope = new Map<SourceString, Element>(), | 562 importScope = new Map<SourceString, Element>(), |
| 554 super(new SourceString(script.name), ElementKind.LIBRARY, null) { | 563 super(new SourceString(script.name), ElementKind.LIBRARY, null) { |
| 555 entryCompilationUnit = new CompilationUnitElement(script, this); | 564 entryCompilationUnit = new CompilationUnitElement(script, this); |
| 565 if (isPatch) { | |
| 566 origin.patch = this; | |
| 567 } | |
| 556 } | 568 } |
| 557 | 569 |
| 570 bool get isPatched => patch !== null; | |
| 571 bool get isPatch => origin !== null; | |
| 558 | 572 |
| 559 bool get isPatched => patch !== null; | 573 LibraryElement get declaration => super.declaration; |
|
ahe
2012/10/02 13:27:04
Why?
Johnni Winther
2012/10/03 09:22:59
To let the editor know that declaration is a Libra
| |
| 574 LibraryElement get implementation => super.implementation; | |
|
ahe
2012/10/02 13:27:04
Why?
Johnni Winther
2012/10/03 09:22:59
Ditto.
| |
| 560 | 575 |
| 561 void addCompilationUnit(CompilationUnitElement element) { | 576 void addCompilationUnit(CompilationUnitElement element) { |
| 562 compilationUnits = compilationUnits.prepend(element); | 577 compilationUnits = compilationUnits.prepend(element); |
| 563 } | 578 } |
| 564 | 579 |
| 565 void addTag(LibraryTag tag, DiagnosticListener listener) { | 580 void addTag(LibraryTag tag, DiagnosticListener listener) { |
| 566 tags = tags.prepend(tag); | 581 tags = tags.prepend(tag); |
| 567 } | 582 } |
| 568 | 583 |
| 569 /** | 584 /** |
| 570 * Adds [element] to the import scope of this library. | 585 * Adds [element] to the import scope of this library. |
| 571 * | 586 * |
| 572 * If an element by the same name is already in the imported scope, an | 587 * 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 | 588 * [ErroneousElement] will be put in the imported scope, allowing for the |
| 574 * detection of ambiguous uses of imported names. | 589 * detection of ambiguous uses of imported names. |
| 575 */ | 590 */ |
| 576 void addImport(Element element, DiagnosticListener listener) { | 591 void addImport(Element element, DiagnosticListener listener) { |
| 577 Element existing = importScope.putIfAbsent(element.name, () => element); | 592 Element existing = importScope.putIfAbsent(element.name, () => element); |
| 578 if (existing !== element && existing !== null) { | 593 if (existing !== element && existing !== null) { |
| 579 if (!existing.isErroneous()) { | 594 if (!existing.isErroneous()) { |
| 580 // TODO(johnniwinther): Provide access to both the new and existing | 595 // TODO(johnniwinther): Provide access to both the new and existing |
| 581 // elements. | 596 // elements. |
| 582 importScope[element.name] = new ErroneousElement( | 597 importScope[element.name] = new ErroneousElement( |
| 583 MessageKind.DUPLICATE_IMPORT, | 598 MessageKind.DUPLICATE_IMPORT, |
| 584 [element.name], element.name, this); | 599 [element.name], element.name, this); |
| 585 } | 600 } |
| 586 } | 601 } |
| 587 } | 602 } |
| 588 | 603 |
| 604 LibraryElement getLibrary() => isPatch ? origin : this; | |
| 589 | 605 |
| 590 /** | 606 /** |
| 591 * Look up a top-level element in this library. The element could | 607 * Look up a top-level element in this library. The element could |
| 592 * potentially have been imported from another library. Returns | 608 * potentially have been imported from another library. Returns |
| 593 * null if no such element exist and an [ErroneousElement] if multiple | 609 * null if no such element exist and an [ErroneousElement] if multiple |
| 594 * elements have been imported. | 610 * elements have been imported. |
| 595 */ | 611 */ |
| 596 Element find(SourceString elementName) { | 612 Element find(SourceString elementName) { |
| 597 Element result = localScope[elementName]; | 613 Element result = localScope[elementName]; |
| 598 if (result === null) { | 614 if (result === null) { |
| 599 result = importScope[elementName]; | 615 result = importScope[elementName]; |
| 600 } | 616 } |
| 601 return result; | 617 return result; |
| 602 } | 618 } |
| 603 | 619 |
| 604 /** Look up a top-level element in this library, but only look for | 620 /** Look up a top-level element in this library, but only look for |
| 605 * non-imported elements. Returns null if no such element exist. */ | 621 * non-imported elements. Returns null if no such element exist. */ |
| 606 Element findLocal(SourceString elementName) { | 622 Element findLocal(SourceString elementName) { |
| 623 // TODO(johnniwinther): How to handle injected elements in the patch | |
| 624 // library? | |
| 607 Element result = localScope[elementName]; | 625 Element result = localScope[elementName]; |
| 608 if (result === null || result.getLibrary() != this) return null; | 626 if (result === null || result.getLibrary() != this) return null; |
| 609 return result; | 627 return result; |
| 610 } | 628 } |
| 611 | 629 |
| 612 void forEachExport(f(Element element)) { | 630 void forEachExport(f(Element element)) { |
| 613 localScope.forEach((_, Element e) { | 631 localScope.forEach((_, Element e) { |
| 614 if (this === e.getLibrary() | 632 if (this === e.getLibrary() |
| 615 && e.kind !== ElementKind.PREFIX | 633 && e.kind !== ElementKind.PREFIX |
| 616 && e.kind !== ElementKind.FOREIGN | 634 && e.kind !== ElementKind.FOREIGN |
| 617 && !e.name.isPrivate()) { | 635 && !e.name.isPrivate()) { |
| 618 f(e); | 636 f(e); |
| 619 } | 637 } |
| 620 }); | 638 }); |
| 621 } | 639 } |
| 622 | 640 |
| 641 void forEachLocalMember(f(Element element)) { | |
| 642 if (isPatch) { | |
| 643 // Patch libraries return both origin and patch members. | |
|
ahe
2012/10/02 13:27:04
What does "return" mean in this context?
Johnni Winther
2012/10/03 09:22:59
Done.
| |
| 644 origin.localMembers.forEach(f); | |
| 645 | |
| 646 void filterPatch(Element element) { | |
| 647 if (!element.isPatch) { | |
| 648 // Return only the origin element. | |
|
ahe
2012/10/02 13:27:04
What does this comment mean?
Johnni Winther
2012/10/03 09:22:59
Done.
| |
| 649 f(element); | |
| 650 } | |
| 651 } | |
| 652 localMembers.forEach(filterPatch); | |
| 653 } else { | |
| 654 localMembers.forEach(f); | |
| 655 } | |
| 656 } | |
| 657 | |
| 623 bool hasLibraryName() => libraryTag !== null; | 658 bool hasLibraryName() => libraryTag !== null; |
| 624 | 659 |
| 625 /** | 660 /** |
| 626 * Returns the library name (as defined by the #library tag) or for script | 661 * 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 | 662 * (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. | 663 * to private 'library name' for scripts to use for instance in dartdoc. |
| 629 */ | 664 */ |
| 630 String getLibraryOrScriptName() { | 665 String getLibraryOrScriptName() { |
| 631 if (libraryTag !== null) { | 666 if (libraryTag !== null) { |
| 632 return libraryTag.argument.dartString.slowToString(); | 667 return libraryTag.argument.dartString.slowToString(); |
| 633 } else { | 668 } else { |
| 634 // Use the file name as script name. | 669 // Use the file name as script name. |
| 635 String path = uri.path; | 670 String path = uri.path; |
| 636 return path.substring(path.lastIndexOf('/') + 1); | 671 return path.substring(path.lastIndexOf('/') + 1); |
| 637 } | 672 } |
| 638 } | 673 } |
| 639 | 674 |
| 640 Scope buildEnclosingScope() => new TopScope(this); | 675 Scope buildEnclosingScope({bool patchScope: false}) { |
|
ahe
2012/10/02 13:27:04
I would prefer to avoid optional arguments here.
Johnni Winther
2012/10/03 09:22:59
Added a TODO.
| |
| 676 if (origin !== null) { | |
| 677 return new PatchLibraryScope(origin, this); | |
| 678 } if (patchScope && patch !== null) { | |
| 679 return new PatchLibraryScope(this, patch); | |
| 680 } else { | |
| 681 return new TopScope(this); | |
| 682 } | |
| 683 } | |
| 641 | 684 |
| 642 bool get isPlatformLibrary => uri.scheme == "dart"; | 685 bool get isPlatformLibrary => uri.scheme == "dart"; |
| 686 | |
| 687 String toString() { | |
| 688 if (origin !== null) { | |
| 689 return 'patch library(${getLibraryOrScriptName()})'; | |
| 690 } else if (patch !== null) { | |
| 691 return 'origin library(${getLibraryOrScriptName()})'; | |
| 692 } else { | |
| 693 return 'library(${getLibraryOrScriptName()})'; | |
| 694 } | |
| 695 } | |
| 643 } | 696 } |
| 644 | 697 |
| 645 class PrefixElement extends Element { | 698 class PrefixElement extends Element { |
| 646 Map<SourceString, Element> imported; | 699 Map<SourceString, Element> imported; |
| 647 Token firstPosition; | 700 Token firstPosition; |
| 648 | 701 |
| 649 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) | 702 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) |
| 650 : imported = new Map<SourceString, Element>(), | 703 : imported = new Map<SourceString, Element>(), |
| 651 super(prefix, ElementKind.PREFIX, enclosing); | 704 super(prefix, ElementKind.PREFIX, enclosing); |
| 652 | 705 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 687 Typedef node = parseNode(compiler); | 740 Typedef node = parseNode(compiler); |
| 688 Link<DartType> parameters = | 741 Link<DartType> parameters = |
| 689 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); | 742 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); |
| 690 cachedType = new TypedefType(this, parameters); | 743 cachedType = new TypedefType(this, parameters); |
| 691 compiler.resolveTypedef(this); | 744 compiler.resolveTypedef(this); |
| 692 return cachedType; | 745 return cachedType; |
| 693 } | 746 } |
| 694 | 747 |
| 695 Link<DartType> get typeVariables => cachedType.typeArguments; | 748 Link<DartType> get typeVariables => cachedType.typeArguments; |
| 696 | 749 |
| 697 Scope buildScope() => | |
| 698 new TypeDeclarationScope(enclosingElement.buildScope(), this); | |
| 699 | 750 |
| 751 Scope buildScope({bool patchScope: false}) => new TypeDeclarationScope( | |
|
ahe
2012/10/02 13:27:04
Optional arguments :-(
ahe
2012/10/02 13:27:04
If it doesn't fit on one line, use don't use the s
Johnni Winther
2012/10/03 09:22:59
Added a TODO.
Johnni Winther
2012/10/03 09:22:59
Done.
| |
| 752 enclosingElement.buildScope(patchScope: patchScope), this); | |
| 700 TypedefElement cloneTo(Element enclosing, DiagnosticListener listener) { | 753 TypedefElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 701 TypedefElement result = new TypedefElement(name, enclosing); | 754 TypedefElement result = new TypedefElement(name, enclosing); |
| 702 return result; | 755 return result; |
| 703 } | 756 } |
| 704 } | 757 } |
| 705 | 758 |
| 706 class VariableElement extends Element { | 759 class VariableElement extends Element { |
| 707 final VariableListElement variables; | 760 final VariableListElement variables; |
| 708 Expression cachedNode; // The send or the identifier in the variables list. | 761 Expression cachedNode; // The send or the identifier in the variables list. |
| 709 | 762 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 847 } else { | 900 } else { |
| 848 result = new VariableListElement(kind, modifiers, enclosing); | 901 result = new VariableListElement(kind, modifiers, enclosing); |
| 849 } | 902 } |
| 850 return result; | 903 return result; |
| 851 } | 904 } |
| 852 | 905 |
| 853 bool isInstanceMember() { | 906 bool isInstanceMember() { |
| 854 return isMember() && !modifiers.isStatic(); | 907 return isMember() && !modifiers.isStatic(); |
| 855 } | 908 } |
| 856 | 909 |
| 857 Scope buildScope() { | 910 Scope buildScope({bool patchScope: false}) { |
|
ahe
2012/10/02 13:27:04
Optional arguments :-(
Johnni Winther
2012/10/03 09:22:59
Added a TODO.
| |
| 858 Scope result = new VariableScope(enclosingElement.buildScope(), this); | 911 Scope result = new VariableScope( |
| 912 enclosingElement.buildScope(patchScope: patchScope), this); | |
| 859 if (enclosingElement.isClass()) { | 913 if (enclosingElement.isClass()) { |
| 860 ClassScope clsScope = result.parent; | 914 Scope clsScope = result.parent; |
| 861 clsScope.inStaticContext = !isInstanceMember(); | 915 clsScope.inStaticContext = !isInstanceMember(); |
| 862 } | 916 } |
| 863 return result; | 917 return result; |
| 864 } | 918 } |
| 865 } | 919 } |
| 866 | 920 |
| 867 class ForeignElement extends Element { | 921 class ForeignElement extends Element { |
| 868 ForeignElement(SourceString name, ContainerElement enclosingElement) | 922 ForeignElement(SourceString name, ContainerElement enclosingElement) |
| 869 : super(name, ElementKind.FOREIGN, enclosingElement); | 923 : super(name, ElementKind.FOREIGN, enclosingElement); |
| 870 | 924 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 981 | 1035 |
| 982 FunctionSignature functionSignature; | 1036 FunctionSignature functionSignature; |
| 983 | 1037 |
| 984 /** | 1038 /** |
| 985 * A function declaration that should be parsed instead of the current one. | 1039 * 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 | 1040 * The patch should be parsed as if it was in the current scope. Its |
| 987 * signature must match this function's signature. | 1041 * signature must match this function's signature. |
| 988 */ | 1042 */ |
| 989 // TODO(lrn): Consider using [defaultImplementation] to store the patch. | 1043 // TODO(lrn): Consider using [defaultImplementation] to store the patch. |
| 990 FunctionElement patch = null; | 1044 FunctionElement patch = null; |
| 1045 FunctionElement origin = null; | |
| 991 | 1046 |
| 992 /** | 1047 /** |
| 993 * If this is an interface constructor, [defaultImplementation] will | 1048 * If this is an interface constructor, [defaultImplementation] will |
| 994 * changed by the resolver to point to the default | 1049 * changed by the resolver to point to the default |
| 995 * implementation. Otherwise, [:defaultImplementation === this:]. | 1050 * implementation. Otherwise, [:defaultImplementation === this:]. |
| 996 */ | 1051 */ |
| 997 FunctionElement defaultImplementation; | 1052 FunctionElement defaultImplementation; |
| 998 | 1053 |
| 999 FunctionElement(SourceString name, | 1054 FunctionElement(SourceString name, |
| 1000 ElementKind kind, | 1055 ElementKind kind, |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1020 FunctionExpression this.cachedNode, | 1075 FunctionExpression this.cachedNode, |
| 1021 ElementKind kind, | 1076 ElementKind kind, |
| 1022 Modifiers this.modifiers, | 1077 Modifiers this.modifiers, |
| 1023 Element enclosing, | 1078 Element enclosing, |
| 1024 FunctionSignature this.functionSignature) | 1079 FunctionSignature this.functionSignature) |
| 1025 : super(name, kind, enclosing) { | 1080 : super(name, kind, enclosing) { |
| 1026 defaultImplementation = this; | 1081 defaultImplementation = this; |
| 1027 } | 1082 } |
| 1028 | 1083 |
| 1029 bool get isPatched => patch !== null; | 1084 bool get isPatched => patch !== null; |
| 1085 bool get isPatch => origin !== null; | |
| 1030 | 1086 |
| 1031 /** | 1087 /** |
| 1032 * Applies a patch function to this function. The patch function's body | 1088 * Applies a patch function to this function. The patch function's body |
| 1033 * is used as replacement when parsing this function's body. | 1089 * is used as replacement when parsing this function's body. |
| 1034 * This method must not be called after the function has been parsed, | 1090 * This method must not be called after the function has been parsed, |
| 1035 * and it must be called at most once. | 1091 * and it must be called at most once. |
| 1036 */ | 1092 */ |
| 1037 void setPatch(FunctionElement patchElement) { | 1093 void setPatch(FunctionElement patchElement) { |
| 1038 // Sanity checks. The caller must check these things before calling. | 1094 // Sanity checks. The caller must check these things before calling. |
| 1039 assert(patch === null); | 1095 assert(patch === null); |
| 1040 assert(cachedNode === null); | |
| 1041 this.patch = patchElement; | 1096 this.patch = patchElement; |
| 1042 cachedNode = patchElement.cachedNode; | |
| 1043 } | 1097 } |
| 1044 | 1098 |
| 1045 bool isInstanceMember() { | 1099 bool isInstanceMember() { |
| 1046 return isMember() | 1100 return isMember() |
| 1047 && !isConstructor() | 1101 && !isConstructor() |
| 1048 && !modifiers.isStatic(); | 1102 && !modifiers.isStatic(); |
| 1049 } | 1103 } |
| 1050 | 1104 |
| 1051 FunctionSignature computeSignature(Compiler compiler) { | 1105 FunctionSignature computeSignature(Compiler compiler) { |
| 1052 if (functionSignature !== null) return functionSignature; | 1106 if (functionSignature !== null) return functionSignature; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1069 } | 1123 } |
| 1070 | 1124 |
| 1071 FunctionType computeType(Compiler compiler) { | 1125 FunctionType computeType(Compiler compiler) { |
| 1072 if (type != null) return type; | 1126 if (type != null) return type; |
| 1073 type = compiler.computeFunctionType(declaration, | 1127 type = compiler.computeFunctionType(declaration, |
| 1074 computeSignature(compiler)); | 1128 computeSignature(compiler)); |
| 1075 return type; | 1129 return type; |
| 1076 } | 1130 } |
| 1077 | 1131 |
| 1078 Node parseNode(DiagnosticListener listener) { | 1132 Node parseNode(DiagnosticListener listener) { |
| 1079 if (cachedNode !== null) return cachedNode; | |
| 1080 if (patch === null) { | 1133 if (patch === null) { |
| 1081 if (modifiers != null && modifiers.isExternal()) { | 1134 if (modifiers != null && modifiers.isExternal()) { |
| 1082 listener.cancel("Compiling external function with no implementation.", | 1135 listener.cancel("Compiling external function with no implementation.", |
| 1083 element: this); | 1136 element: this); |
| 1084 } | 1137 } |
| 1085 return null; | |
| 1086 } | 1138 } |
| 1087 cachedNode = patch.parseNode(listener); | |
| 1088 return cachedNode; | 1139 return cachedNode; |
| 1089 } | 1140 } |
| 1090 | 1141 |
| 1091 Token position() => cachedNode.getBeginToken(); | 1142 Token position() => cachedNode.getBeginToken(); |
| 1092 | 1143 |
| 1093 FunctionElement asFunctionElement() => this; | 1144 FunctionElement asFunctionElement() => this; |
| 1094 | 1145 |
| 1095 String toString() { | 1146 String toString() { |
| 1096 if (isPatch) { | 1147 if (isPatch) { |
| 1097 return 'patch ${super.toString()}'; | 1148 return 'patch ${super.toString()}'; |
| 1098 } else if (isPatched) { | 1149 } else if (isPatched) { |
| 1099 return 'origin ${super.toString()}'; | 1150 return 'origin ${super.toString()}'; |
| 1100 } else { | 1151 } else { |
| 1101 return super.toString(); | 1152 return super.toString(); |
| 1102 } | 1153 } |
| 1103 } | 1154 } |
| 1104 | 1155 |
| 1105 Scope buildScope() { | 1156 Scope buildScope({bool patchScope: false}) { |
|
ahe
2012/10/02 13:27:04
Yuck!
Johnni Winther
2012/10/03 09:22:59
Added a TODO.
| |
| 1106 Scope result = | 1157 Scope result = new MethodScope( |
| 1107 new MethodScope(enclosingElement.buildScope(), this); | 1158 enclosingElement.buildScope(patchScope: patchScope), this); |
| 1108 if (enclosingElement.isClass()) { | 1159 if (enclosingElement.isClass()) { |
| 1109 Scope clsScope = result.parent; | 1160 Scope clsScope = result.parent; |
| 1110 clsScope.inStaticContext = !isInstanceMember() && !isConstructor(); | 1161 clsScope.inStaticContext = !isInstanceMember() && !isConstructor(); |
| 1111 } | 1162 } |
| 1112 return result; | 1163 return result; |
| 1113 } | 1164 } |
| 1114 } | 1165 } |
| 1115 | 1166 |
| 1116 class ConstructorBodyElement extends FunctionElement { | 1167 class ConstructorBodyElement extends FunctionElement { |
| 1117 FunctionElement constructor; | 1168 FunctionElement constructor; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1223 int resolutionState; | 1274 int resolutionState; |
| 1224 | 1275 |
| 1225 // backendMembers are members that have been added by the backend to simplify | 1276 // backendMembers are members that have been added by the backend to simplify |
| 1226 // compilation. They don't have any user-side counter-part. | 1277 // compilation. They don't have any user-side counter-part. |
| 1227 Link<Element> backendMembers = const EmptyLink<Element>(); | 1278 Link<Element> backendMembers = const EmptyLink<Element>(); |
| 1228 | 1279 |
| 1229 Link<DartType> allSupertypes; | 1280 Link<DartType> allSupertypes; |
| 1230 | 1281 |
| 1231 // Lazily applied patch of class members. | 1282 // Lazily applied patch of class members. |
| 1232 ClassElement patch = null; | 1283 ClassElement patch = null; |
| 1284 ClassElement origin = null; | |
| 1233 | 1285 |
| 1234 ClassElement(SourceString name, Element enclosing, this.id, int initialState) | 1286 ClassElement(SourceString name, Element enclosing, this.id, int initialState) |
| 1235 : supertypeLoadState = initialState, | 1287 : supertypeLoadState = initialState, |
| 1236 resolutionState = initialState, | 1288 resolutionState = initialState, |
| 1237 super(name, ElementKind.CLASS, enclosing); | 1289 super(name, ElementKind.CLASS, enclosing); |
| 1238 | 1290 |
| 1239 InterfaceType computeType(compiler) { | 1291 InterfaceType computeType(compiler) { |
| 1240 if (type == null) { | 1292 if (type == null) { |
| 1241 ClassNode node = parseNode(compiler); | 1293 if (origin === null) { |
| 1242 Link<DartType> parameters = | 1294 ClassNode node = parseNode(compiler); |
| 1243 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); | 1295 Link<DartType> parameters = |
| 1244 type = new InterfaceType(this, parameters); | 1296 TypeDeclarationElement.createTypeVariables(this, |
| 1297 node.typeParameters); | |
| 1298 type = new InterfaceType(this, parameters); | |
| 1299 } else { | |
| 1300 type = origin.computeType(compiler); | |
| 1301 } | |
| 1245 } | 1302 } |
| 1246 return type; | 1303 return type; |
| 1247 } | 1304 } |
| 1248 | 1305 |
| 1249 bool get isPatched => patch != null; | 1306 bool get isPatched => patch != null; |
| 1307 bool get isPatch => origin != null; | |
| 1308 | |
| 1309 ClassElement get declaration => super.declaration; | |
| 1310 ClassElement get implementation => super.implementation; | |
| 1250 | 1311 |
| 1251 /** | 1312 /** |
| 1252 * Return [:true:] if this element is the [:Object:] class for the [compiler]. | 1313 * Return [:true:] if this element is the [:Object:] class for the [compiler]. |
| 1253 */ | 1314 */ |
| 1254 bool isObject(Compiler compiler) => | 1315 bool isObject(Compiler compiler) => |
| 1255 declaration === compiler.objectClass; | 1316 declaration === compiler.objectClass; |
| 1256 | 1317 |
| 1257 Link<DartType> get typeVariables => type.arguments; | 1318 Link<DartType> get typeVariables => type.arguments; |
| 1258 | 1319 |
| 1259 ClassElement ensureResolved(Compiler compiler) { | 1320 ClassElement ensureResolved(Compiler compiler) { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1278 Element lookupSuperMember(SourceString memberName) { | 1339 Element lookupSuperMember(SourceString memberName) { |
| 1279 return lookupSuperMemberInLibrary(memberName, getLibrary()); | 1340 return lookupSuperMemberInLibrary(memberName, getLibrary()); |
| 1280 } | 1341 } |
| 1281 | 1342 |
| 1282 /** | 1343 /** |
| 1283 * Lookup super members for the class that is accessible in [library]. | 1344 * Lookup super members for the class that is accessible in [library]. |
| 1284 * This will ignore constructors. | 1345 * This will ignore constructors. |
| 1285 */ | 1346 */ |
| 1286 Element lookupSuperMemberInLibrary(SourceString memberName, | 1347 Element lookupSuperMemberInLibrary(SourceString memberName, |
| 1287 LibraryElement library) { | 1348 LibraryElement library) { |
| 1349 bool includeInjectedMembers = isPatch; | |
| 1288 bool isPrivate = memberName.isPrivate(); | 1350 bool isPrivate = memberName.isPrivate(); |
| 1289 for (ClassElement s = superclass; s != null; s = s.superclass) { | 1351 for (ClassElement s = superclass; s != null; s = s.superclass) { |
| 1290 // Private members from a different library are not visible. | 1352 // Private members from a different library are not visible. |
| 1291 if (isPrivate && library !== s.getLibrary()) continue; | 1353 if (isPrivate && library !== s.getLibrary()) continue; |
| 1354 s = includeInjectedMembers ? s.implementation : s; | |
| 1292 Element e = s.lookupLocalMember(memberName); | 1355 Element e = s.lookupLocalMember(memberName); |
| 1293 if (e === null) continue; | 1356 if (e === null) continue; |
| 1294 // Static members are not inherited. | 1357 // Static members are not inherited. |
| 1295 if (e.modifiers.isStatic()) continue; | 1358 if (e.modifiers.isStatic()) continue; |
| 1296 return e; | 1359 return e; |
| 1297 } | 1360 } |
| 1298 if (isInterface()) { | 1361 if (isInterface()) { |
| 1299 return lookupSuperInterfaceMember(memberName, getLibrary()); | 1362 return lookupSuperInterfaceMember(memberName, getLibrary()); |
| 1300 } | 1363 } |
| 1301 return null; | 1364 return null; |
| 1302 } | 1365 } |
| 1303 | 1366 |
| 1304 Element lookupSuperInterfaceMember(SourceString memberName, | 1367 Element lookupSuperInterfaceMember(SourceString memberName, |
| 1305 LibraryElement fromLibrary) { | 1368 LibraryElement fromLibrary) { |
| 1369 bool includeInjectedMembers = isPatch; | |
| 1306 bool isPrivate = memberName.isPrivate(); | 1370 bool isPrivate = memberName.isPrivate(); |
| 1307 for (InterfaceType t in interfaces) { | 1371 for (InterfaceType t in interfaces) { |
| 1308 ClassElement cls = t.element; | 1372 ClassElement cls = t.element; |
| 1373 cls = includeInjectedMembers ? cls.implementation : cls; | |
| 1309 Element e = cls.lookupLocalMember(memberName); | 1374 Element e = cls.lookupLocalMember(memberName); |
| 1310 if (e === null) continue; | 1375 if (e === null) continue; |
| 1311 // Private members from a different library are not visible. | 1376 // Private members from a different library are not visible. |
| 1312 if (isPrivate && fromLibrary !== e.getLibrary()) continue; | 1377 if (isPrivate && fromLibrary !== e.getLibrary()) continue; |
| 1313 // Static members are not inherited. | 1378 // Static members are not inherited. |
| 1314 if (e.modifiers.isStatic()) continue; | 1379 if (e.modifiers.isStatic()) continue; |
| 1315 return e; | 1380 return e; |
| 1316 } | 1381 } |
| 1317 return null; | 1382 return null; |
| 1318 } | 1383 } |
| 1319 | 1384 |
| 1320 /** | 1385 /** |
| 1321 * Find the first member in the class chain with the given [selector]. | 1386 * Find the first member in the class chain with the given [selector]. |
| 1322 * | 1387 * |
| 1323 * This method is NOT to be used for resolving | 1388 * This method is NOT to be used for resolving |
| 1324 * unqualified sends because it does not implement the scoping | 1389 * unqualified sends because it does not implement the scoping |
| 1325 * rules, where library scope comes before superclass scope. | 1390 * rules, where library scope comes before superclass scope. |
| 1391 * | |
| 1392 * When called on the implementation element both members declared in the | |
| 1393 * origin and the patch class are returned. | |
| 1326 */ | 1394 */ |
| 1327 Element lookupSelector(Selector selector) { | 1395 Element lookupSelector(Selector selector) { |
| 1328 SourceString memberName = selector.name; | 1396 SourceString memberName = selector.name; |
| 1329 LibraryElement library = selector.library; | 1397 LibraryElement library = selector.library; |
| 1330 Element localMember = lookupLocalMember(memberName); | 1398 Element localMember = lookupLocalMember(memberName); |
| 1331 if (localMember != null && | 1399 if (localMember != null && |
| 1332 (!memberName.isPrivate() || getLibrary() == library)) { | 1400 (!memberName.isPrivate() || getLibrary() == library)) { |
| 1333 return localMember; | 1401 return localMember; |
| 1334 } | 1402 } |
| 1335 return lookupSuperMemberInLibrary(memberName, library); | 1403 return lookupSuperMemberInLibrary(memberName, library); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1398 // Search in scope to be sure we search patched constructors. | 1466 // Search in scope to be sure we search patched constructors. |
| 1399 for (var element in localScope.getValues()) { | 1467 for (var element in localScope.getValues()) { |
| 1400 if (element.isConstructor()) return true; | 1468 if (element.isConstructor()) return true; |
| 1401 } | 1469 } |
| 1402 return false; | 1470 return false; |
| 1403 } | 1471 } |
| 1404 | 1472 |
| 1405 Link<Element> get constructors { | 1473 Link<Element> get constructors { |
| 1406 // TODO(ajohnsen): See if we can avoid this method at some point. | 1474 // TODO(ajohnsen): See if we can avoid this method at some point. |
| 1407 Link<Element> result = const EmptyLink<Element>(); | 1475 Link<Element> result = const EmptyLink<Element>(); |
| 1408 for (Element member in localMembers) { | 1476 // TODO(johnniwinther): Should we include injected constructors? |
| 1477 forEachMember((_, Element member) { | |
| 1409 if (member.isConstructor()) result = result.prepend(member); | 1478 if (member.isConstructor()) result = result.prepend(member); |
| 1410 } | 1479 }); |
| 1411 return result; | 1480 return result; |
| 1412 } | 1481 } |
| 1413 | 1482 |
| 1414 /** | 1483 /** |
| 1415 * Returns the super class, if any. | 1484 * Returns the super class, if any. |
| 1416 * | 1485 * |
| 1417 * The returned element may not be resolved yet. | 1486 * The returned element may not be resolved yet. |
| 1418 */ | 1487 */ |
| 1419 ClassElement get superclass { | 1488 ClassElement get superclass { |
| 1420 assert(supertypeLoadState == STATE_DONE); | 1489 assert(supertypeLoadState == STATE_DONE); |
| 1421 return supertype === null ? null : supertype.element; | 1490 return supertype === null ? null : supertype.element; |
| 1422 } | 1491 } |
| 1423 | 1492 |
| 1424 /** | 1493 /** |
| 1425 * Runs through all members of this class. | 1494 * Runs through all members of this class. |
| 1426 * | 1495 * |
| 1427 * The enclosing class is passed to the callback. This is useful when | 1496 * The enclosing class is passed to the callback. This is useful when |
| 1428 * [includeSuperMembers] is [:true:]. | 1497 * [includeSuperMembers] is [:true:]. |
| 1498 * | |
| 1499 * When called on an implementation element both the members in the origin | |
| 1500 * and patch class are included. | |
| 1429 */ | 1501 */ |
| 1502 // TODO(johnniwinther): Clean up lookup to get rid of the include predicates. | |
| 1430 void forEachMember([void f(ClassElement enclosingClass, Element member), | 1503 void forEachMember([void f(ClassElement enclosingClass, Element member), |
| 1431 includeBackendMembers = false, | 1504 includeBackendMembers = false, |
| 1432 includeSuperMembers = false]) { | 1505 includeSuperMembers = false]) { |
| 1506 bool includeInjectedMembers = isPatch; | |
| 1433 Set<ClassElement> seen = new Set<ClassElement>(); | 1507 Set<ClassElement> seen = new Set<ClassElement>(); |
| 1434 ClassElement classElement = this; | 1508 ClassElement classElement = declaration; |
| 1435 do { | 1509 do { |
| 1436 if (seen.contains(classElement)) return; | 1510 if (seen.contains(classElement)) return; |
| 1437 seen.add(classElement); | 1511 seen.add(classElement); |
| 1438 | 1512 |
| 1439 // Iterate through the members in textual order, which requires | 1513 // Iterate through the members in textual order, which requires |
| 1440 // to reverse the data structure [localMembers] we created. | 1514 // to reverse the data structure [localMembers] we created. |
| 1441 // Textual order may be important for certain operations, for | 1515 // Textual order may be important for certain operations, for |
| 1442 // example when emitting the initializers of fields. | 1516 // example when emitting the initializers of fields. |
| 1443 for (Element element in classElement.localMembers.reverse()) { | 1517 for (Element element in classElement.localMembers.reverse()) { |
| 1444 f(classElement, element); | 1518 f(classElement, element); |
| 1445 } | 1519 } |
| 1446 if (includeBackendMembers) { | 1520 if (includeBackendMembers) { |
| 1447 for (Element element in classElement.backendMembers) { | 1521 for (Element element in classElement.backendMembers) { |
| 1448 f(classElement, element); | 1522 f(classElement, element); |
| 1449 } | 1523 } |
| 1450 } | 1524 } |
| 1525 if (includeInjectedMembers) { | |
| 1526 if (classElement.patch != null) { | |
| 1527 for (Element element in classElement.patch.localMembers.reverse()) { | |
|
ahe
2012/10/02 13:27:04
Why are you calling reverse here?
Johnni Winther
2012/10/03 09:22:59
Because it was done above for [:classElement.local
| |
| 1528 if (!element.isPatch) { | |
| 1529 f(classElement, element); | |
| 1530 } | |
| 1531 } | |
| 1532 } | |
| 1533 } | |
| 1451 classElement = includeSuperMembers ? classElement.superclass : null; | 1534 classElement = includeSuperMembers ? classElement.superclass : null; |
| 1452 } while(classElement !== null); | 1535 } while(classElement !== null); |
| 1453 } | 1536 } |
| 1454 | 1537 |
| 1455 /** | 1538 /** |
| 1456 * Runs through all instance-field members of this class. | 1539 * Runs through all instance-field members of this class. |
| 1457 * | 1540 * |
| 1458 * The enclosing class is passed to the callback. This is useful when | 1541 * The enclosing class is passed to the callback. This is useful when |
| 1459 * [includeSuperMembers] is [:true:]. | 1542 * [includeSuperMembers] is [:true:]. |
| 1460 * | 1543 * |
| 1461 * When [includeBackendMembers] and [includeSuperMembers] are both [:true:] | 1544 * When [includeBackendMembers] and [includeSuperMembers] are both [:true:] |
| 1462 * then the fields are visited in the same order as they need to be given | 1545 * then the fields are visited in the same order as they need to be given |
| 1463 * to the JavaScript constructor. | 1546 * to the JavaScript constructor. |
| 1547 * | |
| 1548 * When called on the implementation element both the fields declared in the | |
| 1549 * origin and in the patch are included. | |
| 1464 */ | 1550 */ |
| 1465 void forEachInstanceField([void f(ClassElement enclosingClass, Element field), | 1551 void forEachInstanceField([void f(ClassElement enclosingClass, Element field), |
| 1466 includeBackendMembers = false, | 1552 includeBackendMembers = false, |
| 1467 includeSuperMembers = false]) { | 1553 includeSuperMembers = false]) { |
| 1468 // Filters so that [f] is only invoked with instance fields. | 1554 // Filters so that [f] is only invoked with instance fields. |
| 1469 void fieldFilter(ClassElement enclosingClass, Element member) { | 1555 void fieldFilter(ClassElement enclosingClass, Element member) { |
| 1470 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { | 1556 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { |
| 1471 f(enclosingClass, member); | 1557 f(enclosingClass, member); |
| 1472 } | 1558 } |
| 1473 } | 1559 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1496 for (ClassElement s = this; s != null; s = s.superclass) { | 1582 for (ClassElement s = this; s != null; s = s.superclass) { |
| 1497 if (s === cls) return true; | 1583 if (s === cls) return true; |
| 1498 } | 1584 } |
| 1499 return false; | 1585 return false; |
| 1500 } | 1586 } |
| 1501 | 1587 |
| 1502 bool isInterface() => false; | 1588 bool isInterface() => false; |
| 1503 bool isNative() => nativeName != null; | 1589 bool isNative() => nativeName != null; |
| 1504 int hashCode() => id; | 1590 int hashCode() => id; |
| 1505 | 1591 |
| 1506 Scope buildScope() => | 1592 Scope buildScope({bool patchScope: false}) { |
|
ahe
2012/10/02 13:27:04
Optional parameters :-(
Johnni Winther
2012/10/03 09:22:59
Added a TODO.
| |
| 1507 new ClassScope(enclosingElement.buildScope(), this); | 1593 if (origin !== null) { |
| 1594 return new PatchClassScope( | |
| 1595 enclosingElement.buildScope(patchScope: patchScope), origin, this); | |
| 1596 } else if (patchScope && patch !== null) { | |
| 1597 return new PatchClassScope( | |
| 1598 enclosingElement.buildScope(patchScope: patchScope), this, patch); | |
| 1599 } else { | |
| 1600 return new ClassScope( | |
| 1601 enclosingElement.buildScope(patchScope: patchScope), this); | |
| 1602 } | |
| 1603 } | |
| 1604 | |
| 1605 Scope buildLocalScope() { | |
| 1606 if (origin !== null) { | |
| 1607 return new LocalPatchClassScope(origin, this); | |
| 1608 } else { | |
| 1609 return new LocalClassScope(this); | |
| 1610 } | |
| 1611 } | |
| 1508 | 1612 |
| 1509 ClassElement cloneTo(Element enclosing, DiagnosticListener listener) { | 1613 ClassElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 1510 listener.internalErrorOnElement(this, 'unsupported operation'); | 1614 listener.internalErrorOnElement(this, 'unsupported operation'); |
| 1511 } | 1615 } |
| 1512 | 1616 |
| 1513 Link<DartType> get allSupertypesAndSelf { | 1617 Link<DartType> get allSupertypesAndSelf { |
| 1514 return allSupertypes.prepend(new InterfaceType(this)); | 1618 return allSupertypes.prepend(new InterfaceType(this)); |
| 1515 } | 1619 } |
| 1620 | |
| 1621 String toString() { | |
| 1622 if (origin !== null) { | |
| 1623 return 'patch ${super.toString()}'; | |
| 1624 } else if (patch !== null) { | |
| 1625 return 'origin ${super.toString()}'; | |
| 1626 } else { | |
| 1627 return super.toString(); | |
| 1628 } | |
| 1629 } | |
| 1516 } | 1630 } |
| 1517 | 1631 |
| 1518 class Elements { | 1632 class Elements { |
| 1519 static bool isUnresolved(Element e) => e == null || e.isErroneous(); | 1633 static bool isUnresolved(Element e) => e == null || e.isErroneous(); |
| 1520 static bool isErroneousElement(Element e) => e != null && e.isErroneous(); | 1634 static bool isErroneousElement(Element e) => e != null && e.isErroneous(); |
| 1521 | 1635 |
| 1522 static bool isLocal(Element element) { | 1636 static bool isLocal(Element element) { |
| 1523 return !Elements.isUnresolved(element) | 1637 return !Elements.isUnresolved(element) |
| 1524 && !element.isInstanceMember() | 1638 && !element.isInstanceMember() |
| 1525 && !isStaticOrTopLevelField(element) | 1639 && !isStaticOrTopLevelField(element) |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1790 | 1904 |
| 1791 MetadataAnnotation ensureResolved(Compiler compiler) { | 1905 MetadataAnnotation ensureResolved(Compiler compiler) { |
| 1792 if (resolutionState == STATE_NOT_STARTED) { | 1906 if (resolutionState == STATE_NOT_STARTED) { |
| 1793 compiler.resolver.resolveMetadataAnnotation(this); | 1907 compiler.resolver.resolveMetadataAnnotation(this); |
| 1794 } | 1908 } |
| 1795 return this; | 1909 return this; |
| 1796 } | 1910 } |
| 1797 | 1911 |
| 1798 String toString() => 'MetadataAnnotation($value, $resolutionState)'; | 1912 String toString() => 'MetadataAnnotation($value, $resolutionState)'; |
| 1799 } | 1913 } |
| OLD | NEW |