| 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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 | 116 |
| 117 import 'dart:async'; | 117 import 'dart:async'; |
| 118 | 118 |
| 119 import "tree/tree.dart" as tree; | 119 import "tree/tree.dart" as tree; |
| 120 import "dart2jslib.dart" as leg; // CompilerTask, Compiler. | 120 import "dart2jslib.dart" as leg; // CompilerTask, Compiler. |
| 121 import "scanner/scannerlib.dart"; // Scanner, Parsers, Listeners | 121 import "scanner/scannerlib.dart"; // Scanner, Parsers, Listeners |
| 122 import "elements/elements.dart"; | 122 import "elements/elements.dart"; |
| 123 import "elements/modelx.dart" | 123 import "elements/modelx.dart" |
| 124 show LibraryElementX, | 124 show LibraryElementX, |
| 125 MetadataAnnotationX, | 125 MetadataAnnotationX, |
| 126 ClassElementX, |
| 126 FunctionElementX; | 127 FunctionElementX; |
| 127 import 'util/util.dart'; | 128 import 'util/util.dart'; |
| 128 | 129 |
| 129 class PatchParserTask extends leg.CompilerTask { | 130 class PatchParserTask extends leg.CompilerTask { |
| 130 PatchParserTask(leg.Compiler compiler): super(compiler); | 131 PatchParserTask(leg.Compiler compiler): super(compiler); |
| 131 final String name = "Patching Parser"; | 132 final String name = "Patching Parser"; |
| 132 | 133 |
| 133 /** | 134 /** |
| 134 * Scans a library patch file, applies the method patches and | 135 * Scans a library patch file, applies the method patches and |
| 135 * injections to the library, and returns a list of class | 136 * injections to the library, and returns a list of class |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 listener.reportError( | 435 listener.reportError( |
| 435 origin, leg.MessageKind.PATCH_NON_CLASS, {'className': patch.name}); | 436 origin, leg.MessageKind.PATCH_NON_CLASS, {'className': patch.name}); |
| 436 listener.reportInfo( | 437 listener.reportInfo( |
| 437 patch, leg.MessageKind.PATCH_POINT_TO_CLASS, {'className': patch.name}); | 438 patch, leg.MessageKind.PATCH_POINT_TO_CLASS, {'className': patch.name}); |
| 438 return; | 439 return; |
| 439 } | 440 } |
| 440 patchClass(listener, origin, patch); | 441 patchClass(listener, origin, patch); |
| 441 } | 442 } |
| 442 | 443 |
| 443 void patchClass(leg.DiagnosticListener listener, | 444 void patchClass(leg.DiagnosticListener listener, |
| 444 ClassElement origin, | 445 ClassElementX origin, |
| 445 ClassElement patch) { | 446 ClassElementX patch) { |
| 446 if (origin.isPatched) { | 447 if (origin.isPatched) { |
| 447 listener.internalError(origin, | 448 listener.internalError(origin, |
| 448 "Patching the same class more than once."); | 449 "Patching the same class more than once."); |
| 449 } | 450 } |
| 450 // TODO(johnniwinther): Change to functions on the ElementX class. | 451 origin.applyPatch(patch); |
| 451 origin.patch = patch; | |
| 452 patch.origin = origin; | |
| 453 } | 452 } |
| 454 | 453 |
| 455 void tryPatchGetter(leg.DiagnosticListener listener, | 454 void tryPatchGetter(leg.DiagnosticListener listener, |
| 456 Element origin, | 455 Element origin, |
| 457 FunctionElement patch) { | 456 FunctionElement patch) { |
| 458 if (!origin.isAbstractField()) { | 457 if (!origin.isAbstractField()) { |
| 459 listener.reportError( | 458 listener.reportError( |
| 460 origin, leg.MessageKind.PATCH_NON_GETTER, {'name': origin.name}); | 459 origin, leg.MessageKind.PATCH_NON_GETTER, {'name': origin.name}); |
| 461 listener.reportInfo( | 460 listener.reportInfo( |
| 462 patch, | 461 patch, |
| 463 leg.MessageKind.PATCH_POINT_TO_GETTER, {'getterName': patch.name}); | 462 leg.MessageKind.PATCH_POINT_TO_GETTER, {'getterName': patch.name}); |
| 464 return; | 463 return; |
| 465 } | 464 } |
| 466 AbstractFieldElement originField = origin; | 465 AbstractFieldElement originField = origin; |
| 467 if (originField.getter == null) { | 466 if (originField.getter == null) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 listener.reportInfo( | 507 listener.reportInfo( |
| 509 patch, | 508 patch, |
| 510 leg.MessageKind.PATCH_POINT_TO_CONSTRUCTOR, | 509 leg.MessageKind.PATCH_POINT_TO_CONSTRUCTOR, |
| 511 {'constructorName': patch.name}); | 510 {'constructorName': patch.name}); |
| 512 return; | 511 return; |
| 513 } | 512 } |
| 514 patchFunction(listener, origin, patch); | 513 patchFunction(listener, origin, patch); |
| 515 } | 514 } |
| 516 | 515 |
| 517 void tryPatchFunction(leg.DiagnosticListener listener, | 516 void tryPatchFunction(leg.DiagnosticListener listener, |
| 518 Element origin, | 517 Element origin, |
| 519 FunctionElement patch) { | 518 FunctionElement patch) { |
| 520 if (!origin.isFunction()) { | 519 if (!origin.isFunction()) { |
| 521 listener.reportError( | 520 listener.reportError( |
| 522 origin, | 521 origin, |
| 523 leg.MessageKind.PATCH_NON_FUNCTION, {'functionName': patch.name}); | 522 leg.MessageKind.PATCH_NON_FUNCTION, {'functionName': patch.name}); |
| 524 listener.reportInfo( | 523 listener.reportInfo( |
| 525 patch, | 524 patch, |
| 526 leg.MessageKind.PATCH_POINT_TO_FUNCTION, {'functionName': patch.name}); | 525 leg.MessageKind.PATCH_POINT_TO_FUNCTION, {'functionName': patch.name}); |
| 527 return; | 526 return; |
| 528 } | 527 } |
| 529 patchFunction(listener, origin, patch); | 528 patchFunction(listener, origin, patch); |
| 530 } | 529 } |
| 531 | 530 |
| 532 void patchFunction(leg.DiagnosticListener listener, | 531 void patchFunction(leg.DiagnosticListener listener, |
| 533 FunctionElementX origin, | 532 FunctionElementX origin, |
| 534 FunctionElementX patch) { | 533 FunctionElementX patch) { |
| 535 if (!origin.modifiers.isExternal()) { | 534 if (!origin.modifiers.isExternal()) { |
| 536 listener.reportError(origin, leg.MessageKind.PATCH_NON_EXTERNAL); | 535 listener.reportError(origin, leg.MessageKind.PATCH_NON_EXTERNAL); |
| 537 listener.reportInfo( | 536 listener.reportInfo( |
| 538 patch, | 537 patch, |
| 539 leg.MessageKind.PATCH_POINT_TO_FUNCTION, {'functionName': patch.name}); | 538 leg.MessageKind.PATCH_POINT_TO_FUNCTION, {'functionName': patch.name}); |
| 540 return; | 539 return; |
| 541 } | 540 } |
| 542 if (origin.isPatched) { | 541 if (origin.isPatched) { |
| 543 listener.internalError(origin, | 542 listener.internalError(origin, |
| 544 "Trying to patch a function more than once."); | 543 "Trying to patch a function more than once."); |
| 545 } | 544 } |
| 546 if (origin.cachedNode != null) { | 545 if (origin.cachedNode != null) { |
| 547 listener.internalError(origin, | 546 listener.internalError(origin, |
| 548 "Trying to patch an already compiled function."); | 547 "Trying to patch an already compiled function."); |
| 549 } | 548 } |
| 550 // Don't just assign the patch field. This also updates the cachedNode. | 549 origin.applyPatch(patch); |
| 551 // TODO(johnniwinther): Change to functions on the ElementX class. | |
| 552 origin.setPatch(patch); | |
| 553 patch.origin = origin; | |
| 554 } | 550 } |
| 555 | 551 |
| 556 // TODO(johnniwinther): Add unittest when patch is (real) metadata. | 552 // TODO(johnniwinther): Add unittest when patch is (real) metadata. |
| 557 bool isPatchElement(Element element) { | 553 bool isPatchElement(Element element) { |
| 558 // TODO(lrn): More checks needed if we introduce metadata for real. | 554 // TODO(lrn): More checks needed if we introduce metadata for real. |
| 559 // In that case, it must have the identifier "native" as metadata. | 555 // In that case, it must have the identifier "native" as metadata. |
| 560 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { | 556 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { |
| 561 if (link.head is PatchMetadataAnnotation) return true; | 557 if (link.head is PatchMetadataAnnotation) return true; |
| 562 } | 558 } |
| 563 return false; | 559 return false; |
| 564 } | 560 } |
| OLD | NEW |