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

Unified Diff: utils/template/codegen.dart

Issue 137013002: Removed obsolete code (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Removed libraries not used Created 6 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « utils/lib/file_system_vm.dart ('k') | utils/template/htmltree.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/template/codegen.dart
diff --git a/utils/template/codegen.dart b/utils/template/codegen.dart
deleted file mode 100644
index d2b07ab7ff25ed4a9a11aea24ef3f6e91d2582bf..0000000000000000000000000000000000000000
--- a/utils/template/codegen.dart
+++ /dev/null
@@ -1,1013 +0,0 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-class CGBlock {
- int _blockType; // Code type of this block
- int _indent; // Number of spaces to prefix for each statement
- bool _inEach; // This block or any currently active blocks is a
- // #each. If so then any element marked with a
- // var attribute is repeated therefore the var
- // is a List type instead of an Element type.
- String _localName; // optional local name for #each or #with
- List<CGStatement> _stmts;
- int localIndex; // Local variable index (e.g., e0, e1, etc.)
-
- // Block Types:
- static const int CONSTRUCTOR = 0;
- static const int EACH = 1;
- static const int WITH = 2;
-
- CGBlock([this._indent = 4,
- this._blockType = CGBlock.CONSTRUCTOR,
- this._inEach = false,
- this._localName = null]) :
- _stmts = new List<CGStatement>(), localIndex = 0 {
- assert(_blockType >= CGBlock.CONSTRUCTOR && _blockType <= CGBlock.WITH);
- }
-
- bool get anyStatements => !_stmts.isEmpty;
- bool get isConstructor => _blockType == CGBlock.CONSTRUCTOR;
- bool get isEach => _blockType == CGBlock.EACH;
- bool get isWith => _blockType == CGBlock.WITH;
-
- bool get hasLocalName => _localName != null;
- String get localName => _localName;
-
- CGStatement push(var elem, var parentName, [bool exact = false]) {
- var varName;
- if (elem is TemplateElement && elem.hasVar) {
- varName = elem.varName;
- } else {
- varName = localIndex++;
- }
-
- CGStatement stmt = new CGStatement(elem, _indent, parentName, varName,
- exact, _inEach);
- _stmts.add(stmt);
-
- return stmt;
- }
-
- void pop() {
- _stmts.removeLast();
- }
-
- void add(String value) {
- if (_stmts.last != null) {
- _stmts.last.add(value);
- }
- }
-
- CGStatement get last => _stmts.length > 0 ? _stmts.last : null;
-
- /**
- * Returns mixed list of elements marked with the var attribute. If the
- * element is inside of a #each the name exposed is:
- *
- * List varName;
- *
- * otherwise it's:
- *
- * var varName;
- *
- * TODO(terry): For scalars var varName should be Element tag type e.g.,
- *
- * DivElement varName;
- */
- String get globalDeclarations {
- StringBuffer buff = new StringBuffer();
- for (final CGStatement stmt in _stmts) {
- buff.write(stmt.globalDeclaration());
- }
-
- return buff.toString();
- }
-
- /**
- * List of statement constructors for each var inside a #each.
- *
- * ${#each products}
- * <div var=myVar>...</div>
- * ${/each}
- *
- * returns:
- *
- * myVar = [];
- */
- String get globalInitializers {
- StringBuffer buff = new StringBuffer();
- for (final CGStatement stmt in _stmts) {
- buff.write(stmt.globalInitializers());
- }
-
- return buff.toString();
- }
-
- String get codeBody {
- StringBuffer buff = new StringBuffer();
-
- for (final CGStatement stmt in _stmts) {
- buff.write(stmt.emitDartStatement());
- }
-
- return buff.toString();
- }
-}
-
-class CGStatement {
- bool _exact; // If True not HTML construct instead exact stmt
- bool _repeating; // Stmt in a #each this block or nested block.
- StringBuffer _buff;
- var _elem;
- int _indent;
- var parentName;
- String varName;
- bool _globalVariable;
- bool _closed;
-
- CGStatement(this._elem, this._indent, this.parentName, var varNameOrIndex,
- [this._exact = false, this._repeating = false]) :
- _buff = new StringBuffer(), _closed = false {
-
- if (varNameOrIndex is String) {
- // We have the global variable name
- varName = varNameOrIndex;
- _globalVariable = true;
- } else {
- // local index generate local variable name.
- varName = "e${varNameOrIndex}";
- _globalVariable = false;
- }
- }
-
- bool get hasGlobalVariable => _globalVariable;
- String get variableName => varName;
-
- String globalDeclaration() {
- if (hasGlobalVariable) {
- String spaces = Codegen.spaces(_indent);
- return (_repeating) ?
- " List ${varName}; // Repeated elements.\n" : " var ${varName};\n";
- }
-
- return "";
- }
-
- String globalInitializers() {
- if (hasGlobalVariable && _repeating) {
- return " ${varName} = [];\n";
- }
-
- return "";
- }
-
- void add(String value) {
- _buff.write(value);
- }
-
- bool get isClosed => _closed;
-
- void close() {
- if (_elem is TemplateElement && _elem.scoped) {
- add("</${_elem.tagName}>");
- }
- _closed = true;
- }
-
- String emitDartStatement() {
- StringBuffer statement = new StringBuffer();
-
- String spaces = Codegen.spaces(_indent);
-
- if (_exact) {
- statement.add("${spaces}${_buff.toString()};\n");
- } else {
- String localVar = "";
- String tmpRepeat;
- if (hasGlobalVariable) {
- if (_repeating) {
- tmpRepeat = "tmp_${varName}";
- localVar = "var ";
- }
- } else {
- localVar = "var ";
- }
-
- /* Emiting the following code fragment where varName is the attribute
- value for var=
-
- varName = new Element.html('HTML GOES HERE');
- parent.elements.add(varName);
-
- for repeating elements in a #each:
-
- var tmp_nnn = new Element.html('HTML GOES HERE');
- varName.add(tmp_nnn);
- parent.elements.add(tmp_nnn);
-
- for elements w/o var attribute set:
-
- var eNNN = new Element.html('HTML GOES HERE');
- parent.elements.add(eNNN);
- */
- if (_elem is TemplateCall) {
- // Call template NameEntry2
- String cls = _elem.toCall;
- String params = _elem.params;
- statement.add("\n${spaces}// Call template ${cls}.\n");
- statement.add(
- "${spaces}${localVar}${varName} = new ${cls}${params};\n");
- statement.add(
- "${spaces}${parentName}.elements.add(${varName}.root);\n");
- } else {
- bool isTextNode = _elem is TemplateText;
- String createType = isTextNode ? "Text" : "Element.html";
- if (tmpRepeat == null) {
- statement.add("${spaces}${localVar}${varName} = new ${createType}('");
- } else {
- statement.add(
- "${spaces}${localVar}${tmpRepeat} = new ${createType}('");
- }
- statement.add(isTextNode ? _buff.toString().trim() : _buff.toString());
-
- if (tmpRepeat == null) {
- statement.add(
- "');\n${spaces}${parentName}.elements.add(${varName});\n");
- } else {
- statement.add(
- "');\n${spaces}${parentName}.elements.add(${tmpRepeat});\n");
- statement.add("${spaces}${varName}.add(${tmpRepeat});\n");
- }
- }
- }
-
- return statement.toString();
- }
-}
-
-class Codegen {
- static const String SPACES = " ";
- static String spaces(int numSpaces) {
- return SPACES.substring(0, numSpaces);
- }
-
- // TODO(terry): Before generating Dart class need a validate phase that
- // checks mangles all class names to be prefix with the
- // template name to avoid any class name collisions. Also,
- // investigate possible runtime check mode to insure that only
- // valid CSS class names are used (in case someone uses strings
- // and not the generated getters to the CSS class selector. This
- // mode would be slower would require that every class name set
- // (maybe jQuery too) is for a particular view (requires walking
- // the HTML tree looking for a parent template prefix that
- // matches the CSS prefix. (more thinking needed).
- static String generate(List<Template> templates, String filename) {
- List<String> fileParts = filename.split('.');
- assert(fileParts.length == 2);
- filename = fileParts[0];
-
- StringBuffer buff = new StringBuffer();
- int injectId = 0; // Inject function id
-
- buff.write("// Generated Dart class from HTML template.\n");
- buff.write("// DO NOT EDIT.\n\n");
-
- String addStylesheetFuncName = "add_${filename}_templatesStyles";
-
- for (final template in templates) {
- // Emit the template class.
- TemplateSignature sig = template.signature;
- buff.write(_emitClass(sig.name, sig.params, template.content,
- addStylesheetFuncName));
- }
-
- // TODO(terry): Stylesheet aggregator should not be global needs to be
- // bound to this template file not global to the app.
-
- // Emit the stylesheet aggregator.
- buff.write("\n\n// Inject all templates stylesheet once into the head.\n");
- buff.write("bool ${filename}_stylesheet_added = false;\n");
- buff.write("void ${addStylesheetFuncName}() {\n");
- buff.write(" if (!${filename}_stylesheet_added) {\n");
- buff.write(" StringBuffer styles = new StringBuffer();\n\n");
-
- buff.write(" // All templates stylesheet.\n");
-
- for (final template in templates) {
- TemplateSignature sig = template.signature;
- buff.write(" styles.add(${sig.name}.stylesheet);\n");
- }
-
- buff.write("\n ${filename}_stylesheet_added = true;\n");
-
- buff.write(" document.head.elements.add(new Element.html('<style>"
- "\${styles.toString()}</style>'));\n");
- buff.write(" }\n");
- buff.write("}\n");
-
- return buff.toString();
- }
-
- static String _emitCSSSelectors(css.Stylesheet stylesheet) {
- if (stylesheet == null) {
- return "";
- }
-
- List<String> classes = [];
-
- for (final production in stylesheet.topLevels) {
- if (production is css.IncludeDirective) {
- for (final topLevel in production.styleSheet.topLevels) {
- if (topLevel is css.RuleSet) {
- classes = css.Generate.computeClassSelectors(topLevel, classes);
- }
- }
- } else if (production is css.RuleSet) {
- classes = css.Generate.computeClassSelectors(production, classes);
- }
- }
-
- List<String> dartNames = [];
-
- for (final String knownClass in classes) {
- StringBuffer dartName = new StringBuffer();
- List<String> splits = knownClass.split('-');
- if (splits.length > 0) {
- dartName.add(splits[0]);
- for (int idx = 1; idx < splits.length; idx++) {
- String part = splits[idx];
- // Character between 'a'..'z' mapped to 'A'..'Z'
- dartName.add("${part[0].toUpperCase()}${part.substring(1)}");
- }
- dartNames.add(dartName.toString());
- }
- }
-
- StringBuffer buff = new StringBuffer();
- if (classes.length > 0) {
- assert(classes.length == dartNames.length);
- buff.write("\n // CSS class selectors for this template.\n");
- for (int i = 0; i < classes.length; i++) {
- buff.write(
- " static String get ${dartNames[i]} => \"${classes[i]}\";\n");
- }
- }
-
- return buff.toString();
- }
-
- static String _emitClass(String className,
- List<Map<Identifier, Identifier>> params,
- TemplateContent content,
- String addStylesheetFuncName) {
- StringBuffer buff = new StringBuffer();
-
- // Emit the template class.
- buff.write("class ${className} {\n");
-
- buff.write(" Map<String, Object> _scopes;\n");
- buff.write(" Element _fragment;\n\n");
-
- bool anyParams = false;
- for (final param in params) {
- buff.write(" ${param['type']} ${param['name']};\n");
- anyParams = true;
- }
- if (anyParams) buff.write("\n");
-
- ElemCG ecg = new ElemCG();
-
- if (!ecg.pushBlock()) {
- world.error("Error at ${content}");
- }
-
- var root = content.html.children.length > 0 ? content.html.children[0] :
- content.html;
- bool firstTime = true;
- for (var child in root.children) {
- if (child is TemplateText) {
- if (!firstTime) {
- ecg.closeStatement();
- }
-
- String textNodeValue = child.value.trim();
- if (textNodeValue.length > 0) {
- CGStatement stmt = ecg.pushStatement(child, "_fragment");
- }
- }
- ecg.emitConstructHtml(child, "", "_fragment");
- firstTime = false;
- }
-
- // Create all element names marked with var.
- String decls = ecg.globalDeclarations;
- if (decls.length > 0) {
- buff.write("\n // Elements bound to a variable:\n");
- buff.write("${decls}\n");
- }
-
- // Create the constructor.
- buff.write(" ${className}(");
- bool firstParam = true;
- for (final param in params) {
- if (!firstParam) {
- buff.write(", ");
- }
- buff.write("this.${param['name']}");
- firstParam = false;
- }
- buff.write(") : _scopes = new Map<String, Object>() {\n");
-
- String initializers = ecg.globalInitializers;
- if (initializers.length > 0) {
- buff.write(" //Global initializers.\n");
- buff.write("${initializers}\n");
- }
-
- buff.write(" // Insure stylesheet for template exist in the document.\n");
- buff.write(" ${addStylesheetFuncName}();\n\n");
-
- buff.write(" _fragment = new DocumentFragment();\n");
-
- buff.write(ecg.codeBody); // HTML for constructor to build.
-
- buff.write(" }\n\n"); // End constructor
-
- buff.write(emitGetters(content.getters));
-
- buff.write(" Element get root => _fragment;\n");
-
- // Emit all CSS class selectors:
- buff.write(_emitCSSSelectors(content.css));
-
- // Emit the injection functions.
- buff.write("\n // Injection functions:");
- for (final expr in ecg.expressions) {
- buff.write("${expr}");
- }
-
- buff.write("\n // Each functions:\n");
- for (var eachFunc in ecg.eachs) {
- buff.write("${eachFunc}\n");
- }
-
- buff.write("\n // With functions:\n");
- for (var withFunc in ecg.withs) {
- buff.write("${withFunc}\n");
- }
-
- buff.write("\n // CSS for this template.\n");
- buff.write(" static const String stylesheet = ");
-
- if (content.css != null) {
- buff.write("\'\'\'\n ${content.css.toString()}\n");
- buff.write(" \'\'\';\n\n");
-
- // TODO(terry): Emit all known selectors for this template.
- buff.write(" // Stylesheet class selectors:\n");
- } else {
- buff.write("\"\";\n");
- }
-
- buff.write(" String safeHTML(String html) {\n");
- buff.write(" // TODO(terry): Escaping for XSS vulnerabilities TBD.\n");
- buff.write(" return html;\n");
- buff.write(" }\n");
-
- buff.write("}\n"); // End class
-
- return buff.toString();
- }
-
- // TODO(terry): Need to generate function to inject any TemplateExpressions
- // to call SafeHTML wrapper.
- static String emitGetters(List<TemplateGetter> getters) {
- StringBuffer buff = new StringBuffer();
- for (final TemplateGetter getter in getters) {
- buff.write(' String ${getter.getterSignatureAsString()} {\n');
- buff.write(' return \'\'\'');
- var docFrag = getter.docFrag.children[0];
- for (final child in docFrag.children) {
- buff.write(child.toString().trim());
- }
- buff.write('\'\'\';\n');
- buff.write(' }\n\n');
- }
-
- return buff.toString();
- }
-}
-
-class ElemCG {
- // List of identifiers and quoted strings (single and double quoted).
- var identRe = new RegExp(
- "\s*('\"\\'\\\"[^'\"\\'\\\"]+'\"\\'\\\"|[_A-Za-z][_A-Za-z0-9]*)");
-
- List<CGBlock> _cgBlocks;
- StringBuffer _globalDecls; // Global var declarations for all blocks.
- StringBuffer _globalInits; // Global List var initializtion for all
- // blocks in a #each.
- String funcCall; // Func call after element creation?
- List<String> expressions; // List of injection function declarations.
- List<String> eachs; // List of each function declarations.
- List<String> withs; // List of with function declarations.
-
- ElemCG() :
- expressions = [],
- eachs = [],
- withs = [],
- _cgBlocks = [],
- _globalDecls = new StringBuffer(),
- _globalInits = new StringBuffer();
-
- bool get isLastBlockConstructor {
- CGBlock block = _cgBlocks.last;
- return block.isConstructor;
- }
-
- List<String> activeBlocksLocalNames() {
- List<String> result = [];
-
- for (final CGBlock block in _cgBlocks) {
- if (block.isEach || block.isWith) {
- if (block.hasLocalName) {
- result.add(block.localName);
- }
- }
- }
-
- return result;
- }
-
- /**
- * Active block with this localName.
- */
- bool matchBlocksLocalName(String name) {
- for (final CGBlock block in _cgBlocks) {
- if (block.isEach || block.isWith) {
- if (block.hasLocalName && block.localName == name) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Any active blocks?
- */
- bool isNestedBlock() {
- for (final CGBlock block in _cgBlocks) {
- if (block.isEach || block.isWith) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Any active blocks with localName?
- */
- bool isNestedNamedBlock() {
- for (final CGBlock block in _cgBlocks) {
- if ((block.isEach || block.isWith) && block.hasLocalName) {
- return true;
- }
- }
-
- return false;
- }
-
- // Any current active #each blocks.
- bool anyEachBlocks(int blockToCreateType) {
- bool result = blockToCreateType == CGBlock.EACH;
-
- for (final CGBlock block in _cgBlocks) {
- if (block.isEach) {
- result = result || true;
- }
- }
-
- return result;
- }
-
- bool pushBlock([int indent = 4, int blockType = CGBlock.CONSTRUCTOR,
- String itemName = null]) {
- if (itemName != null && matchBlocksLocalName(itemName)) {
- world.error("Active block already exist with local name: ${itemName}.");
- return false;
- } else if (itemName == null && this.isNestedBlock()) {
- world.error('''
-Nested #each or #with must have a localName;
- \n #each list [localName]\n #with object [localName]''');
- return false;
- }
- _cgBlocks.add(
- new CGBlock(indent, blockType, anyEachBlocks(blockType), itemName));
-
- return true;
- }
-
- void popBlock() {
- _globalDecls.add(lastBlock.globalDeclarations);
- _globalInits.add(lastBlock.globalInitializers);
- _cgBlocks.removeLast();
- }
-
- CGStatement pushStatement(var elem, var parentName) {
- return lastBlock.push(elem, parentName, false);
- }
-
- CGStatement pushExactStatement(var elem, var parentName) {
- return lastBlock.push(elem, parentName, true);
- }
-
- bool get isClosedStatement {
- return (lastBlock != null && lastBlock.last != null) ?
- lastBlock.last.isClosed : false;
- }
-
- void closeStatement() {
- if (lastBlock != null && lastBlock.last != null &&
- !lastBlock.last.isClosed) {
- lastBlock.last.close();
- }
- }
-
- String get lastVariableName {
- if (lastBlock != null && lastBlock.last != null) {
- return lastBlock.last.variableName;
- }
- }
-
- String get lastParentName {
- if (lastBlock != null && lastBlock.last != null) {
- return lastBlock.last.parentName;
- }
- }
-
- CGBlock get lastBlock => _cgBlocks.length > 0 ? _cgBlocks.last : null;
-
- void add(String str) {
- _cgBlocks.last.add(str);
- }
-
- String get globalDeclarations {
- assert(_cgBlocks.length == 1); // Only constructor body should be left.
- _globalDecls.add(lastBlock.globalDeclarations);
- return _globalDecls.toString();
- }
-
- String get globalInitializers {
- assert(_cgBlocks.length == 1); // Only constructor body should be left.
- _globalInits.add(lastBlock.globalInitializers);
- return _globalInits.toString();
- }
-
- String get codeBody {
- closeStatement();
- return _cgBlocks.last.codeBody;
- }
-
- /* scopeName for expression
- * parentVarOrIndex if # it's a local variable if string it's an exposed
- * name (specified by the var attribute) for this element.
- *
- */
- emitElement(var elem,
- [String scopeName = "",
- var parentVarOrIdx = 0,
- bool immediateNestedEach = false]) {
- if (elem is TemplateElement) {
- if (!elem.isFragment) {
- add("<${elem.tagName}${elem.attributesToString()}>");
- }
- String prevParent = lastVariableName;
- for (var childElem in elem.children) {
- if (childElem is TemplateElement) {
- closeStatement();
- if (childElem.hasVar) {
- emitConstructHtml(childElem, scopeName, prevParent,
- childElem.varName);
- } else {
- emitConstructHtml(childElem, scopeName, prevParent);
- }
- closeStatement();
- } else {
- emitElement(childElem, scopeName, parentVarOrIdx);
- }
- }
-
- // Close this tag.
- closeStatement();
- } else if (elem is TemplateText) {
- String outputValue = elem.value.trim();
- if (outputValue.length > 0) {
- bool emitTextNode = false;
- if (isClosedStatement) {
- String prevParent = lastParentName;
- CGStatement stmt = pushStatement(elem, prevParent);
- emitTextNode = true;
- }
-
- // TODO(terry): Need to interpolate following:
- // {sp} → space
- // {nil} → empty string
- // {\r} → carriage return
- // {\n} → new line (line feed)
- // {\t} → tab
- // {lb} → left brace
- // {rb} → right brace
-
- add("${outputValue}"); // remove leading/trailing whitespace.
-
- if (emitTextNode) {
- closeStatement();
- }
- }
- } else if (elem is TemplateExpression) {
- emitExpressions(elem, scopeName);
- } else if (elem is TemplateEachCommand) {
- // Signal to caller new block coming in, returns "each_" prefix
- emitEach(elem, "List", elem.listName.name, "parent", immediateNestedEach,
- elem.hasLoopItem ? elem.loopItem.name : null);
- } else if (elem is TemplateWithCommand) {
- // Signal to caller new block coming in, returns "each_" prefix
- emitWith(elem, "var", elem.objectName.name, "parent",
- elem.hasBlockItem ? elem.blockItem.name : null);
- } else if (elem is TemplateCall) {
- emitCall(elem, parentVarOrIdx);
- }
- }
-
- // TODO(terry): Hack prefixing all names with "${scopeName}." but don't touch
- // quoted strings.
- String _resolveNames(String expr, String prefixPart) {
- StringBuffer newExpr = new StringBuffer();
- Iterable<Match> matches = identRe.allMatches(expr);
-
- int lastIdx = 0;
- for (Match m in matches) {
- if (m.start > lastIdx) {
- newExpr.add(expr.substring(lastIdx, m.start));
- }
-
- bool identifier = true;
- if (m.start > 0) {
- int charCode = expr.codeUnitAt(m.start - 1);
- // Starts with ' or " then it's not an identifier.
- identifier = charCode != 34 /* " */ && charCode != 39 /* ' */;
- }
-
- String strMatch = expr.substring(m.start, m.end);
- if (identifier) {
- newExpr.add("${prefixPart}.${strMatch}");
- } else {
- // Quoted string don't touch.
- newExpr.add("${strMatch}");
- }
- lastIdx = m.end;
- }
-
- if (expr.length > lastIdx) {
- newExpr.add(expr.substring(lastIdx));
- }
-
- return newExpr.toString();
- }
-
- /**
- * Construct the HTML each top-level node get's it's own variable.
- *
- * TODO(terry): Might want to optimize if the other top-level nodes have no
- * control structures (with, each, if, etc.). We could
- * synthesize a root node and create all the top-level nodes
- * under the root node with one innerHTML.
- */
- void emitConstructHtml(var elem,
- [String scopeName = "",
- String parentName = "parent",
- var varIndex = 0,
- bool immediateNestedEach = false]) {
- if (elem is TemplateElement) {
- CGStatement stmt = pushStatement(elem, parentName);
- emitElement(elem, scopeName, stmt.hasGlobalVariable ?
- stmt.variableName : varIndex);
- } else {
- emitElement(elem, scopeName, varIndex, immediateNestedEach);
- }
- }
-
- /* Any references to products.sales needs to be remaped to item.sales
- * for now it's a hack look for first dot and replace with item.
- */
- String eachIterNameToItem(String iterName) {
- String newName = iterName;
- var dotForIter = iterName.indexOf('.');
- if (dotForIter >= 0) {
- newName = "_item${iterName.substring(dotForIter)}";
- }
-
- return newName;
- }
-
- emitExpressions(TemplateExpression elem, String scopeName) {
- StringBuffer func = new StringBuffer();
-
- String newExpr = elem.expression;
- bool anyNesting = isNestedNamedBlock();
- if (scopeName.length > 0 && !anyNesting) {
- // In a block #command need the scope passed in.
- add("\$\{inject_${expressions.length}(_item)\}");
- func.add("\n String inject_${expressions.length}(var _item) {\n");
- // Escape all single-quotes, this expression is embedded as a string
- // parameter for the call to safeHTML.
- newExpr = _resolveNames(newExpr.replaceAll("'", "\\'"), "_item");
- } else {
- // Not in a block #command item isn't passed in.
- add("\$\{inject_${expressions.length}()\}");
- func.add("\n String inject_${expressions.length}() {\n");
-
- if (anyNesting) {
- func.add(defineScopes());
- }
- }
-
- // Construct the active scope names for name resolution.
-
- func.add(" return safeHTML('\$\{${newExpr}\}');\n");
- func.add(" }\n");
-
- expressions.add(func.toString());
- }
-
- emitCall(TemplateCall elem, String scopeName) {
- pushStatement(elem, scopeName);
- }
-
- emitEach(TemplateEachCommand elem, String iterType, String iterName,
- var parentVarOrIdx, bool nestedImmediateEach, [String itemName = null]) {
- TemplateDocument docFrag = elem.documentFragment;
-
- int eachIndex = eachs.length;
- eachs.add("");
-
- StringBuffer funcBuff = new StringBuffer();
- // Prepare function call "each_N(iterName," parent param computed later.
- String funcName = "each_${eachIndex}";
-
- funcBuff.add(" ${funcName}(${iterType} items, Element parent) {\n");
-
- String paramName = injectParamName(itemName);
- if (paramName == null) {
- world.error("Use a different local name; ${itemName} is reserved.");
- }
- funcBuff.add(" for (var ${paramName} in items) {\n");
-
- if (!pushBlock(6, CGBlock.EACH, itemName)) {
- world.error("Error at ${elem}");
- }
-
- addScope(6, funcBuff, itemName);
-
- TemplateElement docFragChild = docFrag.children[0];
- var children = docFragChild.isFragment ?
- docFragChild.children : docFrag.children;
- for (var child in children) {
- // If any immediate children of the parent #each is an #each then
- // so we need to pass the outer #each parent not the last statement's
- // variableName when calling the nested #each.
- bool eachChild = (child is TemplateEachCommand);
- emitConstructHtml(child, iterName, parentVarOrIdx, 0, eachChild);
- }
-
- funcBuff.add(codeBody);
-
- removeScope(6, funcBuff, itemName);
-
- popBlock();
-
- funcBuff.add(" }\n");
- funcBuff.add(" }\n");
-
- eachs[eachIndex] = funcBuff.toString();
-
- // If nested each then we want to pass the parent otherwise we'll use the
- // varName.
- var varName = nestedImmediateEach ? "parent" : lastBlockVarName;
-
- pushExactStatement(elem, parentVarOrIdx);
-
- // Setup call to each func as "each_n(xxxxx, " the parent param is filled
- // in later when we known the parent variable.
- String eachParam =
- (itemName == null) ? eachIterNameToItem(iterName) : iterName;
- add("${funcName}(${eachParam}, ${varName})");
-}
-
- emitWith(TemplateWithCommand elem, String withType, String withName,
- var parentVarIndex, [String itemName = null]) {
- TemplateDocument docFrag = elem.documentFragment;
-
- int withIndex = withs.length;
- withs.add("");
-
- StringBuffer funcBuff = new StringBuffer();
- // Prepare function call "each_N(iterName," parent param computed later.
- String funcName = "with_${withIndex}";
-
- String paramName = injectParamName(itemName);
- if (paramName == null) {
- world.error("Use a different local name; ${itemName} is reserved.");
- }
- funcBuff.add(" ${funcName}(${withType} ${paramName}, Element parent) {\n");
-
- if (!pushBlock(4, CGBlock.WITH, itemName)) {
- world.error("Error at ${elem}");
- }
-
- TemplateElement docFragChild = docFrag.children[0];
- var children = docFragChild.isFragment ?
- docFragChild.children : docFrag.children;
- for (var child in children) {
- emitConstructHtml(child, withName, "parent");
- }
-
- addScope(4, funcBuff, itemName);
- funcBuff.add(codeBody);
- removeScope(4, funcBuff, itemName);
-
- popBlock();
-
- funcBuff.add(" }\n");
-
- withs[withIndex] = funcBuff.toString();
-
- // Compute parent node variable before pushing with statement.
- String parentVarName = lastBlockVarName;
-
- pushExactStatement(elem, parentVarIndex);
-
- // Setup call to each func as "each_n(xxxxx, " the parent param is filled
- // in later when we known the parent variable.
- add("${funcName}(${withName}, ${parentVarName})");
- }
-
- String get lastBlockVarName {
- var varName;
- if (lastBlock != null && lastBlock.anyStatements) {
- varName = lastBlock.last.variableName;
- } else {
- varName = "_fragment";
- }
-
- return varName;
- }
-
- String injectParamName(String name) {
- // Local name _item is reserved.
- if (name != null && name == "_item") {
- return null; // Local name is not valid.
- }
-
- return (name == null) ? "_item" : name;
- }
-
- addScope(int indent, StringBuffer buff, String item) {
- String spaces = Codegen.spaces(indent);
-
- if (item == null) {
- item = "_item";
- }
- buff.write("${spaces}_scopes[\"${item}\"] = ${item};\n");
- }
-
- removeScope(int indent, StringBuffer buff, String item) {
- String spaces = Codegen.spaces(indent);
-
- if (item == null) {
- item = "_item";
- }
- buff.write("${spaces}_scopes.remove(\"${item}\");\n");
- }
-
- String defineScopes() {
- StringBuffer buff = new StringBuffer();
-
- // Construct the active scope names for name resolution.
- List<String> names = activeBlocksLocalNames();
- if (names.length > 0) {
- buff.write(" // Local scoped block names.\n");
- for (String name in names) {
- buff.write(" var ${name} = _scopes[\"${name}\"];\n");
- }
- buff.write("\n");
- }
-
- return buff.toString();
- }
-
-}
« no previous file with comments | « utils/lib/file_system_vm.dart ('k') | utils/template/htmltree.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698