From 07cbc8d3afee368ed143f62302d1b1a51e0f09bc Mon Sep 17 00:00:00 2001 From: Mihai Bazon Date: Fri, 17 Aug 2012 17:56:16 +0300 Subject: added some comments about the rules governing parens --- lib/output.js | 59 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/output.js b/lib/output.js index 54707f05..b7bf79d2 100644 --- a/lib/output.js +++ b/lib/output.js @@ -228,6 +228,7 @@ function OutputStream(options) { nodetype.DEFMETHOD("print", function(stream){ var self = this; stream.push_node(self); + //stream.print("«" + self.TYPE + ":" + self.start.line + ":" + self.start.col + "»"); if (self.needs_parens(stream)) { stream.with_parens(function(){ generator(self, stream); @@ -268,23 +269,29 @@ function OutputStream(options) { PARENS(AST_Seq, function(output){ var p = output.parent(); - return p instanceof AST_Call - || p instanceof AST_Binary - || p instanceof AST_VarDef - || p instanceof AST_Dot - || p instanceof AST_Array - || p instanceof AST_ObjectProperty - || p instanceof AST_Conditional; + return p instanceof AST_Call // (foo, bar)() —or— foo(1, (2, 3), 4) + || p instanceof AST_Binary // 1 + (2, 3) + 4 → 7 + || p instanceof AST_VarDef // var a = (1, 2), b = a + a; → b = 4 + || p instanceof AST_Dot // (1, {foo:2}).foo → 2 + || p instanceof AST_Array // [ 1, (2, 3), 4 ] → [ 1, 3, 4 ] + || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo → 2 + || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) + * → 20 (side effect, set a = 10 and b = 20) */ + ; }); PARENS(AST_Binary, function(output){ var p = output.parent(); + // (foo && bar)() if (p instanceof AST_Call && p.expression === this) return true; + // typeof (foo && bar) if (p instanceof AST_Unary) return true; + // (foo && bar)["prop"], (foo && bar).prop if (p instanceof AST_PropAccess && p.expression === this) return true; + // this deals with precedence: 3 * (2 + 1) if (p instanceof AST_Binary) { var po = p.operator, pp = PRECEDENCE[po]; var so = this.operator, sp = PRECEDENCE[so]; @@ -298,6 +305,7 @@ function OutputStream(options) { return true; } } + // for (var i = (foo in bar);;); ← perhaps useless, but valid syntax if (this.operator == "in") { // the “NoIn” stuff :-\ // UglifyJS 1.3.3 misses this one. @@ -313,26 +321,32 @@ function OutputStream(options) { PARENS(AST_New, function(output){ var p = output.parent(); + // (new Date).getTime(); if (p instanceof AST_Dot && no_constructor_parens(this, output)) return true; }); function assign_and_conditional_paren_rules(output) { var p = output.parent(); + // !(a = false) → true if (p instanceof AST_Unary) return true; + // 1 + (a = 2) + 3 → 3, side effect setting a = 2 if (p instanceof AST_Binary && !(p instanceof AST_Assign)) return true; + // (a = func)() —or— new (a = Object)() if (p instanceof AST_Call && p.expression === this) return true; + // (a = foo) ? bar : baz if (p instanceof AST_Conditional && p.condition === this) return true; + // (a = foo)["prop"] —or— (a = foo).prop if (p instanceof AST_PropAccess && p.expression === this) return true; }; - PARENS(AST_Conditional, assign_and_conditional_paren_rules); PARENS(AST_Assign, assign_and_conditional_paren_rules); + PARENS(AST_Conditional, assign_and_conditional_paren_rules); /* -----[ PRINTERS ]----- */ @@ -639,11 +653,6 @@ function OutputStream(options) { }); }); }); - function no_constructor_parens(self, output) { - return (self.args.length == 0 - // && !output.options("beautify") - ); - }; DEFPRINT(AST_New, function(self, output){ output.print("new"); output.space(); @@ -779,15 +788,16 @@ function OutputStream(options) { function first_in_statement(output) { var a = output.stack(), i = a.length, node = a[--i], p = a[--i]; while (i > 0) { - if (p instanceof AST_Statement) return true; - if ((p instanceof AST_Seq && p.first === node) || - (p instanceof AST_Call && p.expression === node) || - (p instanceof AST_Dot && p.expression === node) || - (p instanceof AST_Sub && p.expression === node) || - (p instanceof AST_Conditional && p.condition === node) || - (p instanceof AST_Binary && p.first === node) || - (p instanceof AST_Assign && p.first === node) || - (p instanceof AST_UnaryPostfix && p.expression === node)) + if (p instanceof AST_Statement) + return true; + if ((p instanceof AST_Seq && p.first === node ) || + (p instanceof AST_Call && p.expression === node ) || + (p instanceof AST_Dot && p.expression === node ) || + (p instanceof AST_Sub && p.expression === node ) || + (p instanceof AST_Conditional && p.condition === node ) || + (p instanceof AST_Binary && p.first === node ) || + (p instanceof AST_Assign && p.first === node ) || + (p instanceof AST_UnaryPostfix && p.expression === node )) { node = p; p = a[--i]; @@ -797,6 +807,11 @@ function OutputStream(options) { } }; + // self should be AST_New. decide if we want to show parens or not. + function no_constructor_parens(self, output) { + return self.args.length == 0 && !output.options("beautify"); + }; + function best_of(a) { var best = a[0], len = best.length; for (var i = 1; i < a.length; ++i) { -- cgit v1.2.3