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

Unified Diff: lib/src/js/printer.dart

Issue 949383003: use js_ast instead of strings to generate JS (Closed) Base URL: git@github.com:dart-lang/dart-dev-compiler.git@master
Patch Set: add redirecting ctor test Created 5 years, 10 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 | « lib/src/js/nodes.dart ('k') | lib/src/js/template.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/js/printer.dart
diff --git a/lib/src/js/printer.dart b/lib/src/js/printer.dart
index 6ee3f3ecf4df70108506f7786ea3d789019b3c0c..bbb6dc466039ae7c88630e596585e0dbb0e98af8 100644
--- a/lib/src/js/printer.dart
+++ b/lib/src/js/printer.dart
@@ -9,11 +9,13 @@ class JavaScriptPrintingOptions {
final bool shouldCompressOutput;
final bool minifyLocalVariables;
final bool preferSemicolonToNewlineInMinifiedOutput;
+ final bool avoidKeywordsInIdentifiers;
JavaScriptPrintingOptions(
{this.shouldCompressOutput: false,
this.minifyLocalVariables: false,
- this.preferSemicolonToNewlineInMinifiedOutput: false});
+ this.preferSemicolonToNewlineInMinifiedOutput: false,
+ this.avoidKeywordsInIdentifiers: false});
}
@@ -344,6 +346,20 @@ class Printer implements NodeVisitor {
blockBody(loop.body, needsSeparation: false, needsNewline: true);
}
+ visitForOf(ForOf loop) {
+ outIndent("for");
+ spaceOut();
+ out("(");
+ visitNestedExpression(loop.leftHandSide, EXPRESSION,
+ newInForInit: true, newAtStatementBegin: false);
+ out(" of");
+ pendingSpace = true;
+ visitNestedExpression(loop.iterable, EXPRESSION,
+ newInForInit: false, newAtStatementBegin: false);
+ out(")");
+ blockBody(loop.body, needsSeparation: false, needsNewline: true);
+ }
+
visitWhile(While loop) {
outIndent("while");
spaceOut();
@@ -540,7 +556,7 @@ class Printer implements NodeVisitor {
// (function() { ... })().
// ({a: 2, b: 3}.toString()).
(newAtStatementBegin && (node is NamedFunction ||
- node is Fun ||
+ node is FunctionExpression ||
node is ObjectInitializer));
if (needsParentheses) {
inForInit = false;
@@ -556,7 +572,8 @@ class Printer implements NodeVisitor {
}
visitVariableDeclarationList(VariableDeclarationList list) {
- out("var ");
+ out(list.keyword);
+ out(" ");
visitCommaSeparated(list.declarations, ASSIGNMENT,
newInForInit: inForInit, newAtStatementBegin: false);
}
@@ -763,6 +780,10 @@ class Printer implements NodeVisitor {
out("this");
}
+ visitSuper(Super node) {
+ out("super");
+ }
+
visitVariableDeclaration(VariableDeclaration decl) {
out(localNamer.getName(decl.name));
}
@@ -789,11 +810,57 @@ class Printer implements NodeVisitor {
return false;
}
}
- // TODO(floitsch): normally we should also check that the field is not a
- // reserved word. We don't generate fields with reserved word names except
- // for 'super'.
- if (field == '"super"') return false;
- return true;
+
+ if (options.avoidKeywordsInIdentifiers) {
+ return !_isJsKeyword(field.substring(1, field.length - 1));
+ } else {
+ // TODO(floitsch): normally we should also check that the field is not a
+ // reserved word. We don't generate fields with reserved word names except
+ // for 'super'.
+ return field != '"super"';
+ }
+ }
+
+ static bool _isJsKeyword(String keyword) {
+ switch (keyword) {
+ case "break":
+ case "case":
+ case "catch":
+ case "class":
+ case "const":
+ case "continue":
+ case "debugger":
+ case "default":
+ case "delete":
+ case "do":
+ case "else":
+ case "export":
+ case "extends":
+ case "finally":
+ case "for":
+ case "function":
+ case "if":
+ case "import":
+ case "in":
+ case "instanceof":
+ case "let":
+ case "new":
+ case "return":
+ case "static":
+ case "super":
+ case "switch":
+ case "this":
+ case "throw":
+ case "try":
+ case "typeof":
+ case "var":
+ case "void":
+ case "while":
+ case "with":
+ case "yield":
+ return true;
+ }
+ return false;
}
visitAccess(PropertyAccess access) {
@@ -829,6 +896,27 @@ class Printer implements NodeVisitor {
functionOut(fun, null, vars);
}
+ visitArrowFun(ArrowFun fun) {
+ VarCollector vars = new VarCollector();
+ vars.visitArrowFun(fun);
+ localNamer.enterScope(vars);
+ out("(");
+ if (fun.params != null) {
+ visitCommaSeparated(fun.params, PRIMARY,
+ newInForInit: false, newAtStatementBegin: false);
+ }
+ out(")");
+ spaceOut();
+ out("=>");
+ if (fun.body is Expression) {
+ spaceOut();
+ fun.body.accept(this);
+ } else {
+ blockBody(fun.body, needsSeparation: false, needsNewline: false);
+ }
+ localNamer.leaveScope();
+ }
+
visitLiteralBool(LiteralBool node) {
out(node.value ? "true" : "false");
}
@@ -883,20 +971,21 @@ class Printer implements NodeVisitor {
List<Property> properties = node.properties;
out("{");
indentMore();
+
+ var isOneLiner = !properties.any((p) => p.value is FunctionExpression);
for (int i = 0; i < properties.length; i++) {
- Expression value = properties[i].value;
if (i != 0) {
out(",");
- if (node.isOneLiner) spaceOut();
+ if (isOneLiner) spaceOut();
}
- if (!node.isOneLiner) {
+ if (!isOneLiner) {
forceLine();
indent();
}
visit(properties[i]);
}
indentLess();
- if (!node.isOneLiner && !properties.isEmpty) {
+ if (!isOneLiner) {
lineOut();
indent();
}
@@ -904,19 +993,7 @@ class Printer implements NodeVisitor {
}
visitProperty(Property node) {
- if (node.name is LiteralString) {
- LiteralString nameString = node.name;
- String name = nameString.value;
- if (isValidJavaScriptId(name)) {
- out(name.substring(1, name.length - 1));
- } else {
- out(name);
- }
- } else {
- assert(node.name is LiteralNumber);
- LiteralNumber nameNumber = node.name;
- out(nameNumber.value);
- }
+ propertyNameOut(node.name);
out(":");
spaceOut();
visitNestedExpression(node.value, ASSIGNMENT,
@@ -927,6 +1004,117 @@ class Printer implements NodeVisitor {
out(node.pattern);
}
+ visitTemplateString(TemplateString node) {
+ out('`');
+ for (var element in node.elements) {
+ if (element is String) {
+ out(element);
+ } else {
+ out(r'${');
+ visit(element);
+ out('}');
+ }
+ }
+ out('`');
+ }
+
+ visitTaggedTemplate(TaggedTemplate node) {
+ visit(node.tag);
+ visit(node.template);
+ }
+
+ visitClassDeclaration(ClassDeclaration node) {
+ indent();
+ visit(node.classExpr);
+ lineOut();
+ }
+
+ visitClassExpression(ClassExpression node) {
+ out('class ');
+ visit(node.name);
+ if (node.heritage != null) {
+ out(' extends ');
+ visit(node.heritage);
+ spaceOut();
+ }
+ out('{');
+ lineOut();
+ indentMore();
+ for (var method in node.methods) {
+ indent();
+ visit(method);
+ lineOut();
+ }
+ indentLess();
+ indent();
+ out('}');
+ }
+
+ visitMethod(Method node) {
+ if (node.isStatic) {
+ out('static ');
+ }
+ if (node.isGetter) {
+ out('get ');
+ } else if (node.isSetter) {
+ out('set ');
+ }
+ var vars = new VarCollector();
+ vars.visitMethod(node);
+
+ propertyNameOut(node.name, inMethod: true);
+
+ localNamer.enterScope(vars);
+ out("(");
+ var fun = node.function;
+ if (fun.params != null) {
+ visitCommaSeparated(fun.params, PRIMARY,
+ newInForInit: false, newAtStatementBegin: false);
+ }
+ out(")");
+ // TODO(jmesserly): async modifiers
+ if (fun.body.statements.isEmpty) {
+ spaceOut();
+ out("{}");
+ } else {
+ blockBody(fun.body, needsSeparation: false, needsNewline: false);
+ }
+ localNamer.leaveScope();
+ }
+
+ visitPropertyName(PropertyName node) => propertyNameOut(node);
+
+ void propertyNameOut(Expression node, {bool inMethod: false}) {
+ inForInit = false;
+ atStatementBegin = false;
+
+ if (node is LiteralNumber) {
+ LiteralNumber nameNumber = node;
+ out(nameNumber.value);
+ } else {
+ String quotedName;
+ if (node is PropertyName) {
+ quotedName = "'${node.name}'";
+ } else if (node is LiteralString) {
+ quotedName = node.value;
+ }
+ if (quotedName != null) {
+ if (isValidJavaScriptId(quotedName)) {
+ out(quotedName.substring(1, quotedName.length - 1));
+ } else {
+ if (inMethod) out("[");
+ out(quotedName);
+ if (inMethod) out("]");
+ }
+ } else {
+ // ComputedPropertyName
+ out("[");
+ visit(node);
+ out("]");
+ }
+ }
+ }
+
visitLiteralExpression(LiteralExpression node) {
String template = node.template;
List<Expression> inputs = node.inputs;
@@ -965,6 +1153,15 @@ class Printer implements NodeVisitor {
visitInterpolatedSelector(InterpolatedSelector node) =>
visitInterpolatedNode(node);
+ visitInterpolatedPropertyName(InterpolatedPropertyName node) =>
+ visitInterpolatedNode(node);
+
+ visitInterpolatedMethod(InterpolatedMethod node) =>
+ visitInterpolatedNode(node);
+
+ visitInterpolatedVariableDeclaration(InterpolatedVariableDeclaration node) =>
+ visitInterpolatedNode(node);
+
visitInterpolatedStatement(InterpolatedStatement node) {
outLn('#${node.nameOrPosition}');
}
@@ -982,6 +1179,18 @@ class Printer implements NodeVisitor {
}
}
+ void visitCommentExpression(CommentExpression node) {
+ if (shouldCompressOutput) return;
+ String comment = node.comment.trim();
+ if (comment.isEmpty) return;
+ if (comment.startsWith('/*')) {
+ out(comment);
+ } else {
+ out('/* $comment */');
+ }
+ visit(node.expression);
+ }
+
void visitAwait(Await node) {
out("await ");
visit(node.expression);
@@ -1021,7 +1230,7 @@ class VarCollector extends BaseVisitor {
void forEachVar(void fn(String v)) => vars.forEach(fn);
void forEachParam(void fn(String p)) => params.forEach(fn);
- void collectVarsInFunction(Fun fun) {
+ void collectVarsInFunction(FunctionExpression fun) {
if (!nested) {
nested = true;
if (fun.params != null) {
@@ -1029,7 +1238,7 @@ class VarCollector extends BaseVisitor {
params.add(fun.params[i].name);
}
}
- visitBlock(fun.body);
+ fun.body.accept(this);
nested = false;
}
}
@@ -1044,10 +1253,19 @@ class VarCollector extends BaseVisitor {
collectVarsInFunction(namedFunction.function);
}
+ void visitMethod(Method declaration) {
+ // Note that we don't bother collecting the name of the function.
+ collectVarsInFunction(declaration.function);
+ }
+
void visitFun(Fun fun) {
collectVarsInFunction(fun);
}
+ void visitArrowFun(ArrowFun fun) {
+ collectVarsInFunction(fun);
+ }
+
void visitThis(This node) {}
void visitVariableDeclaration(VariableDeclaration decl) {
@@ -1081,6 +1299,7 @@ class DanglingElseVisitor extends BaseVisitor<bool> {
}
bool visitFor(For node) => node.body.accept(this);
bool visitForIn(ForIn node) => node.body.accept(this);
+ bool visitForOf(ForOf node) => node.body.accept(this);
bool visitWhile(While node) => node.body.accept(this);
bool visitDo(Do node) => false;
bool visitContinue(Continue node) => false;
@@ -1102,6 +1321,7 @@ class DanglingElseVisitor extends BaseVisitor<bool> {
bool visitLabeledStatement(LabeledStatement node)
=> node.body.accept(this);
bool visitLiteralStatement(LiteralStatement node) => true;
+ bool visitClassDeclaration(ClassDeclaration) => false;
bool visitExpression(Expression node) => false;
}
« no previous file with comments | « lib/src/js/nodes.dart ('k') | lib/src/js/template.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698