| 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 | 5 |
| 6 /** | 6 /** |
| 7 * If true, print a warning for each method that was resolved, but not | 7 * If true, print a warning for each method that was resolved, but not |
| 8 * compiled. | 8 * compiled. |
| 9 */ | 9 */ |
| 10 final bool REPORT_EXCESS_RESOLUTION = false; | 10 final bool REPORT_EXCESS_RESOLUTION = false; |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 //patchDartLibrary(coreImplLibrary, 'coreimpl'); | 374 //patchDartLibrary(coreImplLibrary, 'coreimpl'); |
| 375 } | 375 } |
| 376 | 376 |
| 377 void patchDartLibrary(LibraryElement library, String dartLibraryPath) { | 377 void patchDartLibrary(LibraryElement library, String dartLibraryPath) { |
| 378 if (library.isPatched) return; | 378 if (library.isPatched) return; |
| 379 Uri patchUri = resolvePatchUri(dartLibraryPath); | 379 Uri patchUri = resolvePatchUri(dartLibraryPath); |
| 380 if (patchUri !== null) { | 380 if (patchUri !== null) { |
| 381 patchParser.patchLibrary(patchUri, library); | 381 patchParser.patchLibrary(patchUri, library); |
| 382 // We allow foreign functions in patched libraries. | 382 // We allow foreign functions in patched libraries. |
| 383 addForeignFunctions(library); // Is safe even if already added. | 383 addForeignFunctions(library); // Is safe even if already added. |
| 384 // TODO(lrn): Make this lazy. | |
| 385 applyClassPatches(library); | |
| 386 } | 384 } |
| 387 } | 385 } |
| 388 | 386 |
| 389 void applyClassPatches(LibraryElement library) { | |
| 390 for (Element element in library.localMembers) { | |
| 391 if (element.isClass()) { | |
| 392 ClassElement classElement = element; | |
| 393 if (classElement.isPatched) { | |
| 394 applyClassPatch(classElement, classElement.patch); | |
| 395 } | |
| 396 } | |
| 397 } | |
| 398 } | |
| 399 | |
| 400 void applyContainerPatch(ScopeContainerElement original, | 387 void applyContainerPatch(ScopeContainerElement original, |
| 401 Link<Element> patches) { | 388 Link<Element> patches) { |
| 402 while (!patches.isEmpty()) { | 389 while (!patches.isEmpty()) { |
| 403 Element patchElement = patches.head; | 390 Element patchElement = patches.head; |
| 404 Element originalElement = original.localLookup(patchElement.name); | 391 Element originalElement = original.localLookup(patchElement.name); |
| 405 if (patchElement.isAccessor()) { | 392 if (patchElement.isAccessor()) { |
| 406 // TODO(lrn): When we change to always add accessors to members, and | 393 // TODO(lrn): When we change to always add accessors to members, and |
| 407 // not add abstract fields, the logic here should be reversed. | 394 // not add abstract fields, the logic here should be reversed. |
| 408 // For now, access getters through the abstract field and skip | 395 // For now, access getters through the abstract field and skip |
| 409 // any accessors. | 396 // any accessors. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 | 461 |
| 475 void patchMember(Element originalElement, Element patchElement) { | 462 void patchMember(Element originalElement, Element patchElement) { |
| 476 // The original library has an element with the same name as the patch | 463 // The original library has an element with the same name as the patch |
| 477 // library element. | 464 // library element. |
| 478 // In this case, the patch library element must be a function marked as | 465 // In this case, the patch library element must be a function marked as |
| 479 // "patch" and it must have the same signature as the function it patches. | 466 // "patch" and it must have the same signature as the function it patches. |
| 480 if (!isPatchElement(patchElement)) { | 467 if (!isPatchElement(patchElement)) { |
| 481 internalError("Cannot overwrite existing '" | 468 internalError("Cannot overwrite existing '" |
| 482 "${originalElement.name.slowToString()}' with non-patch."); | 469 "${originalElement.name.slowToString()}' with non-patch."); |
| 483 } | 470 } |
| 484 if (originalElement is PartialClassElement) { | |
| 485 // Only happens when patching a library. Dart does not, yet, have nested | |
| 486 // classes. | |
| 487 if (patchElement is! PartialClassElement) { | |
| 488 internalError("Trying to patch class with non-class", | |
| 489 element:originalElement); | |
| 490 } | |
| 491 applyClassPatch(originalElement, patchElement); | |
| 492 return; | |
| 493 } | |
| 494 if (originalElement is! FunctionElement) { | 471 if (originalElement is! FunctionElement) { |
| 495 // TODO(lrn): Handle class declarations too. | 472 // TODO(lrn): Handle class declarations too. |
| 496 internalError("Can only patch functions", element: originalElement); | 473 internalError("Can only patch functions", element: originalElement); |
| 497 } | 474 } |
| 498 FunctionElement original = originalElement; | 475 FunctionElement original = originalElement; |
| 499 if (!original.modifiers.isExternal()) { | 476 if (!original.modifiers.isExternal()) { |
| 500 internalError("Can only patch external functions.", element: original); | 477 internalError("Can only patch external functions.", element: original); |
| 501 } | 478 } |
| 502 if (patchElement is! FunctionElement || | 479 if (patchElement is! FunctionElement || |
| 503 !patchSignatureMatches(original, patchElement)) { | 480 !patchSignatureMatches(original, patchElement)) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 520 element: element); | 497 element: element); |
| 521 } | 498 } |
| 522 if (element.cachedNode !== null) { | 499 if (element.cachedNode !== null) { |
| 523 internalError("Trying to patch an already compiled function.", | 500 internalError("Trying to patch an already compiled function.", |
| 524 element: element); | 501 element: element); |
| 525 } | 502 } |
| 526 // Don't just assign the patch field. This also updates the cachedNode. | 503 // Don't just assign the patch field. This also updates the cachedNode. |
| 527 element.setPatch(patchElement); | 504 element.setPatch(patchElement); |
| 528 } | 505 } |
| 529 | 506 |
| 530 void applyClassPatch(PartialClassElement original, | |
| 531 PartialClassElement patch) { | |
| 532 // Eagerly parse the class so we can patch it. | |
| 533 // TODO(lrn): Perhaps find a way to delay parsing until the class is needed, | |
| 534 // i.e., until [parseNode] is called on [original]. | |
| 535 ClassNode node = original.parseNode(this); | |
| 536 // Parse patch class with "patch" parser. | |
| 537 ClassNode patchNode = patchParser.parsePatchClassNode(patch); | |
| 538 Link<Element> patches = patch.localMembers; | |
| 539 applyContainerPatch(original, patches); | |
| 540 } | |
| 541 | |
| 542 /** | 507 /** |
| 543 * Get an [Uri] pointing to a patch for the dart: library with | 508 * Get an [Uri] pointing to a patch for the dart: library with |
| 544 * the given path. Returns null if there is no patch. | 509 * the given path. Returns null if there is no patch. |
| 545 */ | 510 */ |
| 546 abstract Uri resolvePatchUri(String dartLibraryPath); | 511 abstract Uri resolvePatchUri(String dartLibraryPath); |
| 547 | 512 |
| 548 /** Define the JS helper functions in the given library. */ | 513 /** Define the JS helper functions in the given library. */ |
| 549 void addForeignFunctions(LibraryElement library) { | 514 void addForeignFunctions(LibraryElement library) { |
| 550 library.addToScope(new ForeignElement( | 515 library.addToScope(new ForeignElement( |
| 551 const SourceString('JS'), library), this); | 516 const SourceString('JS'), library), this); |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 final endOffset = end.charOffset + end.slowCharCount; | 900 final endOffset = end.charOffset + end.slowCharCount; |
| 936 | 901 |
| 937 // [begin] and [end] might be the same for the same empty token. This | 902 // [begin] and [end] might be the same for the same empty token. This |
| 938 // happens for instance when scanning '$$'. | 903 // happens for instance when scanning '$$'. |
| 939 assert(endOffset >= beginOffset); | 904 assert(endOffset >= beginOffset); |
| 940 return f(beginOffset, endOffset); | 905 return f(beginOffset, endOffset); |
| 941 } | 906 } |
| 942 | 907 |
| 943 String toString() => 'SourceSpan($uri, $begin, $end)'; | 908 String toString() => 'SourceSpan($uri, $begin, $end)'; |
| 944 } | 909 } |
| OLD | NEW |