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 /** Collects several code emitters for the template tool. */ | 5 /** Collects several code emitters for the template tool. */ |
6 library emitters; | 6 library emitters; |
7 | 7 |
8 import 'dart:json' as json; | 8 import 'dart:json' as json; |
9 | 9 |
10 import 'package:csslib/parser.dart' as css; | 10 import 'package:csslib/parser.dart' as css; |
11 import 'package:csslib/visitor.dart'; | 11 import 'package:csslib/visitor.dart'; |
12 import 'package:html5lib/dom.dart'; | 12 import 'package:html5lib/dom.dart'; |
13 import 'package:html5lib/dom_parsing.dart'; | 13 import 'package:html5lib/dom_parsing.dart'; |
14 import 'package:source_maps/span.dart' show Span, FixedLocation; | 14 import 'package:source_maps/span.dart' show Span, FixedLocation; |
15 | 15 |
16 import 'code_printer.dart'; | 16 import 'code_printer.dart'; |
17 import 'codegen.dart' as codegen; | 17 import 'codegen.dart' as codegen; |
18 import 'dart_parser.dart' show DartCodeInfo; | |
18 import 'html5_utils.dart'; | 19 import 'html5_utils.dart'; |
19 import 'html5_setters.g.dart'; | 20 import 'html5_setters.g.dart'; |
20 import 'info.dart'; | 21 import 'info.dart'; |
21 import 'messages.dart'; | 22 import 'messages.dart'; |
22 import 'utils.dart'; | 23 import 'utils.dart'; |
23 | 24 |
24 /** | 25 /** |
25 * Context used by an emitter. Typically representing where to generate code | 26 * Context used by an emitter. Typically representing where to generate code |
26 * and additional information, such as total number of generated identifiers. | 27 * and additional information, such as total number of generated identifiers. |
27 */ | 28 */ |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
428 } | 429 } |
429 | 430 |
430 visit(elemInfo); | 431 visit(elemInfo); |
431 | 432 |
432 bool hasExtends = info.extendsComponent != null; | 433 bool hasExtends = info.extendsComponent != null; |
433 var codeInfo = info.userCode; | 434 var codeInfo = info.userCode; |
434 if (codeInfo == null) { | 435 if (codeInfo == null) { |
435 var superclass = hasExtends ? info.extendsComponent.constructor | 436 var superclass = hasExtends ? info.extendsComponent.constructor |
436 : 'autogenerated.WebComponent'; | 437 : 'autogenerated.WebComponent'; |
437 codeInfo = new DartCodeInfo(null, null, [], | 438 codeInfo = new DartCodeInfo(null, null, [], |
438 'class ${info.constructor} extends $superclass {\n}'); | 439 'class ${info.constructor} extends $superclass {\n}', null); |
439 } | 440 } |
440 | 441 |
441 var code = codeInfo.code; | 442 var code = codeInfo.code; |
442 var match = new RegExp('class ${info.constructor}[^{]*{').firstMatch(code); | 443 var match = codeInfo.findClass(info.constructor); |
443 if (match != null) { | 444 if (match != null) { |
444 var printer = new CodePrinter(0); | 445 var printer = new CodePrinter(0); |
445 var libraryName = (codeInfo.libraryName != null) | 446 var libraryName = (codeInfo.libraryName != null) |
446 ? codeInfo.libraryName | 447 ? codeInfo.libraryName |
447 : info.tagName.replaceAll(new RegExp('[-./]'), '_'); | 448 : info.tagName.replaceAll(new RegExp('[-./]'), '_'); |
448 var declaringPath = info.declaringFile.path; | 449 var declaringPath = info.declaringFile.path; |
449 printer.addLine(codegen.header(declaringPath, libraryName)); | 450 printer.addLine(codegen.header(declaringPath, libraryName)); |
450 | 451 |
451 // Add exisitng import, export, and part directives. | 452 // Add existing import, export, and part directives. |
452 for (var directive in codeInfo.directives) { | 453 for (var directive in codeInfo.directives) { |
453 printer.addLine(codegen.directiveText(directive, info, pathInfo)); | 454 // TODO(jmesserly): add span here |
455 printer.addLine(directive.toString()); | |
454 } | 456 } |
455 | 457 |
456 // Add imports only for those components used by this component. | 458 // Add imports only for those components used by this component. |
457 var imports = info.usedComponents.keys.map( | 459 var imports = info.usedComponents.keys.map( |
458 (c) => pathInfo.relativePath(info, c)); | 460 (c) => pathInfo.relativePath(info, c)); |
459 | 461 |
460 if (hasExtends) { | 462 if (hasExtends) { |
461 // Inject an import to the base component. | 463 // Inject an import to the base component. |
462 printer.addLine(codegen.importList( | 464 printer.addLine(codegen.importList( |
463 [pathInfo.relativePath(info, info.extendsComponent)])); | 465 [pathInfo.relativePath(info, info.extendsComponent)])); |
464 } | 466 } |
465 | 467 |
466 var cssClasses = json.stringify( | 468 var cssClasses = json.stringify( |
467 computeCssClasses(info, scopedStyles: cssPolyfill)); | 469 computeCssClasses(info, scopedStyles: cssPolyfill)); |
468 return printer | 470 return printer |
469 ..add(codegen.importList(imports), | 471 ..add(codegen.importList(imports), |
470 location: new FixedLocation(0, declaringPath.toString(), 0, 0)) | 472 location: new FixedLocation(0, declaringPath.toString(), 0, 0)) |
471 ..addLine('') | 473 ..addLine('') |
472 ..add(code.substring(0, match.end)) | 474 // TODO(jmesserly): add span here |
475 ..add(code.substring(codeInfo.directivesEnd, match.leftBracket.end)) | |
473 ..add('\n') | 476 ..add('\n') |
474 ..indent += 1 | 477 ..indent += 1 |
475 ..addLine('/** Autogenerated from the template. */') | 478 ..addLine('/** Autogenerated from the template. */') |
476 ..addLine('') | 479 ..addLine('') |
477 ..addLine('/** CSS class constants. */') | 480 ..addLine('/** CSS class constants. */') |
478 ..addLine('static Map<String, String> _css = $cssClasses;') | 481 ..addLine('static Map<String, String> _css = $cssClasses;') |
479 ..addLine('') | 482 ..addLine('') |
480 ..addLine('/**') | 483 ..addLine('/**') |
481 ..addLine(" * Shadow root for this component. We use 'var' to allow" | 484 ..addLine(" * Shadow root for this component. We use 'var' to allow" |
482 " simulating shadow DOM") | 485 " simulating shadow DOM") |
(...skipping 25 matching lines...) Expand all Loading... | |
508 ..addLine(_clearFields(_context.declarations)) | 511 ..addLine(_clearFields(_context.declarations)) |
509 ..addLine('}') | 512 ..addLine('}') |
510 ..addLine('') | 513 ..addLine('') |
511 ..addLine('void composeChildren() {') | 514 ..addLine('void composeChildren() {') |
512 ..addLine(' super.composeChildren();') | 515 ..addLine(' super.composeChildren();') |
513 ..addLine(' if (_root is! autogenerated.ShadowRoot) _root = this;') | 516 ..addLine(' if (_root is! autogenerated.ShadowRoot) _root = this;') |
514 ..addLine('}') | 517 ..addLine('}') |
515 ..addLine('') | 518 ..addLine('') |
516 ..addLine('/** Original code from the component. */') | 519 ..addLine('/** Original code from the component. */') |
517 ..indent -= 1 | 520 ..indent -= 1 |
518 ..add(code.substring(match.end)); | 521 // TODO(jmesserly): add span here |
522 ..add(code.substring(match.leftBracket.end)); | |
523 | |
519 } else { | 524 } else { |
520 messages.error('please provide a class definition ' | 525 messages.error('please provide a class definition ' |
521 'for ${info.constructor}:\n $code', info.element.sourceSpan, | 526 'for ${info.constructor}:\n $code', info.element.sourceSpan, |
522 file: info.inputPath); | 527 file: info.inputPath); |
523 return null; | 528 return null; |
524 } | 529 } |
525 } | 530 } |
526 } | 531 } |
527 | 532 |
528 /** Generates the class corresponding to the main html page. */ | 533 /** Generates the class corresponding to the main html page. */ |
529 class MainPageEmitter extends RecursiveEmitter { | 534 class MainPageEmitter extends RecursiveEmitter { |
530 MainPageEmitter(FileInfo fileInfo) : super(fileInfo, new Context(indent: 1)); | 535 MainPageEmitter(FileInfo fileInfo) : super(fileInfo, new Context(indent: 1)); |
531 | 536 |
532 CodePrinter run(Document document, PathInfo pathInfo) { | 537 CodePrinter run(Document document, PathInfo pathInfo) { |
533 visit(_fileInfo.bodyInfo); | 538 visit(_fileInfo.bodyInfo); |
534 | 539 |
535 // fix up the URLs to content that is not modified by the compiler | 540 // fix up the URLs to content that is not modified by the compiler |
536 document.queryAll('script').forEach((tag) { | 541 document.queryAll('script').forEach((tag) { |
537 var src = tag.attributes["src"]; | 542 var src = tag.attributes["src"]; |
538 if (tag.attributes['type'] == 'application/dart') { | 543 if (tag.attributes['type'] == 'application/dart') { |
539 tag.remove(); | 544 tag.remove(); |
540 } else if (src != null) { | 545 } else if (src != null) { |
541 tag.attributes["src"] = pathInfo.transformUrl(_fileInfo.path, src); | 546 tag.attributes["src"] = pathInfo.transformUrl(_fileInfo.path, src); |
542 } | 547 } |
543 }); | 548 }); |
544 document.queryAll('link').forEach((tag) { | 549 document.queryAll('link').forEach((tag) { |
545 var href = tag.attributes['href']; | 550 var href = tag.attributes['href']; |
546 if (tag.attributes['rel'] == 'components') { | 551 if (tag.attributes['rel'] == 'components') { |
547 tag.remove(); | 552 tag.remove(); |
548 } else if (href != null) { | 553 } else if (href != null) { |
549 tag.attributes['href'] = pathInfo.transformUrl(_fileInfo.path, href); | 554 tag.attributes['href'] = pathInfo.transformUrl(_fileInfo.path, href); |
550 } | 555 } |
551 }); | 556 }); |
552 | 557 |
553 var printer = new CodePrinter(0); | 558 var printer = new CodePrinter(0); |
554 | 559 |
555 // Inject library name if not pressent. | 560 // Inject library name if not pressent. |
556 var codeInfo = _fileInfo.userCode; | 561 var codeInfo = _fileInfo.userCode; |
557 if (codeInfo == null) { | 562 if (codeInfo == null) { |
558 codeInfo = new DartCodeInfo(null, null, [], 'main(){\n}'); | 563 codeInfo = new DartCodeInfo(null, null, [], 'main(){\n}'); |
559 } | 564 } |
560 var libraryName = codeInfo.libraryName != null | 565 var libraryName = codeInfo.libraryName != null |
561 ? codeInfo.libraryName : _fileInfo.libraryName; | 566 ? codeInfo.libraryName : _fileInfo.libraryName; |
562 printer.add(codegen.header(_fileInfo.path, libraryName)); | 567 printer.add(codegen.header(_fileInfo.path, libraryName)); |
563 | 568 |
564 // Add exisitng import, export, and part directives. | 569 // Add existing import, export, and part directives. |
565 for (var directive in codeInfo.directives) { | 570 for (var directive in codeInfo.directives) { |
566 printer.addLine(codegen.directiveText(directive, _fileInfo, pathInfo)); | 571 // TODO(jmesserly): add span here |
572 printer.addLine(directive.toString()); | |
567 } | 573 } |
568 | 574 |
569 // Import only those components used by the page. | 575 // Import only those components used by the page. |
570 var imports = _fileInfo.usedComponents.keys.map( | 576 var imports = _fileInfo.usedComponents.keys.map( |
571 (c) => pathInfo.relativePath(_fileInfo, c)); | 577 (c) => pathInfo.relativePath(_fileInfo, c)); |
572 return printer..add(codegen.importList(imports)) | 578 return printer..add(codegen.importList(imports)) |
573 ..addLine('') | 579 ..addLine('') |
574 ..addLine('') | 580 ..addLine('') |
575 ..addLine('// Original code') | 581 ..addLine('// Original code') |
576 ..add(codeInfo.code) | 582 // TODO(jmesserly): add span here |
577 ..addLine('') | 583 ..add(codeInfo.codeAfterDirectives()) |
578 ..addLine('// Additional generated code') | 584 ..addLine('') |
579 ..addLine('void init_autogenerated() {') | 585 ..addLine('// Additional generated code') |
580 ..indent += 1 | 586 ..addLine('void init_autogenerated() {') |
581 ..addLine('var _root = autogenerated.document.body;') | 587 ..indent += 1 |
582 ..add(_context.declarations) | 588 ..addLine('var _root = autogenerated.document.body;') |
583 ..addLine('var __t = new autogenerated.Template(_root);') | 589 ..add(_context.declarations) |
584 ..add(_context.printer) | 590 ..addLine('var __t = new autogenerated.Template(_root);') |
585 ..addLine('__t.create();') | 591 ..add(_context.printer) |
586 ..addLine('__t..insert();') | 592 ..addLine('__t.create();') |
587 ..indent -= 1 | 593 ..addLine('__t..insert();') |
588 ..addLine('}'); | 594 ..indent -= 1 |
595 ..addLine('}'); | |
589 } | 596 } |
590 } | 597 } |
591 | 598 |
599 /** Emits a .dart file using the [DartCodeInfo]. */ | |
600 CodePrinter emitDartFile(FileInfo fileInfo, PathInfo pathInfo) { | |
601 var printer = new CodePrinter(0); | |
602 | |
603 // Inject library name if not pressent. | |
604 var codeInfo = fileInfo.userCode; | |
605 var libraryName = codeInfo.libraryName; | |
Siggi Cherem (dart-lang)
2013/02/13 01:43:24
unused variable
Jennifer Messerly
2013/02/13 05:43:15
Done. Also fixed "pressent" typo I had copied
| |
606 printer.add(codegen.header(fileInfo.path, codeInfo.libraryName)); | |
607 | |
608 // Add existing import, export, and part directives. | |
609 // TODO(jmesserly): add spans here | |
610 for (var directive in codeInfo.directives) { | |
611 printer.addLine(directive.toString()); | |
612 } | |
613 printer.add(codeInfo.codeAfterDirectives()); | |
614 return printer; | |
615 } | |
616 | |
592 /** Clears all fields in [declarations]. */ | 617 /** Clears all fields in [declarations]. */ |
593 String _clearFields(Declarations declarations) { | 618 String _clearFields(Declarations declarations) { |
594 if (declarations.declarations.isEmpty) return ''; | 619 if (declarations.declarations.isEmpty) return ''; |
595 var buff = new StringBuffer(); | 620 var buff = new StringBuffer(); |
596 for (var d in declarations.declarations) { | 621 for (var d in declarations.declarations) { |
597 buff.add('${d.name} = '); | 622 buff.add('${d.name} = '); |
598 } | 623 } |
599 buff.add('null;'); | 624 buff.add('null;'); |
600 return buff.toString(); | 625 return buff.toString(); |
601 } | 626 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
655 } | 680 } |
656 typeName = htmlElementExtends[typeName]; | 681 typeName = htmlElementExtends[typeName]; |
657 } | 682 } |
658 // If we didn't find a DOM setter, and this is a component, set a property on | 683 // If we didn't find a DOM setter, and this is a component, set a property on |
659 // the component. | 684 // the component. |
660 if (info.component != null && !name.startsWith('data-')) { | 685 if (info.component != null && !name.startsWith('data-')) { |
661 return 'xtag.${toCamelCase(name)}'; | 686 return 'xtag.${toCamelCase(name)}'; |
662 } | 687 } |
663 return "attributes['$name']"; | 688 return "attributes['$name']"; |
664 } | 689 } |
OLD | NEW |