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 compiler; | 5 library compiler; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection' show SplayTreeMap; | 8 import 'dart:collection' show SplayTreeMap; |
9 import 'dart:json' as json; | 9 import 'dart:json' as json; |
10 import 'package:analyzer_experimental/src/generated/ast.dart' show Directive, Ur
iBasedDirective; | 10 import 'package:analyzer_experimental/src/generated/ast.dart' show Directive, Ur
iBasedDirective; |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 } | 547 } |
548 } | 548 } |
549 } | 549 } |
550 | 550 |
551 /** Emit the generated code corresponding to each input file. */ | 551 /** Emit the generated code corresponding to each input file. */ |
552 void _emit() { | 552 void _emit() { |
553 for (var file in files) { | 553 for (var file in files) { |
554 if (file.isDart || file.isStyleSheet) continue; | 554 if (file.isDart || file.isStyleSheet) continue; |
555 _time('Codegen', file.path, () { | 555 _time('Codegen', file.path, () { |
556 var fileInfo = info[file.path]; | 556 var fileInfo = info[file.path]; |
557 fixupHtmlCss(fileInfo, options, getCssPolyfillKind); | 557 fixupHtmlCss(fileInfo, options); |
558 _emitComponents(fileInfo); | 558 _emitComponents(fileInfo); |
559 }); | 559 }); |
560 } | 560 } |
561 | 561 |
562 var entryPoint = files[0]; | 562 var entryPoint = files[0]; |
563 assert(info[entryPoint.path].isEntryPoint); | 563 assert(info[entryPoint.path].isEntryPoint); |
564 _emitMainDart(entryPoint); | 564 _emitMainDart(entryPoint); |
565 _emitMainHtml(entryPoint); | 565 _emitMainHtml(entryPoint); |
566 | 566 |
567 assert(_unqiueOutputs()); | 567 assert(_unqiueOutputs()); |
568 } | 568 } |
569 | 569 |
570 bool _unqiueOutputs() { | 570 bool _unqiueOutputs() { |
571 var seen = new Set(); | 571 var seen = new Set(); |
572 for (var file in output) { | 572 for (var file in output) { |
573 if (seen.contains(file.path)) { | 573 if (seen.contains(file.path)) { |
574 throw new StateError('internal error: ' | 574 throw new StateError('internal error: ' |
575 'duplicate output file ${file.path}. Files were: $output'); | 575 'duplicate output file ${file.path}. Files were: $output'); |
576 } | 576 } |
577 seen.add(file.path); | 577 seen.add(file.path); |
578 } | 578 } |
579 return true; | 579 return true; |
580 } | 580 } |
581 | 581 |
582 /** Emit the main .dart file. */ | 582 /** Emit the main .dart file. */ |
583 void _emitMainDart(SourceFile file) { | 583 void _emitMainDart(SourceFile file) { |
584 var fileInfo = info[file.path]; | 584 var fileInfo = info[file.path]; |
585 var printer = new EntryPointEmitter(fileInfo, global) | 585 |
586 .run(_pathMapper, _edits[fileInfo.userCode], options.rewriteUrls); | 586 var codeInfo = fileInfo.userCode; |
587 _emitFileAndSourceMaps(fileInfo, printer, fileInfo.dartCodeUrl); | 587 if (codeInfo != null) { |
| 588 var printer = new CodePrinter(0); |
| 589 if (codeInfo.libraryName == null) { |
| 590 printer.addLine('library ${fileInfo.libraryName};'); |
| 591 } |
| 592 printer.add(codeInfo.code); |
| 593 _emitFileAndSourceMaps(fileInfo, printer, fileInfo.dartCodeUrl); |
| 594 } |
588 } | 595 } |
589 | 596 |
590 // TODO(jmesserly): refactor this out of Compiler. | 597 // TODO(jmesserly): refactor this out of Compiler. |
591 /** Generate an html file with the (trimmed down) main html page. */ | 598 /** Generate an html file with the (trimmed down) main html page. */ |
592 void _emitMainHtml(SourceFile file) { | 599 void _emitMainHtml(SourceFile file) { |
593 var fileInfo = info[file.path]; | 600 var fileInfo = info[file.path]; |
594 | 601 |
595 var bootstrapName = '${path.basename(file.path)}_bootstrap.dart'; | 602 var bootstrapName = '${path.basename(file.path)}_bootstrap.dart'; |
596 var bootstrapPath = path.join(path.dirname(file.path), bootstrapName); | 603 var bootstrapPath = path.join(path.dirname(file.path), bootstrapName); |
597 var bootstrapOutPath = _pathMapper.outputPath(bootstrapPath, ''); | 604 var bootstrapOutPath = _pathMapper.outputPath(bootstrapPath, ''); |
598 var bootstrapOutName = path.basename(bootstrapOutPath); | 605 var bootstrapOutName = path.basename(bootstrapOutPath); |
599 output.add(new OutputFile(bootstrapOutPath, _bootstrapCode( | 606 var bootstrapInfo = new FileInfo(new UrlInfo('', bootstrapPath, null)); |
600 _pathMapper.importUrlFor(new FileInfo( | 607 var printer = generateBootstrapCode(bootstrapInfo, fileInfo, global, |
601 new UrlInfo('', bootstrapPath, null)), fileInfo)))); | 608 _pathMapper, options); |
| 609 printer.build(bootstrapOutPath); |
| 610 output.add(new OutputFile( |
| 611 bootstrapOutPath, printer.text, source: file.path)); |
602 | 612 |
603 var document = file.document; | 613 var document = file.document; |
604 var hasCss = _emitAllCss(); | 614 var hasCss = _emitAllCss(); |
605 transformMainHtml(document, fileInfo, _pathMapper, hasCss, | 615 transformMainHtml(document, fileInfo, _pathMapper, hasCss, |
606 options.rewriteUrls, _messages); | 616 options.rewriteUrls, _messages, global); |
607 | 617 |
608 document.body.nodes.add(parseFragment( | 618 document.body.nodes.add(parseFragment( |
609 '<script type="application/dart" src="$bootstrapOutName"></script>')); | 619 '<script type="application/dart" src="$bootstrapOutName"></script>')); |
610 | 620 |
611 output.add(new OutputFile(_pathMapper.outputPath(file.path, '.html'), | 621 output.add(new OutputFile(_pathMapper.outputPath(file.path, '.html'), |
612 document.outerHtml, source: file.path)); | 622 document.outerHtml, source: file.path)); |
613 } | 623 } |
614 | 624 |
615 // TODO(jmesserly): refactor this and other CSS related transforms out of | 625 // TODO(jmesserly): refactor this and other CSS related transforms out of |
616 // Compiler. | 626 // Compiler. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 if (buff.isEmpty) { | 681 if (buff.isEmpty) { |
672 buff.write( | 682 buff.write( |
673 '/* Auto-generated from components style tags. */\n' | 683 '/* Auto-generated from components style tags. */\n' |
674 '/* DO NOT EDIT. */\n\n'); | 684 '/* DO NOT EDIT. */\n\n'); |
675 } | 685 } |
676 buff.write( | 686 buff.write( |
677 '/* ==================================================== \n' | 687 '/* ==================================================== \n' |
678 ' Component ${component.tagName} stylesheet \n' | 688 ' Component ${component.tagName} stylesheet \n' |
679 ' ==================================================== */\n'); | 689 ' ==================================================== */\n'); |
680 | 690 |
681 var polyType = getCssPolyfillKind(component); | 691 var cssPolyfillKind = CssPolyfillKind.of(options, component); |
682 var tagName = component.tagName; | 692 var tagName = component.tagName; |
683 if (!component.hasAuthorStyles) { | 693 if (!component.hasAuthorStyles) { |
684 if (_cssResetStyleSheet != null && !options.mangleCss) { | 694 if (_cssResetStyleSheet != null && !options.mangleCss) { |
685 // If component doesn't have apply-author-styles then we need to | 695 // If component doesn't have apply-author-styles then we need to |
686 // reset the CSS the styles for the component (if css-reset file | 696 // reset the CSS the styles for the component (if css-reset file |
687 // option was passed). | 697 // option was passed). |
688 buff.write('\n/* Start CSS Reset */\n'); | 698 buff.write('\n/* Start CSS Reset */\n'); |
689 buff.write(emitComponentStyleSheet(_cssResetStyleSheet, tagName, | 699 buff.write(emitComponentStyleSheet(_cssResetStyleSheet, tagName, |
690 polyType)); | 700 cssPolyfillKind)); |
691 buff.write('/* End CSS Reset */\n\n'); | 701 buff.write('/* End CSS Reset */\n\n'); |
692 } | 702 } |
693 } | 703 } |
694 buff.write(emitComponentStyleSheet(styleSheet, tagName, polyType)); | 704 buff.write(emitComponentStyleSheet(styleSheet, tagName, |
| 705 cssPolyfillKind)); |
695 buff.write('\n\n'); | 706 buff.write('\n\n'); |
696 } | 707 } |
697 } | 708 } |
698 } | 709 } |
699 } | 710 } |
700 | 711 |
701 if (buff.isEmpty) return false; | 712 if (buff.isEmpty) return false; |
702 | 713 |
703 var cssPath = _pathMapper.outputPath(_mainPath, '.css', true); | 714 var cssPath = _pathMapper.outputPath(_mainPath, '.css', true); |
704 output.add(new OutputFile(cssPath, buff.toString())); | 715 output.add(new OutputFile(cssPath, buff.toString())); |
705 return true; | 716 return true; |
706 } | 717 } |
707 | 718 |
708 /** Emits the Dart code for all components in [fileInfo]. */ | 719 /** Emits the Dart code for all components in [fileInfo]. */ |
709 void _emitComponents(FileInfo fileInfo) { | 720 void _emitComponents(FileInfo fileInfo) { |
710 for (var component in fileInfo.declaredComponents) { | 721 for (var component in fileInfo.declaredComponents) { |
711 // TODO(terry): Handle one stylesheet per component see fixupHtmlCss. | 722 // TODO(terry): Handle one stylesheet per component see fixupHtmlCss. |
712 if (component.styleSheets.length > 1 && options.processCss) { | 723 if (component.styleSheets.length > 1 && options.processCss) { |
713 var span = component.externalFile != null | 724 var span = component.externalFile != null |
714 ? component.externalFile.sourceSpan : null; | 725 ? component.externalFile.sourceSpan : null; |
715 _messages.warning( | 726 _messages.warning( |
716 'Component has more than one stylesheet - first stylesheet used.', | 727 'Component has more than one stylesheet - first stylesheet used.', |
717 span); | 728 span); |
718 } | 729 } |
719 var polyType = getCssPolyfillKind(component); | 730 var printer = new WebComponentEmitter(fileInfo, _messages, |
720 var printer = new WebComponentEmitter(fileInfo, _messages, polyType) | 731 CssPolyfillKind.of(options, component)) |
721 .run(component, _pathMapper, _edits[component.userCode]); | 732 .run(component, _pathMapper, _edits[component.userCode]); |
722 _emitFileAndSourceMaps(component, printer, component.externalFile); | 733 _emitFileAndSourceMaps(component, printer, component.externalFile); |
723 } | 734 } |
724 } | 735 } |
725 | 736 |
726 /** Given a component and CompilerOptions compute the CSS polyfill to emit. */ | |
727 CssPolyfillKind getCssPolyfillKind(ComponentInfo component) { | |
728 if (!useCssPolyfill(options, component)) return CssPolyfillKind.NO_POLYFILL; | |
729 | |
730 if (options.mangleCss) return CssPolyfillKind.MANGLED_POLYFILL; | |
731 | |
732 if (!component.hasAuthorStyles && !hasCssReset) | |
733 return CssPolyfillKind.MANGLED_POLYFILL; | |
734 | |
735 return CssPolyfillKind.SCOPED_POLYFILL; | |
736 } | |
737 | |
738 /** | 737 /** |
739 * Emits a file that was created using [CodePrinter] and it's corresponding | 738 * Emits a file that was created using [CodePrinter] and it's corresponding |
740 * source map file. | 739 * source map file. |
741 */ | 740 */ |
742 void _emitFileAndSourceMaps( | 741 void _emitFileAndSourceMaps( |
743 LibraryInfo lib, CodePrinter printer, UrlInfo dartCodeUrl) { | 742 LibraryInfo lib, CodePrinter printer, UrlInfo dartCodeUrl) { |
744 // Bail if we had an error generating the code for the file. | 743 // Bail if we had an error generating the code for the file. |
745 if (printer == null) return; | 744 if (printer == null) return; |
746 | 745 |
747 var libPath = _pathMapper.outputLibraryPath(lib); | 746 var libPath = _pathMapper.outputLibraryPath(lib); |
(...skipping 20 matching lines...) Expand all Loading... |
768 var filename = path.basename(filePath); | 767 var filename = path.basename(filePath); |
769 for (int i = (60 - logMessage.length - filename.length); i > 0 ; i--) { | 768 for (int i = (60 - logMessage.length - filename.length); i > 0 ; i--) { |
770 message.write(' '); | 769 message.write(' '); |
771 } | 770 } |
772 message.write(filename); | 771 message.write(filename); |
773 return time(message.toString(), callback, | 772 return time(message.toString(), callback, |
774 printTime: options.verbose || printTime); | 773 printTime: options.verbose || printTime); |
775 } | 774 } |
776 } | 775 } |
777 | 776 |
778 // TODO(terry): Replace with enum when supported. | |
779 /** Enum for type of polyfills supported. */ | |
780 class CssPolyfillKind { | |
781 final index; | |
782 const CssPolyfillKind(this.index); | |
783 | |
784 /** Emit CSS selectors as seen (no polyfill). */ | |
785 static const NO_POLYFILL = const CssPolyfillKind(0); | |
786 | |
787 /** Emit CSS selectors scoped to the "is" attribute of the component. */ | |
788 static const SCOPED_POLYFILL = const CssPolyfillKind(1); | |
789 | |
790 /** Emit CSS selectors mangled. */ | |
791 static const MANGLED_POLYFILL = const CssPolyfillKind(2); | |
792 } | |
793 | |
794 /** | |
795 * The code that will be used to bootstrap the application, this is inlined in | |
796 * the main.html.html output file. | |
797 */ | |
798 String _bootstrapCode(String userMainImport) => """ | |
799 library bootstrap; | |
800 | |
801 import '$userMainImport' as userMain; | |
802 | |
803 main() { | |
804 userMain.main(); | |
805 userMain.init_autogenerated(); | |
806 } | |
807 """; | |
OLD | NEW |