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, fileType: 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((linkedCssContent) => | |
253 new SourceFile(path, fileType: SourceFile.STYLESHEET) | |
254 ..linkedCssContent = linkedCssContent.trim()) | |
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.linkedCssContent, 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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 } | 438 } |
405 if (newUri != null) { | 439 if (newUri != null) { |
406 directive.uri = createStringLiteral(newUri); | 440 directive.uri = createStringLiteral(newUri); |
407 } | 441 } |
408 } | 442 } |
409 } | 443 } |
410 | 444 |
411 /** Run the analyzer on every input html file. */ | 445 /** Run the analyzer on every input html file. */ |
412 void _analyze() { | 446 void _analyze() { |
413 var uniqueIds = new IntIterator(); | 447 var uniqueIds = new IntIterator(); |
448 var uriVisitor; | |
414 for (var file in files) { | 449 for (var file in files) { |
415 if (file.isDart) continue; | 450 var fileInfo = info[file.path]; |
416 _time('Analyzed contents', file.path, () => | 451 if (file.isHtml) { |
417 analyzeFile(file, info, uniqueIds, _messages)); | 452 if (fileInfo.isEntryPoint) { |
453 assert(uriVisitor == null); | |
454 uriVisitor = new UriVisitor(_pathInfo, _mainPath, fileInfo.path); | |
455 } | |
456 _time('Analyzed contents', file.path, () => | |
457 analyzeFile(file, info, uniqueIds, _messages)); | |
458 } else if (file.isStyleSheet) { | |
459 // Parse each linked style sheet. | |
460 assert(uriVisitor != null); | |
461 _processStylesheet(uriVisitor, fileInfo, options: options); | |
Siggi Cherem (dart-lang)
2013/03/07 22:14:20
seems like something is broken here? the parameter
terry
2013/03/08 20:11:24
The name in processStylesheet was pathInfo (it's s
| |
462 } | |
418 } | 463 } |
419 } | 464 } |
420 | 465 |
421 /** Emit the generated code corresponding to each input file. */ | 466 /** Emit the generated code corresponding to each input file. */ |
422 void _emit() { | 467 void _emit() { |
423 for (var file in files) { | 468 for (var file in files) { |
424 if (file.isDart) continue; | 469 if (file.isDart) continue; |
425 _time('Codegen', file.path, () { | 470 _time('Codegen', file.path, () { |
426 var fileInfo = info[file.path]; | 471 var fileInfo = info[file.path]; |
427 cleanHtmlNodes(fileInfo); | 472 cleanHtmlNodes(fileInfo); |
428 _processStylesheet(fileInfo, options: options); | 473 var uriVisitor = new UriVisitor(_pathInfo, _mainPath, fileInfo.path); |
474 _processStylesheet(uriVisitor, fileInfo, options: options); | |
Siggi Cherem (dart-lang)
2013/03/07 22:14:20
remove the uri visitor here?
terry
2013/03/08 20:11:24
This is the UriVisitor for each component to handl
| |
429 fixupHtmlCss(fileInfo, options); | 475 fixupHtmlCss(fileInfo, options); |
430 _emitComponents(fileInfo); | 476 _emitComponents(fileInfo); |
431 if (fileInfo.isEntryPoint) { | 477 if (fileInfo.isEntryPoint) { |
432 _emitMainDart(file); | 478 _emitMainDart(file); |
433 _emitMainHtml(file); | 479 _emitMainHtml(file); |
434 } | 480 } |
435 }); | 481 }); |
436 } | 482 } |
483 | |
484 _emitAllCss(); | |
437 } | 485 } |
438 | 486 |
439 /** Emit the main .dart file. */ | 487 /** Emit the main .dart file. */ |
440 void _emitMainDart(SourceFile file) { | 488 void _emitMainDart(SourceFile file) { |
441 var fileInfo = info[file.path]; | 489 var fileInfo = info[file.path]; |
442 var printer = new MainPageEmitter(fileInfo) | 490 var printer = new MainPageEmitter(fileInfo) |
443 .run(file.document, _pathInfo, _edits[fileInfo.userCode], | 491 .run(file.document, _pathInfo, _edits[fileInfo.userCode], |
444 options.rewriteUrls); | 492 options.rewriteUrls); |
445 _emitFileAndSourceMaps(fileInfo, printer, fileInfo.inputPath); | 493 _emitFileAndSourceMaps(fileInfo, printer, fileInfo.inputPath); |
446 } | 494 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
484 if (link.attributes["rel"] == "components") { | 532 if (link.attributes["rel"] == "components") { |
485 link.remove(); | 533 link.remove(); |
486 } | 534 } |
487 } | 535 } |
488 | 536 |
489 _addAutoGeneratedComment(file); | 537 _addAutoGeneratedComment(file); |
490 output.add(new OutputFile(_pathInfo.outputPath(file.path, '.html'), | 538 output.add(new OutputFile(_pathInfo.outputPath(file.path, '.html'), |
491 document.outerHtml, source: file.path)); | 539 document.outerHtml, source: file.path)); |
492 } | 540 } |
493 | 541 |
542 /** Generate an CSS file for all style sheets (main and components). */ | |
543 void _emitAllCss() { | |
544 StringBuffer allCssBuff = new StringBuffer(); | |
545 | |
546 var mainFile; | |
547 | |
548 // Emit all linked style sheet files first. | |
549 for (var file in files) { | |
550 var fileInfo = info[file.path]; | |
551 if (fileInfo.isEntryPoint) mainFile = file; | |
552 if (file.isStyleSheet) { | |
553 for (var styleSheet in fileInfo.styleSheets) { | |
554 allCssBuff.write( | |
555 '/* ==================================================== */\n' | |
556 '/* Linked style sheet href = ${file.path.filename} */\n' | |
557 '/* ==================================================== */\n'); | |
558 allCssBuff.write(emitStyleSheet(styleSheet)); | |
559 allCssBuff.write('\n\n'); | |
560 } | |
561 } | |
562 } | |
563 | |
564 // Emit all CSS in each component (style scoped). | |
565 for (var file in files) { | |
566 var fileInfo = info[file.path]; | |
567 if (!file.isStyleSheet) { | |
568 for (var component in fileInfo.declaredComponents) { | |
569 for (var styleSheet in component.styleSheets) { | |
570 allCssBuff.write( | |
571 '/* ==================================================== */\n' | |
572 '/* Component ${component.tagName} stylesheet */\n' | |
573 '/* ==================================================== */\n'); | |
574 allCssBuff.write(emitStyleSheet(styleSheet, component.tagName)); | |
575 allCssBuff.write('\n\n'); | |
576 } | |
577 } | |
578 } | |
579 } | |
580 | |
581 assert(mainFile != null); | |
582 | |
583 var allCss = allCssBuff.toString(); | |
584 if (!allCss.isEmpty) { | |
585 var allCssFile = '${mainFile.path.filename}.css'; | |
586 var allCssPath = mainFile.path.directoryPath.append(allCssFile); | |
587 var allCssOutPath = _pathInfo.outputPath(allCssPath, ''); | |
588 output.add(new OutputFile(allCssOutPath, allCss)); | |
589 } | |
590 } | |
591 | |
494 /** Emits the Dart code for all components in [fileInfo]. */ | 592 /** Emits the Dart code for all components in [fileInfo]. */ |
495 void _emitComponents(FileInfo fileInfo) { | 593 void _emitComponents(FileInfo fileInfo) { |
496 for (var component in fileInfo.declaredComponents) { | 594 for (var component in fileInfo.declaredComponents) { |
497 var printer = new WebComponentEmitter(fileInfo, _messages) | 595 var printer = new WebComponentEmitter(fileInfo, _messages) |
498 .run(component, _pathInfo, _edits[component.userCode]); | 596 .run(component, _pathInfo, _edits[component.userCode]); |
499 _emitFileAndSourceMaps(component, printer, component.externalFile); | 597 _emitFileAndSourceMaps(component, printer, component.externalFile); |
500 } | 598 } |
501 } | 599 } |
502 | 600 |
503 /** | 601 /** |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
553 'See http://www.w3.org/TR/html5-diff/#doctype', | 651 'See http://www.w3.org/TR/html5-diff/#doctype', |
554 doctype.sourceSpan, file: file.path); | 652 doctype.sourceSpan, file: file.path); |
555 } | 653 } |
556 } | 654 } |
557 document.nodes.insertAt(commentIndex, parseFragment( | 655 document.nodes.insertAt(commentIndex, parseFragment( |
558 '\n<!-- This file was auto-generated from ${file.path}. -->\n')); | 656 '\n<!-- This file was auto-generated from ${file.path}. -->\n')); |
559 } | 657 } |
560 } | 658 } |
561 | 659 |
562 /** Parse all stylesheet for polyfilling assciated with [info]. */ | 660 /** Parse all stylesheet for polyfilling assciated with [info]. */ |
563 void _processStylesheet(info, {CompilerOptions options : null}) { | 661 void _processStylesheet(pathInfo, info, {CompilerOptions options : null}) { |
564 new _ProcessCss(options).visit(info); | 662 new _ProcessCss(pathInfo, options).visit(info); |
663 } | |
664 | |
665 StyleSheet _parseCSS(String src, String content, UriVisitor uriVisitor, | |
Siggi Cherem (dart-lang)
2013/03/07 22:14:20
style nit: change to _parseCss (3 letter acronym c
terry
2013/03/08 20:11:24
Done.
| |
666 CompilerOptions options) { | |
667 if (!content.trim().isEmpty) { | |
668 // TODO(terry): Add --checked when fully implemented and error handling. | |
669 var styleSheet = css.parse(content, options: | |
670 [options.warningsAsErrors ? '--warnings_as_errors' : '', 'memory']); | |
671 uriVisitor.visitTree(styleSheet); | |
672 if (options.debugCss) { | |
673 print('\nCSS source: $src'); | |
674 print('==========\n'); | |
675 print(treeToDebugString(styleSheet)); | |
676 } | |
677 return styleSheet; | |
678 } | |
565 } | 679 } |
566 | 680 |
567 /** Post-analysis of style sheet; parsed ready for emitting with polyfill. */ | 681 /** Post-analysis of style sheet; parsed ready for emitting with polyfill. */ |
568 class _ProcessCss extends InfoVisitor { | 682 class _ProcessCss extends InfoVisitor { |
683 final UriVisitor uriVisitor; | |
569 final CompilerOptions options; | 684 final CompilerOptions options; |
685 ComponentInfo component; | |
570 | 686 |
571 _ProcessCss(this.options); | 687 _ProcessCss(this.uriVisitor, this.options); |
572 | |
573 // TODO(terry): Add --checked when fully implemented and error handling too. | |
574 StyleSheet _parseCss(String cssInput, CompilerOptions option) => | |
575 css.parse(cssInput, options: | |
576 [option.warningsAsErrors ? '--warnings_as_errors' : '', 'memory']); | |
577 | 688 |
578 void visitComponentInfo(ComponentInfo info) { | 689 void visitComponentInfo(ComponentInfo info) { |
579 if (!info.cssSource.isEmpty) { | 690 var oldComponent = component; |
580 info.styleSheet = _parseCss(info.cssSource.toString(), options); | 691 component = info; |
581 info.cssSource = null; // Once CSS parsed original not needed. | |
582 | 692 |
583 if (options.debugCss) { | 693 super.visitComponentInfo(info); |
584 print('\nComponent: ${info.tagName}'); | 694 |
585 print('==========\n'); | 695 component = oldComponent; |
586 print(treeToDebugString(info.styleSheet)); | 696 } |
697 | |
698 void visitElementInfo(ElementInfo info) { | |
699 if (component != null) { | |
700 var node = info.node; | |
701 if (node.tagName == 'style' && node.attributes.containsKey("scoped")) { | |
702 // Get contents of style tag. | |
703 var content = node.nodes.single.value.toString(); | |
704 var styleSheet = _parseCSS(component.tagName, content, uriVisitor, | |
705 options); | |
706 if (styleSheet != null) { | |
707 component.styleSheets.add(styleSheet); | |
708 } | |
587 } | 709 } |
588 } | 710 } |
589 | 711 |
590 super.visitComponentInfo(info); | 712 super.visitElementInfo(info); |
591 } | 713 } |
592 } | 714 } |
OLD | NEW |