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

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

Issue 2748103010: Run dartfmt on js_ast (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
« no previous file with comments | « pkg/js_ast/lib/src/nodes.dart ('k') | pkg/js_ast/lib/src/template.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of js_ast; 5 part of js_ast;
6 6
7
8 typedef String Renamer(Name); 7 typedef String Renamer(Name);
9 8
10 class JavaScriptPrintingOptions { 9 class JavaScriptPrintingOptions {
11 final bool shouldCompressOutput; 10 final bool shouldCompressOutput;
12 final bool minifyLocalVariables; 11 final bool minifyLocalVariables;
13 final bool preferSemicolonToNewlineInMinifiedOutput; 12 final bool preferSemicolonToNewlineInMinifiedOutput;
14 final Renamer renamerForNames; 13 final Renamer renamerForNames;
15 14
16 JavaScriptPrintingOptions( 15 JavaScriptPrintingOptions(
17 {this.shouldCompressOutput: false, 16 {this.shouldCompressOutput: false,
18 this.minifyLocalVariables: false, 17 this.minifyLocalVariables: false,
19 this.preferSemicolonToNewlineInMinifiedOutput: false, 18 this.preferSemicolonToNewlineInMinifiedOutput: false,
20 this.renamerForNames: identityRenamer}); 19 this.renamerForNames: identityRenamer});
21 20
22 static String identityRenamer(Name name) => name.name; 21 static String identityRenamer(Name name) => name.name;
23 } 22 }
24 23
25
26 /// An environment in which JavaScript printing is done. Provides emitting of 24 /// An environment in which JavaScript printing is done. Provides emitting of
27 /// text and pre- and post-visit callbacks. 25 /// text and pre- and post-visit callbacks.
28 abstract class JavaScriptPrintingContext { 26 abstract class JavaScriptPrintingContext {
29 /// Signals an error. This should happen only for serious internal errors. 27 /// Signals an error. This should happen only for serious internal errors.
30 void error(String message) { throw message; } 28 void error(String message) {
29 throw message;
30 }
31 31
32 /// Adds [string] to the output. 32 /// Adds [string] to the output.
33 void emit(String string); 33 void emit(String string);
34 34
35 /// Callback for the start of printing of [node]. [startPosition] is the 35 /// Callback for the start of printing of [node]. [startPosition] is the
36 /// position of the first non-whitespace character of [node]. 36 /// position of the first non-whitespace character of [node].
37 /// 37 ///
38 /// [enterNode] is called in pre-traversal order. 38 /// [enterNode] is called in pre-traversal order.
39 void enterNode(Node node, int startPosition) {} 39 void enterNode(Node node, int startPosition) {}
40 40
41 /// Callback for the end of printing of [node]. [startPosition] is the 41 /// Callback for the end of printing of [node]. [startPosition] is the
42 /// position of the first non-whitespace character of [node] (also provided 42 /// position of the first non-whitespace character of [node] (also provided
43 /// in the [enterNode] callback), [endPosition] is the position immediately 43 /// in the [enterNode] callback), [endPosition] is the position immediately
44 /// following the last character of [node]. [closingPosition] is the 44 /// following the last character of [node]. [closingPosition] is the
45 /// position of the ending delimiter of [node]. This is only provided for 45 /// position of the ending delimiter of [node]. This is only provided for
46 /// [Fun] nodes and is `null` otherwise. 46 /// [Fun] nodes and is `null` otherwise.
47 /// 47 ///
48 /// [enterNode] is called in post-traversal order. 48 /// [enterNode] is called in post-traversal order.
49 void exitNode(Node node, 49 void exitNode(
50 int startPosition, 50 Node node, int startPosition, int endPosition, int closingPosition) {}
51 int endPosition,
52 int closingPosition) {}
53 } 51 }
54 52
55 /// A simple implementation of [JavaScriptPrintingContext] suitable for tests. 53 /// A simple implementation of [JavaScriptPrintingContext] suitable for tests.
56 class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext { 54 class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext {
57 final StringBuffer buffer = new StringBuffer(); 55 final StringBuffer buffer = new StringBuffer();
58 56
59 void emit(String string) { 57 void emit(String string) {
60 buffer.write(string); 58 buffer.write(string);
61 } 59 }
62 60
63 String getText() => buffer.toString(); 61 String getText() => buffer.toString();
64 } 62 }
65 63
66
67 class Printer implements NodeVisitor { 64 class Printer implements NodeVisitor {
68 final JavaScriptPrintingOptions options; 65 final JavaScriptPrintingOptions options;
69 final JavaScriptPrintingContext context; 66 final JavaScriptPrintingContext context;
70 final bool shouldCompressOutput; 67 final bool shouldCompressOutput;
71 final DanglingElseVisitor danglingElseVisitor; 68 final DanglingElseVisitor danglingElseVisitor;
72 final LocalNamer localNamer; 69 final LocalNamer localNamer;
73 70
74 int _charCount = 0; 71 int _charCount = 0;
75 bool inForInit = false; 72 bool inForInit = false;
76 bool atStatementBegin = false; 73 bool atStatementBegin = false;
77 bool pendingSemicolon = false; 74 bool pendingSemicolon = false;
78 bool pendingSpace = false; 75 bool pendingSpace = false;
79 76
80 // The current indentation level. 77 // The current indentation level.
81 int _indentLevel = 0; 78 int _indentLevel = 0;
82 // A cache of all indentation strings used so far. 79 // A cache of all indentation strings used so far.
83 List<String> _indentList = <String>[""]; 80 List<String> _indentList = <String>[""];
84 81
85 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]'); 82 static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]');
86 static final expressionContinuationRegExp = new RegExp(r'^[-+([]'); 83 static final expressionContinuationRegExp = new RegExp(r'^[-+([]');
87 84
88 Printer(JavaScriptPrintingOptions options, 85 Printer(JavaScriptPrintingOptions options, JavaScriptPrintingContext context)
89 JavaScriptPrintingContext context)
90 : options = options, 86 : options = options,
91 context = context, 87 context = context,
92 shouldCompressOutput = options.shouldCompressOutput, 88 shouldCompressOutput = options.shouldCompressOutput,
93 danglingElseVisitor = new DanglingElseVisitor(context), 89 danglingElseVisitor = new DanglingElseVisitor(context),
94 localNamer = determineRenamer(options.shouldCompressOutput, 90 localNamer = determineRenamer(
95 options.minifyLocalVariables); 91 options.shouldCompressOutput, options.minifyLocalVariables);
96 92
97 static LocalNamer determineRenamer(bool shouldCompressOutput, 93 static LocalNamer determineRenamer(
98 bool allowVariableMinification) { 94 bool shouldCompressOutput, bool allowVariableMinification) {
99 return (shouldCompressOutput && allowVariableMinification) 95 return (shouldCompressOutput && allowVariableMinification)
100 ? new MinifyRenamer() : new IdentityNamer(); 96 ? new MinifyRenamer()
97 : new IdentityNamer();
101 } 98 }
102 99
103
104 // The current indentation string. 100 // The current indentation string.
105 String get indentation { 101 String get indentation {
106 // Lazily add new indentation strings as required. 102 // Lazily add new indentation strings as required.
107 while (_indentList.length <= _indentLevel) { 103 while (_indentList.length <= _indentLevel) {
108 _indentList.add(_indentList.last + " "); 104 _indentList.add(_indentList.last + " ");
109 } 105 }
110 return _indentList[_indentLevel]; 106 return _indentList[_indentLevel];
111 } 107 }
112 108
113 void indentMore() { 109 void indentMore() {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 currentNode = currentNode.exitNode(context, _charCount); 225 currentNode = currentNode.exitNode(context, _charCount);
230 } 226 }
231 227
232 void visit(Node node) { 228 void visit(Node node) {
233 startNode(node); 229 startNode(node);
234 node.accept(this); 230 node.accept(this);
235 endNode(node); 231 endNode(node);
236 } 232 }
237 233
238 void visitCommaSeparated(List<Node> nodes, int hasRequiredType, 234 void visitCommaSeparated(List<Node> nodes, int hasRequiredType,
239 {bool newInForInit, bool newAtStatementBegin}) { 235 {bool newInForInit, bool newAtStatementBegin}) {
240 for (int i = 0; i < nodes.length; i++) { 236 for (int i = 0; i < nodes.length; i++) {
241 if (i != 0) { 237 if (i != 0) {
242 atStatementBegin = false; 238 atStatementBegin = false;
243 out(","); 239 out(",");
244 spaceOut(); 240 spaceOut();
245 } 241 }
246 visitNestedExpression(nodes[i], hasRequiredType, 242 visitNestedExpression(nodes[i], hasRequiredType,
247 newInForInit: newInForInit, 243 newInForInit: newInForInit, newAtStatementBegin: newAtStatementBegin);
248 newAtStatementBegin: newAtStatementBegin);
249 } 244 }
250 } 245 }
251 246
252 void visitAll(List<Node> nodes) { 247 void visitAll(List<Node> nodes) {
253 nodes.forEach(visit); 248 nodes.forEach(visit);
254 } 249 }
255 250
256 @override 251 @override
257 void visitProgram(Program program) { 252 void visitProgram(Program program) {
258 if (program.body.isNotEmpty) { 253 if (program.body.isNotEmpty) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 313
319 @override 314 @override
320 void visitBlock(Block block) { 315 void visitBlock(Block block) {
321 blockOut(block, shouldIndent: true, needsNewline: true); 316 blockOut(block, shouldIndent: true, needsNewline: true);
322 } 317 }
323 318
324 @override 319 @override
325 void visitExpressionStatement(ExpressionStatement node) { 320 void visitExpressionStatement(ExpressionStatement node) {
326 indent(); 321 indent();
327 visitNestedExpression(node.expression, EXPRESSION, 322 visitNestedExpression(node.expression, EXPRESSION,
328 newInForInit: false, newAtStatementBegin: true); 323 newInForInit: false, newAtStatementBegin: true);
329 outSemicolonLn(); 324 outSemicolonLn();
330 } 325 }
331 326
332 @override 327 @override
333 void visitEmptyStatement(EmptyStatement node) { 328 void visitEmptyStatement(EmptyStatement node) {
334 outIndentLn(";"); 329 outIndentLn(";");
335 } 330 }
336 331
337 void ifOut(If node, bool shouldIndent) { 332 void ifOut(If node, bool shouldIndent) {
338 Statement then = unwrapBlockIfSingleStatement(node.then); 333 Statement then = unwrapBlockIfSingleStatement(node.then);
339 Statement elsePart = node.otherwise; 334 Statement elsePart = node.otherwise;
340 bool hasElse = node.hasElse; 335 bool hasElse = node.hasElse;
341 336
342 // Handle dangling elses and a work-around for Android 4.0 stock browser. 337 // Handle dangling elses and a work-around for Android 4.0 stock browser.
343 // Android 4.0 requires braces for a single do-while in the `then` branch. 338 // Android 4.0 requires braces for a single do-while in the `then` branch.
344 // See issue 10923. 339 // See issue 10923.
345 if (hasElse) { 340 if (hasElse) {
346 bool needsBraces = then.accept(danglingElseVisitor) || then is Do; 341 bool needsBraces = then.accept(danglingElseVisitor) || then is Do;
347 if (needsBraces) { 342 if (needsBraces) {
348 then = new Block(<Statement>[then]); 343 then = new Block(<Statement>[then]);
349 } 344 }
350 } 345 }
351 if (shouldIndent) indent(); 346 if (shouldIndent) indent();
352 out("if"); 347 out("if");
353 spaceOut(); 348 spaceOut();
354 out("("); 349 out("(");
355 visitNestedExpression(node.condition, EXPRESSION, 350 visitNestedExpression(node.condition, EXPRESSION,
356 newInForInit: false, newAtStatementBegin: false); 351 newInForInit: false, newAtStatementBegin: false);
357 out(")"); 352 out(")");
358 bool thenWasBlock = 353 bool thenWasBlock =
359 blockBody(then, needsSeparation: false, needsNewline: !hasElse); 354 blockBody(then, needsSeparation: false, needsNewline: !hasElse);
360 if (hasElse) { 355 if (hasElse) {
361 if (thenWasBlock) { 356 if (thenWasBlock) {
362 spaceOut(); 357 spaceOut();
363 } else { 358 } else {
364 indent(); 359 indent();
365 } 360 }
366 out("else"); 361 out("else");
367 if (elsePart is If) { 362 if (elsePart is If) {
368 pendingSpace = true; 363 pendingSpace = true;
369 startNode(elsePart); 364 startNode(elsePart);
370 ifOut(elsePart, false); 365 ifOut(elsePart, false);
371 endNode(elsePart); 366 endNode(elsePart);
372 } else { 367 } else {
373 blockBody(unwrapBlockIfSingleStatement(elsePart), 368 blockBody(unwrapBlockIfSingleStatement(elsePart),
374 needsSeparation: true, needsNewline: true); 369 needsSeparation: true, needsNewline: true);
375 } 370 }
376 } 371 }
377 } 372 }
378 373
379 @override 374 @override
380 void visitIf(If node) { 375 void visitIf(If node) {
381 ifOut(node, true); 376 ifOut(node, true);
382 } 377 }
383 378
384 @override 379 @override
385 void visitFor(For loop) { 380 void visitFor(For loop) {
386 outIndent("for"); 381 outIndent("for");
387 spaceOut(); 382 spaceOut();
388 out("("); 383 out("(");
389 if (loop.init != null) { 384 if (loop.init != null) {
390 visitNestedExpression(loop.init, EXPRESSION, 385 visitNestedExpression(loop.init, EXPRESSION,
391 newInForInit: true, newAtStatementBegin: false); 386 newInForInit: true, newAtStatementBegin: false);
392 } 387 }
393 out(";"); 388 out(";");
394 if (loop.condition != null) { 389 if (loop.condition != null) {
395 spaceOut(); 390 spaceOut();
396 visitNestedExpression(loop.condition, EXPRESSION, 391 visitNestedExpression(loop.condition, EXPRESSION,
397 newInForInit: false, newAtStatementBegin: false); 392 newInForInit: false, newAtStatementBegin: false);
398 } 393 }
399 out(";"); 394 out(";");
400 if (loop.update != null) { 395 if (loop.update != null) {
401 spaceOut(); 396 spaceOut();
402 visitNestedExpression(loop.update, EXPRESSION, 397 visitNestedExpression(loop.update, EXPRESSION,
403 newInForInit: false, newAtStatementBegin: false); 398 newInForInit: false, newAtStatementBegin: false);
404 } 399 }
405 out(")"); 400 out(")");
406 blockBody(unwrapBlockIfSingleStatement(loop.body), 401 blockBody(unwrapBlockIfSingleStatement(loop.body),
407 needsSeparation: false, needsNewline: true); 402 needsSeparation: false, needsNewline: true);
408 } 403 }
409 404
410 @override 405 @override
411 void visitForIn(ForIn loop) { 406 void visitForIn(ForIn loop) {
412 outIndent("for"); 407 outIndent("for");
413 spaceOut(); 408 spaceOut();
414 out("("); 409 out("(");
415 visitNestedExpression(loop.leftHandSide, EXPRESSION, 410 visitNestedExpression(loop.leftHandSide, EXPRESSION,
416 newInForInit: true, newAtStatementBegin: false); 411 newInForInit: true, newAtStatementBegin: false);
417 out(" in"); 412 out(" in");
418 pendingSpace = true; 413 pendingSpace = true;
419 visitNestedExpression(loop.object, EXPRESSION, 414 visitNestedExpression(loop.object, EXPRESSION,
420 newInForInit: false, newAtStatementBegin: false); 415 newInForInit: false, newAtStatementBegin: false);
421 out(")"); 416 out(")");
422 blockBody(unwrapBlockIfSingleStatement(loop.body), 417 blockBody(unwrapBlockIfSingleStatement(loop.body),
423 needsSeparation: false, needsNewline: true); 418 needsSeparation: false, needsNewline: true);
424 } 419 }
425 420
426 @override 421 @override
427 void visitWhile(While loop) { 422 void visitWhile(While loop) {
428 outIndent("while"); 423 outIndent("while");
429 spaceOut(); 424 spaceOut();
430 out("("); 425 out("(");
431 visitNestedExpression(loop.condition, EXPRESSION, 426 visitNestedExpression(loop.condition, EXPRESSION,
432 newInForInit: false, newAtStatementBegin: false); 427 newInForInit: false, newAtStatementBegin: false);
433 out(")"); 428 out(")");
434 blockBody(unwrapBlockIfSingleStatement(loop.body), 429 blockBody(unwrapBlockIfSingleStatement(loop.body),
435 needsSeparation: false, needsNewline: true); 430 needsSeparation: false, needsNewline: true);
436 } 431 }
437 432
438 @override 433 @override
439 void visitDo(Do loop) { 434 void visitDo(Do loop) {
440 outIndent("do"); 435 outIndent("do");
441 if (blockBody(unwrapBlockIfSingleStatement(loop.body), 436 if (blockBody(unwrapBlockIfSingleStatement(loop.body),
442 needsSeparation: true, needsNewline: false)) { 437 needsSeparation: true, needsNewline: false)) {
443 spaceOut(); 438 spaceOut();
444 } else { 439 } else {
445 indent(); 440 indent();
446 } 441 }
447 out("while"); 442 out("while");
448 spaceOut(); 443 spaceOut();
449 out("("); 444 out("(");
450 visitNestedExpression(loop.condition, EXPRESSION, 445 visitNestedExpression(loop.condition, EXPRESSION,
451 newInForInit: false, newAtStatementBegin: false); 446 newInForInit: false, newAtStatementBegin: false);
452 out(")"); 447 out(")");
453 outSemicolonLn(); 448 outSemicolonLn();
454 } 449 }
455 450
456 @override 451 @override
457 void visitContinue(Continue node) { 452 void visitContinue(Continue node) {
458 if (node.targetLabel == null) { 453 if (node.targetLabel == null) {
459 outIndent("continue"); 454 outIndent("continue");
460 } else { 455 } else {
461 outIndent("continue ${node.targetLabel}"); 456 outIndent("continue ${node.targetLabel}");
(...skipping 12 matching lines...) Expand all
474 } 469 }
475 470
476 @override 471 @override
477 void visitReturn(Return node) { 472 void visitReturn(Return node) {
478 if (node.value == null) { 473 if (node.value == null) {
479 outIndent("return"); 474 outIndent("return");
480 } else { 475 } else {
481 outIndent("return"); 476 outIndent("return");
482 pendingSpace = true; 477 pendingSpace = true;
483 visitNestedExpression(node.value, EXPRESSION, 478 visitNestedExpression(node.value, EXPRESSION,
484 newInForInit: false, newAtStatementBegin: false); 479 newInForInit: false, newAtStatementBegin: false);
485 } 480 }
486 outSemicolonLn(); 481 outSemicolonLn();
487 } 482 }
488 483
489 @override 484 @override
490 void visitDartYield(DartYield node) { 485 void visitDartYield(DartYield node) {
491 if (node.hasStar) { 486 if (node.hasStar) {
492 outIndent("yield*"); 487 outIndent("yield*");
493 } else { 488 } else {
494 outIndent("yield"); 489 outIndent("yield");
495 } 490 }
496 pendingSpace = true; 491 pendingSpace = true;
497 visitNestedExpression(node.expression, EXPRESSION, 492 visitNestedExpression(node.expression, EXPRESSION,
498 newInForInit: false, newAtStatementBegin: false); 493 newInForInit: false, newAtStatementBegin: false);
499 outSemicolonLn(); 494 outSemicolonLn();
500 } 495 }
501 496
502 @override 497 @override
503 void visitThrow(Throw node) { 498 void visitThrow(Throw node) {
504 outIndent("throw"); 499 outIndent("throw");
505 pendingSpace = true; 500 pendingSpace = true;
506 visitNestedExpression(node.expression, EXPRESSION, 501 visitNestedExpression(node.expression, EXPRESSION,
507 newInForInit: false, newAtStatementBegin: false); 502 newInForInit: false, newAtStatementBegin: false);
508 outSemicolonLn(); 503 outSemicolonLn();
509 } 504 }
510 505
511 @override 506 @override
512 void visitTry(Try node) { 507 void visitTry(Try node) {
513 outIndent("try"); 508 outIndent("try");
514 blockBody(node.body, needsSeparation: true, needsNewline: false); 509 blockBody(node.body, needsSeparation: true, needsNewline: false);
515 if (node.catchPart != null) { 510 if (node.catchPart != null) {
516 visit(node.catchPart); 511 visit(node.catchPart);
517 } 512 }
518 if (node.finallyPart != null) { 513 if (node.finallyPart != null) {
519 spaceOut(); 514 spaceOut();
520 out("finally"); 515 out("finally");
521 blockBody(node.finallyPart, needsSeparation: true, needsNewline: true); 516 blockBody(node.finallyPart, needsSeparation: true, needsNewline: true);
522 } else { 517 } else {
523 lineOut(); 518 lineOut();
524 } 519 }
525 } 520 }
526 521
527 @override 522 @override
528 void visitCatch(Catch node) { 523 void visitCatch(Catch node) {
529 spaceOut(); 524 spaceOut();
530 out("catch"); 525 out("catch");
531 spaceOut(); 526 spaceOut();
532 out("("); 527 out("(");
533 visitNestedExpression(node.declaration, EXPRESSION, 528 visitNestedExpression(node.declaration, EXPRESSION,
534 newInForInit: false, newAtStatementBegin: false); 529 newInForInit: false, newAtStatementBegin: false);
535 out(")"); 530 out(")");
536 blockBody(node.body, needsSeparation: false, needsNewline: false); 531 blockBody(node.body, needsSeparation: false, needsNewline: false);
537 } 532 }
538 533
539 @override 534 @override
540 void visitSwitch(Switch node) { 535 void visitSwitch(Switch node) {
541 outIndent("switch"); 536 outIndent("switch");
542 spaceOut(); 537 spaceOut();
543 out("("); 538 out("(");
544 visitNestedExpression(node.key, EXPRESSION, 539 visitNestedExpression(node.key, EXPRESSION,
545 newInForInit: false, newAtStatementBegin: false); 540 newInForInit: false, newAtStatementBegin: false);
546 out(")"); 541 out(")");
547 spaceOut(); 542 spaceOut();
548 outLn("{"); 543 outLn("{");
549 indentMore(); 544 indentMore();
550 visitAll(node.cases); 545 visitAll(node.cases);
551 indentLess(); 546 indentLess();
552 outIndentLn("}"); 547 outIndentLn("}");
553 } 548 }
554 549
555 @override 550 @override
556 void visitCase(Case node) { 551 void visitCase(Case node) {
557 outIndent("case"); 552 outIndent("case");
558 pendingSpace = true; 553 pendingSpace = true;
559 visitNestedExpression(node.expression, EXPRESSION, 554 visitNestedExpression(node.expression, EXPRESSION,
560 newInForInit: false, newAtStatementBegin: false); 555 newInForInit: false, newAtStatementBegin: false);
561 outLn(":"); 556 outLn(":");
562 if (!node.body.statements.isEmpty) { 557 if (!node.body.statements.isEmpty) {
563 indentMore(); 558 indentMore();
564 blockOutWithoutBraces(node.body); 559 blockOutWithoutBraces(node.body);
565 indentLess(); 560 indentLess();
566 } 561 }
567 } 562 }
568 563
569 @override 564 @override
570 void visitDefault(Default node) { 565 void visitDefault(Default node) {
(...skipping 20 matching lines...) Expand all
591 outIndent("${node.label}:"); 586 outIndent("${node.label}:");
592 blockBody(body, needsSeparation: false, needsNewline: true); 587 blockBody(body, needsSeparation: false, needsNewline: true);
593 } 588 }
594 589
595 int functionOut(Fun fun, Node name, VarCollector vars) { 590 int functionOut(Fun fun, Node name, VarCollector vars) {
596 out("function"); 591 out("function");
597 if (name != null) { 592 if (name != null) {
598 out(" "); 593 out(" ");
599 // Name must be a [Decl]. Therefore only test for primary expressions. 594 // Name must be a [Decl]. Therefore only test for primary expressions.
600 visitNestedExpression(name, PRIMARY, 595 visitNestedExpression(name, PRIMARY,
601 newInForInit: false, newAtStatementBegin: false); 596 newInForInit: false, newAtStatementBegin: false);
602 } 597 }
603 localNamer.enterScope(vars); 598 localNamer.enterScope(vars);
604 out("("); 599 out("(");
605 if (fun.params != null) { 600 if (fun.params != null) {
606 visitCommaSeparated(fun.params, PRIMARY, 601 visitCommaSeparated(fun.params, PRIMARY,
607 newInForInit: false, newAtStatementBegin: false); 602 newInForInit: false, newAtStatementBegin: false);
608 } 603 }
609 out(")"); 604 out(")");
610 switch (fun.asyncModifier) { 605 switch (fun.asyncModifier) {
611 case const AsyncModifier.sync(): 606 case const AsyncModifier.sync():
612 break; 607 break;
613 case const AsyncModifier.async(): 608 case const AsyncModifier.async():
614 out(' ', isWhitespace: true); 609 out(' ', isWhitespace: true);
615 out('async'); 610 out('async');
616 break; 611 break;
617 case const AsyncModifier.syncStar(): 612 case const AsyncModifier.syncStar():
618 out(' ', isWhitespace: true); 613 out(' ', isWhitespace: true);
619 out('sync*'); 614 out('sync*');
620 break; 615 break;
621 case const AsyncModifier.asyncStar(): 616 case const AsyncModifier.asyncStar():
622 out(' ', isWhitespace: true); 617 out(' ', isWhitespace: true);
623 out('async*'); 618 out('async*');
624 break; 619 break;
625 } 620 }
626 spaceOut(); 621 spaceOut();
627 int closingPosition = 622 int closingPosition =
628 blockOut(fun.body, shouldIndent: false, needsNewline: false); 623 blockOut(fun.body, shouldIndent: false, needsNewline: false);
629 localNamer.leaveScope(); 624 localNamer.leaveScope();
630 return closingPosition; 625 return closingPosition;
631
632 } 626 }
633 627
634 @override 628 @override
635 visitFunctionDeclaration(FunctionDeclaration declaration) { 629 visitFunctionDeclaration(FunctionDeclaration declaration) {
636 VarCollector vars = new VarCollector(); 630 VarCollector vars = new VarCollector();
637 vars.visitFunctionDeclaration(declaration); 631 vars.visitFunctionDeclaration(declaration);
638 indent(); 632 indent();
639 startNode(declaration.function); 633 startNode(declaration.function);
640 currentNode.closingPosition = 634 currentNode.closingPosition =
641 functionOut(declaration.function, declaration.name, vars); 635 functionOut(declaration.function, declaration.name, vars);
642 endNode(declaration.function); 636 endNode(declaration.function);
643 lineOut(); 637 lineOut();
644 } 638 }
645 639
646 visitNestedExpression(Expression node, int requiredPrecedence, 640 visitNestedExpression(Expression node, int requiredPrecedence,
647 {bool newInForInit, bool newAtStatementBegin}) { 641 {bool newInForInit, bool newAtStatementBegin}) {
648 bool needsParentheses = 642 bool needsParentheses =
649 // a - (b + c). 643 // a - (b + c).
650 (requiredPrecedence != EXPRESSION && 644 (requiredPrecedence != EXPRESSION &&
651 node.precedenceLevel < requiredPrecedence) || 645 node.precedenceLevel < requiredPrecedence) ||
652 // for (a = (x in o); ... ; ... ) { ... } 646 // for (a = (x in o); ... ; ... ) { ... }
653 (newInForInit && node is Binary && node.op == "in") || 647 (newInForInit && node is Binary && node.op == "in") ||
654 // (function() { ... })(). 648 // (function() { ... })().
655 // ({a: 2, b: 3}.toString()). 649 // ({a: 2, b: 3}.toString()).
656 (newAtStatementBegin && (node is NamedFunction || 650 (newAtStatementBegin &&
657 node is Fun || 651 (node is NamedFunction ||
658 node is ObjectInitializer)); 652 node is Fun ||
653 node is ObjectInitializer));
659 if (needsParentheses) { 654 if (needsParentheses) {
660 inForInit = false; 655 inForInit = false;
661 atStatementBegin = false; 656 atStatementBegin = false;
662 out("("); 657 out("(");
663 visit(node); 658 visit(node);
664 out(")"); 659 out(")");
665 } else { 660 } else {
666 inForInit = newInForInit; 661 inForInit = newInForInit;
667 atStatementBegin = newAtStatementBegin; 662 atStatementBegin = newAtStatementBegin;
668 visit(node); 663 visit(node);
669 } 664 }
670 } 665 }
671 666
672 @override 667 @override
673 visitVariableDeclarationList(VariableDeclarationList list) { 668 visitVariableDeclarationList(VariableDeclarationList list) {
674 out("var "); 669 out("var ");
675 visitCommaSeparated(list.declarations, ASSIGNMENT, 670 visitCommaSeparated(list.declarations, ASSIGNMENT,
676 newInForInit: inForInit, newAtStatementBegin: false); 671 newInForInit: inForInit, newAtStatementBegin: false);
677 } 672 }
678 673
679 @override 674 @override
680 visitAssignment(Assignment assignment) { 675 visitAssignment(Assignment assignment) {
681 visitNestedExpression(assignment.leftHandSide, CALL, 676 visitNestedExpression(assignment.leftHandSide, CALL,
682 newInForInit: inForInit, 677 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
683 newAtStatementBegin: atStatementBegin);
684 if (assignment.value != null) { 678 if (assignment.value != null) {
685 spaceOut(); 679 spaceOut();
686 String op = assignment.op; 680 String op = assignment.op;
687 if (op != null) out(op); 681 if (op != null) out(op);
688 out("="); 682 out("=");
689 spaceOut(); 683 spaceOut();
690 visitNestedExpression(assignment.value, ASSIGNMENT, 684 visitNestedExpression(assignment.value, ASSIGNMENT,
691 newInForInit: inForInit, 685 newInForInit: inForInit, newAtStatementBegin: false);
692 newAtStatementBegin: false);
693 } 686 }
694 } 687 }
695 688
696 @override 689 @override
697 visitVariableInitialization(VariableInitialization initialization) { 690 visitVariableInitialization(VariableInitialization initialization) {
698 visitAssignment(initialization); 691 visitAssignment(initialization);
699 } 692 }
700 693
701 @override 694 @override
702 visitConditional(Conditional cond) { 695 visitConditional(Conditional cond) {
703 visitNestedExpression(cond.condition, LOGICAL_OR, 696 visitNestedExpression(cond.condition, LOGICAL_OR,
704 newInForInit: inForInit, 697 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
705 newAtStatementBegin: atStatementBegin);
706 spaceOut(); 698 spaceOut();
707 out("?"); 699 out("?");
708 spaceOut(); 700 spaceOut();
709 // The then part is allowed to have an 'in'. 701 // The then part is allowed to have an 'in'.
710 visitNestedExpression(cond.then, ASSIGNMENT, 702 visitNestedExpression(cond.then, ASSIGNMENT,
711 newInForInit: false, newAtStatementBegin: false); 703 newInForInit: false, newAtStatementBegin: false);
712 spaceOut(); 704 spaceOut();
713 out(":"); 705 out(":");
714 spaceOut(); 706 spaceOut();
715 visitNestedExpression(cond.otherwise, ASSIGNMENT, 707 visitNestedExpression(cond.otherwise, ASSIGNMENT,
716 newInForInit: inForInit, newAtStatementBegin: false); 708 newInForInit: inForInit, newAtStatementBegin: false);
717 } 709 }
718 710
719 @override 711 @override
720 visitNew(New node) { 712 visitNew(New node) {
721 out("new "); 713 out("new ");
722 visitNestedExpression(node.target, LEFT_HAND_SIDE, 714 visitNestedExpression(node.target, LEFT_HAND_SIDE,
723 newInForInit: inForInit, newAtStatementBegin: false); 715 newInForInit: inForInit, newAtStatementBegin: false);
724 out("("); 716 out("(");
725 visitCommaSeparated(node.arguments, ASSIGNMENT, 717 visitCommaSeparated(node.arguments, ASSIGNMENT,
726 newInForInit: false, newAtStatementBegin: false); 718 newInForInit: false, newAtStatementBegin: false);
727 out(")"); 719 out(")");
728 } 720 }
729 721
730 @override 722 @override
731 visitCall(Call call) { 723 visitCall(Call call) {
732 visitNestedExpression(call.target, CALL, 724 visitNestedExpression(call.target, CALL,
733 newInForInit: inForInit, 725 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
734 newAtStatementBegin: atStatementBegin);
735 out("("); 726 out("(");
736 visitCommaSeparated(call.arguments, ASSIGNMENT, 727 visitCommaSeparated(call.arguments, ASSIGNMENT,
737 newInForInit: false, newAtStatementBegin: false); 728 newInForInit: false, newAtStatementBegin: false);
738 out(")"); 729 out(")");
739 } 730 }
740 731
741 @override 732 @override
742 void visitBinary(Binary binary) { 733 void visitBinary(Binary binary) {
743 Expression left = binary.left; 734 Expression left = binary.left;
744 Expression right = binary.right; 735 Expression right = binary.right;
745 String op = binary.op; 736 String op = binary.op;
746 int leftPrecedenceRequirement; 737 int leftPrecedenceRequirement;
747 int rightPrecedenceRequirement; 738 int rightPrecedenceRequirement;
748 bool leftSpace = true; // left<HERE>op right 739 bool leftSpace = true; // left<HERE>op right
749 switch (op) { 740 switch (op) {
750 case ',': 741 case ',':
751 // x, (y, z) <=> (x, y), z. 742 // x, (y, z) <=> (x, y), z.
752 leftPrecedenceRequirement = EXPRESSION; 743 leftPrecedenceRequirement = EXPRESSION;
753 rightPrecedenceRequirement = EXPRESSION; 744 rightPrecedenceRequirement = EXPRESSION;
754 leftSpace = false; 745 leftSpace = false;
755 break; 746 break;
756 case "||": 747 case "||":
757 leftPrecedenceRequirement = LOGICAL_OR; 748 leftPrecedenceRequirement = LOGICAL_OR;
758 // x || (y || z) <=> (x || y) || z. 749 // x || (y || z) <=> (x || y) || z.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 case "%": 806 case "%":
816 leftPrecedenceRequirement = MULTIPLICATIVE; 807 leftPrecedenceRequirement = MULTIPLICATIVE;
817 // We cannot remove parenthesis for "*" because of precision issues. 808 // We cannot remove parenthesis for "*" because of precision issues.
818 rightPrecedenceRequirement = UNARY; 809 rightPrecedenceRequirement = UNARY;
819 break; 810 break;
820 default: 811 default:
821 context.error("Forgot operator: $op"); 812 context.error("Forgot operator: $op");
822 } 813 }
823 814
824 visitNestedExpression(left, leftPrecedenceRequirement, 815 visitNestedExpression(left, leftPrecedenceRequirement,
825 newInForInit: inForInit, 816 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
826 newAtStatementBegin: atStatementBegin);
827 817
828 if (op == "in" || op == "instanceof") { 818 if (op == "in" || op == "instanceof") {
829 // There are cases where the space is not required but without further 819 // There are cases where the space is not required but without further
830 // analysis we cannot know. 820 // analysis we cannot know.
831 out(" ", isWhitespace: true); 821 out(" ", isWhitespace: true);
832 out(op); 822 out(op);
833 out(" ", isWhitespace: true); 823 out(" ", isWhitespace: true);
834 } else { 824 } else {
835 if (leftSpace) spaceOut(); 825 if (leftSpace) spaceOut();
836 out(op); 826 out(op);
837 spaceOut(); 827 spaceOut();
838 } 828 }
839 visitNestedExpression(right, rightPrecedenceRequirement, 829 visitNestedExpression(right, rightPrecedenceRequirement,
840 newInForInit: inForInit, 830 newInForInit: inForInit, newAtStatementBegin: false);
841 newAtStatementBegin: false);
842 } 831 }
843 832
844 @override 833 @override
845 void visitPrefix(Prefix unary) { 834 void visitPrefix(Prefix unary) {
846 String op = unary.op; 835 String op = unary.op;
847 switch (op) { 836 switch (op) {
848 case "delete": 837 case "delete":
849 case "void": 838 case "void":
850 case "typeof": 839 case "typeof":
851 // There are cases where the space is not required but without further 840 // There are cases where the space is not required but without further
852 // analysis we cannot know. 841 // analysis we cannot know.
853 out(op); 842 out(op);
854 out(" ", isWhitespace: true); 843 out(" ", isWhitespace: true);
855 break; 844 break;
856 case "+": 845 case "+":
857 case "++": 846 case "++":
858 if (lastCharCode == charCodes.$PLUS) out(" ", isWhitespace: true); 847 if (lastCharCode == charCodes.$PLUS) out(" ", isWhitespace: true);
859 out(op); 848 out(op);
860 break; 849 break;
861 case "-": 850 case "-":
862 case "--": 851 case "--":
863 if (lastCharCode == charCodes.$MINUS) out(" ", isWhitespace: true); 852 if (lastCharCode == charCodes.$MINUS) out(" ", isWhitespace: true);
864 out(op); 853 out(op);
865 break; 854 break;
866 default: 855 default:
867 out(op); 856 out(op);
868 } 857 }
869 visitNestedExpression(unary.argument, UNARY, 858 visitNestedExpression(unary.argument, UNARY,
870 newInForInit: inForInit, newAtStatementBegin: false); 859 newInForInit: inForInit, newAtStatementBegin: false);
871 } 860 }
872 861
873 @override 862 @override
874 void visitPostfix(Postfix postfix) { 863 void visitPostfix(Postfix postfix) {
875 visitNestedExpression(postfix.argument, CALL, 864 visitNestedExpression(postfix.argument, CALL,
876 newInForInit: inForInit, 865 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
877 newAtStatementBegin: atStatementBegin);
878 out(postfix.op); 866 out(postfix.op);
879 } 867 }
880 868
881 @override 869 @override
882 void visitVariableUse(VariableUse ref) { 870 void visitVariableUse(VariableUse ref) {
883 out(localNamer.getName(ref.name)); 871 out(localNamer.getName(ref.name));
884 } 872 }
885 873
886 @override 874 @override
887 void visitThis(This node) { 875 void visitThis(This node) {
(...skipping 14 matching lines...) Expand all
902 return charCodes.$0 <= charCode && charCode <= charCodes.$9; 890 return charCodes.$0 <= charCode && charCode <= charCodes.$9;
903 } 891 }
904 892
905 bool isValidJavaScriptId(String field) { 893 bool isValidJavaScriptId(String field) {
906 if (field.length < 3) return false; 894 if (field.length < 3) return false;
907 // Ignore the leading and trailing string-delimiter. 895 // Ignore the leading and trailing string-delimiter.
908 for (int i = 1; i < field.length - 1; i++) { 896 for (int i = 1; i < field.length - 1; i++) {
909 // TODO(floitsch): allow more characters. 897 // TODO(floitsch): allow more characters.
910 int charCode = field.codeUnitAt(i); 898 int charCode = field.codeUnitAt(i);
911 if (!(charCodes.$a <= charCode && charCode <= charCodes.$z || 899 if (!(charCodes.$a <= charCode && charCode <= charCodes.$z ||
912 charCodes.$A <= charCode && charCode <= charCodes.$Z || 900 charCodes.$A <= charCode && charCode <= charCodes.$Z ||
913 charCode == charCodes.$$ || 901 charCode == charCodes.$$ ||
914 charCode == charCodes.$_ || 902 charCode == charCodes.$_ ||
915 i != 1 && isDigit(charCode))) { 903 i != 1 && isDigit(charCode))) {
916 return false; 904 return false;
917 } 905 }
918 } 906 }
919 // TODO(floitsch): normally we should also check that the field is not a 907 // TODO(floitsch): normally we should also check that the field is not a
920 // reserved word. We don't generate fields with reserved word names except 908 // reserved word. We don't generate fields with reserved word names except
921 // for 'super'. 909 // for 'super'.
922 if (field == '"super"') return false; 910 if (field == '"super"') return false;
923 if (field == '"catch"') return false; 911 if (field == '"catch"') return false;
924 return true; 912 return true;
925 } 913 }
926 914
927 @override 915 @override
928 void visitAccess(PropertyAccess access) { 916 void visitAccess(PropertyAccess access) {
929 visitNestedExpression(access.receiver, CALL, 917 visitNestedExpression(access.receiver, CALL,
930 newInForInit: inForInit, 918 newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
931 newAtStatementBegin: atStatementBegin);
932 Node selector = access.selector; 919 Node selector = access.selector;
933 if (selector is LiteralString) { 920 if (selector is LiteralString) {
934 LiteralString selectorString = selector; 921 LiteralString selectorString = selector;
935 String fieldWithQuotes = selectorString.value; 922 String fieldWithQuotes = selectorString.value;
936 if (isValidJavaScriptId(fieldWithQuotes)) { 923 if (isValidJavaScriptId(fieldWithQuotes)) {
937 if (access.receiver is LiteralNumber && 924 if (access.receiver is LiteralNumber &&
938 lastCharCode != charCodes.$CLOSE_PAREN) { 925 lastCharCode != charCodes.$CLOSE_PAREN) {
939 out(" ", isWhitespace: true); 926 out(" ", isWhitespace: true);
940 } 927 }
941 out("."); 928 out(".");
942 startNode(selector); 929 startNode(selector);
943 out(fieldWithQuotes.substring(1, fieldWithQuotes.length - 1)); 930 out(fieldWithQuotes.substring(1, fieldWithQuotes.length - 1));
944 endNode(selector); 931 endNode(selector);
945 return; 932 return;
946 } 933 }
947 } else if (selector is Name) { 934 } else if (selector is Name) {
948 if (access.receiver is LiteralNumber && 935 if (access.receiver is LiteralNumber &&
949 lastCharCode != charCodes.$CLOSE_PAREN) { 936 lastCharCode != charCodes.$CLOSE_PAREN) {
950 out(" ", isWhitespace: true); 937 out(" ", isWhitespace: true);
951 } 938 }
952 out("."); 939 out(".");
953 startNode(selector); 940 startNode(selector);
954 selector.accept(this); 941 selector.accept(this);
955 endNode(selector); 942 endNode(selector);
956 return; 943 return;
957 } 944 }
958 out("["); 945 out("[");
959 visitNestedExpression(selector, EXPRESSION, 946 visitNestedExpression(selector, EXPRESSION,
960 newInForInit: false, newAtStatementBegin: false); 947 newInForInit: false, newAtStatementBegin: false);
961 out("]"); 948 out("]");
962 } 949 }
963 950
964 @override 951 @override
965 void visitNamedFunction(NamedFunction namedFunction) { 952 void visitNamedFunction(NamedFunction namedFunction) {
966 VarCollector vars = new VarCollector(); 953 VarCollector vars = new VarCollector();
967 vars.visitNamedFunction(namedFunction); 954 vars.visitNamedFunction(namedFunction);
968 startNode(namedFunction.function); 955 startNode(namedFunction.function);
969 currentNode.closingPosition = 956 currentNode.closingPosition =
970 functionOut(namedFunction.function, namedFunction.name, vars); 957 functionOut(namedFunction.function, namedFunction.name, vars);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1044 // in last position. Otherwise `[,]` (having length 1) would become 1031 // in last position. Otherwise `[,]` (having length 1) would become
1045 // equal to `[]` (the empty array) 1032 // equal to `[]` (the empty array)
1046 // and [1,,] (array with 1 and a hole) would become [1,] = [1]. 1033 // and [1,,] (array with 1 and a hole) would become [1,] = [1].
1047 startNode(element); 1034 startNode(element);
1048 out(","); 1035 out(",");
1049 endNode(element); 1036 endNode(element);
1050 continue; 1037 continue;
1051 } 1038 }
1052 if (i != 0) spaceOut(); 1039 if (i != 0) spaceOut();
1053 visitNestedExpression(element, ASSIGNMENT, 1040 visitNestedExpression(element, ASSIGNMENT,
1054 newInForInit: false, newAtStatementBegin: false); 1041 newInForInit: false, newAtStatementBegin: false);
1055 // We can skip the trailing "," for the last element (since it's not 1042 // We can skip the trailing "," for the last element (since it's not
1056 // an array hole). 1043 // an array hole).
1057 if (i != elements.length - 1) out(","); 1044 if (i != elements.length - 1) out(",");
1058 } 1045 }
1059 out("]"); 1046 out("]");
1060 } 1047 }
1061 1048
1062 @override 1049 @override
1063 void visitArrayHole(ArrayHole node) { 1050 void visitArrayHole(ArrayHole node) {
1064 context.error("Unreachable"); 1051 context.error("Unreachable");
1065 } 1052 }
1066 1053
1067 @override 1054 @override
1068 void visitObjectInitializer(ObjectInitializer node) { 1055 void visitObjectInitializer(ObjectInitializer node) {
1069 // Print all the properties on one line until we see a function-valued 1056 // Print all the properties on one line until we see a function-valued
1070 // property. Ideally, we would use a proper pretty-printer to make the 1057 // property. Ideally, we would use a proper pretty-printer to make the
1071 // decision based on layout. 1058 // decision based on layout.
1072 bool exitOneLinerMode(Expression value) { 1059 bool exitOneLinerMode(Expression value) {
1073 return 1060 return value is Fun ||
1074 value is Fun ||
1075 value is ArrayInitializer && value.elements.any((e) => e is Fun); 1061 value is ArrayInitializer && value.elements.any((e) => e is Fun);
1076 } 1062 }
1077 1063
1078 bool isOneLiner = node.isOneLiner || shouldCompressOutput; 1064 bool isOneLiner = node.isOneLiner || shouldCompressOutput;
1079 List<Property> properties = node.properties; 1065 List<Property> properties = node.properties;
1080 out("{"); 1066 out("{");
1081 indentMore(); 1067 indentMore();
1082 for (int i = 0; i < properties.length; i++) { 1068 for (int i = 0; i < properties.length; i++) {
1083 Node value = properties[i].value; 1069 Node value = properties[i].value;
1084 if (isOneLiner && exitOneLinerMode(value)) isOneLiner = false; 1070 if (isOneLiner && exitOneLinerMode(value)) isOneLiner = false;
(...skipping 30 matching lines...) Expand all
1115 node.name.accept(this); 1101 node.name.accept(this);
1116 } else { 1102 } else {
1117 assert(node.name is LiteralNumber); 1103 assert(node.name is LiteralNumber);
1118 LiteralNumber nameNumber = node.name; 1104 LiteralNumber nameNumber = node.name;
1119 out(nameNumber.value); 1105 out(nameNumber.value);
1120 } 1106 }
1121 endNode(node.name); 1107 endNode(node.name);
1122 out(":"); 1108 out(":");
1123 spaceOut(); 1109 spaceOut();
1124 visitNestedExpression(node.value, ASSIGNMENT, 1110 visitNestedExpression(node.value, ASSIGNMENT,
1125 newInForInit: false, newAtStatementBegin: false); 1111 newInForInit: false, newAtStatementBegin: false);
1126 } 1112 }
1127 1113
1128 @override 1114 @override
1129 void visitRegExpLiteral(RegExpLiteral node) { 1115 void visitRegExpLiteral(RegExpLiteral node) {
1130 out(node.pattern); 1116 out(node.pattern);
1131 } 1117 }
1132 1118
1133 @override 1119 @override
1134 void visitLiteralExpression(LiteralExpression node) { 1120 void visitLiteralExpression(LiteralExpression node) {
1135 String template = node.template; 1121 String template = node.template;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 } 1184 }
1199 } 1185 }
1200 1186
1201 @override 1187 @override
1202 void visitAwait(Await node) { 1188 void visitAwait(Await node) {
1203 out("await "); 1189 out("await ");
1204 visit(node.expression); 1190 visit(node.expression);
1205 } 1191 }
1206 } 1192 }
1207 1193
1208
1209 class OrderedSet<T> { 1194 class OrderedSet<T> {
1210 final Set<T> set; 1195 final Set<T> set;
1211 final List<T> list; 1196 final List<T> list;
1212 1197
1213 OrderedSet() : set = new Set<T>(), list = <T>[]; 1198 OrderedSet()
1199 : set = new Set<T>(),
1200 list = <T>[];
1214 1201
1215 void add(T x) { 1202 void add(T x) {
1216 if (set.add(x)) { 1203 if (set.add(x)) {
1217 // [Set.add] returns `true` if 'x' was added. 1204 // [Set.add] returns `true` if 'x' was added.
1218 list.add(x); 1205 list.add(x);
1219 } 1206 }
1220 } 1207 }
1221 1208
1222 void forEach(void fun(T x)) { 1209 void forEach(void fun(T x)) {
1223 list.forEach(fun); 1210 list.forEach(fun);
1224 } 1211 }
1225 } 1212 }
1226 1213
1227 // Collects all the var declarations in the function. We need to do this in a 1214 // Collects all the var declarations in the function. We need to do this in a
1228 // separate pass because JS vars are lifted to the top of the function. 1215 // separate pass because JS vars are lifted to the top of the function.
1229 class VarCollector extends BaseVisitor { 1216 class VarCollector extends BaseVisitor {
1230 bool nested; 1217 bool nested;
1231 bool enableRenaming = true; 1218 bool enableRenaming = true;
1232 final OrderedSet<String> vars; 1219 final OrderedSet<String> vars;
1233 final OrderedSet<String> params; 1220 final OrderedSet<String> params;
1234 1221
1235 static final String disableVariableMinificationPattern = "::norenaming::"; 1222 static final String disableVariableMinificationPattern = "::norenaming::";
1236 static final String enableVariableMinificationPattern = "::dorenaming::"; 1223 static final String enableVariableMinificationPattern = "::dorenaming::";
1237 1224
1238 VarCollector() : nested = false, 1225 VarCollector()
1239 vars = new OrderedSet<String>(), 1226 : nested = false,
1240 params = new OrderedSet<String>(); 1227 vars = new OrderedSet<String>(),
1228 params = new OrderedSet<String>();
1241 1229
1242 void forEachVar(void fn(String v)) => vars.forEach(fn); 1230 void forEachVar(void fn(String v)) => vars.forEach(fn);
1243 void forEachParam(void fn(String p)) => params.forEach(fn); 1231 void forEachParam(void fn(String p)) => params.forEach(fn);
1244 1232
1245 void collectVarsInFunction(Fun fun) { 1233 void collectVarsInFunction(Fun fun) {
1246 if (!nested) { 1234 if (!nested) {
1247 nested = true; 1235 nested = true;
1248 if (fun.params != null) { 1236 if (fun.params != null) {
1249 for (int i = 0; i < fun.params.length; i++) { 1237 for (int i = 0; i < fun.params.length; i++) {
1250 params.add(fun.params[i].name); 1238 params.add(fun.params[i].name);
(...skipping 26 matching lines...) Expand all
1277 } else if (node.comment.contains(enableVariableMinificationPattern)) { 1265 } else if (node.comment.contains(enableVariableMinificationPattern)) {
1278 enableRenaming = true; 1266 enableRenaming = true;
1279 } 1267 }
1280 } 1268 }
1281 1269
1282 void visitVariableDeclaration(VariableDeclaration decl) { 1270 void visitVariableDeclaration(VariableDeclaration decl) {
1283 if (enableRenaming && decl.allowRename) vars.add(decl.name); 1271 if (enableRenaming && decl.allowRename) vars.add(decl.name);
1284 } 1272 }
1285 } 1273 }
1286 1274
1287
1288 /** 1275 /**
1289 * Returns true, if the given node must be wrapped into braces when used 1276 * Returns true, if the given node must be wrapped into braces when used
1290 * as then-statement in an [If] that has an else branch. 1277 * as then-statement in an [If] that has an else branch.
1291 */ 1278 */
1292 class DanglingElseVisitor extends BaseVisitor<bool> { 1279 class DanglingElseVisitor extends BaseVisitor<bool> {
1293 JavaScriptPrintingContext context; 1280 JavaScriptPrintingContext context;
1294 1281
1295 DanglingElseVisitor(this.context); 1282 DanglingElseVisitor(this.context);
1296 1283
1297 bool visitProgram(Program node) => false; 1284 bool visitProgram(Program node) => false;
1298 1285
1299 bool visitNode(Statement node) { 1286 bool visitNode(Statement node) {
1300 context.error("Forgot node: $node"); 1287 context.error("Forgot node: $node");
1301 return null; 1288 return null;
1302 } 1289 }
1303 1290
1304 bool visitBlock(Block node) => false; 1291 bool visitBlock(Block node) => false;
1305 bool visitExpressionStatement(ExpressionStatement node) => false; 1292 bool visitExpressionStatement(ExpressionStatement node) => false;
1306 bool visitEmptyStatement(EmptyStatement node) => false; 1293 bool visitEmptyStatement(EmptyStatement node) => false;
1307 bool visitIf(If node) { 1294 bool visitIf(If node) {
1308 if (!node.hasElse) return true; 1295 if (!node.hasElse) return true;
1309 return node.otherwise.accept(this); 1296 return node.otherwise.accept(this);
1310 } 1297 }
1298
1311 bool visitFor(For node) => node.body.accept(this); 1299 bool visitFor(For node) => node.body.accept(this);
1312 bool visitForIn(ForIn node) => node.body.accept(this); 1300 bool visitForIn(ForIn node) => node.body.accept(this);
1313 bool visitWhile(While node) => node.body.accept(this); 1301 bool visitWhile(While node) => node.body.accept(this);
1314 bool visitDo(Do node) => false; 1302 bool visitDo(Do node) => false;
1315 bool visitContinue(Continue node) => false; 1303 bool visitContinue(Continue node) => false;
1316 bool visitBreak(Break node) => false; 1304 bool visitBreak(Break node) => false;
1317 bool visitReturn(Return node) => false; 1305 bool visitReturn(Return node) => false;
1318 bool visitThrow(Throw node) => false; 1306 bool visitThrow(Throw node) => false;
1319 bool visitTry(Try node) { 1307 bool visitTry(Try node) {
1320 if (node.finallyPart != null) { 1308 if (node.finallyPart != null) {
1321 return node.finallyPart.accept(this); 1309 return node.finallyPart.accept(this);
1322 } else { 1310 } else {
1323 return node.catchPart.accept(this); 1311 return node.catchPart.accept(this);
1324 } 1312 }
1325 } 1313 }
1314
1326 bool visitCatch(Catch node) => node.body.accept(this); 1315 bool visitCatch(Catch node) => node.body.accept(this);
1327 bool visitSwitch(Switch node) => false; 1316 bool visitSwitch(Switch node) => false;
1328 bool visitCase(Case node) => false; 1317 bool visitCase(Case node) => false;
1329 bool visitDefault(Default node) => false; 1318 bool visitDefault(Default node) => false;
1330 bool visitFunctionDeclaration(FunctionDeclaration node) => false; 1319 bool visitFunctionDeclaration(FunctionDeclaration node) => false;
1331 bool visitLabeledStatement(LabeledStatement node) 1320 bool visitLabeledStatement(LabeledStatement node) => node.body.accept(this);
1332 => node.body.accept(this);
1333 bool visitLiteralStatement(LiteralStatement node) => true; 1321 bool visitLiteralStatement(LiteralStatement node) => true;
1334 1322
1335 bool visitExpression(Expression node) => false; 1323 bool visitExpression(Expression node) => false;
1336 } 1324 }
1337 1325
1338
1339 abstract class LocalNamer { 1326 abstract class LocalNamer {
1340 String getName(String oldName); 1327 String getName(String oldName);
1341 String declareVariable(String oldName); 1328 String declareVariable(String oldName);
1342 String declareParameter(String oldName); 1329 String declareParameter(String oldName);
1343 void enterScope(VarCollector vars); 1330 void enterScope(VarCollector vars);
1344 void leaveScope(); 1331 void leaveScope();
1345 } 1332 }
1346 1333
1347
1348 class IdentityNamer implements LocalNamer { 1334 class IdentityNamer implements LocalNamer {
1349 String getName(String oldName) => oldName; 1335 String getName(String oldName) => oldName;
1350 String declareVariable(String oldName) => oldName; 1336 String declareVariable(String oldName) => oldName;
1351 String declareParameter(String oldName) => oldName; 1337 String declareParameter(String oldName) => oldName;
1352 void enterScope(VarCollector vars) {} 1338 void enterScope(VarCollector vars) {}
1353 void leaveScope() {} 1339 void leaveScope() {}
1354 } 1340 }
1355 1341
1356
1357 class MinifyRenamer implements LocalNamer { 1342 class MinifyRenamer implements LocalNamer {
1358 final List<Map<String, String>> maps = []; 1343 final List<Map<String, String>> maps = [];
1359 final List<int> parameterNumberStack = []; 1344 final List<int> parameterNumberStack = [];
1360 final List<int> variableNumberStack = []; 1345 final List<int> variableNumberStack = [];
1361 int parameterNumber = 0; 1346 int parameterNumber = 0;
1362 int variableNumber = 0; 1347 int variableNumber = 0;
1363 1348
1364 MinifyRenamer(); 1349 MinifyRenamer();
1365 1350
1366 void enterScope(VarCollector vars) { 1351 void enterScope(VarCollector vars) {
(...skipping 18 matching lines...) Expand all
1385 if (replacement != null) return replacement; 1370 if (replacement != null) return replacement;
1386 } 1371 }
1387 return oldName; 1372 return oldName;
1388 } 1373 }
1389 1374
1390 static const LOWER_CASE_LETTERS = 26; 1375 static const LOWER_CASE_LETTERS = 26;
1391 static const LETTERS = LOWER_CASE_LETTERS; 1376 static const LETTERS = LOWER_CASE_LETTERS;
1392 static const DIGITS = 10; 1377 static const DIGITS = 10;
1393 1378
1394 static int nthLetter(int n) { 1379 static int nthLetter(int n) {
1395 return (n < LOWER_CASE_LETTERS) ? 1380 return (n < LOWER_CASE_LETTERS)
1396 charCodes.$a + n : 1381 ? charCodes.$a + n
1397 charCodes.$A + n - LOWER_CASE_LETTERS; 1382 : charCodes.$A + n - LOWER_CASE_LETTERS;
1398 } 1383 }
1399 1384
1400 // Parameters go from a to z and variables go from z to a. This makes each 1385 // Parameters go from a to z and variables go from z to a. This makes each
1401 // argument list and each top-of-function var declaration look similar and 1386 // argument list and each top-of-function var declaration look similar and
1402 // helps gzip compress the file. If we have more than 26 arguments and 1387 // helps gzip compress the file. If we have more than 26 arguments and
1403 // variables then we meet somewhere in the middle of the alphabet. After 1388 // variables then we meet somewhere in the middle of the alphabet. After
1404 // that we give up trying to be nice to the compression algorithm and just 1389 // that we give up trying to be nice to the compression algorithm and just
1405 // use the same namespace for arguments and variables, starting with A, and 1390 // use the same namespace for arguments and variables, starting with A, and
1406 // moving on to a0, a1, etc. 1391 // moving on to a0, a1, etc.
1407 String declareVariable(String oldName) { 1392 String declareVariable(String oldName) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1497 } 1482 }
1498 } 1483 }
1499 1484
1500 EnterExitNode exitNode(JavaScriptPrintingContext context, int position) { 1485 EnterExitNode exitNode(JavaScriptPrintingContext context, int position) {
1501 // Enter must happen before exit. 1486 // Enter must happen before exit.
1502 addToNode(context, position); 1487 addToNode(context, position);
1503 context.exitNode(node, startPosition, position, closingPosition); 1488 context.exitNode(node, startPosition, position, closingPosition);
1504 return parent; 1489 return parent;
1505 } 1490 }
1506 } 1491 }
OLDNEW
« no previous file with comments | « pkg/js_ast/lib/src/nodes.dart ('k') | pkg/js_ast/lib/src/template.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698