Chromium Code Reviews| 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 _processImports(fileInfo); | 156 _processImports(fileInfo); |
| 157 | 157 |
| 158 // Load component files referenced by [file]. | 158 // Load component files referenced by [file]. |
| 159 for (var href in fileInfo.componentLinks) { | 159 for (var href in fileInfo.componentLinks) { |
| 160 if (!_processed.contains(href)) { | 160 if (!_processed.contains(href)) { |
| 161 _processed.add(href); | 161 _processed.add(href); |
| 162 _tasks.add(_parseHtmlFile(href).then(_processHtmlFile)); | 162 _tasks.add(_parseHtmlFile(href).then(_processHtmlFile)); |
| 163 } | 163 } |
| 164 } | 164 } |
| 165 | 165 |
| 166 // Load stylesheet files referenced by [file]. | |
| 167 for (var href in fileInfo.styleSheetHref) { | |
| 168 if (!_processed.contains(href)) { | |
| 169 _processed.add(href); | |
| 170 _tasks.add(_parseStyleSheetFile(href).then(_processStyleSheetFile)); | |
| 171 } | |
| 172 } | |
| 173 | |
| 166 // Load .dart files being referenced in the page. | 174 // Load .dart files being referenced in the page. |
| 167 var src = fileInfo.externalFile; | 175 var src = fileInfo.externalFile; |
| 168 if (src != null && !_processed.contains(src)) { | 176 if (src != null && !_processed.contains(src)) { |
| 169 _processed.add(src); | 177 _processed.add(src); |
| 170 _tasks.add(_parseDartFile(src).then(_processDartFile)); | 178 _tasks.add(_parseDartFile(src).then(_processDartFile)); |
| 171 } | 179 } |
| 172 | 180 |
| 173 // Load .dart files being referenced in components. | 181 // Load .dart files being referenced in components. |
| 174 for (var component in fileInfo.declaredComponents) { | 182 for (var component in fileInfo.declaredComponents) { |
| 175 var src = component.externalFile; | 183 var src = component.externalFile; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 189 file.document = _time('Parsed', path, | 197 file.document = _time('Parsed', path, |
| 190 () => parseHtml(source, path, _messages)); | 198 () => parseHtml(source, path, _messages)); |
| 191 return file; | 199 return file; |
| 192 }) | 200 }) |
| 193 .catchError((e) => _readError(e, path)); | 201 .catchError((e) => _readError(e, path)); |
| 194 } | 202 } |
| 195 | 203 |
| 196 /** Parse [filename] and treat it as a .dart file. */ | 204 /** Parse [filename] and treat it as a .dart file. */ |
| 197 Future<SourceFile> _parseDartFile(Path path) { | 205 Future<SourceFile> _parseDartFile(Path path) { |
| 198 return fileSystem.readText(path) | 206 return fileSystem.readText(path) |
| 199 .then((code) => new SourceFile(path, isDart: true)..code = code) | 207 .then((code) => new SourceFile(path, type: SourceFile.DART) |
| 208 ..code = code) | |
| 200 .catchError((e) => _readError(e, path)); | 209 .catchError((e) => _readError(e, path)); |
| 201 } | 210 } |
| 202 | 211 |
| 203 SourceFile _readError(error, Path path) { | 212 SourceFile _readError(error, Path path) { |
| 204 _messages.error('exception while reading file, original message:\n $error', | 213 _messages.error('exception while reading file, original message:\n $error', |
| 205 null, file: path); | 214 null, file: path); |
| 206 | 215 |
| 207 return null; | 216 return null; |
| 208 } | 217 } |
| 209 | 218 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 230 if (uri.startsWith('package:web_ui/observe')) { | 239 if (uri.startsWith('package:web_ui/observe')) { |
| 231 _useObservers = true; | 240 _useObservers = true; |
| 232 } | 241 } |
| 233 } else if (!_processed.contains(src)) { | 242 } else if (!_processed.contains(src)) { |
| 234 _processed.add(src); | 243 _processed.add(src); |
| 235 _tasks.add(_parseDartFile(src).then(_processDartFile)); | 244 _tasks.add(_parseDartFile(src).then(_processDartFile)); |
| 236 } | 245 } |
| 237 } | 246 } |
| 238 } | 247 } |
| 239 | 248 |
| 249 /** Parse [filename] and treat it as a .dart file. */ | |
| 250 Future<SourceFile> _parseStyleSheetFile(Path path) { | |
| 251 return fileSystem.readText(path) | |
| 252 .then((code) => | |
| 253 new SourceFile(path, type: SourceFile.STYLESHEET) | |
| 254 ..code = code.trim()) | |
|
Siggi Cherem (dart-lang)
2013/03/08 21:57:52
Maybe remove 'trim' here?
You are also trimming t
terry
2013/03/08 22:42:23
I like it _parseCss only.
On 2013/03/08 21:57:52,
| |
| 255 .catchError((e) => _readError(e, path)); | |
| 256 } | |
| 257 | |
| 258 void _processStyleSheetFile(SourceFile cssFile) { | |
| 259 if (!_shouldProcessFile(cssFile)) return; | |
| 260 | |
| 261 files.add(cssFile); | |
| 262 | |
| 263 var fileInfo = new FileInfo(cssFile.path); | |
| 264 info[cssFile.path] = fileInfo; | |
| 265 | |
| 266 var uriVisitor = new UriVisitor(_pathInfo, _mainPath, fileInfo.path); | |
| 267 var styleSheet = _parseCss(cssFile.path.toString(), | |
| 268 cssFile.code, uriVisitor, options); | |
| 269 if (styleSheet != null) { | |
| 270 fileInfo.styleSheets.add(styleSheet); | |
| 271 } | |
| 272 } | |
| 273 | |
| 240 Path _getDirectivePath(LibraryInfo libInfo, Directive directive) { | 274 Path _getDirectivePath(LibraryInfo libInfo, Directive directive) { |
| 241 var uriDirective = (directive as UriBasedDirective).uri; | 275 var uriDirective = (directive as UriBasedDirective).uri; |
| 242 var uri = uriDirective.value; | 276 var uri = uriDirective.value; |
| 243 if (uri.startsWith('dart:')) return null; | 277 if (uri.startsWith('dart:')) return null; |
| 244 | 278 |
| 245 if (uri.startsWith('package:')) { | 279 if (uri.startsWith('package:')) { |
| 246 // Don't process our own package -- we'll implement @observable manually. | 280 // Don't process our own package -- we'll implement @observable manually. |
| 247 if (uri.startsWith('package:web_ui/')) return null; | 281 if (uri.startsWith('package:web_ui/')) return null; |
| 248 | 282 |
| 249 return _pathInfo.packageRoot.join(new Path(uri.substring(8))); | 283 return _pathInfo.packageRoot.join(new Path(uri.substring(8))); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 if (newUri != null) { | 441 if (newUri != null) { |
| 408 directive.uri = createStringLiteral(newUri); | 442 directive.uri = createStringLiteral(newUri); |
| 409 } | 443 } |
| 410 } | 444 } |
| 411 } | 445 } |
| 412 | 446 |
| 413 /** Run the analyzer on every input html file. */ | 447 /** Run the analyzer on every input html file. */ |
| 414 void _analyze() { | 448 void _analyze() { |
| 415 var uniqueIds = new IntIterator(); | 449 var uniqueIds = new IntIterator(); |
| 416 for (var file in files) { | 450 for (var file in files) { |
| 417 if (file.isDart) continue; | 451 var fileInfo = info[file.path]; |
|
Siggi Cherem (dart-lang)
2013/03/08 21:57:52
delete this unused variable
terry
2013/03/08 22:42:23
Done.
| |
| 418 _time('Analyzed contents', file.path, () => | 452 if (file.isHtml) { |
| 419 analyzeFile(file, info, uniqueIds, _messages)); | 453 _time('Analyzed contents', file.path, () => |
| 454 analyzeFile(file, info, uniqueIds, _messages)); | |
| 455 } | |
| 420 } | 456 } |
| 421 } | 457 } |
| 422 | 458 |
| 423 /** Emit the generated code corresponding to each input file. */ | 459 /** Emit the generated code corresponding to each input file. */ |
| 424 void _emit() { | 460 void _emit() { |
| 425 for (var file in files) { | 461 for (var file in files) { |
| 426 if (file.isDart) continue; | 462 if (file.isDart || file.isStyleSheet) continue; |
| 427 _time('Codegen', file.path, () { | 463 _time('Codegen', file.path, () { |
| 428 var fileInfo = info[file.path]; | 464 var fileInfo = info[file.path]; |
| 429 cleanHtmlNodes(fileInfo); | 465 cleanHtmlNodes(fileInfo); |
| 430 _processStylesheet(fileInfo, options: options); | 466 if (!fileInfo.isEntryPoint) { |
|
Siggi Cherem (dart-lang)
2013/03/08 21:57:52
&& options.processCss
terry
2013/03/08 22:42:23
I'm not sure this is right. Don't we want to supp
Siggi Cherem (dart-lang)
2013/03/09 01:32:10
my understanding was that 'processCss' is not just
| |
| 467 // Check all components files for <style> tags and parse the CSS. | |
| 468 var uriVisitor = new UriVisitor(_pathInfo, _mainPath, fileInfo.path); | |
| 469 _processStylesheet(uriVisitor, fileInfo, options: options); | |
| 470 } | |
| 431 fixupHtmlCss(fileInfo, options); | 471 fixupHtmlCss(fileInfo, options); |
| 432 _emitComponents(fileInfo); | 472 _emitComponents(fileInfo); |
| 433 if (fileInfo.isEntryPoint) { | 473 if (fileInfo.isEntryPoint) { |
| 434 _emitMainDart(file); | 474 _emitMainDart(file); |
| 435 _emitMainHtml(file); | 475 _emitMainHtml(file); |
| 436 } | 476 } |
| 437 }); | 477 }); |
| 438 } | 478 } |
| 479 | |
| 480 if (options.processCss) { | |
| 481 _emitAllCss(); | |
| 482 } | |
| 439 } | 483 } |
| 440 | 484 |
| 441 /** Emit the main .dart file. */ | 485 /** Emit the main .dart file. */ |
| 442 void _emitMainDart(SourceFile file) { | 486 void _emitMainDart(SourceFile file) { |
| 443 var fileInfo = info[file.path]; | 487 var fileInfo = info[file.path]; |
| 444 var printer = new MainPageEmitter(fileInfo) | 488 var printer = new MainPageEmitter(fileInfo, options.processCss) |
| 445 .run(file.document, _pathInfo, _edits[fileInfo.userCode], | 489 .run(file.document, _pathInfo, _edits[fileInfo.userCode], |
| 446 options.rewriteUrls); | 490 options.rewriteUrls); |
| 447 _emitFileAndSourceMaps(fileInfo, printer, fileInfo.inputPath); | 491 _emitFileAndSourceMaps(fileInfo, printer, fileInfo.inputPath); |
| 448 } | 492 } |
| 449 | 493 |
| 450 /** Generate an html file with the (trimmed down) main html page. */ | 494 /** Generate an html file with the (trimmed down) main html page. */ |
| 451 void _emitMainHtml(SourceFile file) { | 495 void _emitMainHtml(SourceFile file) { |
| 452 var fileInfo = info[file.path]; | 496 var fileInfo = info[file.path]; |
| 453 | 497 |
| 454 var bootstrapName = '${file.path.filename}_bootstrap.dart'; | 498 var bootstrapName = '${file.path.filename}_bootstrap.dart'; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 486 if (link.attributes["rel"] == "components") { | 530 if (link.attributes["rel"] == "components") { |
| 487 link.remove(); | 531 link.remove(); |
| 488 } | 532 } |
| 489 } | 533 } |
| 490 | 534 |
| 491 _addAutoGeneratedComment(file); | 535 _addAutoGeneratedComment(file); |
| 492 output.add(new OutputFile(_pathInfo.outputPath(file.path, '.html'), | 536 output.add(new OutputFile(_pathInfo.outputPath(file.path, '.html'), |
| 493 document.outerHtml, source: file.path)); | 537 document.outerHtml, source: file.path)); |
| 494 } | 538 } |
| 495 | 539 |
| 540 /** Generate an CSS file for all style sheets (main and components). */ | |
| 541 void _emitAllCss() { | |
| 542 StringBuffer allCssBuff = new StringBuffer(); | |
|
Siggi Cherem (dart-lang)
2013/03/08 21:57:52
style nit: use var
terry
2013/03/08 22:42:23
Done.
| |
| 543 | |
|
Siggi Cherem (dart-lang)
2013/03/08 21:57:52
style nit, delete empty line
terry
2013/03/08 22:42:23
Done.
| |
| 544 var mainFile; | |
| 545 | |
| 546 // Emit all linked style sheet files first. | |
| 547 for (var file in files) { | |
| 548 var fileInfo = info[file.path]; | |
| 549 if (fileInfo.isEntryPoint) mainFile = file; | |
| 550 if (file.isStyleSheet) { | |
| 551 for (var styleSheet in fileInfo.styleSheets) { | |
| 552 allCssBuff.write( | |
| 553 '/* ==================================================== */\n' | |
| 554 '/* Linked style sheet href = ${file.path.filename} */\n' | |
| 555 '/* ==================================================== */\n'); | |
| 556 allCssBuff.write(emitStyleSheet(styleSheet)); | |
| 557 allCssBuff.write('\n\n'); | |
| 558 } | |
| 559 } | |
| 560 } | |
| 561 | |
| 562 // Emit all CSS in each component (style scoped). | |
| 563 for (var file in files) { | |
| 564 var fileInfo = info[file.path]; | |
|
Siggi Cherem (dart-lang)
2013/03/08 21:57:52
move this down inside the next if
terry
2013/03/08 22:42:23
Done.
| |
| 565 if (!file.isStyleSheet) { | |
|
Siggi Cherem (dart-lang)
2013/03/08 21:57:52
!file.isStylesheet => file.isHtml
(skip dart files
terry
2013/03/08 22:42:23
Right should only be isHtml (dart and stylesheets
| |
| 566 for (var component in fileInfo.declaredComponents) { | |
| 567 for (var styleSheet in component.styleSheets) { | |
| 568 allCssBuff.write( | |
| 569 '/* ==================================================== */\n' | |
| 570 '/* Component ${component.tagName} stylesheet */\n' | |
| 571 '/* ==================================================== */\n'); | |
| 572 allCssBuff.write(emitStyleSheet(styleSheet, component.tagName)); | |
| 573 allCssBuff.write('\n\n'); | |
| 574 } | |
| 575 } | |
| 576 } | |
| 577 } | |
| 578 | |
| 579 assert(mainFile != null); | |
| 580 | |
| 581 var allCss = allCssBuff.toString(); | |
| 582 if (!allCss.isEmpty) { | |
| 583 var allCssFile = '${mainFile.path.filename}.css'; | |
| 584 var allCssPath = mainFile.path.directoryPath.append(allCssFile); | |
| 585 var allCssOutPath = _pathInfo.outputPath(allCssPath, ''); | |
| 586 output.add(new OutputFile(allCssOutPath, allCss)); | |
| 587 } | |
| 588 } | |
| 589 | |
| 496 /** Emits the Dart code for all components in [fileInfo]. */ | 590 /** Emits the Dart code for all components in [fileInfo]. */ |
| 497 void _emitComponents(FileInfo fileInfo) { | 591 void _emitComponents(FileInfo fileInfo) { |
| 498 for (var component in fileInfo.declaredComponents) { | 592 for (var component in fileInfo.declaredComponents) { |
| 593 // TODO(terry): Handle one stylesheet per component see fixupHtmlCss. | |
| 594 if (component.styleSheets.length > 1) { | |
|
Siggi Cherem (dart-lang)
2013/03/08 21:57:52
&& options.processCss
terry
2013/03/08 22:42:23
Done.
terry
2013/03/08 22:42:23
Done.
| |
| 595 _messages.warning( | |
| 596 'Component has more than one stylesheet' | |
| 597 ' - first stylesheet used.', null, file: component.externalFile); | |
| 598 } | |
| 499 var printer = new WebComponentEmitter(fileInfo, _messages) | 599 var printer = new WebComponentEmitter(fileInfo, _messages) |
| 500 .run(component, _pathInfo, _edits[component.userCode]); | 600 .run(component, _pathInfo, _edits[component.userCode]); |
| 501 _emitFileAndSourceMaps(component, printer, component.externalFile); | 601 _emitFileAndSourceMaps(component, printer, component.externalFile); |
| 502 } | 602 } |
| 503 } | 603 } |
| 504 | 604 |
| 505 /** | 605 /** |
| 506 * Emits a file that was created using [CodePrinter] and it's corresponding | 606 * Emits a file that was created using [CodePrinter] and it's corresponding |
| 507 * source map file. | 607 * source map file. |
| 508 */ | 608 */ |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 558 'See http://www.w3.org/TR/html5-diff/#doctype', | 658 'See http://www.w3.org/TR/html5-diff/#doctype', |
| 559 doctype.sourceSpan, file: file.path); | 659 doctype.sourceSpan, file: file.path); |
| 560 } | 660 } |
| 561 } | 661 } |
| 562 document.nodes.insertAt(commentIndex, parseFragment( | 662 document.nodes.insertAt(commentIndex, parseFragment( |
| 563 '\n<!-- This file was auto-generated from ${file.path}. -->\n')); | 663 '\n<!-- This file was auto-generated from ${file.path}. -->\n')); |
| 564 } | 664 } |
| 565 } | 665 } |
| 566 | 666 |
| 567 /** Parse all stylesheet for polyfilling assciated with [info]. */ | 667 /** Parse all stylesheet for polyfilling assciated with [info]. */ |
| 568 void _processStylesheet(info, {CompilerOptions options : null}) { | 668 void _processStylesheet(uriVisitor, info, {CompilerOptions options : null}) { |
| 569 new _ProcessCss(options).visit(info); | 669 new _ProcessCss(uriVisitor, options).visit(info); |
| 670 } | |
| 671 | |
| 672 StyleSheet _parseCss(String src, String content, UriVisitor uriVisitor, | |
| 673 CompilerOptions options) { | |
| 674 if (!content.trim().isEmpty) { | |
| 675 // TODO(terry): Add --checked when fully implemented and error handling. | |
| 676 var styleSheet = css.parse(content, options: | |
| 677 [options.warningsAsErrors ? '--warnings_as_errors' : '', 'memory']); | |
| 678 uriVisitor.visitTree(styleSheet); | |
| 679 if (options.debugCss) { | |
| 680 print('\nCSS source: $src'); | |
| 681 print('==========\n'); | |
| 682 print(treeToDebugString(styleSheet)); | |
| 683 } | |
| 684 return styleSheet; | |
| 685 } | |
| 570 } | 686 } |
| 571 | 687 |
| 572 /** Post-analysis of style sheet; parsed ready for emitting with polyfill. */ | 688 /** Post-analysis of style sheet; parsed ready for emitting with polyfill. */ |
| 573 class _ProcessCss extends InfoVisitor { | 689 class _ProcessCss extends InfoVisitor { |
| 690 final UriVisitor uriVisitor; | |
| 574 final CompilerOptions options; | 691 final CompilerOptions options; |
| 692 ComponentInfo component; | |
| 575 | 693 |
| 576 _ProcessCss(this.options); | 694 _ProcessCss(this.uriVisitor, this.options); |
| 577 | |
| 578 // TODO(terry): Add --checked when fully implemented and error handling too. | |
| 579 StyleSheet _parseCss(String cssInput, CompilerOptions option) => | |
| 580 css.parse(cssInput, options: | |
| 581 [option.warningsAsErrors ? '--warnings_as_errors' : '', 'memory']); | |
| 582 | 695 |
| 583 void visitComponentInfo(ComponentInfo info) { | 696 void visitComponentInfo(ComponentInfo info) { |
| 584 if (!info.cssSource.isEmpty) { | 697 var oldComponent = component; |
| 585 info.styleSheet = _parseCss(info.cssSource.toString(), options); | 698 component = info; |
| 586 info.cssSource = null; // Once CSS parsed original not needed. | |
| 587 | 699 |
| 588 if (options.debugCss) { | 700 super.visitComponentInfo(info); |
| 589 print('\nComponent: ${info.tagName}'); | 701 |
| 590 print('==========\n'); | 702 component = oldComponent; |
| 591 print(treeToDebugString(info.styleSheet)); | 703 } |
| 704 | |
| 705 void visitElementInfo(ElementInfo info) { | |
| 706 if (component != null) { | |
| 707 var node = info.node; | |
| 708 if (node.tagName == 'style' && node.attributes.containsKey("scoped")) { | |
| 709 // Get contents of style tag. | |
| 710 var content = node.nodes.single.value.toString(); | |
|
Siggi Cherem (dart-lang)
2013/03/08 21:57:52
do we need a 'toString'? I'm not sure what's the t
terry
2013/03/08 22:42:23
Yep only need .value
On 2013/03/08 21:57:52, Sigg
| |
| 711 var styleSheet = _parseCss(component.tagName, content, uriVisitor, | |
| 712 options); | |
| 713 if (styleSheet != null) { | |
| 714 component.styleSheets.add(styleSheet); | |
| 715 } | |
| 592 } | 716 } |
| 593 } | 717 } |
| 594 | 718 |
| 595 super.visitComponentInfo(info); | 719 super.visitElementInfo(info); |
| 596 } | 720 } |
| 597 } | 721 } |
| OLD | NEW |