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 |