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 part of js_ast; | 5 part of js_ast; |
6 | 6 |
7 | 7 |
8 class JavaScriptPrintingOptions { | 8 class JavaScriptPrintingOptions { |
9 final bool shouldCompressOutput; | 9 final bool shouldCompressOutput; |
10 final bool minifyLocalVariables; | 10 final bool minifyLocalVariables; |
11 final bool preferSemicolonToNewlineInMinifiedOutput; | 11 final bool preferSemicolonToNewlineInMinifiedOutput; |
| 12 final bool allowSingleLineIfStatements; |
12 | 13 |
13 /// True to allow keywords in properties, such as `obj.var` or `obj.function` | 14 /// True to allow keywords in properties, such as `obj.var` or `obj.function` |
14 /// Modern JS engines support this. | 15 /// Modern JS engines support this. |
15 final bool allowKeywordsInProperties; | 16 final bool allowKeywordsInProperties; |
16 | 17 |
17 /// Workaround if `this` is not bound in arrow functions. | 18 /// Workaround if `this` is not bound in arrow functions. |
18 final bool arrowFnBindThisWorkaround; | 19 final bool arrowFnBindThisWorkaround; |
19 | 20 |
20 JavaScriptPrintingOptions( | 21 JavaScriptPrintingOptions( |
21 {this.shouldCompressOutput: false, | 22 {this.shouldCompressOutput: false, |
22 this.minifyLocalVariables: false, | 23 this.minifyLocalVariables: false, |
23 this.preferSemicolonToNewlineInMinifiedOutput: false, | 24 this.preferSemicolonToNewlineInMinifiedOutput: false, |
24 this.allowKeywordsInProperties: false, | 25 this.allowKeywordsInProperties: false, |
| 26 this.allowSingleLineIfStatements: false, |
25 this.arrowFnBindThisWorkaround: false}); | 27 this.arrowFnBindThisWorkaround: false}); |
26 } | 28 } |
27 | 29 |
28 | 30 |
29 /// An environment in which JavaScript printing is done. Provides emitting of | 31 /// An environment in which JavaScript printing is done. Provides emitting of |
30 /// text and pre- and post-visit callbacks. | 32 /// text and pre- and post-visit callbacks. |
31 abstract class JavaScriptPrintingContext { | 33 abstract class JavaScriptPrintingContext { |
32 /// Signals an error. This should happen only for serious internal errors. | 34 /// Signals an error. This should happen only for serious internal errors. |
33 void error(String message) { throw message; } | 35 void error(String message) { throw message; } |
34 | 36 |
(...skipping 29 matching lines...) Expand all Loading... |
64 bool inForInit = false; | 66 bool inForInit = false; |
65 bool atStatementBegin = false; | 67 bool atStatementBegin = false; |
66 bool inNewTarget = false; | 68 bool inNewTarget = false; |
67 bool pendingSemicolon = false; | 69 bool pendingSemicolon = false; |
68 bool pendingSpace = false; | 70 bool pendingSpace = false; |
69 | 71 |
70 // The current indentation level. | 72 // The current indentation level. |
71 int _indentLevel = 0; | 73 int _indentLevel = 0; |
72 // A cache of all indentation strings used so far. | 74 // A cache of all indentation strings used so far. |
73 List<String> _indentList = <String>[""]; | 75 List<String> _indentList = <String>[""]; |
| 76 /// Whether the next call to [indent] should just be a no-op. |
| 77 bool _skipNextIndent = false; |
74 | 78 |
75 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]'); | 79 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]'); |
76 static final expressionContinuationRegExp = new RegExp(r'^[-+([]'); | 80 static final expressionContinuationRegExp = new RegExp(r'^[-+([]'); |
77 | 81 |
78 Printer(JavaScriptPrintingOptions options, | 82 Printer(JavaScriptPrintingOptions options, |
79 JavaScriptPrintingContext context, | 83 JavaScriptPrintingContext context, |
80 {LocalNamer localNamer}) | 84 {LocalNamer localNamer}) |
81 : options = options, | 85 : options = options, |
82 context = context, | 86 context = context, |
83 shouldCompressOutput = options.shouldCompressOutput, | 87 shouldCompressOutput = options.shouldCompressOutput, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 if (shouldCompressOutput) { | 178 if (shouldCompressOutput) { |
175 pendingSemicolon = true; | 179 pendingSemicolon = true; |
176 } else { | 180 } else { |
177 out(";"); | 181 out(";"); |
178 forceLine(); | 182 forceLine(); |
179 } | 183 } |
180 } | 184 } |
181 | 185 |
182 void outIndent(String str) { indent(); out(str); } | 186 void outIndent(String str) { indent(); out(str); } |
183 void outIndentLn(String str) { indent(); outLn(str); } | 187 void outIndentLn(String str) { indent(); outLn(str); } |
| 188 |
| 189 void skipNextIndent() { |
| 190 _skipNextIndent = true; |
| 191 } |
| 192 |
184 void indent() { | 193 void indent() { |
| 194 if (_skipNextIndent) { |
| 195 _skipNextIndent = false; |
| 196 return; |
| 197 } |
185 if (!shouldCompressOutput) { | 198 if (!shouldCompressOutput) { |
186 out(indentation); | 199 out(indentation); |
187 } | 200 } |
188 } | 201 } |
189 | 202 |
190 visit(Node node) { | 203 visit(Node node) { |
191 context.enterNode(node); | 204 context.enterNode(node); |
192 node.accept(this); | 205 node.accept(this); |
193 context.exitNode(node); | 206 context.exitNode(node); |
194 } | 207 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 then = new Block(<Statement>[then]); | 305 then = new Block(<Statement>[then]); |
293 } | 306 } |
294 } | 307 } |
295 if (shouldIndent) indent(); | 308 if (shouldIndent) indent(); |
296 out("if"); | 309 out("if"); |
297 spaceOut(); | 310 spaceOut(); |
298 out("("); | 311 out("("); |
299 visitNestedExpression(node.condition, EXPRESSION, | 312 visitNestedExpression(node.condition, EXPRESSION, |
300 newInForInit: false, newAtStatementBegin: false); | 313 newInForInit: false, newAtStatementBegin: false); |
301 out(")"); | 314 out(")"); |
302 bool thenWasBlock = | 315 bool thenWasBlock; |
303 blockBody(then, needsSeparation: false, needsNewline: !hasElse); | 316 if (options.allowSingleLineIfStatements && !hasElse && then is! Block) { |
| 317 thenWasBlock = false; |
| 318 spaceOut(); |
| 319 skipNextIndent(); |
| 320 visit(then); |
| 321 } else { |
| 322 thenWasBlock = |
| 323 blockBody(then, needsSeparation: false, needsNewline: !hasElse); |
| 324 } |
304 if (hasElse) { | 325 if (hasElse) { |
305 if (thenWasBlock) { | 326 if (thenWasBlock) { |
306 spaceOut(); | 327 spaceOut(); |
307 } else { | 328 } else { |
308 indent(); | 329 indent(); |
309 } | 330 } |
310 out("else"); | 331 out("else"); |
311 if (elsePart is If) { | 332 if (elsePart is If) { |
312 pendingSpace = true; | 333 pendingSpace = true; |
313 ifOut(elsePart, false); | 334 ifOut(elsePart, false); |
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1608 declare(node.name); | 1629 declare(node.name); |
1609 node.function.accept(this); | 1630 node.function.accept(this); |
1610 } | 1631 } |
1611 | 1632 |
1612 visitClassExpression(ClassExpression node) { | 1633 visitClassExpression(ClassExpression node) { |
1613 declare(node.name); | 1634 declare(node.name); |
1614 if (node.heritage != null) node.heritage.accept(this); | 1635 if (node.heritage != null) node.heritage.accept(this); |
1615 for (Method element in node.methods) element.accept(this); | 1636 for (Method element in node.methods) element.accept(this); |
1616 } | 1637 } |
1617 } | 1638 } |
OLD | NEW |