| 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 * This library contains the infrastructure to parse and integrate patch files. | 6 * This library contains the infrastructure to parse and integrate patch files. |
| 7 * | 7 * |
| 8 * Three types of elements can be patched: [LibraryElement], [ClassElement], | 8 * Three types of elements can be patched: [LibraryElement], [ClassElement], |
| 9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded | 9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded |
| 10 * together with the corresponding origin library. Which libraries that are | 10 * together with the corresponding origin library. Which libraries that are |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 class PatchParserTask extends leg.CompilerTask { | 126 class PatchParserTask extends leg.CompilerTask { |
| 127 PatchParserTask(leg.Compiler compiler): super(compiler); | 127 PatchParserTask(leg.Compiler compiler): super(compiler); |
| 128 final String name = "Patching Parser"; | 128 final String name = "Patching Parser"; |
| 129 | 129 |
| 130 /** | 130 /** |
| 131 * Scans a library patch file, applies the method patches and | 131 * Scans a library patch file, applies the method patches and |
| 132 * injections to the library, and returns a list of class | 132 * injections to the library, and returns a list of class |
| 133 * patches. | 133 * patches. |
| 134 */ | 134 */ |
| 135 Future patchLibrary(leg.LibraryDependencyHandler handler, | 135 Future patchLibrary(leg.LibraryDependencyHandler handler, |
| 136 Uri patchUri, LibraryElement originLibrary) { | 136 Uri patchUri, LibraryElement originLibrary) { |
| 137 return compiler.readScript(patchUri, null).then((leg.Script script) { | 137 return compiler.readScript(originLibrary, patchUri) |
| 138 .then((leg.Script script) { |
| 138 var patchLibrary = new LibraryElementX(script, null, originLibrary); | 139 var patchLibrary = new LibraryElementX(script, null, originLibrary); |
| 139 return compiler.withCurrentElement(patchLibrary, () { | 140 return compiler.withCurrentElement(patchLibrary, () { |
| 140 handler.registerNewLibrary(patchLibrary); | 141 handler.registerNewLibrary(patchLibrary); |
| 141 var imports = new LinkBuilder<tree.LibraryTag>(); | 142 var imports = new LinkBuilder<tree.LibraryTag>(); |
| 142 compiler.withCurrentElement(patchLibrary.entryCompilationUnit, () { | 143 compiler.withCurrentElement(patchLibrary.entryCompilationUnit, () { |
| 143 // This patches the elements of the patch library into [library]. | 144 // This patches the elements of the patch library into [library]. |
| 144 // Injected elements are added directly under the compilation unit. | 145 // Injected elements are added directly under the compilation unit. |
| 145 // Patch elements are stored on the patched functions or classes. | 146 // Patch elements are stored on the patched functions or classes. |
| 146 scanLibraryElements(patchLibrary.entryCompilationUnit, imports); | 147 scanLibraryElements(patchLibrary.entryCompilationUnit, imports); |
| 147 }); | 148 }); |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 patch, leg.MessageKind.PATCH_POINT_TO_CLASS, {'className': patch.name}); | 434 patch, leg.MessageKind.PATCH_POINT_TO_CLASS, {'className': patch.name}); |
| 434 return; | 435 return; |
| 435 } | 436 } |
| 436 patchClass(listener, origin, patch); | 437 patchClass(listener, origin, patch); |
| 437 } | 438 } |
| 438 | 439 |
| 439 void patchClass(leg.DiagnosticListener listener, | 440 void patchClass(leg.DiagnosticListener listener, |
| 440 ClassElement origin, | 441 ClassElement origin, |
| 441 ClassElement patch) { | 442 ClassElement patch) { |
| 442 if (origin.isPatched) { | 443 if (origin.isPatched) { |
| 443 listener.internalErrorOnElement( | 444 listener.internalError(origin, |
| 444 origin, "Patching the same class more than once."); | 445 "Patching the same class more than once."); |
| 445 } | 446 } |
| 446 // TODO(johnniwinther): Change to functions on the ElementX class. | 447 // TODO(johnniwinther): Change to functions on the ElementX class. |
| 447 origin.patch = patch; | 448 origin.patch = patch; |
| 448 patch.origin = origin; | 449 patch.origin = origin; |
| 449 } | 450 } |
| 450 | 451 |
| 451 void tryPatchGetter(leg.DiagnosticListener listener, | 452 void tryPatchGetter(leg.DiagnosticListener listener, |
| 452 Element origin, | 453 Element origin, |
| 453 FunctionElement patch) { | 454 FunctionElement patch) { |
| 454 if (!origin.isAbstractField()) { | 455 if (!origin.isAbstractField()) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 FunctionElement origin, | 530 FunctionElement origin, |
| 530 FunctionElement patch) { | 531 FunctionElement patch) { |
| 531 if (!origin.modifiers.isExternal()) { | 532 if (!origin.modifiers.isExternal()) { |
| 532 listener.reportError(origin, leg.MessageKind.PATCH_NON_EXTERNAL); | 533 listener.reportError(origin, leg.MessageKind.PATCH_NON_EXTERNAL); |
| 533 listener.reportInfo( | 534 listener.reportInfo( |
| 534 patch, | 535 patch, |
| 535 leg.MessageKind.PATCH_POINT_TO_FUNCTION, {'functionName': patch.name}); | 536 leg.MessageKind.PATCH_POINT_TO_FUNCTION, {'functionName': patch.name}); |
| 536 return; | 537 return; |
| 537 } | 538 } |
| 538 if (origin.isPatched) { | 539 if (origin.isPatched) { |
| 539 listener.internalErrorOnElement(origin, | 540 listener.internalError(origin, |
| 540 "Trying to patch a function more than once."); | 541 "Trying to patch a function more than once."); |
| 541 } | 542 } |
| 542 if (origin.cachedNode != null) { | 543 if (origin.cachedNode != null) { |
| 543 listener.internalErrorOnElement(origin, | 544 listener.internalError(origin, |
| 544 "Trying to patch an already compiled function."); | 545 "Trying to patch an already compiled function."); |
| 545 } | 546 } |
| 546 // Don't just assign the patch field. This also updates the cachedNode. | 547 // Don't just assign the patch field. This also updates the cachedNode. |
| 547 // TODO(johnniwinther): Change to functions on the ElementX class. | 548 // TODO(johnniwinther): Change to functions on the ElementX class. |
| 548 origin.setPatch(patch); | 549 origin.setPatch(patch); |
| 549 patch.origin = origin; | 550 patch.origin = origin; |
| 550 } | 551 } |
| 551 | 552 |
| 552 // TODO(johnniwinther): Add unittest when patch is (real) metadata. | 553 // TODO(johnniwinther): Add unittest when patch is (real) metadata. |
| 553 bool isPatchElement(Element element) { | 554 bool isPatchElement(Element element) { |
| 554 // TODO(lrn): More checks needed if we introduce metadata for real. | 555 // TODO(lrn): More checks needed if we introduce metadata for real. |
| 555 // In that case, it must have the identifier "native" as metadata. | 556 // In that case, it must have the identifier "native" as metadata. |
| 556 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { | 557 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { |
| 557 if (link.head is PatchMetadataAnnotation) return true; | 558 if (link.head is PatchMetadataAnnotation) return true; |
| 558 } | 559 } |
| 559 return false; | 560 return false; |
| 560 } | 561 } |
| OLD | NEW |