Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(540)

Side by Side Diff: lib/src/compiler.dart

Issue 22962005: Merge pull request #581 from kevmoo/polymer (Closed) Base URL: https://github.com/dart-lang/web-ui.git@polymer
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/src/code_printer.dart ('k') | lib/src/compiler_options.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
10 import 'package:analyzer_experimental/src/generated/ast.dart' show Directive, Ur iBasedDirective; 11 import 'package:analyzer_experimental/src/generated/ast.dart' show Directive, Ur iBasedDirective;
11 import 'package:csslib/visitor.dart' show StyleSheet, treeToDebugString; 12 import 'package:csslib/visitor.dart' show StyleSheet, treeToDebugString;
12 import 'package:html5lib/dom.dart'; 13 import 'package:html5lib/dom.dart';
13 import 'package:html5lib/parser.dart'; 14 import 'package:html5lib/parser.dart';
15 import 'package:observe/transform.dart' show transformObservables;
14 import 'package:source_maps/span.dart' show Span; 16 import 'package:source_maps/span.dart' show Span;
17 import 'package:source_maps/refactor.dart' show TextEditTransaction;
18 import 'package:source_maps/printer.dart';
15 19
16 import 'analyzer.dart'; 20 import 'analyzer.dart';
17 import 'code_printer.dart'; 21 import 'css_analyzer.dart' show analyzeCss, findUrlsImported,
22 findImportsInStyleSheet, parseCss;
23 import 'css_emitters.dart' show rewriteCssUris,
24 emitComponentStyleSheet, emitOriginalCss, emitStyleSheet;
18 import 'dart_parser.dart'; 25 import 'dart_parser.dart';
19 import 'emitters.dart'; 26 import 'emitters.dart';
20 import 'file_system.dart'; 27 import 'file_system.dart';
21 import 'files.dart'; 28 import 'files.dart';
22 import 'html_css_fixup.dart';
23 import 'info.dart'; 29 import 'info.dart';
24 import 'messages.dart'; 30 import 'messages.dart';
25 import 'observable_transform.dart' show transformObservables;
26 import 'compiler_options.dart'; 31 import 'compiler_options.dart';
27 import 'paths.dart'; 32 import 'paths.dart';
28 import 'refactor.dart';
29 import 'utils.dart'; 33 import 'utils.dart';
30 34
31 /** 35 /**
32 * Parses an HTML file [contents] and returns a DOM-like tree. 36 * Parses an HTML file [contents] and returns a DOM-like tree.
33 * Note that [contents] will be a [String] if coming from a browser-based 37 * Note that [contents] will be a [String] if coming from a browser-based
34 * [FileSystem], or it will be a [List<int>] if running on the command line. 38 * [FileSystem], or it will be a [List<int>] if running on the command line.
35 * 39 *
36 * Adds emitted error/warning to [messages], if [messages] is supplied. 40 * Adds emitted error/warning to [messages], if [messages] is supplied.
37 */ 41 */
38 Document parseHtml(contents, String sourcePath, Messages messages) { 42 Document parseHtml(contents, String sourcePath, Messages messages) {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 bool isEntryPoint = _processed.length == 1; 149 bool isEntryPoint = _processed.length == 1;
146 150
147 files.add(file); 151 files.add(file);
148 152
149 var fileInfo = _time('Analyzed definitions', inputUrl.url, () { 153 var fileInfo = _time('Analyzed definitions', inputUrl.url, () {
150 return analyzeDefinitions(global, inputUrl, file.document, 154 return analyzeDefinitions(global, inputUrl, file.document,
151 _pathMapper.packageRoot, _messages, isEntryPoint: isEntryPoint); 155 _pathMapper.packageRoot, _messages, isEntryPoint: isEntryPoint);
152 }); 156 });
153 info[inputUrl.resolvedPath] = fileInfo; 157 info[inputUrl.resolvedPath] = fileInfo;
154 158
155 if (isEntryPoint && options.hasCssReset) { 159 if (isEntryPoint && _resetCssFile != null) {
156 _processed.add(_resetCssFile); 160 _processed.add(_resetCssFile);
157 _tasks.add(_parseCssFile(new UrlInfo(_resetCssFile, _resetCssFile, 161 _tasks.add(_parseCssFile(new UrlInfo(_resetCssFile, _resetCssFile,
158 null))); 162 null)));
159 } 163 }
160 164
161 _setOutputFilenames(fileInfo); 165 _setOutputFilenames(fileInfo);
162 _processImports(fileInfo); 166 _processImports(fileInfo);
163 167
164 // Load component files referenced by [file]. 168 // Load component files referenced by [file].
165 for (var link in fileInfo.componentLinks) { 169 for (var link in fileInfo.componentLinks) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 .then((code) { 269 .then((code) {
266 if (code == null) return; 270 if (code == null) return;
267 var file = new SourceFile(filePath, type: SourceFile.DART); 271 var file = new SourceFile(filePath, type: SourceFile.DART);
268 file.code = code; 272 file.code = code;
269 _processDartFile(inputUrl, file); 273 _processDartFile(inputUrl, file);
270 }); 274 });
271 } 275 }
272 276
273 /** Parse a stylesheet file. */ 277 /** Parse a stylesheet file. */
274 Future _parseCssFile(UrlInfo inputUrl) { 278 Future _parseCssFile(UrlInfo inputUrl) {
275 if (!options.processCss || 279 if (!options.emulateScopedCss ||
276 !_pathMapper.checkInputPath(inputUrl, _messages)) { 280 !_pathMapper.checkInputPath(inputUrl, _messages)) {
277 return new Future<SourceFile>.value(null); 281 return new Future<SourceFile>.value(null);
278 } 282 }
279 var filePath = inputUrl.resolvedPath; 283 var filePath = inputUrl.resolvedPath;
280 return fileSystem.readText(filePath) 284 return fileSystem.readText(filePath)
281 .catchError((e) => _readError(e, inputUrl, isWarning: true)) 285 .catchError((e) => _readError(e, inputUrl, isWarning: true))
282 .then((code) { 286 .then((code) {
283 if (code == null) return; 287 if (code == null) return;
284 var file = new SourceFile(filePath, type: SourceFile.STYLESHEET); 288 var file = new SourceFile(filePath, type: SourceFile.STYLESHEET);
285 file.code = code; 289 file.code = code;
(...skipping 16 matching lines...) Expand all
302 } 306 }
303 307
304 void _processDartFile(UrlInfo inputUrl, SourceFile dartFile) { 308 void _processDartFile(UrlInfo inputUrl, SourceFile dartFile) {
305 if (dartFile == null) return; 309 if (dartFile == null) return;
306 310
307 files.add(dartFile); 311 files.add(dartFile);
308 312
309 var resolvedPath = inputUrl.resolvedPath; 313 var resolvedPath = inputUrl.resolvedPath;
310 var fileInfo = new FileInfo(inputUrl); 314 var fileInfo = new FileInfo(inputUrl);
311 info[resolvedPath] = fileInfo; 315 info[resolvedPath] = fileInfo;
312 fileInfo.inlinedCode = 316 fileInfo.inlinedCode = parseDartCode(resolvedPath, dartFile.code);
313 parseDartCode(resolvedPath, dartFile.code, _messages);
314 fileInfo.outputFilename = 317 fileInfo.outputFilename =
315 _pathMapper.mangle(path.basename(resolvedPath), '.dart', false); 318 _pathMapper.mangle(path.basename(resolvedPath), '.dart', false);
316 319
317 _processImports(fileInfo); 320 _processImports(fileInfo);
318 } 321 }
319 322
320 void _processImports(LibraryInfo library) { 323 void _processImports(LibraryInfo library) {
321 if (library.userCode == null) return; 324 if (library.userCode == null) return;
322 325
323 for (var directive in library.userCode.directives) { 326 for (var directive in library.userCode.directives) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 /** 381 /**
379 * Transform Dart source code. 382 * Transform Dart source code.
380 * Currently, the only transformation is [transformObservables]. 383 * Currently, the only transformation is [transformObservables].
381 * Calls _emitModifiedDartFiles to write the transformed files. 384 * Calls _emitModifiedDartFiles to write the transformed files.
382 */ 385 */
383 void _transformDart() { 386 void _transformDart() {
384 var libraries = _findAllDartLibraries(); 387 var libraries = _findAllDartLibraries();
385 388
386 var transformed = []; 389 var transformed = [];
387 for (var lib in libraries) { 390 for (var lib in libraries) {
388 var transaction = transformObservables(lib.userCode, _messages); 391 var userCode = lib.userCode;
392 var transaction = transformObservables(userCode.compilationUnit,
393 userCode.sourceFile, userCode.code, _messages);
389 if (transaction != null) { 394 if (transaction != null) {
390 _edits[lib.userCode] = transaction; 395 _edits[lib.userCode] = transaction;
391 if (transaction.hasEdits) { 396 if (transaction.hasEdits) {
392 transformed.add(lib); 397 transformed.add(lib);
393 } else if (lib.htmlFile != null) { 398 } else if (lib.htmlFile != null) {
394 // All web components will be transformed too. Track that. 399 // All web components will be transformed too. Track that.
395 transformed.add(lib); 400 transformed.add(lib);
396 } 401 }
397 } 402 }
398 } 403 }
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 } 539 }
535 } 540 }
536 } 541 }
537 542
538 /** Run the analyzer on every input html file. */ 543 /** Run the analyzer on every input html file. */
539 void _analyze() { 544 void _analyze() {
540 var uniqueIds = new IntIterator(); 545 var uniqueIds = new IntIterator();
541 for (var file in files) { 546 for (var file in files) {
542 if (file.isHtml) { 547 if (file.isHtml) {
543 _time('Analyzed contents', file.path, () => 548 _time('Analyzed contents', file.path, () =>
544 analyzeFile(file, info, uniqueIds, global, _messages)); 549 analyzeFile(file, info, uniqueIds, global, _messages,
550 options.emulateScopedCss));
545 } 551 }
546 } 552 }
547 } 553 }
548 554
549 /** Emit the generated code corresponding to each input file. */ 555 /** Emit the generated code corresponding to each input file. */
550 void _emit() { 556 void _emit() {
551 for (var file in files) { 557 for (var file in files) {
552 if (file.isDart || file.isStyleSheet) continue; 558 if (file.isDart || file.isStyleSheet) continue;
553 _time('Codegen', file.path, () { 559 _time('Codegen', file.path, () {
554 var fileInfo = info[file.path]; 560 var fileInfo = info[file.path];
555 fixupHtmlCss(fileInfo, options);
556 _emitComponents(fileInfo); 561 _emitComponents(fileInfo);
557 }); 562 });
558 } 563 }
559 564
560 var entryPoint = files[0]; 565 var entryPoint = files[0];
561 assert(info[entryPoint.path].isEntryPoint); 566 assert(info[entryPoint.path].isEntryPoint);
562 _emitMainDart(entryPoint); 567 _emitMainDart(entryPoint);
563 _emitMainHtml(entryPoint); 568 _emitMainHtml(entryPoint);
564 569
565 assert(_unqiueOutputs()); 570 assert(_unqiueOutputs());
(...skipping 10 matching lines...) Expand all
576 } 581 }
577 return true; 582 return true;
578 } 583 }
579 584
580 /** Emit the main .dart file. */ 585 /** Emit the main .dart file. */
581 void _emitMainDart(SourceFile file) { 586 void _emitMainDart(SourceFile file) {
582 var fileInfo = info[file.path]; 587 var fileInfo = info[file.path];
583 588
584 var codeInfo = fileInfo.userCode; 589 var codeInfo = fileInfo.userCode;
585 if (codeInfo != null) { 590 if (codeInfo != null) {
586 var printer = new CodePrinter(0); 591 var printer = new NestedPrinter(0);
587 if (codeInfo.libraryName == null) { 592 if (codeInfo.libraryName == null) {
588 printer.addLine('library ${fileInfo.libraryName};'); 593 printer.addLine('library ${fileInfo.libraryName};');
589 } 594 }
590 printer.add(codeInfo.code); 595 printer.add(codeInfo.code);
591 _emitFileAndSourceMaps(fileInfo, printer, fileInfo.dartCodeUrl); 596 _emitFileAndSourceMaps(fileInfo, printer, fileInfo.dartCodeUrl);
592 } 597 }
593 } 598 }
594 599
595 // TODO(jmesserly): refactor this out of Compiler. 600 // TODO(jmesserly): refactor this out of Compiler.
596 /** Generate an html file with the (trimmed down) main html page. */ 601 /** Generate an html file with the (trimmed down) main html page. */
(...skipping 23 matching lines...) Expand all
620 document.outerHtml, source: file.path)); 625 document.outerHtml, source: file.path));
621 } 626 }
622 627
623 // TODO(jmesserly): refactor this and other CSS related transforms out of 628 // TODO(jmesserly): refactor this and other CSS related transforms out of
624 // Compiler. 629 // Compiler.
625 /** 630 /**
626 * Generate an CSS file for all style sheets (main and components). 631 * Generate an CSS file for all style sheets (main and components).
627 * Returns true if a file was generated, otherwise false. 632 * Returns true if a file was generated, otherwise false.
628 */ 633 */
629 bool _emitAllCss() { 634 bool _emitAllCss() {
630 if (!options.processCss) return false; 635 if (!options.emulateScopedCss) return false;
631 636
632 var buff = new StringBuffer(); 637 var buff = new StringBuffer();
633 638
634 // Emit all linked style sheet files first. 639 // Emit all linked style sheet files first.
635 for (var file in files) { 640 for (var file in files) {
636 var css = new StringBuffer(); 641 var css = new StringBuffer();
637 var fileInfo = info[file.path]; 642 var fileInfo = info[file.path];
638 if (file.isStyleSheet) { 643 if (file.isStyleSheet) {
639 for (var styleSheet in fileInfo.styleSheets) { 644 for (var styleSheet in fileInfo.styleSheets) {
640 // Translate any URIs in CSS. 645 // Translate any URIs in CSS.
641 var uriVisitor = new UriVisitor(_pathMapper, 646 rewriteCssUris(_pathMapper, fileInfo.inputUrl.resolvedPath,
642 fileInfo.inputUrl.resolvedPath, options.rewriteUrls); 647 options.rewriteUrls, styleSheet);
643 uriVisitor.visitTree(styleSheet);
644
645 if (options.debugCss) {
646 print('\nCSS source: ${fileInfo.inputUrl.resolvedPath}');
647 print('==========\n');
648 print(treeToDebugString(styleSheet));
649 }
650
651 css.write( 648 css.write(
652 '/* Auto-generated from style sheet href = ${file.path} */\n' 649 '/* Auto-generated from style sheet href = ${file.path} */\n'
653 '/* DO NOT EDIT. */\n\n'); 650 '/* DO NOT EDIT. */\n\n');
654 css.write(emitStyleSheet(styleSheet, fileInfo)); 651 css.write(emitStyleSheet(styleSheet, fileInfo));
655 css.write('\n\n'); 652 css.write('\n\n');
656 } 653 }
657 654
658 // Emit the linked style sheet in the output directory. 655 // Emit the linked style sheet in the output directory.
659 if (fileInfo.inputUrl.url != _resetCssFile) { 656 if (fileInfo.inputUrl.url != _resetCssFile) {
660 var outCss = _pathMapper.outputPath(fileInfo.inputUrl.resolvedPath, 657 var outCss = _pathMapper.outputPath(fileInfo.inputUrl.resolvedPath,
661 ''); 658 '');
662 output.add(new OutputFile(outCss, css.toString())); 659 output.add(new OutputFile(outCss, css.toString()));
663 } 660 }
664 } 661 }
665 } 662 }
666 663
667 // Emit all CSS for each component (style scoped). 664 // Emit all CSS for each component (style scoped).
668 for (var file in files) { 665 for (var file in files) {
669 if (file.isHtml) { 666 if (file.isHtml) {
670 var fileInfo = info[file.path]; 667 var fileInfo = info[file.path];
671 for (var component in fileInfo.declaredComponents) { 668 for (var component in fileInfo.declaredComponents) {
672 for (var styleSheet in component.styleSheets) { 669 for (var styleSheet in component.styleSheets) {
673
674 // Translate any URIs in CSS. 670 // Translate any URIs in CSS.
675 var uriVisitor = new UriVisitor(_pathMapper, 671 rewriteCssUris(_pathMapper, fileInfo.inputUrl.resolvedPath,
676 fileInfo.inputUrl.resolvedPath, options.rewriteUrls); 672 options.rewriteUrls, styleSheet);
677 uriVisitor.visitTree(styleSheet);
678 673
679 if (buff.isEmpty) { 674 if (buff.isEmpty) {
680 buff.write( 675 buff.write(
681 '/* Auto-generated from components style tags. */\n' 676 '/* Auto-generated from components style tags. */\n'
682 '/* DO NOT EDIT. */\n\n'); 677 '/* DO NOT EDIT. */\n\n');
683 } 678 }
684 buff.write( 679 buff.write(
685 '/* ==================================================== \n' 680 '/* ==================================================== \n'
686 ' Component ${component.tagName} stylesheet \n' 681 ' Component ${component.tagName} stylesheet \n'
687 ' ==================================================== */\n'); 682 ' ==================================================== */\n');
688 683
689 var cssPolyfillKind = CssPolyfillKind.of(options, component);
690 var tagName = component.tagName; 684 var tagName = component.tagName;
691 if (!component.hasAuthorStyles) { 685 if (!component.hasAuthorStyles) {
692 if (_cssResetStyleSheet != null && !options.mangleCss) { 686 if (_cssResetStyleSheet != null) {
693 // If component doesn't have apply-author-styles then we need to 687 // If component doesn't have apply-author-styles then we need to
694 // reset the CSS the styles for the component (if css-reset file 688 // reset the CSS the styles for the component (if css-reset file
695 // option was passed). 689 // option was passed).
696 buff.write('\n/* Start CSS Reset */\n'); 690 buff.write('\n/* Start CSS Reset */\n');
697 buff.write(emitComponentStyleSheet(_cssResetStyleSheet, tagName, 691 var style;
698 cssPolyfillKind)); 692 if (options.emulateScopedCss) {
693 style = emitComponentStyleSheet(_cssResetStyleSheet, tagName);
694 } else {
695 style = emitOriginalCss(_cssResetStyleSheet);
696 }
697 buff.write(style);
699 buff.write('/* End CSS Reset */\n\n'); 698 buff.write('/* End CSS Reset */\n\n');
700 } 699 }
701 } 700 }
702 buff.write(emitComponentStyleSheet(styleSheet, tagName, 701 if (options.emulateScopedCss) {
703 cssPolyfillKind)); 702 buff.write(emitComponentStyleSheet(styleSheet, tagName));
703 } else {
704 buff.write(emitOriginalCss(styleSheet));
705 }
704 buff.write('\n\n'); 706 buff.write('\n\n');
705 } 707 }
706 } 708 }
707 } 709 }
708 } 710 }
709 711
710 if (buff.isEmpty) return false; 712 if (buff.isEmpty) return false;
711 713
712 var cssPath = _pathMapper.outputPath(_mainPath, '.css', true); 714 var cssPath = _pathMapper.outputPath(_mainPath, '.css', true);
713 output.add(new OutputFile(cssPath, buff.toString())); 715 output.add(new OutputFile(cssPath, buff.toString()));
714 return true; 716 return true;
715 } 717 }
716 718
717 /** Emits the Dart code for all components in [fileInfo]. */ 719 /** Emits the Dart code for all components in [fileInfo]. */
718 void _emitComponents(FileInfo fileInfo) { 720 void _emitComponents(FileInfo fileInfo) {
719 for (var component in fileInfo.declaredComponents) { 721 for (var component in fileInfo.declaredComponents) {
720 // TODO(terry): Handle one stylesheet per component see fixupHtmlCss. 722 // TODO(terry): Handle more than one stylesheet per component
721 if (component.styleSheets.length > 1 && options.processCss) { 723 if (component.styleSheets.length > 1 && options.emulateScopedCss) {
722 var span = component.externalFile != null 724 var span = component.externalFile != null
723 ? component.externalFile.sourceSpan : null; 725 ? component.externalFile.sourceSpan : null;
724 _messages.warning( 726 _messages.warning(
725 'Component has more than one stylesheet - first stylesheet used.', 727 'Component has more than one stylesheet - first stylesheet used.',
726 span); 728 span);
727 } 729 }
728 var printer = new WebComponentEmitter(fileInfo, _messages, 730 var printer = emitPolymerElement(
729 CssPolyfillKind.of(options, component)) 731 component, _pathMapper, _edits[component.userCode], options);
730 .run(component, _pathMapper, _edits[component.userCode]);
731 _emitFileAndSourceMaps(component, printer, component.externalFile); 732 _emitFileAndSourceMaps(component, printer, component.externalFile);
732 } 733 }
733 } 734 }
734 735
735 /** 736 /**
736 * Emits a file that was created using [CodePrinter] and it's corresponding 737 * Emits a file that was created using [NestedPrinter] and it's corresponding
737 * source map file. 738 * source map file.
738 */ 739 */
739 void _emitFileAndSourceMaps( 740 void _emitFileAndSourceMaps(
740 LibraryInfo lib, CodePrinter printer, UrlInfo dartCodeUrl) { 741 LibraryInfo lib, NestedPrinter printer, UrlInfo dartCodeUrl) {
741 // Bail if we had an error generating the code for the file. 742 // Bail if we had an error generating the code for the file.
742 if (printer == null) return; 743 if (printer == null) return;
743 744
744 var libPath = _pathMapper.outputLibraryPath(lib); 745 var libPath = _pathMapper.outputLibraryPath(lib);
745 var dir = path.dirname(libPath); 746 var dir = path.dirname(libPath);
746 var filename = path.basename(libPath); 747 var filename = path.basename(libPath);
747 printer.add('\n//# sourceMappingURL=$filename.map'); 748 printer.add('\n//# sourceMappingURL=$filename.map');
748 printer.build(libPath); 749 printer.build(libPath);
749 var sourcePath = dartCodeUrl != null ? dartCodeUrl.resolvedPath : null; 750 var sourcePath = dartCodeUrl != null ? dartCodeUrl.resolvedPath : null;
750 output.add(new OutputFile(libPath, printer.text, source: sourcePath)); 751 output.add(new OutputFile(libPath, printer.text, source: sourcePath));
(...skipping 13 matching lines...) Expand all
764 message.write(logMessage); 765 message.write(logMessage);
765 var filename = path.basename(filePath); 766 var filename = path.basename(filePath);
766 for (int i = (60 - logMessage.length - filename.length); i > 0 ; i--) { 767 for (int i = (60 - logMessage.length - filename.length); i > 0 ; i--) {
767 message.write(' '); 768 message.write(' ');
768 } 769 }
769 message.write(filename); 770 message.write(filename);
770 return time(message.toString(), callback, 771 return time(message.toString(), callback,
771 printTime: options.verbose || printTime); 772 printTime: options.verbose || printTime);
772 } 773 }
773 } 774 }
774
OLDNEW
« no previous file with comments | « lib/src/code_printer.dart ('k') | lib/src/compiler_options.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698