| 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 |