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 library mirrors_dart2js; | 5 library mirrors_dart2js; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 import 'dart:uri'; | 9 import 'dart:uri'; |
10 | 10 |
11 import '../../compiler.dart' as diagnostics; | 11 import '../../compiler.dart' as diagnostics; |
12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
13 import '../resolution/resolution.dart' show ResolverTask, ResolverVisitor; | 13 import '../resolution/resolution.dart' show ResolverTask, ResolverVisitor; |
14 import '../apiimpl.dart' as api; | 14 import '../apiimpl.dart' as api; |
15 import '../scanner/scannerlib.dart'; | 15 import '../scanner/scannerlib.dart' hide SourceString; |
16 import '../ssa/ssa.dart'; | 16 import '../ssa/ssa.dart'; |
17 import '../dart2jslib.dart'; | 17 import '../dart2jslib.dart'; |
18 import '../filenames.dart'; | 18 import '../filenames.dart'; |
19 import '../source_file.dart'; | 19 import '../source_file.dart'; |
20 import '../tree/tree.dart'; | 20 import '../tree/tree.dart'; |
21 import '../util/util.dart'; | 21 import '../util/util.dart'; |
22 import '../util/uri_extras.dart'; | 22 import '../util/uri_extras.dart'; |
23 import '../dart2js.dart'; | 23 import '../dart2js.dart'; |
24 import '../util/characters.dart'; | 24 import '../util/characters.dart'; |
25 | 25 |
26 import 'mirrors.dart'; | 26 import 'mirrors.dart'; |
| 27 import 'mirrors_util.dart'; |
27 import 'util.dart'; | 28 import 'util.dart'; |
28 | 29 |
29 //------------------------------------------------------------------------------ | 30 //------------------------------------------------------------------------------ |
30 // Utility types and functions for the dart2js mirror system | 31 // Utility types and functions for the dart2js mirror system |
31 //------------------------------------------------------------------------------ | 32 //------------------------------------------------------------------------------ |
32 | 33 |
33 bool _isPrivate(String name) { | 34 bool _isPrivate(String name) { |
34 return name.startsWith('_'); | 35 return name.startsWith('_'); |
35 } | 36 } |
36 | 37 |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 [Path packageRoot, List<String> opts = const <String>[]]) | 386 [Path packageRoot, List<String> opts = const <String>[]]) |
386 : cwd = getCurrentDirectory(), sourceFiles = <String, SourceFile>{} { | 387 : cwd = getCurrentDirectory(), sourceFiles = <String, SourceFile>{} { |
387 var libraryUri = cwd.resolve(libraryRoot.toString()); | 388 var libraryUri = cwd.resolve(libraryRoot.toString()); |
388 var packageUri; | 389 var packageUri; |
389 if (packageRoot != null) { | 390 if (packageRoot != null) { |
390 packageUri = cwd.resolve(packageRoot.toString()); | 391 packageUri = cwd.resolve(packageRoot.toString()); |
391 } else { | 392 } else { |
392 packageUri = libraryUri; | 393 packageUri = libraryUri; |
393 } | 394 } |
394 _compiler = new api.Compiler(provider, handler, | 395 _compiler = new api.Compiler(provider, handler, |
395 libraryUri, packageUri, <String>[]); | 396 libraryUri, packageUri, opts); |
396 var scriptUri = cwd.resolve(script.toString()); | 397 var scriptUri = cwd.resolve(script.toString()); |
397 // TODO(johnniwinther): Detect file not found | 398 // TODO(johnniwinther): Detect file not found |
398 _compiler.run(scriptUri); | 399 _compiler.run(scriptUri); |
399 } | 400 } |
400 | 401 |
401 Dart2JsCompilation.library(List<Path> libraries, Path libraryRoot, | 402 Dart2JsCompilation.library(List<Path> libraries, Path libraryRoot, |
402 [Path packageRoot, List<String> opts = const <String>[]]) | 403 [Path packageRoot, List<String> opts = const <String>[]]) |
403 : cwd = getCurrentDirectory(), sourceFiles = <String, SourceFile>{} { | 404 : cwd = getCurrentDirectory(), sourceFiles = <String, SourceFile>{} { |
404 var libraryUri = cwd.resolve(libraryRoot.toString()); | 405 var libraryUri = cwd.resolve(libraryRoot.toString()); |
405 var packageUri; | 406 var packageUri; |
406 if (packageRoot != null) { | 407 if (packageRoot != null) { |
407 packageUri = cwd.resolve(packageRoot.toString()); | 408 packageUri = cwd.resolve(packageRoot.toString()); |
408 } else { | 409 } else { |
409 packageUri = libraryUri; | 410 packageUri = libraryUri; |
410 } | 411 } |
411 _compiler = new LibraryCompiler(provider, handler, | 412 _compiler = new LibraryCompiler(provider, handler, |
412 libraryUri, packageUri, <String>[]); | 413 libraryUri, packageUri, opts); |
413 var librariesUri = <Uri>[]; | 414 var librariesUri = <Uri>[]; |
414 for (Path library in libraries) { | 415 for (Path library in libraries) { |
415 librariesUri.add(cwd.resolve(library.toString())); | 416 librariesUri.add(cwd.resolve(library.toString())); |
416 // TODO(johnniwinther): Detect file not found | 417 // TODO(johnniwinther): Detect file not found |
417 } | 418 } |
418 LibraryCompiler libraryCompiler = _compiler; | 419 LibraryCompiler libraryCompiler = _compiler; |
419 libraryCompiler.runList(librariesUri); | 420 libraryCompiler.runList(librariesUri); |
420 } | 421 } |
421 | 422 |
422 MirrorSystem get mirrors => new Dart2JsMirrorSystem(_compiler); | 423 MirrorSystem get mirrors => new Dart2JsMirrorSystem(_compiler); |
(...skipping 12 matching lines...) Expand all Loading... |
435 } | 436 } |
436 | 437 |
437 abstract class Dart2JsDeclarationMirror extends Dart2JsMirror | 438 abstract class Dart2JsDeclarationMirror extends Dart2JsMirror |
438 implements DeclarationMirror { | 439 implements DeclarationMirror { |
439 | 440 |
440 bool get isTopLevel => owner != null && owner is LibraryMirror; | 441 bool get isTopLevel => owner != null && owner is LibraryMirror; |
441 | 442 |
442 bool get isPrivate => _isPrivate(simpleName); | 443 bool get isPrivate => _isPrivate(simpleName); |
443 | 444 |
444 /** | 445 /** |
445 * Returns the first token for the source of this declaration. | 446 * Returns the first token for the source of this declaration, not including |
| 447 * metadata annotations. |
446 */ | 448 */ |
447 Token getBeginToken(); | 449 Token getBeginToken(); |
448 | 450 |
449 /** | 451 /** |
450 * Returns the last token for the source of this declaration. | 452 * Returns the last token for the source of this declaration. |
451 */ | 453 */ |
452 Token getEndToken(); | 454 Token getEndToken(); |
453 | 455 |
454 /** | 456 /** |
455 * Returns the script for the source of this declaration. | 457 * Returns the script for the source of this declaration. |
456 */ | 458 */ |
457 Script getScript(); | 459 Script getScript(); |
458 | |
459 SourceLocation get location { | |
460 Token beginToken = getBeginToken(); | |
461 Script script = getScript(); | |
462 SourceSpan span; | |
463 if (beginToken == null) { | |
464 span = new SourceSpan(script.uri, 0, 0); | |
465 } else { | |
466 Token endToken = getEndToken(); | |
467 span = mirrors.compiler.spanFromTokens(beginToken, endToken, script.uri); | |
468 } | |
469 return new Dart2JsSourceLocation(script, span); | |
470 } | |
471 } | |
472 | |
473 abstract class Dart2JsMemberMirror extends Dart2JsElementMirror | |
474 implements MemberMirror { | |
475 | |
476 Dart2JsMemberMirror(Dart2JsMirrorSystem system, Element element) | |
477 : super(system, element); | |
478 | |
479 bool get isConstructor => false; | |
480 | |
481 bool get isVariable => false; | |
482 | |
483 bool get isMethod => false; | |
484 | |
485 bool get isStatic => false; | |
486 | |
487 bool get isParameter => false; | |
488 } | 460 } |
489 | 461 |
490 abstract class Dart2JsTypeMirror extends Dart2JsDeclarationMirror | 462 abstract class Dart2JsTypeMirror extends Dart2JsDeclarationMirror |
491 implements TypeMirror { | 463 implements TypeMirror { |
492 | |
493 } | 464 } |
494 | 465 |
495 abstract class Dart2JsElementMirror extends Dart2JsDeclarationMirror { | 466 abstract class Dart2JsElementMirror extends Dart2JsDeclarationMirror { |
496 final Dart2JsMirrorSystem mirrors; | 467 final Dart2JsMirrorSystem mirrors; |
497 final Element _element; | 468 final Element _element; |
498 List<InstanceMirror> _metadata; | 469 List<InstanceMirror> _metadata; |
499 | 470 |
500 Dart2JsElementMirror(this.mirrors, this._element) { | 471 Dart2JsElementMirror(this.mirrors, this._element) { |
501 assert (mirrors != null); | 472 assert (mirrors != null); |
502 assert (_element != null); | 473 assert (_element != null); |
503 } | 474 } |
504 | 475 |
505 String get simpleName => _element.name.slowToString(); | 476 String get simpleName => _element.name.slowToString(); |
506 | 477 |
507 String get displayName => simpleName; | 478 String get displayName => simpleName; |
508 | 479 |
509 /** | 480 /** |
510 * Computes the first token for this declaration using the first metadata | 481 * Computes the first token for this declaration using the begin token of the |
511 * annotation, the begin token of the element node or element position as | 482 * element node or element position as indicator. |
512 * indicator. | |
513 */ | 483 */ |
514 Token getBeginToken() { | 484 Token getBeginToken() { |
515 if (!_element.metadata.isEmpty) { | |
516 for (MetadataAnnotation metadata in _element.metadata) { | |
517 if (metadata.beginToken != null) { | |
518 return metadata.beginToken; | |
519 } | |
520 } | |
521 } | |
522 // TODO(johnniwinther): Avoid calling [parseNode]. | 485 // TODO(johnniwinther): Avoid calling [parseNode]. |
523 Node node = _element.parseNode(mirrors.compiler); | 486 Node node = _element.parseNode(mirrors.compiler); |
524 if (node == null) { | 487 if (node == null) { |
525 return _element.position(); | 488 return _element.position(); |
526 } | 489 } |
527 return node.getBeginToken(); | 490 return node.getBeginToken(); |
528 } | 491 } |
529 | 492 |
530 /** | 493 /** |
531 * Computes the last token for this declaration using the end token of the | 494 * Computes the last token for this declaration using the end token of the |
532 * element node or element position as indicator. | 495 * element node or element position as indicator. |
533 */ | 496 */ |
534 Token getEndToken() { | 497 Token getEndToken() { |
535 // TODO(johnniwinther): Avoid calling [parseNode]. | 498 // TODO(johnniwinther): Avoid calling [parseNode]. |
536 Node node = _element.parseNode(mirrors.compiler); | 499 Node node = _element.parseNode(mirrors.compiler); |
537 if (node == null) { | 500 if (node == null) { |
538 return _element.position(); | 501 return _element.position(); |
539 } | 502 } |
540 return node.getEndToken(); | 503 return node.getEndToken(); |
541 } | 504 } |
542 | 505 |
| 506 /** |
| 507 * Returns the first token for the source of this declaration, including |
| 508 * metadata annotations. |
| 509 */ |
| 510 Token getFirstToken() { |
| 511 if (!_element.metadata.isEmpty) { |
| 512 for (MetadataAnnotation metadata in _element.metadata) { |
| 513 if (metadata.beginToken != null) { |
| 514 return metadata.beginToken; |
| 515 } |
| 516 } |
| 517 } |
| 518 return getBeginToken(); |
| 519 } |
| 520 |
543 Script getScript() => _element.getCompilationUnit().script; | 521 Script getScript() => _element.getCompilationUnit().script; |
544 | 522 |
| 523 SourceLocation get location { |
| 524 Token beginToken = getFirstToken(); |
| 525 Script script = getScript(); |
| 526 SourceSpan span; |
| 527 if (beginToken == null) { |
| 528 span = new SourceSpan(script.uri, 0, 0); |
| 529 } else { |
| 530 Token endToken = getEndToken(); |
| 531 span = mirrors.compiler.spanFromTokens(beginToken, endToken, script.uri); |
| 532 } |
| 533 return new Dart2JsSourceLocation(script, span); |
| 534 } |
| 535 |
545 String toString() => _element.toString(); | 536 String toString() => _element.toString(); |
546 | 537 |
547 int get hashCode => qualifiedName.hashCode; | 538 int get hashCode => qualifiedName.hashCode; |
548 | 539 |
| 540 void _appendCommentTokens(Token commentToken) { |
| 541 while (commentToken != null && commentToken.kind == COMMENT_TOKEN) { |
| 542 _metadata.add(new Dart2JsCommentInstanceMirror( |
| 543 mirrors, commentToken.slowToString())); |
| 544 commentToken = commentToken.next; |
| 545 } |
| 546 } |
| 547 |
549 List<InstanceMirror> get metadata { | 548 List<InstanceMirror> get metadata { |
550 if (_metadata == null) { | 549 if (_metadata == null) { |
551 _metadata = <InstanceMirror>[]; | 550 _metadata = <InstanceMirror>[]; |
552 for (MetadataAnnotation metadata in _element.metadata) { | 551 for (MetadataAnnotation metadata in _element.metadata) { |
| 552 _appendCommentTokens(mirrors.compiler.commentMap[metadata.beginToken]); |
553 metadata.ensureResolved(mirrors.compiler); | 553 metadata.ensureResolved(mirrors.compiler); |
554 _metadata.add( | 554 _metadata.add( |
555 _convertConstantToInstanceMirror(mirrors, metadata.value)); | 555 _convertConstantToInstanceMirror(mirrors, metadata.value)); |
556 } | 556 } |
| 557 _appendCommentTokens(mirrors.compiler.commentMap[getBeginToken()]); |
557 } | 558 } |
558 // TODO(johnniwinther): Return an unmodifiable list instead. | 559 // TODO(johnniwinther): Return an unmodifiable list instead. |
559 return new List<InstanceMirror>.from(_metadata); | 560 return new List<InstanceMirror>.from(_metadata); |
560 } | 561 } |
561 } | 562 } |
562 | 563 |
| 564 abstract class Dart2JsMemberMirror extends Dart2JsElementMirror |
| 565 implements MemberMirror { |
| 566 |
| 567 Dart2JsMemberMirror(Dart2JsMirrorSystem system, Element element) |
| 568 : super(system, element); |
| 569 |
| 570 bool get isConstructor => false; |
| 571 |
| 572 bool get isVariable => false; |
| 573 |
| 574 bool get isMethod => false; |
| 575 |
| 576 bool get isStatic => false; |
| 577 |
| 578 bool get isParameter => false; |
| 579 } |
| 580 |
563 //------------------------------------------------------------------------------ | 581 //------------------------------------------------------------------------------ |
564 // Mirror system implementation. | 582 // Mirror system implementation. |
565 //------------------------------------------------------------------------------ | 583 //------------------------------------------------------------------------------ |
566 | 584 |
567 class Dart2JsMirrorSystem implements MirrorSystem { | 585 class Dart2JsMirrorSystem implements MirrorSystem { |
568 final api.Compiler compiler; | 586 final api.Compiler compiler; |
569 Map<String, Dart2JsLibraryMirror> _libraries; | 587 Map<String, Dart2JsLibraryMirror> _libraries; |
570 Map<LibraryElement, Dart2JsLibraryMirror> _libraryMap; | 588 Map<LibraryElement, Dart2JsLibraryMirror> _libraryMap; |
571 | 589 |
572 Dart2JsMirrorSystem(this.compiler) | 590 Dart2JsMirrorSystem(this.compiler) |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 }); | 742 }); |
725 } | 743 } |
726 } | 744 } |
727 | 745 |
728 Map<String, ClassMirror> get classes { | 746 Map<String, ClassMirror> get classes { |
729 _ensureClasses(); | 747 _ensureClasses(); |
730 return new ImmutableMapWrapper<String, ClassMirror>(_classes); | 748 return new ImmutableMapWrapper<String, ClassMirror>(_classes); |
731 } | 749 } |
732 | 750 |
733 /** | 751 /** |
734 * Computes the first token of this library using the first metadata | 752 * Computes the first token of this library using the first library tag as |
735 * annotation or the first library tag as indicator. | 753 * indicator. |
736 */ | 754 */ |
737 Token getBeginToken() { | 755 Token getBeginToken() { |
738 if (!_element.metadata.isEmpty) { | |
739 for (MetadataAnnotation metadata in _element.metadata) { | |
740 if (metadata.beginToken != null) { | |
741 return metadata.beginToken; | |
742 } | |
743 } | |
744 } | |
745 if (_library.libraryTag != null) { | 756 if (_library.libraryTag != null) { |
746 return _library.libraryTag.getBeginToken(); | 757 return _library.libraryTag.getBeginToken(); |
747 } else if (!_library.tags.isEmpty) { | 758 } else if (!_library.tags.isEmpty) { |
748 return _library.tags.reverse().head.getBeginToken(); | 759 return _library.tags.reverse().head.getBeginToken(); |
749 } | 760 } |
750 return null; | 761 return null; |
751 } | 762 } |
752 | 763 |
753 /** | 764 /** |
754 * Computes the first token of this library using the last library tag as | 765 * Computes the first token of this library using the last library tag as |
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1664 | 1675 |
1665 bool get hasReflectee => true; | 1676 bool get hasReflectee => true; |
1666 | 1677 |
1667 get reflectee => null; | 1678 get reflectee => null; |
1668 } | 1679 } |
1669 | 1680 |
1670 class Dart2JsBoolConstantMirror extends Dart2JsConstantMirror { | 1681 class Dart2JsBoolConstantMirror extends Dart2JsConstantMirror { |
1671 Dart2JsBoolConstantMirror(Dart2JsMirrorSystem mirrors, BoolConstant constant) | 1682 Dart2JsBoolConstantMirror(Dart2JsMirrorSystem mirrors, BoolConstant constant) |
1672 : super(mirrors, constant); | 1683 : super(mirrors, constant); |
1673 | 1684 |
| 1685 Dart2JsBoolConstantMirror.fromBool(Dart2JsMirrorSystem mirrors, bool value) |
| 1686 : super(mirrors, value ? new TrueConstant() : new FalseConstant()); |
| 1687 |
1674 BoolConstant get _constant => super._constant; | 1688 BoolConstant get _constant => super._constant; |
1675 | 1689 |
1676 bool get hasReflectee => true; | 1690 bool get hasReflectee => true; |
1677 | 1691 |
1678 get reflectee => _constant is TrueConstant; | 1692 get reflectee => _constant is TrueConstant; |
1679 } | 1693 } |
1680 | 1694 |
1681 class Dart2JsStringConstantMirror extends Dart2JsConstantMirror { | 1695 class Dart2JsStringConstantMirror extends Dart2JsConstantMirror { |
1682 Dart2JsStringConstantMirror(Dart2JsMirrorSystem mirrors, | 1696 Dart2JsStringConstantMirror(Dart2JsMirrorSystem mirrors, |
1683 StringConstant constant) | 1697 StringConstant constant) |
1684 : super(mirrors, constant); | 1698 : super(mirrors, constant); |
1685 | 1699 |
| 1700 Dart2JsStringConstantMirror.fromString(Dart2JsMirrorSystem mirrors, |
| 1701 String text) |
| 1702 : super(mirrors, |
| 1703 new StringConstant(new DartString.literal(text), null)); |
| 1704 |
1686 StringConstant get _constant => super._constant; | 1705 StringConstant get _constant => super._constant; |
1687 | 1706 |
1688 bool get hasReflectee => true; | 1707 bool get hasReflectee => true; |
1689 | 1708 |
1690 get reflectee => _constant.value.slowToString(); | 1709 get reflectee => _constant.value.slowToString(); |
1691 } | 1710 } |
1692 | 1711 |
1693 class Dart2JsNumConstantMirror extends Dart2JsConstantMirror { | 1712 class Dart2JsNumConstantMirror extends Dart2JsConstantMirror { |
1694 Dart2JsNumConstantMirror(Dart2JsMirrorSystem mirrors, | 1713 Dart2JsNumConstantMirror(Dart2JsMirrorSystem mirrors, |
1695 NumConstant constant) | 1714 NumConstant constant) |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1797 | 1816 |
1798 Future<InstanceMirror> getField(String fieldName) { | 1817 Future<InstanceMirror> getField(String fieldName) { |
1799 Constant fieldConstant = _fieldMap[fieldName]; | 1818 Constant fieldConstant = _fieldMap[fieldName]; |
1800 if (fieldConstant != null) { | 1819 if (fieldConstant != null) { |
1801 return new Future<InstanceMirror>.immediate( | 1820 return new Future<InstanceMirror>.immediate( |
1802 _convertConstantToInstanceMirror(mirrors, fieldConstant)); | 1821 _convertConstantToInstanceMirror(mirrors, fieldConstant)); |
1803 } | 1822 } |
1804 return super.getField(fieldName); | 1823 return super.getField(fieldName); |
1805 } | 1824 } |
1806 } | 1825 } |
| 1826 |
| 1827 class Dart2JsCommentInstanceMirror implements CommentInstanceMirror { |
| 1828 final Dart2JsMirrorSystem mirrors; |
| 1829 final String text; |
| 1830 String _trimmedText; |
| 1831 |
| 1832 Dart2JsCommentInstanceMirror(this.mirrors, this.text); |
| 1833 |
| 1834 ClassMirror get type { |
| 1835 return new Dart2JsClassMirror(mirrors, mirrors.compiler.documentClass); |
| 1836 } |
| 1837 |
| 1838 bool get isDocComment => text.startsWith('/**') || text.startsWith('///'); |
| 1839 |
| 1840 String get trimmedText { |
| 1841 if (_trimmedText == null) { |
| 1842 _trimmedText = stripComment(text); |
| 1843 } |
| 1844 return _trimmedText; |
| 1845 } |
| 1846 |
| 1847 bool get hasReflectee => false; |
| 1848 |
| 1849 get reflectee { |
| 1850 // TODO(johnniwinther): Which exception/error should be thrown here? |
| 1851 throw new UnsupportedError('InstanceMirror does not have a reflectee'); |
| 1852 } |
| 1853 |
| 1854 Future<InstanceMirror> getField(String fieldName) { |
| 1855 if (fieldName == 'isDocComment') { |
| 1856 return new Future.immediate( |
| 1857 new Dart2JsBoolConstantMirror.fromBool(mirrors, isDocComment)); |
| 1858 } else if (fieldName == 'text') { |
| 1859 return new Future.immediate( |
| 1860 new Dart2JsStringConstantMirror.fromString(mirrors, text)); |
| 1861 } else if (fieldName == 'trimmedText') { |
| 1862 return new Future.immediate( |
| 1863 new Dart2JsStringConstantMirror.fromString(mirrors, trimmedText)); |
| 1864 } |
| 1865 // TODO(johnniwinther): Which exception/error should be thrown here? |
| 1866 throw new UnsupportedError('InstanceMirror does not have a reflectee'); |
| 1867 } |
| 1868 } |
OLD | NEW |