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

Side by Side Diff: pkg/dev_compiler/lib/src/js_ast/printer.dart

Issue 2752163002: Format all dart dev compiler files (Closed)
Patch Set: Created 3 years, 9 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 unified diff | Download patch
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 part of js_ast; 5 part of js_ast;
6 6
7
8 class JavaScriptPrintingOptions { 7 class JavaScriptPrintingOptions {
9 final bool shouldCompressOutput; 8 final bool shouldCompressOutput;
10 final bool minifyLocalVariables; 9 final bool minifyLocalVariables;
11 final bool preferSemicolonToNewlineInMinifiedOutput; 10 final bool preferSemicolonToNewlineInMinifiedOutput;
12 final bool emitTypes; 11 final bool emitTypes;
13 final bool allowSingleLineIfStatements; 12 final bool allowSingleLineIfStatements;
14 13
15 /// 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`
16 /// Modern JS engines support this. 15 /// Modern JS engines support this.
17 final bool allowKeywordsInProperties; 16 final bool allowKeywordsInProperties;
18 17
19 JavaScriptPrintingOptions( 18 JavaScriptPrintingOptions(
20 {this.shouldCompressOutput: false, 19 {this.shouldCompressOutput: false,
21 this.minifyLocalVariables: false, 20 this.minifyLocalVariables: false,
22 this.preferSemicolonToNewlineInMinifiedOutput: false, 21 this.preferSemicolonToNewlineInMinifiedOutput: false,
23 this.emitTypes: false, 22 this.emitTypes: false,
24 this.allowKeywordsInProperties: false, 23 this.allowKeywordsInProperties: false,
25 this.allowSingleLineIfStatements: false}); 24 this.allowSingleLineIfStatements: false});
26 } 25 }
27 26
28
29 /// An environment in which JavaScript printing is done. Provides emitting of 27 /// An environment in which JavaScript printing is done. Provides emitting of
30 /// text and pre- and post-visit callbacks. 28 /// text and pre- and post-visit callbacks.
31 abstract class JavaScriptPrintingContext { 29 abstract class JavaScriptPrintingContext {
32 /// Signals an error. This should happen only for serious internal errors. 30 /// Signals an error. This should happen only for serious internal errors.
33 void error(String message) { throw message; } 31 void error(String message) {
32 throw message;
33 }
34 34
35 /// Adds [string] to the output. 35 /// Adds [string] to the output.
36 void emit(String string); 36 void emit(String string);
37 37
38 /// Callback immediately before printing [node]. Whitespace may be printed 38 /// Callback immediately before printing [node]. Whitespace may be printed
39 /// after this callback before the first non-whitespace character for [node]. 39 /// after this callback before the first non-whitespace character for [node].
40 void enterNode(Node node) {} 40 void enterNode(Node node) {}
41
41 /// Callback after printing the last character representing [node]. 42 /// Callback after printing the last character representing [node].
42 void exitNode(Node node) {} 43 void exitNode(Node node) {}
43 } 44 }
44 45
45 /// A simple implementation of [JavaScriptPrintingContext] suitable for tests. 46 /// A simple implementation of [JavaScriptPrintingContext] suitable for tests.
46 class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext { 47 class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext {
47 final StringBuffer buffer = new StringBuffer(); 48 final StringBuffer buffer = new StringBuffer();
48 49
49 void emit(String string) { 50 void emit(String string) {
50 buffer.write(string); 51 buffer.write(string);
(...skipping 14 matching lines...) Expand all
65 bool inForInit = false; 66 bool inForInit = false;
66 bool atStatementBegin = false; 67 bool atStatementBegin = false;
67 bool inNewTarget = false; 68 bool inNewTarget = false;
68 bool pendingSemicolon = false; 69 bool pendingSemicolon = false;
69 bool pendingSpace = false; 70 bool pendingSpace = false;
70 71
71 // The current indentation level. 72 // The current indentation level.
72 int _indentLevel = 0; 73 int _indentLevel = 0;
73 // A cache of all indentation strings used so far. 74 // A cache of all indentation strings used so far.
74 List<String> _indentList = <String>[""]; 75 List<String> _indentList = <String>[""];
76
75 /// Whether the next call to [indent] should just be a no-op. 77 /// Whether the next call to [indent] should just be a no-op.
76 bool _skipNextIndent = false; 78 bool _skipNextIndent = false;
77 79
78 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]'); 80 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]');
79 static final expressionContinuationRegExp = new RegExp(r'^[-+([]'); 81 static final expressionContinuationRegExp = new RegExp(r'^[-+([]');
80 82
81 Printer(JavaScriptPrintingOptions options, 83 Printer(JavaScriptPrintingOptions options, JavaScriptPrintingContext context,
82 JavaScriptPrintingContext context, 84 {LocalNamer localNamer})
83 {LocalNamer localNamer})
84 : options = options, 85 : options = options,
85 context = context, 86 context = context,
86 shouldCompressOutput = options.shouldCompressOutput, 87 shouldCompressOutput = options.shouldCompressOutput,
87 danglingElseVisitor = new DanglingElseVisitor(context), 88 danglingElseVisitor = new DanglingElseVisitor(context),
88 localNamer = determineRenamer(localNamer, options); 89 localNamer = determineRenamer(localNamer, options);
89 90
90 static LocalNamer determineRenamer(LocalNamer localNamer, 91 static LocalNamer determineRenamer(
91 JavaScriptPrintingOptions options) { 92 LocalNamer localNamer, JavaScriptPrintingOptions options) {
92 if (localNamer != null) return localNamer; 93 if (localNamer != null) return localNamer;
93 return (options.shouldCompressOutput && options.minifyLocalVariables) 94 return (options.shouldCompressOutput && options.minifyLocalVariables)
94 ? new MinifyRenamer() : new IdentityNamer(); 95 ? new MinifyRenamer()
96 : new IdentityNamer();
95 } 97 }
96 98
97
98 // The current indentation string. 99 // The current indentation string.
99 String get indentation { 100 String get indentation {
100 // Lazily add new indentation strings as required. 101 // Lazily add new indentation strings as required.
101 while (_indentList.length <= _indentLevel) { 102 while (_indentList.length <= _indentLevel) {
102 _indentList.add(_indentList.last + " "); 103 _indentList.add(_indentList.last + " ");
103 } 104 }
104 return _indentList[_indentLevel]; 105 return _indentList[_indentLevel];
105 } 106 }
106 107
107 void indentMore() { 108 void indentMore() {
108 _indentLevel++; 109 _indentLevel++;
109 } 110 }
110 111
111 void indentLess() { 112 void indentLess() {
112 _indentLevel--; 113 _indentLevel--;
113 } 114 }
114 115
115
116 /// Always emit a newline, even under `enableMinification`. 116 /// Always emit a newline, even under `enableMinification`.
117 void forceLine() { 117 void forceLine() {
118 out("\n"); 118 out("\n");
119 } 119 }
120
120 /// Emits a newline for readability. 121 /// Emits a newline for readability.
121 void lineOut() { 122 void lineOut() {
122 if (!shouldCompressOutput) forceLine(); 123 if (!shouldCompressOutput) forceLine();
123 } 124 }
125
124 void spaceOut() { 126 void spaceOut() {
125 if (!shouldCompressOutput) out(" "); 127 if (!shouldCompressOutput) out(" ");
126 } 128 }
127 129
128 String lastAddedString = null; 130 String lastAddedString = null;
129 int get lastCharCode { 131 int get lastCharCode {
130 if (lastAddedString == null) return 0; 132 if (lastAddedString == null) return 0;
131 assert(lastAddedString.length != ""); 133 assert(lastAddedString.length != "");
132 return lastAddedString.codeUnitAt(lastAddedString.length - 1); 134 return lastAddedString.codeUnitAt(lastAddedString.length - 1);
133 } 135 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 177
176 void outSemicolonLn() { 178 void outSemicolonLn() {
177 if (shouldCompressOutput) { 179 if (shouldCompressOutput) {
178 pendingSemicolon = true; 180 pendingSemicolon = true;
179 } else { 181 } else {
180 out(";"); 182 out(";");
181 forceLine(); 183 forceLine();
182 } 184 }
183 } 185 }
184 186
185 void outIndent(String str) { indent(); out(str); } 187 void outIndent(String str) {
186 void outIndentLn(String str) { indent(); outLn(str); } 188 indent();
189 out(str);
190 }
191
192 void outIndentLn(String str) {
193 indent();
194 outLn(str);
195 }
187 196
188 void skipNextIndent() { 197 void skipNextIndent() {
189 _skipNextIndent = true; 198 _skipNextIndent = true;
190 } 199 }
191 200
192 void indent() { 201 void indent() {
193 if (_skipNextIndent) { 202 if (_skipNextIndent) {
194 _skipNextIndent = false; 203 _skipNextIndent = false;
195 return; 204 return;
196 } 205 }
197 if (!shouldCompressOutput) { 206 if (!shouldCompressOutput) {
198 out(indentation); 207 out(indentation);
199 } 208 }
200 } 209 }
201 210
202 visit(Node node) { 211 visit(Node node) {
203 context.enterNode(node); 212 context.enterNode(node);
204 node.accept(this); 213 node.accept(this);
205 context.exitNode(node); 214 context.exitNode(node);
206 } 215 }
207 216
208 visitCommaSeparated(List<Node> nodes, int hasRequiredType, 217 visitCommaSeparated(List<Node> nodes, int hasRequiredType,
209 {bool newInForInit, bool newAtStatementBegin}) { 218 {bool newInForInit, bool newAtStatementBegin}) {
210 for (int i = 0; i < nodes.length; i++) { 219 for (int i = 0; i < nodes.length; i++) {
211 if (i != 0) { 220 if (i != 0) {
212 atStatementBegin = false; 221 atStatementBegin = false;
213 out(","); 222 out(",");
214 spaceOut(); 223 spaceOut();
215 } 224 }
216 visitNestedExpression(nodes[i], hasRequiredType, 225 visitNestedExpression(nodes[i], hasRequiredType,
217 newInForInit: newInForInit, 226 newInForInit: newInForInit, newAtStatementBegin: newAtStatementBegin);
218 newAtStatementBegin: newAtStatementBegin);
219 } 227 }
220 } 228 }
221 229
222 visitAll(List<Node> nodes) { 230 visitAll(List<Node> nodes) {
223 nodes.forEach(visit); 231 nodes.forEach(visit);
224 } 232 }
225 233
226 visitProgram(Program program) { 234 visitProgram(Program program) {
227 if (program.scriptTag != null) { 235 if (program.scriptTag != null) {
228 out('#!${program.scriptTag}\n'); 236 out('#!${program.scriptTag}\n');
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 } 283 }
276 284
277 visitBlock(Block block) { 285 visitBlock(Block block) {
278 blockOut(block, true, true); 286 blockOut(block, true, true);
279 } 287 }
280 288
281 visitExpressionStatement(ExpressionStatement expressionStatement) { 289 visitExpressionStatement(ExpressionStatement expressionStatement) {
282 indent(); 290 indent();
283 outClosureAnnotation(expressionStatement); 291 outClosureAnnotation(expressionStatement);
284 visitNestedExpression(expressionStatement.expression, EXPRESSION, 292 visitNestedExpression(expressionStatement.expression, EXPRESSION,
285 newInForInit: false, newAtStatementBegin: true); 293 newInForInit: false, newAtStatementBegin: true);
286 outSemicolonLn(); 294 outSemicolonLn();
287 } 295 }
288 296
289 visitEmptyStatement(EmptyStatement nop) { 297 visitEmptyStatement(EmptyStatement nop) {
290 outIndentLn(";"); 298 outIndentLn(";");
291 } 299 }
292 300
293 void ifOut(If node, bool shouldIndent) { 301 void ifOut(If node, bool shouldIndent) {
294 Node then = node.then; 302 Node then = node.then;
295 Node elsePart = node.otherwise; 303 Node elsePart = node.otherwise;
296 bool hasElse = node.hasElse; 304 bool hasElse = node.hasElse;
297 305
298 // Handle dangling elses and a work-around for Android 4.0 stock browser. 306 // Handle dangling elses and a work-around for Android 4.0 stock browser.
299 // Android 4.0 requires braces for a single do-while in the `then` branch. 307 // Android 4.0 requires braces for a single do-while in the `then` branch.
300 // See issue 10923. 308 // See issue 10923.
301 if (hasElse) { 309 if (hasElse) {
302 bool needsBraces = node.then.accept(danglingElseVisitor) || then is Do; 310 bool needsBraces = node.then.accept(danglingElseVisitor) || then is Do;
303 if (needsBraces) { 311 if (needsBraces) {
304 then = new Block(<Statement>[then]); 312 then = new Block(<Statement>[then]);
305 } 313 }
306 } 314 }
307 if (shouldIndent) indent(); 315 if (shouldIndent) indent();
308 out("if"); 316 out("if");
309 spaceOut(); 317 spaceOut();
310 out("("); 318 out("(");
311 visitNestedExpression(node.condition, EXPRESSION, 319 visitNestedExpression(node.condition, EXPRESSION,
312 newInForInit: false, newAtStatementBegin: false); 320 newInForInit: false, newAtStatementBegin: false);
313 out(")"); 321 out(")");
314 bool thenWasBlock; 322 bool thenWasBlock;
315 if (options.allowSingleLineIfStatements && !hasElse && then is! Block) { 323 if (options.allowSingleLineIfStatements && !hasElse && then is! Block) {
316 thenWasBlock = false; 324 thenWasBlock = false;
317 spaceOut(); 325 spaceOut();
318 skipNextIndent(); 326 skipNextIndent();
319 visit(then); 327 visit(then);
320 } else { 328 } else {
321 thenWasBlock = 329 thenWasBlock =
322 blockBody(then, needsSeparation: false, needsNewline: !hasElse); 330 blockBody(then, needsSeparation: false, needsNewline: !hasElse);
(...skipping 17 matching lines...) Expand all
340 visitIf(If node) { 348 visitIf(If node) {
341 ifOut(node, true); 349 ifOut(node, true);
342 } 350 }
343 351
344 visitFor(For loop) { 352 visitFor(For loop) {
345 outIndent("for"); 353 outIndent("for");
346 spaceOut(); 354 spaceOut();
347 out("("); 355 out("(");
348 if (loop.init != null) { 356 if (loop.init != null) {
349 visitNestedExpression(loop.init, EXPRESSION, 357 visitNestedExpression(loop.init, EXPRESSION,
350 newInForInit: true, newAtStatementBegin: false); 358 newInForInit: true, newAtStatementBegin: false);
351 } 359 }
352 out(";"); 360 out(";");
353 if (loop.condition != null) { 361 if (loop.condition != null) {
354 spaceOut(); 362 spaceOut();
355 visitNestedExpression(loop.condition, EXPRESSION, 363 visitNestedExpression(loop.condition, EXPRESSION,
356 newInForInit: false, newAtStatementBegin: false); 364 newInForInit: false, newAtStatementBegin: false);
357 } 365 }
358 out(";"); 366 out(";");
359 if (loop.update != null) { 367 if (loop.update != null) {
360 spaceOut(); 368 spaceOut();
361 visitNestedExpression(loop.update, EXPRESSION, 369 visitNestedExpression(loop.update, EXPRESSION,
362 newInForInit: false, newAtStatementBegin: false); 370 newInForInit: false, newAtStatementBegin: false);
363 } 371 }
364 out(")"); 372 out(")");
365 blockBody(loop.body, needsSeparation: false, needsNewline: true); 373 blockBody(loop.body, needsSeparation: false, needsNewline: true);
366 } 374 }
367 375
368 visitForIn(ForIn loop) { 376 visitForIn(ForIn loop) {
369 outIndent("for"); 377 outIndent("for");
370 spaceOut(); 378 spaceOut();
371 out("("); 379 out("(");
372 visitNestedExpression(loop.leftHandSide, EXPRESSION, 380 visitNestedExpression(loop.leftHandSide, EXPRESSION,
373 newInForInit: true, newAtStatementBegin: false); 381 newInForInit: true, newAtStatementBegin: false);
374 out(" in"); 382 out(" in");
375 pendingSpace = true; 383 pendingSpace = true;
376 visitNestedExpression(loop.object, EXPRESSION, 384 visitNestedExpression(loop.object, EXPRESSION,
377 newInForInit: false, newAtStatementBegin: false); 385 newInForInit: false, newAtStatementBegin: false);
378 out(")"); 386 out(")");
379 blockBody(loop.body, needsSeparation: false, needsNewline: true); 387 blockBody(loop.body, needsSeparation: false, needsNewline: true);
380 } 388 }
381 389
382 visitForOf(ForOf loop) { 390 visitForOf(ForOf loop) {
383 outIndent("for"); 391 outIndent("for");
384 spaceOut(); 392 spaceOut();
385 out("("); 393 out("(");
386 visitNestedExpression(loop.leftHandSide, EXPRESSION, 394 visitNestedExpression(loop.leftHandSide, EXPRESSION,
387 newInForInit: true, newAtStatementBegin: false); 395 newInForInit: true, newAtStatementBegin: false);
388 out(" of"); 396 out(" of");
389 pendingSpace = true; 397 pendingSpace = true;
390 visitNestedExpression(loop.iterable, EXPRESSION, 398 visitNestedExpression(loop.iterable, EXPRESSION,
391 newInForInit: false, newAtStatementBegin: false); 399 newInForInit: false, newAtStatementBegin: false);
392 out(")"); 400 out(")");
393 blockBody(loop.body, needsSeparation: false, needsNewline: true); 401 blockBody(loop.body, needsSeparation: false, needsNewline: true);
394 } 402 }
395 403
396 visitWhile(While loop) { 404 visitWhile(While loop) {
397 outIndent("while"); 405 outIndent("while");
398 spaceOut(); 406 spaceOut();
399 out("("); 407 out("(");
400 visitNestedExpression(loop.condition, EXPRESSION, 408 visitNestedExpression(loop.condition, EXPRESSION,
401 newInForInit: false, newAtStatementBegin: false); 409 newInForInit: false, newAtStatementBegin: false);
402 out(")"); 410 out(")");
403 blockBody(loop.body, needsSeparation: false, needsNewline: true); 411 blockBody(loop.body, needsSeparation: false, needsNewline: true);
404 } 412 }
405 413
406 visitDo(Do loop) { 414 visitDo(Do loop) {
407 outIndent("do"); 415 outIndent("do");
408 if (blockBody(loop.body, needsSeparation: true, needsNewline: false)) { 416 if (blockBody(loop.body, needsSeparation: true, needsNewline: false)) {
409 spaceOut(); 417 spaceOut();
410 } else { 418 } else {
411 indent(); 419 indent();
412 } 420 }
413 out("while"); 421 out("while");
414 spaceOut(); 422 spaceOut();
415 out("("); 423 out("(");
416 visitNestedExpression(loop.condition, EXPRESSION, 424 visitNestedExpression(loop.condition, EXPRESSION,
417 newInForInit: false, newAtStatementBegin: false); 425 newInForInit: false, newAtStatementBegin: false);
418 out(")"); 426 out(")");
419 outSemicolonLn(); 427 outSemicolonLn();
420 } 428 }
421 429
422 visitContinue(Continue node) { 430 visitContinue(Continue node) {
423 if (node.targetLabel == null) { 431 if (node.targetLabel == null) {
424 outIndent("continue"); 432 outIndent("continue");
425 } else { 433 } else {
426 outIndent("continue ${node.targetLabel}"); 434 outIndent("continue ${node.targetLabel}");
427 } 435 }
428 outSemicolonLn(); 436 outSemicolonLn();
429 } 437 }
430 438
431 visitBreak(Break node) { 439 visitBreak(Break node) {
432 if (node.targetLabel == null) { 440 if (node.targetLabel == null) {
433 outIndent("break"); 441 outIndent("break");
434 } else { 442 } else {
435 outIndent("break ${node.targetLabel}"); 443 outIndent("break ${node.targetLabel}");
436 } 444 }
437 outSemicolonLn(); 445 outSemicolonLn();
438 } 446 }
439 447
440 visitReturn(Return node) { 448 visitReturn(Return node) {
441 if (node.value == null) { 449 if (node.value == null) {
442 outIndent("return"); 450 outIndent("return");
443 } else { 451 } else {
444 outIndent("return"); 452 outIndent("return");
445 pendingSpace = true; 453 pendingSpace = true;
446 visitNestedExpression(node.value, EXPRESSION, 454 visitNestedExpression(node.value, EXPRESSION,
447 newInForInit: false, newAtStatementBegin: false); 455 newInForInit: false, newAtStatementBegin: false);
448 } 456 }
449 outSemicolonLn(); 457 outSemicolonLn();
450 } 458 }
451 459
452 visitDartYield(DartYield node) { 460 visitDartYield(DartYield node) {
453 if (node.hasStar) { 461 if (node.hasStar) {
454 outIndent("yield*"); 462 outIndent("yield*");
455 } else { 463 } else {
456 outIndent("yield"); 464 outIndent("yield");
457 } 465 }
458 pendingSpace = true; 466 pendingSpace = true;
459 visitNestedExpression(node.expression, EXPRESSION, 467 visitNestedExpression(node.expression, EXPRESSION,
460 newInForInit: false, newAtStatementBegin: false); 468 newInForInit: false, newAtStatementBegin: false);
461 outSemicolonLn(); 469 outSemicolonLn();
462 } 470 }
463 471
464
465 visitThrow(Throw node) { 472 visitThrow(Throw node) {
466 outIndent("throw"); 473 outIndent("throw");
467 pendingSpace = true; 474 pendingSpace = true;
468 visitNestedExpression(node.expression, EXPRESSION, 475 visitNestedExpression(node.expression, EXPRESSION,
469 newInForInit: false, newAtStatementBegin: false); 476 newInForInit: false, newAtStatementBegin: false);
470 outSemicolonLn(); 477 outSemicolonLn();
471 } 478 }
472 479
473 visitTry(Try node) { 480 visitTry(Try node) {
474 outIndent("try"); 481 outIndent("try");
475 blockBody(node.body, needsSeparation: true, needsNewline: false); 482 blockBody(node.body, needsSeparation: true, needsNewline: false);
476 if (node.catchPart != null) { 483 if (node.catchPart != null) {
477 visit(node.catchPart); 484 visit(node.catchPart);
478 } 485 }
479 if (node.finallyPart != null) { 486 if (node.finallyPart != null) {
480 spaceOut(); 487 spaceOut();
481 out("finally"); 488 out("finally");
482 blockBody(node.finallyPart, needsSeparation: true, needsNewline: true); 489 blockBody(node.finallyPart, needsSeparation: true, needsNewline: true);
483 } else { 490 } else {
484 lineOut(); 491 lineOut();
485 } 492 }
486 } 493 }
487 494
488 visitCatch(Catch node) { 495 visitCatch(Catch node) {
489 spaceOut(); 496 spaceOut();
490 out("catch"); 497 out("catch");
491 spaceOut(); 498 spaceOut();
492 out("("); 499 out("(");
493 visitNestedExpression(node.declaration, EXPRESSION, 500 visitNestedExpression(node.declaration, EXPRESSION,
494 newInForInit: false, newAtStatementBegin: false); 501 newInForInit: false, newAtStatementBegin: false);
495 out(")"); 502 out(")");
496 blockBody(node.body, needsSeparation: false, needsNewline: true); 503 blockBody(node.body, needsSeparation: false, needsNewline: true);
497 } 504 }
498 505
499 visitSwitch(Switch node) { 506 visitSwitch(Switch node) {
500 outIndent("switch"); 507 outIndent("switch");
501 spaceOut(); 508 spaceOut();
502 out("("); 509 out("(");
503 visitNestedExpression(node.key, EXPRESSION, 510 visitNestedExpression(node.key, EXPRESSION,
504 newInForInit: false, newAtStatementBegin: false); 511 newInForInit: false, newAtStatementBegin: false);
505 out(")"); 512 out(")");
506 spaceOut(); 513 spaceOut();
507 outLn("{"); 514 outLn("{");
508 indentMore(); 515 indentMore();
509 visitAll(node.cases); 516 visitAll(node.cases);
510 indentLess(); 517 indentLess();
511 outIndentLn("}"); 518 outIndentLn("}");
512 } 519 }
513 520
514 visitCase(Case node) { 521 visitCase(Case node) {
515 outIndent("case"); 522 outIndent("case");
516 pendingSpace = true; 523 pendingSpace = true;
517 visitNestedExpression(node.expression, EXPRESSION, 524 visitNestedExpression(node.expression, EXPRESSION,
518 newInForInit: false, newAtStatementBegin: false); 525 newInForInit: false, newAtStatementBegin: false);
519 outLn(":"); 526 outLn(":");
520 if (!node.body.statements.isEmpty) { 527 if (!node.body.statements.isEmpty) {
521 blockOut(node.body, true, true); 528 blockOut(node.body, true, true);
522 } 529 }
523 } 530 }
524 531
525 visitDefault(Default node) { 532 visitDefault(Default node) {
526 outIndentLn("default:"); 533 outIndentLn("default:");
527 if (!node.body.statements.isEmpty) { 534 if (!node.body.statements.isEmpty) {
528 blockOut(node.body, true, true); 535 blockOut(node.body, true, true);
529 } 536 }
530 } 537 }
531 538
532 visitLabeledStatement(LabeledStatement node) { 539 visitLabeledStatement(LabeledStatement node) {
533 outIndent("${node.label}:"); 540 outIndent("${node.label}:");
534 blockBody(node.body, needsSeparation: false, needsNewline: true); 541 blockBody(node.body, needsSeparation: false, needsNewline: true);
535 } 542 }
536 543
537 void functionOut(Fun fun, Node name) { 544 void functionOut(Fun fun, Node name) {
538 out("function"); 545 out("function");
539 if (fun.isGenerator) out("*"); 546 if (fun.isGenerator) out("*");
540 if (name != null) { 547 if (name != null) {
541 out(" "); 548 out(" ");
542 // Name must be a [Decl]. Therefore only test for primary expressions. 549 // Name must be a [Decl]. Therefore only test for primary expressions.
543 visitNestedExpression(name, PRIMARY, 550 visitNestedExpression(name, PRIMARY,
544 newInForInit: false, newAtStatementBegin: false); 551 newInForInit: false, newAtStatementBegin: false);
545 } 552 }
546 localNamer.enterScope(fun); 553 localNamer.enterScope(fun);
547 outTypeParams(fun.typeParams); 554 outTypeParams(fun.typeParams);
548 out("("); 555 out("(");
549 if (fun.params != null) { 556 if (fun.params != null) {
550 visitCommaSeparated(fun.params, PRIMARY, 557 visitCommaSeparated(fun.params, PRIMARY,
551 newInForInit: false, newAtStatementBegin: false); 558 newInForInit: false, newAtStatementBegin: false);
552 } 559 }
553 out(")"); 560 out(")");
554 outTypeAnnotation(fun.returnType); 561 outTypeAnnotation(fun.returnType);
555 switch (fun.asyncModifier) { 562 switch (fun.asyncModifier) {
556 case const AsyncModifier.sync(): 563 case const AsyncModifier.sync():
557 break; 564 break;
558 case const AsyncModifier.async(): 565 case const AsyncModifier.async():
559 out(' async'); 566 out(' async');
560 break; 567 break;
561 case const AsyncModifier.syncStar(): 568 case const AsyncModifier.syncStar():
562 out(' sync*'); 569 out(' sync*');
563 break; 570 break;
564 case const AsyncModifier.asyncStar(): 571 case const AsyncModifier.asyncStar():
565 out(' async*'); 572 out(' async*');
566 break; 573 break;
567 } 574 }
568 blockBody(fun.body, needsSeparation: false, needsNewline: false); 575 blockBody(fun.body, needsSeparation: false, needsNewline: false);
569 localNamer.leaveScope(); 576 localNamer.leaveScope();
570 } 577 }
571 578
572 visitFunctionDeclaration(FunctionDeclaration declaration) { 579 visitFunctionDeclaration(FunctionDeclaration declaration) {
573 indent(); 580 indent();
574 outClosureAnnotation(declaration); 581 outClosureAnnotation(declaration);
575 functionOut(declaration.function, declaration.name); 582 functionOut(declaration.function, declaration.name);
576 lineOut(); 583 lineOut();
577 } 584 }
578 585
579 visitNestedExpression(Expression node, int requiredPrecedence, 586 visitNestedExpression(Expression node, int requiredPrecedence,
580 {bool newInForInit, bool newAtStatementBegin}) { 587 {bool newInForInit, bool newAtStatementBegin}) {
581 int nodePrecedence = node.precedenceLevel; 588 int nodePrecedence = node.precedenceLevel;
582 bool needsParentheses = 589 bool needsParentheses =
583 // a - (b + c). 590 // a - (b + c).
584 (requiredPrecedence != EXPRESSION && 591 (requiredPrecedence != EXPRESSION &&
585 nodePrecedence < requiredPrecedence) || 592 nodePrecedence < requiredPrecedence) ||
586 // for (a = (x in o); ... ; ... ) { ... } 593 // for (a = (x in o); ... ; ... ) { ... }
587 (newInForInit && node is Binary && node.op == "in") || 594 (newInForInit && node is Binary && node.op == "in") ||
588 // (function() { ... })(). 595 // (function() { ... })().
589 // ({a: 2, b: 3}.toString()). 596 // ({a: 2, b: 3}.toString()).
590 (newAtStatementBegin && (node is NamedFunction || 597 (newAtStatementBegin &&
591 node is FunctionExpression || 598 (node is NamedFunction ||
592 node is ObjectInitializer)); 599 node is FunctionExpression ||
600 node is ObjectInitializer));
593 if (needsParentheses) { 601 if (needsParentheses) {
594 inForInit = false; 602 inForInit = false;
595 atStatementBegin = false; 603 atStatementBegin = false;
596 inNewTarget = false; 604 inNewTarget = false;
597 out("("); 605 out("(");
598 visit(node); 606 visit(node);
599 out(")"); 607 out(")");
600 } else { 608 } else {
601 inForInit = newInForInit; 609 inForInit = newInForInit;
602 atStatementBegin = newAtStatementBegin; 610 atStatementBegin = newAtStatementBegin;
603 visit(node); 611 visit(node);
604 } 612 }
605 } 613 }
606 614
607 visitVariableDeclarationList(VariableDeclarationList list) { 615 visitVariableDeclarationList(VariableDeclarationList list) {
608 outClosureAnnotation(list); 616 outClosureAnnotation(list);
609 // Note: keyword can be null for non-static field declarations. 617 // Note: keyword can be null for non-static field declarations.
610 if (list.keyword != null) { 618 if (list.keyword != null) {
611 out(list.keyword); 619 out(list.keyword);
612 out(" "); 620 out(" ");
613 } 621 }
614 visitCommaSeparated(list.declarations, ASSIGNMENT, 622 visitCommaSeparated(list.declarations, ASSIGNMENT,
615 newInForInit: inForInit, newAtStatementBegin: false); 623 newInForInit: inForInit, newAtStatementBegin: false);
616 } 624 }
617 625
618 visitArrayBindingPattern(ArrayBindingPattern node) { 626 visitArrayBindingPattern(ArrayBindingPattern node) {
619 out("["); 627 out("[");
620 visitCommaSeparated(node.variables, EXPRESSION, 628 visitCommaSeparated(node.variables, EXPRESSION,
621 newInForInit: false, newAtStatementBegin: false); 629 newInForInit: false, newAtStatementBegin: false);
622 out("]"); 630 out("]");
623 } 631 }
632
624 visitObjectBindingPattern(ObjectBindingPattern node) { 633 visitObjectBindingPattern(ObjectBindingPattern node) {
625 out("{"); 634 out("{");
626 visitCommaSeparated(node.variables, EXPRESSION, 635 visitCommaSeparated(node.variables, EXPRESSION,
627 newInForInit: false, newAtStatementBegin: false); 636 newInForInit: false, newAtStatementBegin: false);
628 out("}"); 637 out("}");
629 } 638 }
630 639
631 visitDestructuredVariable(DestructuredVariable node) { 640 visitDestructuredVariable(DestructuredVariable node) {
632 var name = node.name; 641 var name = node.name;
633 var hasName = name != null; 642 var hasName = name != null;
634 if (hasName) { 643 if (hasName) {
635 if (name is LiteralString) { 644 if (name is LiteralString) {
636 out("["); 645 out("[");
637 out(name.value); 646 out(name.value);
638 out("]"); 647 out("]");
639 } else { 648 } else {
640 visit(name); 649 visit(name);
641 } 650 }
642 } 651 }
643 if (node.structure != null) { 652 if (node.structure != null) {
644 if (hasName) { 653 if (hasName) {
645 out(":"); 654 out(":");
646 spaceOut(); 655 spaceOut();
647 } 656 }
648 visit(node.structure); 657 visit(node.structure);
649 } 658 }
650 outTypeAnnotation(node.type); 659 outTypeAnnotation(node.type);
651 if (node.defaultValue != null) { 660 if (node.defaultValue != null) {
652 spaceOut(); 661 spaceOut();
653 out("="); 662 out("=");
654 spaceOut(); 663 spaceOut();
655 visitNestedExpression(node.defaultValue, EXPRESSION, 664 visitNestedExpression(node.defaultValue, EXPRESSION,
656 newInForInit: false, newAtStatementBegin: false); 665 newInForInit: false, newAtStatementBegin: false);
657 } 666 }
658 } 667 }
659 668
660 visitSimpleBindingPattern(SimpleBindingPattern node) { 669 visitSimpleBindingPattern(SimpleBindingPattern node) {
661 visit(node.name); 670 visit(node.name);
662 } 671 }
663 672
664 visitAssignment(Assignment assignment) { 673 visitAssignment(Assignment assignment) {
665 visitNestedExpression(assignment.leftHandSide, LEFT_HAND_SIDE, 674 visitNestedExpression(assignment.leftHandSide, LEFT_HAND_SIDE,
666 newInForInit: inForInit, 675 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
667 newAtStatementBegin: atStatementBegin);
668 if (assignment.value != null) { 676 if (assignment.value != null) {
669 spaceOut(); 677 spaceOut();
670 String op = assignment.op; 678 String op = assignment.op;
671 if (op != null) out(op); 679 if (op != null) out(op);
672 out("="); 680 out("=");
673 spaceOut(); 681 spaceOut();
674 visitNestedExpression(assignment.value, ASSIGNMENT, 682 visitNestedExpression(assignment.value, ASSIGNMENT,
675 newInForInit: inForInit, 683 newInForInit: inForInit, newAtStatementBegin: false);
676 newAtStatementBegin: false);
677 } 684 }
678 } 685 }
679 686
680 visitVariableInitialization(VariableInitialization initialization) { 687 visitVariableInitialization(VariableInitialization initialization) {
681 outClosureAnnotation(initialization); 688 outClosureAnnotation(initialization);
682 visitAssignment(initialization); 689 visitAssignment(initialization);
683 } 690 }
684 691
685 visitConditional(Conditional cond) { 692 visitConditional(Conditional cond) {
686 visitNestedExpression(cond.condition, LOGICAL_OR, 693 visitNestedExpression(cond.condition, LOGICAL_OR,
687 newInForInit: inForInit, 694 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
688 newAtStatementBegin: atStatementBegin);
689 spaceOut(); 695 spaceOut();
690 out("?"); 696 out("?");
691 spaceOut(); 697 spaceOut();
692 // The then part is allowed to have an 'in'. 698 // The then part is allowed to have an 'in'.
693 visitNestedExpression(cond.then, ASSIGNMENT, 699 visitNestedExpression(cond.then, ASSIGNMENT,
694 newInForInit: false, newAtStatementBegin: false); 700 newInForInit: false, newAtStatementBegin: false);
695 spaceOut(); 701 spaceOut();
696 out(":"); 702 out(":");
697 spaceOut(); 703 spaceOut();
698 visitNestedExpression(cond.otherwise, ASSIGNMENT, 704 visitNestedExpression(cond.otherwise, ASSIGNMENT,
699 newInForInit: inForInit, newAtStatementBegin: false); 705 newInForInit: inForInit, newAtStatementBegin: false);
700 } 706 }
701 707
702 visitNew(New node) { 708 visitNew(New node) {
703 out("new "); 709 out("new ");
704 inNewTarget = true; 710 inNewTarget = true;
705 visitNestedExpression(node.target, ACCESS, 711 visitNestedExpression(node.target, ACCESS,
706 newInForInit: inForInit, newAtStatementBegin: false); 712 newInForInit: inForInit, newAtStatementBegin: false);
707 inNewTarget = false; 713 inNewTarget = false;
708 out("("); 714 out("(");
709 visitCommaSeparated(node.arguments, SPREAD, 715 visitCommaSeparated(node.arguments, SPREAD,
710 newInForInit: false, newAtStatementBegin: false); 716 newInForInit: false, newAtStatementBegin: false);
711 out(")"); 717 out(")");
712 } 718 }
713 719
714 visitCall(Call call) { 720 visitCall(Call call) {
715 visitNestedExpression(call.target, LEFT_HAND_SIDE, 721 visitNestedExpression(call.target, LEFT_HAND_SIDE,
716 newInForInit: inForInit, 722 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
717 newAtStatementBegin: atStatementBegin);
718 out("("); 723 out("(");
719 visitCommaSeparated(call.arguments, SPREAD, 724 visitCommaSeparated(call.arguments, SPREAD,
720 newInForInit: false, newAtStatementBegin: false); 725 newInForInit: false, newAtStatementBegin: false);
721 out(")"); 726 out(")");
722 } 727 }
723 728
724 visitBinary(Binary binary) { 729 visitBinary(Binary binary) {
725 Expression left = binary.left; 730 Expression left = binary.left;
726 Expression right = binary.right; 731 Expression right = binary.right;
727 String op = binary.op; 732 String op = binary.op;
728 int leftPrecedenceRequirement; 733 int leftPrecedenceRequirement;
729 int rightPrecedenceRequirement; 734 int rightPrecedenceRequirement;
730 bool leftSpace = true; // left<HERE>op right 735 bool leftSpace = true; // left<HERE>op right
731 switch (op) { 736 switch (op) {
732 case ',': 737 case ',':
733 // x, (y, z) <=> (x, y), z. 738 // x, (y, z) <=> (x, y), z.
734 leftPrecedenceRequirement = EXPRESSION; 739 leftPrecedenceRequirement = EXPRESSION;
735 rightPrecedenceRequirement = EXPRESSION; 740 rightPrecedenceRequirement = EXPRESSION;
736 leftSpace = false; 741 leftSpace = false;
737 break; 742 break;
738 case "||": 743 case "||":
739 leftPrecedenceRequirement = LOGICAL_OR; 744 leftPrecedenceRequirement = LOGICAL_OR;
740 // x || (y || z) <=> (x || y) || z. 745 // x || (y || z) <=> (x || y) || z.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 case "%": 802 case "%":
798 leftPrecedenceRequirement = MULTIPLICATIVE; 803 leftPrecedenceRequirement = MULTIPLICATIVE;
799 // We cannot remove parenthesis for "*" because of precision issues. 804 // We cannot remove parenthesis for "*" because of precision issues.
800 rightPrecedenceRequirement = UNARY; 805 rightPrecedenceRequirement = UNARY;
801 break; 806 break;
802 default: 807 default:
803 context.error("Forgot operator: $op"); 808 context.error("Forgot operator: $op");
804 } 809 }
805 810
806 visitNestedExpression(left, leftPrecedenceRequirement, 811 visitNestedExpression(left, leftPrecedenceRequirement,
807 newInForInit: inForInit, 812 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
808 newAtStatementBegin: atStatementBegin);
809 813
810 if (op == "in" || op == "instanceof") { 814 if (op == "in" || op == "instanceof") {
811 // There are cases where the space is not required but without further 815 // There are cases where the space is not required but without further
812 // analysis we cannot know. 816 // analysis we cannot know.
813 out(" "); 817 out(" ");
814 out(op); 818 out(op);
815 out(" "); 819 out(" ");
816 } else { 820 } else {
817 if (leftSpace) spaceOut(); 821 if (leftSpace) spaceOut();
818 out(op); 822 out(op);
819 spaceOut(); 823 spaceOut();
820 } 824 }
821 visitNestedExpression(right, rightPrecedenceRequirement, 825 visitNestedExpression(right, rightPrecedenceRequirement,
822 newInForInit: inForInit, 826 newInForInit: inForInit, newAtStatementBegin: false);
823 newAtStatementBegin: false);
824 } 827 }
825 828
826 visitPrefix(Prefix unary) { 829 visitPrefix(Prefix unary) {
827 String op = unary.op; 830 String op = unary.op;
828 switch (op) { 831 switch (op) {
829 case "delete": 832 case "delete":
830 case "void": 833 case "void":
831 case "typeof": 834 case "typeof":
832 // There are cases where the space is not required but without further 835 // There are cases where the space is not required but without further
833 // analysis we cannot know. 836 // analysis we cannot know.
834 out(op); 837 out(op);
835 out(" "); 838 out(" ");
836 break; 839 break;
837 case "+": 840 case "+":
838 case "++": 841 case "++":
839 if (lastCharCode == charCodes.$PLUS) out(" "); 842 if (lastCharCode == charCodes.$PLUS) out(" ");
840 out(op); 843 out(op);
841 break; 844 break;
842 case "-": 845 case "-":
843 case "--": 846 case "--":
844 if (lastCharCode == charCodes.$MINUS) out(" "); 847 if (lastCharCode == charCodes.$MINUS) out(" ");
845 out(op); 848 out(op);
846 break; 849 break;
847 default: 850 default:
848 out(op); 851 out(op);
849 } 852 }
850 visitNestedExpression(unary.argument, unary.precedenceLevel, 853 visitNestedExpression(unary.argument, unary.precedenceLevel,
851 newInForInit: inForInit, newAtStatementBegin: false); 854 newInForInit: inForInit, newAtStatementBegin: false);
852 } 855 }
853 856
854 visitSpread(Spread unary) => visitPrefix(unary); 857 visitSpread(Spread unary) => visitPrefix(unary);
855 858
856 visitYield(Yield yield) { 859 visitYield(Yield yield) {
857 out(yield.star ? "yield*" : "yield"); 860 out(yield.star ? "yield*" : "yield");
858 if (yield.value == null) return; 861 if (yield.value == null) return;
859 out(" "); 862 out(" ");
860 visitNestedExpression(yield.value, yield.precedenceLevel, 863 visitNestedExpression(yield.value, yield.precedenceLevel,
861 newInForInit: inForInit, newAtStatementBegin: false); 864 newInForInit: inForInit, newAtStatementBegin: false);
862 } 865 }
863 866
864 visitPostfix(Postfix postfix) { 867 visitPostfix(Postfix postfix) {
865 visitNestedExpression(postfix.argument, LEFT_HAND_SIDE, 868 visitNestedExpression(postfix.argument, LEFT_HAND_SIDE,
866 newInForInit: inForInit, 869 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
867 newAtStatementBegin: atStatementBegin);
868 out(postfix.op); 870 out(postfix.op);
869 } 871 }
870 872
871 visitThis(This node) { 873 visitThis(This node) {
872 out("this"); 874 out("this");
873 } 875 }
874 876
875 visitSuper(Super node) { 877 visitSuper(Super node) {
876 out("super"); 878 out("super");
877 } 879 }
(...skipping 12 matching lines...) Expand all
890 return charCodes.$0 <= charCode && charCode <= charCodes.$9; 892 return charCodes.$0 <= charCode && charCode <= charCodes.$9;
891 } 893 }
892 894
893 bool isValidJavaScriptId(String field) { 895 bool isValidJavaScriptId(String field) {
894 if (field.length < 3) return false; 896 if (field.length < 3) return false;
895 // Ignore the leading and trailing string-delimiter. 897 // Ignore the leading and trailing string-delimiter.
896 for (int i = 1; i < field.length - 1; i++) { 898 for (int i = 1; i < field.length - 1; i++) {
897 // TODO(floitsch): allow more characters. 899 // TODO(floitsch): allow more characters.
898 int charCode = field.codeUnitAt(i); 900 int charCode = field.codeUnitAt(i);
899 if (!(charCodes.$a <= charCode && charCode <= charCodes.$z || 901 if (!(charCodes.$a <= charCode && charCode <= charCodes.$z ||
900 charCodes.$A <= charCode && charCode <= charCodes.$Z || 902 charCodes.$A <= charCode && charCode <= charCodes.$Z ||
901 charCode == charCodes.$$ || 903 charCode == charCodes.$$ ||
902 charCode == charCodes.$_ || 904 charCode == charCodes.$_ ||
903 i != 1 && isDigit(charCode))) { 905 i != 1 && isDigit(charCode))) {
904 return false; 906 return false;
905 } 907 }
906 } 908 }
907 909
908 // TODO(floitsch): normally we should also check that the field is not a 910 // TODO(floitsch): normally we should also check that the field is not a
909 // reserved word. We don't generate fields with reserved word names except 911 // reserved word. We don't generate fields with reserved word names except
910 // for 'super'. 912 // for 'super'.
911 return options.allowKeywordsInProperties || field != '"super"'; 913 return options.allowKeywordsInProperties || field != '"super"';
912 } 914 }
913 915
914 visitAccess(PropertyAccess access) { 916 visitAccess(PropertyAccess access) {
915 // Normally we can omit parens on the receiver if it is a Call, even though 917 // Normally we can omit parens on the receiver if it is a Call, even though
916 // Call expressions have lower precedence. However this optimization doesn't 918 // Call expressions have lower precedence. However this optimization doesn't
917 // work inside New expressions: 919 // work inside New expressions:
918 // 920 //
919 // new obj.foo().bar() 921 // new obj.foo().bar()
920 // 922 //
921 // This will be parsed as: 923 // This will be parsed as:
922 // 924 //
923 // (new obj.foo()).bar() 925 // (new obj.foo()).bar()
924 // 926 //
925 // Which is incorrect. So we must have parenthesis in this case: 927 // Which is incorrect. So we must have parenthesis in this case:
926 // 928 //
927 // new (obj.foo()).bar() 929 // new (obj.foo()).bar()
928 // 930 //
929 int precedence = inNewTarget ? ACCESS : CALL; 931 int precedence = inNewTarget ? ACCESS : CALL;
930 932
931 visitNestedExpression(access.receiver, precedence, 933 visitNestedExpression(access.receiver, precedence,
932 newInForInit: inForInit, 934 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
933 newAtStatementBegin: atStatementBegin);
934 propertyNameOut(access.selector, inAccess: true); 935 propertyNameOut(access.selector, inAccess: true);
935 } 936 }
936 937
937 visitNamedFunction(NamedFunction namedFunction) { 938 visitNamedFunction(NamedFunction namedFunction) {
938 functionOut(namedFunction.function, namedFunction.name); 939 functionOut(namedFunction.function, namedFunction.name);
939 } 940 }
940 941
941 visitFun(Fun fun) { 942 visitFun(Fun fun) {
942 functionOut(fun, null); 943 functionOut(fun, null);
943 } 944 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 // and [1,,] (array with 1 and a hole) would become [1,] = [1]. 1009 // and [1,,] (array with 1 and a hole) would become [1,] = [1].
1009 out(","); 1010 out(",");
1010 continue; 1011 continue;
1011 } 1012 }
1012 if (i != 0 && !multiline) spaceOut(); 1013 if (i != 0 && !multiline) spaceOut();
1013 if (multiline) { 1014 if (multiline) {
1014 forceLine(); 1015 forceLine();
1015 indent(); 1016 indent();
1016 } 1017 }
1017 visitNestedExpression(element, ASSIGNMENT, 1018 visitNestedExpression(element, ASSIGNMENT,
1018 newInForInit: false, newAtStatementBegin: false); 1019 newInForInit: false, newAtStatementBegin: false);
1019 // We can skip the trailing "," for the last element (since it's not 1020 // We can skip the trailing "," for the last element (since it's not
1020 // an array hole). 1021 // an array hole).
1021 if (i != elements.length - 1) out(","); 1022 if (i != elements.length - 1) out(",");
1022 } 1023 }
1023 indentLess(); 1024 indentLess();
1024 if (multiline) { 1025 if (multiline) {
1025 lineOut(); 1026 lineOut();
1026 indent(); 1027 indent();
1027 } 1028 }
1028 out("]"); 1029 out("]");
(...skipping 26 matching lines...) Expand all
1055 indent(); 1056 indent();
1056 } 1057 }
1057 out("}"); 1058 out("}");
1058 } 1059 }
1059 1060
1060 visitProperty(Property node) { 1061 visitProperty(Property node) {
1061 propertyNameOut(node.name); 1062 propertyNameOut(node.name);
1062 out(":"); 1063 out(":");
1063 spaceOut(); 1064 spaceOut();
1064 visitNestedExpression(node.value, ASSIGNMENT, 1065 visitNestedExpression(node.value, ASSIGNMENT,
1065 newInForInit: false, newAtStatementBegin: false); 1066 newInForInit: false, newAtStatementBegin: false);
1066 } 1067 }
1067 1068
1068 visitRegExpLiteral(RegExpLiteral node) { 1069 visitRegExpLiteral(RegExpLiteral node) {
1069 out(node.pattern); 1070 out(node.pattern);
1070 } 1071 }
1071 1072
1072 visitTemplateString(TemplateString node) { 1073 visitTemplateString(TemplateString node) {
1073 out('`'); 1074 out('`');
1074 for (var element in node.elements) { 1075 for (var element in node.elements) {
1075 if (element is String) { 1076 if (element is String) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 if (node != null && node.closureAnnotation != null) { 1178 if (node != null && node.closureAnnotation != null) {
1178 String comment = node.closureAnnotation.toString(indentation); 1179 String comment = node.closureAnnotation.toString(indentation);
1179 if (comment.isNotEmpty) { 1180 if (comment.isNotEmpty) {
1180 out(comment); 1181 out(comment);
1181 lineOut(); 1182 lineOut();
1182 indent(); 1183 indent();
1183 } 1184 }
1184 } 1185 }
1185 } 1186 }
1186 1187
1187 void propertyNameOut(Expression node, {bool inMethod: false, 1188 void propertyNameOut(Expression node,
1188 bool inAccess: false}) { 1189 {bool inMethod: false, bool inAccess: false}) {
1189
1190 if (node is LiteralNumber) { 1190 if (node is LiteralNumber) {
1191 LiteralNumber nameNumber = node; 1191 LiteralNumber nameNumber = node;
1192 if (inAccess) out('['); 1192 if (inAccess) out('[');
1193 out(nameNumber.value); 1193 out(nameNumber.value);
1194 if (inAccess) out(']'); 1194 if (inAccess) out(']');
1195 } else { 1195 } else {
1196 if (node is LiteralString) { 1196 if (node is LiteralString) {
1197 if (isValidJavaScriptId(node.value)) { 1197 if (isValidJavaScriptId(node.value)) {
1198 if (inAccess) out('.'); 1198 if (inAccess) out('.');
1199 out(node.valueWithoutQuotes); 1199 out(node.valueWithoutQuotes);
1200 } else { 1200 } else {
1201 if (inMethod || inAccess) out("["); 1201 if (inMethod || inAccess) out("[");
1202 out(node.value); 1202 out(node.value);
1203 if (inMethod || inAccess) out("]"); 1203 if (inMethod || inAccess) out("]");
1204 } 1204 }
1205 } else { 1205 } else {
1206 // ComputedPropertyName 1206 // ComputedPropertyName
1207 out("["); 1207 out("[");
1208 visitNestedExpression(node, EXPRESSION, 1208 visitNestedExpression(node, EXPRESSION,
1209 newInForInit: false, newAtStatementBegin: false); 1209 newInForInit: false, newAtStatementBegin: false);
1210 out("]"); 1210 out("]");
1211 } 1211 }
1212 } 1212 }
1213 } 1213 }
1214 1214
1215 visitImportDeclaration(ImportDeclaration node) { 1215 visitImportDeclaration(ImportDeclaration node) {
1216 indent(); 1216 indent();
1217 out('import '); 1217 out('import ');
1218 if (node.defaultBinding != null) { 1218 if (node.defaultBinding != null) {
1219 visit(node.defaultBinding); 1219 visit(node.defaultBinding);
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1388 } 1388 }
1389 } 1389 }
1390 1390
1391 // Collects all the var declarations in the function. We need to do this in a 1391 // Collects all the var declarations in the function. We need to do this in a
1392 // separate pass because JS vars are lifted to the top of the function. 1392 // separate pass because JS vars are lifted to the top of the function.
1393 class VarCollector extends BaseVisitor { 1393 class VarCollector extends BaseVisitor {
1394 bool nested; 1394 bool nested;
1395 final Set<String> vars; 1395 final Set<String> vars;
1396 final Set<String> params; 1396 final Set<String> params;
1397 1397
1398 VarCollector() : nested = false, 1398 VarCollector()
1399 vars = new Set<String>(), 1399 : nested = false,
1400 params = new Set<String>(); 1400 vars = new Set<String>(),
1401 params = new Set<String>();
1401 1402
1402 void forEachVar(void fn(String v)) => vars.forEach(fn); 1403 void forEachVar(void fn(String v)) => vars.forEach(fn);
1403 void forEachParam(void fn(String p)) => params.forEach(fn); 1404 void forEachParam(void fn(String p)) => params.forEach(fn);
1404 1405
1405 void collectVarsInFunction(FunctionExpression fun) { 1406 void collectVarsInFunction(FunctionExpression fun) {
1406 if (!nested) { 1407 if (!nested) {
1407 nested = true; 1408 nested = true;
1408 if (fun.params != null) { 1409 if (fun.params != null) {
1409 for (var param in fun.params) { 1410 for (var param in fun.params) {
1410 // TODO(jmesserly): add ES6 support. Currently not needed because 1411 // TODO(jmesserly): add ES6 support. Currently not needed because
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 void visitVariableInitialization(VariableInitialization node) { 1454 void visitVariableInitialization(VariableInitialization node) {
1454 declareVariable(node.declaration); 1455 declareVariable(node.declaration);
1455 if (node.value != null) node.value.accept(this); 1456 if (node.value != null) node.value.accept(this);
1456 } 1457 }
1457 1458
1458 void declareVariable(Identifier decl) { 1459 void declareVariable(Identifier decl) {
1459 if (decl.allowRename) vars.add(decl.name); 1460 if (decl.allowRename) vars.add(decl.name);
1460 } 1461 }
1461 } 1462 }
1462 1463
1463
1464 /** 1464 /**
1465 * Returns true, if the given node must be wrapped into braces when used 1465 * Returns true, if the given node must be wrapped into braces when used
1466 * as then-statement in an [If] that has an else branch. 1466 * as then-statement in an [If] that has an else branch.
1467 */ 1467 */
1468 class DanglingElseVisitor extends BaseVisitor<bool> { 1468 class DanglingElseVisitor extends BaseVisitor<bool> {
1469 JavaScriptPrintingContext context; 1469 JavaScriptPrintingContext context;
1470 1470
1471 DanglingElseVisitor(this.context); 1471 DanglingElseVisitor(this.context);
1472 1472
1473 bool visitProgram(Program node) => false; 1473 bool visitProgram(Program node) => false;
1474 1474
1475 bool visitNode(Node node) { 1475 bool visitNode(Node node) {
1476 context.error("Forgot node: $node"); 1476 context.error("Forgot node: $node");
1477 return null; 1477 return null;
1478 } 1478 }
1479 1479
1480 bool visitBlock(Block node) => false; 1480 bool visitBlock(Block node) => false;
1481 bool visitExpressionStatement(ExpressionStatement node) => false; 1481 bool visitExpressionStatement(ExpressionStatement node) => false;
1482 bool visitEmptyStatement(EmptyStatement node) => false; 1482 bool visitEmptyStatement(EmptyStatement node) => false;
1483 bool visitIf(If node) { 1483 bool visitIf(If node) {
1484 if (!node.hasElse) return true; 1484 if (!node.hasElse) return true;
1485 return node.otherwise.accept(this); 1485 return node.otherwise.accept(this);
1486 } 1486 }
1487
1487 bool visitFor(For node) => node.body.accept(this); 1488 bool visitFor(For node) => node.body.accept(this);
1488 bool visitForIn(ForIn node) => node.body.accept(this); 1489 bool visitForIn(ForIn node) => node.body.accept(this);
1489 bool visitForOf(ForOf node) => node.body.accept(this); 1490 bool visitForOf(ForOf node) => node.body.accept(this);
1490 bool visitWhile(While node) => node.body.accept(this); 1491 bool visitWhile(While node) => node.body.accept(this);
1491 bool visitDo(Do node) => false; 1492 bool visitDo(Do node) => false;
1492 bool visitContinue(Continue node) => false; 1493 bool visitContinue(Continue node) => false;
1493 bool visitBreak(Break node) => false; 1494 bool visitBreak(Break node) => false;
1494 bool visitReturn(Return node) => false; 1495 bool visitReturn(Return node) => false;
1495 bool visitThrow(Throw node) => false; 1496 bool visitThrow(Throw node) => false;
1496 bool visitTry(Try node) { 1497 bool visitTry(Try node) {
1497 if (node.finallyPart != null) { 1498 if (node.finallyPart != null) {
1498 return node.finallyPart.accept(this); 1499 return node.finallyPart.accept(this);
1499 } else { 1500 } else {
1500 return node.catchPart.accept(this); 1501 return node.catchPart.accept(this);
1501 } 1502 }
1502 } 1503 }
1504
1503 bool visitCatch(Catch node) => node.body.accept(this); 1505 bool visitCatch(Catch node) => node.body.accept(this);
1504 bool visitSwitch(Switch node) => false; 1506 bool visitSwitch(Switch node) => false;
1505 bool visitCase(Case node) => false; 1507 bool visitCase(Case node) => false;
1506 bool visitDefault(Default node) => false; 1508 bool visitDefault(Default node) => false;
1507 bool visitFunctionDeclaration(FunctionDeclaration node) => false; 1509 bool visitFunctionDeclaration(FunctionDeclaration node) => false;
1508 bool visitLabeledStatement(LabeledStatement node) 1510 bool visitLabeledStatement(LabeledStatement node) => node.body.accept(this);
1509 => node.body.accept(this);
1510 bool visitLiteralStatement(LiteralStatement node) => true; 1511 bool visitLiteralStatement(LiteralStatement node) => true;
1511 bool visitClassDeclaration(ClassDeclaration node) => false; 1512 bool visitClassDeclaration(ClassDeclaration node) => false;
1512 1513
1513 bool visitExpression(Expression node) => false; 1514 bool visitExpression(Expression node) => false;
1514 } 1515 }
1515 1516
1516
1517 abstract class LocalNamer { 1517 abstract class LocalNamer {
1518 String getName(Identifier node); 1518 String getName(Identifier node);
1519 void enterScope(FunctionExpression node); 1519 void enterScope(FunctionExpression node);
1520 void leaveScope(); 1520 void leaveScope();
1521 } 1521 }
1522 1522
1523
1524 class IdentityNamer implements LocalNamer { 1523 class IdentityNamer implements LocalNamer {
1525 String getName(Identifier node) => node.name; 1524 String getName(Identifier node) => node.name;
1526 void enterScope(FunctionExpression node) {} 1525 void enterScope(FunctionExpression node) {}
1527 void leaveScope() {} 1526 void leaveScope() {}
1528 } 1527 }
1529 1528
1530
1531 class MinifyRenamer implements LocalNamer { 1529 class MinifyRenamer implements LocalNamer {
1532 final List<Map<String, String>> maps = []; 1530 final List<Map<String, String>> maps = [];
1533 final List<int> parameterNumberStack = []; 1531 final List<int> parameterNumberStack = [];
1534 final List<int> variableNumberStack = []; 1532 final List<int> variableNumberStack = [];
1535 int parameterNumber = 0; 1533 int parameterNumber = 0;
1536 int variableNumber = 0; 1534 int variableNumber = 0;
1537 1535
1538 void enterScope(FunctionExpression node) { 1536 void enterScope(FunctionExpression node) {
1539 var vars = new VarCollector(); 1537 var vars = new VarCollector();
1540 node.accept(vars); 1538 node.accept(vars);
(...skipping 19 matching lines...) Expand all
1560 if (replacement != null) return replacement; 1558 if (replacement != null) return replacement;
1561 } 1559 }
1562 return oldName; 1560 return oldName;
1563 } 1561 }
1564 1562
1565 static const LOWER_CASE_LETTERS = 26; 1563 static const LOWER_CASE_LETTERS = 26;
1566 static const LETTERS = LOWER_CASE_LETTERS; 1564 static const LETTERS = LOWER_CASE_LETTERS;
1567 static const DIGITS = 10; 1565 static const DIGITS = 10;
1568 1566
1569 static int nthLetter(int n) { 1567 static int nthLetter(int n) {
1570 return (n < LOWER_CASE_LETTERS) ? 1568 return (n < LOWER_CASE_LETTERS)
1571 charCodes.$a + n : 1569 ? charCodes.$a + n
1572 charCodes.$A + n - LOWER_CASE_LETTERS; 1570 : charCodes.$A + n - LOWER_CASE_LETTERS;
1573 } 1571 }
1574 1572
1575 // Parameters go from a to z and variables go from z to a. This makes each 1573 // Parameters go from a to z and variables go from z to a. This makes each
1576 // argument list and each top-of-function var declaration look similar and 1574 // argument list and each top-of-function var declaration look similar and
1577 // helps gzip compress the file. If we have more than 26 arguments and 1575 // helps gzip compress the file. If we have more than 26 arguments and
1578 // variables then we meet somewhere in the middle of the alphabet. After 1576 // variables then we meet somewhere in the middle of the alphabet. After
1579 // that we give up trying to be nice to the compression algorithm and just 1577 // that we give up trying to be nice to the compression algorithm and just
1580 // use the same namespace for arguments and variables, starting with A, and 1578 // use the same namespace for arguments and variables, starting with A, and
1581 // moving on to a0, a1, etc. 1579 // moving on to a0, a1, etc.
1582 String declareVariable(String oldName) { 1580 String declareVariable(String oldName) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1654 /// [visitIdentifier] otherwise. 1652 /// [visitIdentifier] otherwise.
1655 abstract class VariableDeclarationVisitor<T> extends BaseVisitor<T> { 1653 abstract class VariableDeclarationVisitor<T> extends BaseVisitor<T> {
1656 declare(Identifier node); 1654 declare(Identifier node);
1657 1655
1658 visitFunctionExpression(FunctionExpression node) { 1656 visitFunctionExpression(FunctionExpression node) {
1659 node.params.forEach(_scanVariableBinding); 1657 node.params.forEach(_scanVariableBinding);
1660 node.body.accept(this); 1658 node.body.accept(this);
1661 } 1659 }
1662 1660
1663 _scanVariableBinding(VariableBinding d) { 1661 _scanVariableBinding(VariableBinding d) {
1664 if (d is Identifier) declare(d); 1662 if (d is Identifier)
1665 else d.accept(this); 1663 declare(d);
1664 else
1665 d.accept(this);
1666 } 1666 }
1667 1667
1668 visitRestParameter(RestParameter node) { 1668 visitRestParameter(RestParameter node) {
1669 _scanVariableBinding(node.parameter); 1669 _scanVariableBinding(node.parameter);
1670 super.visitRestParameter(node); 1670 super.visitRestParameter(node);
1671 } 1671 }
1672 1672
1673 visitDestructuredVariable(DestructuredVariable node) { 1673 visitDestructuredVariable(DestructuredVariable node) {
1674 var name = node.name; 1674 var name = node.name;
1675 if (name is Identifier) _scanVariableBinding(name); 1675 if (name is Identifier) _scanVariableBinding(name);
(...skipping 24 matching lines...) Expand all
1700 declare(node.name); 1700 declare(node.name);
1701 node.function.accept(this); 1701 node.function.accept(this);
1702 } 1702 }
1703 1703
1704 visitClassExpression(ClassExpression node) { 1704 visitClassExpression(ClassExpression node) {
1705 declare(node.name); 1705 declare(node.name);
1706 if (node.heritage != null) node.heritage.accept(this); 1706 if (node.heritage != null) node.heritage.accept(this);
1707 for (Method element in node.methods) element.accept(this); 1707 for (Method element in node.methods) element.accept(this);
1708 } 1708 }
1709 } 1709 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/lib/src/js_ast/nodes.dart ('k') | pkg/dev_compiler/lib/src/js_ast/template.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698