| 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 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 | 343 |
| 344 void patchClass(Compiler compiler, | 344 void patchClass(Compiler compiler, |
| 345 ClassElementX origin, | 345 ClassElementX origin, |
| 346 ClassElementX patch) { | 346 ClassElementX patch) { |
| 347 if (origin.isPatched) { | 347 if (origin.isPatched) { |
| 348 compiler.internalError(origin, | 348 compiler.internalError(origin, |
| 349 "Patching the same class more than once."); | 349 "Patching the same class more than once."); |
| 350 } | 350 } |
| 351 origin.applyPatch(patch); | 351 origin.applyPatch(patch); |
| 352 checkNativeAnnotation(compiler, patch); | 352 checkNativeAnnotation(compiler, patch); |
| 353 checkJsInteropAnnotation(compiler, patch); |
| 353 } | 354 } |
| 354 | 355 |
| 355 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its | 356 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its |
| 356 /// native name from the annotation. | 357 /// native name from the annotation. |
| 357 checkNativeAnnotation(Compiler compiler, ClassElement cls) { | 358 checkNativeAnnotation(Compiler compiler, ClassElement cls) { |
| 358 EagerAnnotationHandler.checkAnnotation(compiler, cls, | 359 EagerAnnotationHandler.checkAnnotation(compiler, cls, |
| 359 const NativeAnnotationHandler()); | 360 const NativeAnnotationHandler()); |
| 360 } | 361 } |
| 361 | 362 |
| 363 checkJsInteropAnnotation(Compiler compiler, ClassElement cls) { |
| 364 EagerAnnotationHandler.checkAnnotation(compiler, cls, |
| 365 const JsInteropAnnotationHandler()); |
| 366 } |
| 367 |
| 368 |
| 362 /// Abstract interface for pre-resolution detection of metadata. | 369 /// Abstract interface for pre-resolution detection of metadata. |
| 363 /// | 370 /// |
| 364 /// The detection is handled in two steps: | 371 /// The detection is handled in two steps: |
| 365 /// - match the annotation syntactically and assume that the annotation is valid | 372 /// - match the annotation syntactically and assume that the annotation is valid |
| 366 /// if it looks correct, | 373 /// if it looks correct, |
| 367 /// - setup a deferred action to check that the annotation has a valid constant | 374 /// - setup a deferred action to check that the annotation has a valid constant |
| 368 /// value and report an internal error if not. | 375 /// value and report an internal error if not. |
| 369 abstract class EagerAnnotationHandler<T> { | 376 abstract class EagerAnnotationHandler<T> { |
| 370 /// Checks that [annotation] looks like a matching annotation and optionally | 377 /// Checks that [annotation] looks like a matching annotation and optionally |
| 371 /// applies actions on [element]. Returns a non-null annotation marker if the | 378 /// applies actions on [element]. Returns a non-null annotation marker if the |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 Element element, | 449 Element element, |
| 443 MetadataAnnotation annotation, | 450 MetadataAnnotation annotation, |
| 444 ConstantValue constant) { | 451 ConstantValue constant) { |
| 445 if (constant.getType(compiler.coreTypes).element != | 452 if (constant.getType(compiler.coreTypes).element != |
| 446 compiler.nativeAnnotationClass) { | 453 compiler.nativeAnnotationClass) { |
| 447 compiler.internalError(annotation, 'Invalid @Native(...) annotation.'); | 454 compiler.internalError(annotation, 'Invalid @Native(...) annotation.'); |
| 448 } | 455 } |
| 449 } | 456 } |
| 450 } | 457 } |
| 451 | 458 |
| 459 /// Annotation handler for pre-resolution detection of `@JsName(...)` |
| 460 /// annotations. |
| 461 class JsInteropAnnotationHandler implements EagerAnnotationHandler<String> { |
| 462 const JsInteropAnnotationHandler(); |
| 463 |
| 464 String getJsNameAnnotation(MetadataAnnotation annotation) { |
| 465 if (annotation.beginToken != null && |
| 466 annotation.beginToken.next.value == 'JsName') { |
| 467 // Skipping '@', 'JsName', and '('. |
| 468 Token argument = annotation.beginToken.next.next.next; |
| 469 return (argument is StringToken) ? argument.value : ''; |
| 470 } |
| 471 |
| 472 return null; |
| 473 } |
| 474 |
| 475 String apply(Compiler compiler, |
| 476 Element element, |
| 477 MetadataAnnotation annotation) { |
| 478 if (element.isClass) { |
| 479 String jsName = getJsNameAnnotation(annotation); |
| 480 if (jsName != null) { |
| 481 ClassElementX declaration = element.declaration; |
| 482 // We do not track the class names for JsName annotations as we are not |
| 483 // concerned about checked mode errors these classes. |
| 484 declaration.isJsInterop = true; |
| 485 return jsName; |
| 486 } |
| 487 } |
| 488 return null; |
| 489 } |
| 490 |
| 491 @override |
| 492 void validate(Compiler compiler, |
| 493 Element element, |
| 494 MetadataAnnotation annotation, |
| 495 ConstantValue constant) { |
| 496 } |
| 497 } |
| 498 |
| 452 /// Annotation handler for pre-resolution detection of `@patch` annotations. | 499 /// Annotation handler for pre-resolution detection of `@patch` annotations. |
| 453 class PatchAnnotationHandler implements EagerAnnotationHandler<PatchVersion> { | 500 class PatchAnnotationHandler implements EagerAnnotationHandler<PatchVersion> { |
| 454 const PatchAnnotationHandler(); | 501 const PatchAnnotationHandler(); |
| 455 | 502 |
| 456 PatchVersion getPatchVersion(MetadataAnnotation annotation) { | 503 PatchVersion getPatchVersion(MetadataAnnotation annotation) { |
| 457 if (annotation.beginToken != null) { | 504 if (annotation.beginToken != null) { |
| 458 if (annotation.beginToken.next.value == 'patch') { | 505 if (annotation.beginToken.next.value == 'patch') { |
| 459 return const PatchVersion(null); | 506 return const PatchVersion(null); |
| 460 } else if (annotation.beginToken.next.value == 'patch_full') { | 507 } else if (annotation.beginToken.next.value == 'patch_full') { |
| 461 return const PatchVersion('full'); | 508 return const PatchVersion('full'); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 | 638 |
| 592 class PatchVersion { | 639 class PatchVersion { |
| 593 final String tag; | 640 final String tag; |
| 594 | 641 |
| 595 const PatchVersion(this.tag); | 642 const PatchVersion(this.tag); |
| 596 | 643 |
| 597 bool isActive(String patchTag) => tag == null || tag == patchTag; | 644 bool isActive(String patchTag) => tag == null || tag == patchTag; |
| 598 | 645 |
| 599 String toString() => 'PatchVersion($tag)'; | 646 String toString() => 'PatchVersion($tag)'; |
| 600 } | 647 } |
| OLD | NEW |