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

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

Issue 11275029: Support for specifying an output directory (issue #106) (Closed) Base URL: git@github.com:dart-lang/dart-web-components.git@master
Patch Set: Created 8 years, 1 month 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/directive_parser.dart ('k') | lib/src/info.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 /** Collects several code emitters for the template tool. */ 5 /** Collects several code emitters for the template tool. */
6 // TODO(sigmund): add visitor that applies all emitters on a component 6 // TODO(sigmund): add visitor that applies all emitters on a component
7 // TODO(sigmund): add support for conditionals, so context is changed at that 7 // TODO(sigmund): add support for conditionals, so context is changed at that
8 // point. 8 // point.
9 library emitters; 9 library emitters;
10 10
11 import 'package:html5lib/dom.dart'; 11 import 'package:html5lib/dom.dart';
12 import 'package:html5lib/dom_parsing.dart'; 12 import 'package:html5lib/dom_parsing.dart';
13 13
14 import 'code_printer.dart'; 14 import 'code_printer.dart';
15 import 'codegen.dart' as codegen; 15 import 'codegen.dart' as codegen;
16 import 'messages.dart'; 16 import 'file_system/path.dart';
17 import 'files.dart'; 17 import 'files.dart';
18 import 'info.dart'; 18 import 'info.dart';
19 import 'messages.dart';
19 20
20 /** 21 /**
21 * An emitter for a web component feature. It collects all the logic for 22 * An emitter for a web component feature. It collects all the logic for
22 * emitting a particular feature (such as data-binding, event hookup) with 23 * emitting a particular feature (such as data-binding, event hookup) with
23 * respect to a single HTML element. 24 * respect to a single HTML element.
24 */ 25 */
25 abstract class Emitter<T extends ElementInfo> { 26 abstract class Emitter<T extends ElementInfo> {
26 /** Element for which code is being emitted. */ 27 /** Element for which code is being emitted. */
27 Element elem; 28 Element elem;
28 29
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 super.visitElement(elem); 521 super.visitElement(elem);
521 522
522 _context = oldContext; 523 _context = oldContext;
523 } 524 }
524 } 525 }
525 526
526 /** Generates the class corresponding to a single web component. */ 527 /** Generates the class corresponding to a single web component. */
527 class WebComponentEmitter extends RecursiveEmitter { 528 class WebComponentEmitter extends RecursiveEmitter {
528 WebComponentEmitter(FileInfo info) : super(info); 529 WebComponentEmitter(FileInfo info) : super(info);
529 530
530 String run(ComponentInfo info) { 531 String run(ComponentInfo info, PathInfo pathInfo) {
531 // If this derives from another component, ensure the lifecycle methods are 532 // If this derives from another component, ensure the lifecycle methods are
532 // called in the superclass. 533 // called in the superclass.
533 if (info.extendsComponent != null) { 534 if (info.extendsComponent != null) {
534 _context.createdMethod.add('super.created_autogenerated();'); 535 _context.createdMethod.add('super.created_autogenerated();');
535 _context.insertedMethod.add('super.inserted_autogenerated();'); 536 _context.insertedMethod.add('super.inserted_autogenerated();');
536 _context.removedMethod.add('super.removed_autogenerated();'); 537 _context.removedMethod.add('super.removed_autogenerated();');
537 } 538 }
538 539
539 if (info.element.attributes['apply-author-styles'] != null) { 540 if (info.element.attributes['apply-author-styles'] != null) {
540 _context.createdMethod.add('if (_root is autogenerated.ShadowRoot) ' 541 _context.createdMethod.add('if (_root is autogenerated.ShadowRoot) '
(...skipping 13 matching lines...) Expand all
554 // We have a similar issue in mainDartCode. 555 // We have a similar issue in mainDartCode.
555 _context.createdMethod.add(""" 556 _context.createdMethod.add("""
556 _root.innerHTML = r''' 557 _root.innerHTML = r'''
557 ${info.template.innerHTML.trim()} 558 ${info.template.innerHTML.trim()}
558 '''; 559 ''';
559 """); 560 """);
560 } 561 }
561 562
562 visit(info.element); 563 visit(info.element);
563 564
564 var code = info.userCode; 565 bool hasExtends = info.extendsComponent != null;
565 if (code == null) { 566 var codeInfo = info.userCode;
566 if (info.extendsComponent != null) { 567 if (codeInfo == null) {
567 var superclass = info.extendsComponent.constructor; 568 var superclass = hasExtends ? info.extendsComponent.constructor
568 // TODO(jmesserly): should we add this import even if you have your own 569 : 'autogenerated.WebComponent';
569 // script tag? 570 var imports = hasExtends ? [] : [new DartDirectiveInfo('import',
570 var relativePath = PathInfo.relativePath(info, info.extendsComponent); 571 'package:web_components/web_component.dart', 'autogenerated')];
571 code = ''' 572 codeInfo = new DartCodeInfo(null, null, imports,
572 ${codegen.importList([relativePath])} 573 'class ${info.constructor} extends $superclass {\n}');
573 class ${info.constructor} extends $superclass {\n}
574 ''';
575 } else {
576 code = '''
577 import 'package:web_components/web_component.dart' as autogenerated;
578 class ${info.constructor} extends autogenerated.WebComponent {\n}
579 ''';
580 }
581 } 574 }
575
576 var code = codeInfo.code;
582 var match = new RegExp('class ${info.constructor}[^{]*{').firstMatch(code); 577 var match = new RegExp('class ${info.constructor}[^{]*{').firstMatch(code);
583 if (match != null) { 578 if (match != null) {
584 // TODO(sigmund): clean up and make this more robust. Issue #59.
585 var printer = new CodePrinter(); 579 var printer = new CodePrinter();
586 var libMatch = const RegExp('^library .*;').firstMatch(code); 580 var libraryName = (codeInfo.libraryName != null)
587 int startPos = 0; 581 ? codeInfo.libraryName
588 if (libMatch == null) { 582 : info.tagName.replaceAll(const RegExp('[-./]'), '_');
589 var libraryName = info.tagName.replaceAll(const RegExp('[-./]'), '_'); 583 printer.add(codegen.header(info.declaringFile.path, libraryName));
590 printer.add(codegen.header(info.declaringFile.path, libraryName)); 584
591 } else { 585 // Add exisitng import, export, and part directives.
592 printer.add('// Generated from ${info.inputPath.filename}\n' 586 for (var directive in codeInfo.directives) {
593 '// DO NOT EDIT.'); 587 printer.add(codegen.directiveText(directive, info, pathInfo));
594 printer.add(code.substring(0, libMatch.end()));
595 printer.add(codegen.imports);
596 startPos = libMatch.end();
597 } 588 }
598 // Import only those components used by this component. 589
590 // Add imports only for those components used by this component.
599 var imports = info.usedComponents.getKeys().map( 591 var imports = info.usedComponents.getKeys().map(
600 (c) => PathInfo.relativePath(info, c)); 592 (c) => PathInfo.relativePath(info, c));
593
594 if (hasExtends) {
595 // Inject an import to the base component.
596 printer.add(codegen.importList(
597 [PathInfo.relativePath(info, info.extendsComponent)]));
598 }
599
601 printer.add(codegen.importList(imports)) 600 printer.add(codegen.importList(imports))
602 .add(code.substring(startPos, match.end())) 601 .add(code.substring(0, match.end()))
603 .add('\n') 602 .add('\n')
604 .add(codegen.componentCode(info.constructor, 603 .add(codegen.componentCode(info.constructor,
605 _context.declarations.formatString(1), 604 _context.declarations.formatString(1),
606 _context.createdMethod.formatString(2), 605 _context.createdMethod.formatString(2),
607 _context.insertedMethod.formatString(2), 606 _context.insertedMethod.formatString(2),
608 _context.removedMethod.formatString(2))) 607 _context.removedMethod.formatString(2)))
609 .add(code.substring(match.end())); 608 .add(code.substring(match.end()));
610 return printer.formatString(); 609 return printer.formatString();
611 } else { 610 } else {
612 messages.error('please provide a class definition ' 611 messages.error('please provide a class definition '
613 'for ${info.constructor}:\n $code', info.element.span, 612 'for ${info.constructor}:\n $code', info.element.span,
614 file: info.inputPath); 613 file: info.inputPath);
615 return code; 614 return '';
616 } 615 }
617 } 616 }
618 } 617 }
619 618
620 /** Generates the class corresponding to the main html page. */ 619 /** Generates the class corresponding to the main html page. */
621 class MainPageEmitter extends RecursiveEmitter { 620 class MainPageEmitter extends RecursiveEmitter {
622 MainPageEmitter(FileInfo info) : super(info); 621 MainPageEmitter(FileInfo info) : super(info);
623 622
624 String run(Document document) { 623 String run(Document document, PathInfo pathInfo) {
625 // The body of an element tag will not be part of the main HTML page. Each 624 // The body of an element tag will not be part of the main HTML page. Each
626 // element will be generated programatically as a dart web component by 625 // element will be generated programatically as a dart web component by
627 // [WebComponentEmitter] above. 626 // [WebComponentEmitter] above.
628 document.queryAll('element').forEach((tag) => tag.remove()); 627 document.queryAll('element').forEach((tag) => tag.remove());
628
629 // fix up the URLs to content that is not modified by the compiler
630 document.queryAll('script').forEach((tag) {
631 var src = tag.attributes["src"];
632 if (tag.attributes['type'] != 'application/dart' && src != null) {
633 tag.attributes["src"] = pathInfo.transferDirectiveUrl(_info, src);
634 }
635 });
636 document.queryAll('link').forEach((tag) {
637 var href = tag.attributes['href'];
638 if (tag.attributes['rel'] != 'components' && href != null) {
639 tag.attributes['href'] = pathInfo.transferDirectiveUrl(_info, href);
640 }
641 });
642
629 visit(document); 643 visit(document);
630 644
631 var printer = new CodePrinter(); 645 var printer = new CodePrinter();
632 var startPos = 0;
633 646
634 // Inject library name if not pressent. 647 // Inject library name if not pressent.
635 // TODO(sigmund): consider parsing the top-level syntax of a dart file 648 var codeInfo = _info.userCode;
636 // instead of this ad-hoc regex (issue #95). 649 var libraryName = codeInfo.libraryName != null
637 var code = _info.userCode; 650 ? codeInfo.libraryName : _info.libraryName;
638 var match = const RegExp('^library .*;').firstMatch(code); 651 printer.add(codegen.header(_info.path, libraryName));
639 if (match == null) { 652
640 printer.add(codegen.header(_info.path, _info.libraryName)); 653 // Add exisitng import, export, and part directives.
641 } else { 654 for (var directive in codeInfo.directives) {
642 printer.add('// Generated from ${_info.inputPath}\n// DO NOT EDIT.') 655 printer.add(codegen.directiveText(directive, _info, pathInfo));
643 .add(code.substring(0, match.end()))
644 .add(codegen.imports);
645 startPos = match.end();
646 } 656 }
647 657
648 // Import only those components used by the page. 658 // Import only those components used by the page.
649 var imports = _info.usedComponents.getKeys().map( 659 var imports = _info.usedComponents.getKeys().map(
650 (c) => PathInfo.relativePath(_info, c)); 660 (c) => PathInfo.relativePath(_info, c));
651 printer.add(codegen.importList(imports)) 661 printer.add(codegen.importList(imports))
652 .add(codegen.mainDartCode(code.substring(startPos), 662 .add(codegen.mainDartCode(codeInfo.code,
653 _context.declarations.formatString(0), 663 _context.declarations.formatString(0),
654 _context.createdMethod.formatString(1), 664 _context.createdMethod.formatString(1),
655 _context.insertedMethod.formatString(1), 665 _context.insertedMethod.formatString(1),
656 document.body.innerHTML.trim())); 666 document.body.innerHTML.trim()));
657 return printer.formatString(); 667 return printer.formatString();
658 } 668 }
659 } 669 }
OLDNEW
« no previous file with comments | « lib/src/directive_parser.dart ('k') | lib/src/info.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698