added some comments about the rules governing parens
This commit is contained in:
@@ -228,6 +228,7 @@ function OutputStream(options) {
|
|||||||
nodetype.DEFMETHOD("print", function(stream){
|
nodetype.DEFMETHOD("print", function(stream){
|
||||||
var self = this;
|
var self = this;
|
||||||
stream.push_node(self);
|
stream.push_node(self);
|
||||||
|
//stream.print("«" + self.TYPE + ":" + self.start.line + ":" + self.start.col + "»");
|
||||||
if (self.needs_parens(stream)) {
|
if (self.needs_parens(stream)) {
|
||||||
stream.with_parens(function(){
|
stream.with_parens(function(){
|
||||||
generator(self, stream);
|
generator(self, stream);
|
||||||
@@ -268,23 +269,29 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
PARENS(AST_Seq, function(output){
|
PARENS(AST_Seq, function(output){
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
return p instanceof AST_Call
|
return p instanceof AST_Call // (foo, bar)() —or— foo(1, (2, 3), 4)
|
||||||
|| p instanceof AST_Binary
|
|| p instanceof AST_Binary // 1 + (2, 3) + 4 → 7
|
||||||
|| p instanceof AST_VarDef
|
|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; → b = 4
|
||||||
|| p instanceof AST_Dot
|
|| p instanceof AST_Dot // (1, {foo:2}).foo → 2
|
||||||
|| p instanceof AST_Array
|
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] → [ 1, 3, 4 ]
|
||||||
|| p instanceof AST_ObjectProperty
|
|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo → 2
|
||||||
|| p instanceof AST_Conditional;
|
|| 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){
|
PARENS(AST_Binary, function(output){
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
|
// (foo && bar)()
|
||||||
if (p instanceof AST_Call && p.expression === this)
|
if (p instanceof AST_Call && p.expression === this)
|
||||||
return true;
|
return true;
|
||||||
|
// typeof (foo && bar)
|
||||||
if (p instanceof AST_Unary)
|
if (p instanceof AST_Unary)
|
||||||
return true;
|
return true;
|
||||||
|
// (foo && bar)["prop"], (foo && bar).prop
|
||||||
if (p instanceof AST_PropAccess && p.expression === this)
|
if (p instanceof AST_PropAccess && p.expression === this)
|
||||||
return true;
|
return true;
|
||||||
|
// this deals with precedence: 3 * (2 + 1)
|
||||||
if (p instanceof AST_Binary) {
|
if (p instanceof AST_Binary) {
|
||||||
var po = p.operator, pp = PRECEDENCE[po];
|
var po = p.operator, pp = PRECEDENCE[po];
|
||||||
var so = this.operator, sp = PRECEDENCE[so];
|
var so = this.operator, sp = PRECEDENCE[so];
|
||||||
@@ -298,6 +305,7 @@ function OutputStream(options) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// for (var i = (foo in bar);;); ← perhaps useless, but valid syntax
|
||||||
if (this.operator == "in") {
|
if (this.operator == "in") {
|
||||||
// the “NoIn” stuff :-\
|
// the “NoIn” stuff :-\
|
||||||
// UglifyJS 1.3.3 misses this one.
|
// UglifyJS 1.3.3 misses this one.
|
||||||
@@ -313,26 +321,32 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
PARENS(AST_New, function(output){
|
PARENS(AST_New, function(output){
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
|
// (new Date).getTime();
|
||||||
if (p instanceof AST_Dot && no_constructor_parens(this, output))
|
if (p instanceof AST_Dot && no_constructor_parens(this, output))
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
function assign_and_conditional_paren_rules(output) {
|
function assign_and_conditional_paren_rules(output) {
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
|
// !(a = false) → true
|
||||||
if (p instanceof AST_Unary)
|
if (p instanceof AST_Unary)
|
||||||
return true;
|
return true;
|
||||||
|
// 1 + (a = 2) + 3 → 3, side effect setting a = 2
|
||||||
if (p instanceof AST_Binary && !(p instanceof AST_Assign))
|
if (p instanceof AST_Binary && !(p instanceof AST_Assign))
|
||||||
return true;
|
return true;
|
||||||
|
// (a = func)() —or— new (a = Object)()
|
||||||
if (p instanceof AST_Call && p.expression === this)
|
if (p instanceof AST_Call && p.expression === this)
|
||||||
return true;
|
return true;
|
||||||
|
// (a = foo) ? bar : baz
|
||||||
if (p instanceof AST_Conditional && p.condition === this)
|
if (p instanceof AST_Conditional && p.condition === this)
|
||||||
return true;
|
return true;
|
||||||
|
// (a = foo)["prop"] —or— (a = foo).prop
|
||||||
if (p instanceof AST_PropAccess && p.expression === this)
|
if (p instanceof AST_PropAccess && p.expression === this)
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
PARENS(AST_Conditional, assign_and_conditional_paren_rules);
|
|
||||||
PARENS(AST_Assign, assign_and_conditional_paren_rules);
|
PARENS(AST_Assign, assign_and_conditional_paren_rules);
|
||||||
|
PARENS(AST_Conditional, assign_and_conditional_paren_rules);
|
||||||
|
|
||||||
/* -----[ PRINTERS ]----- */
|
/* -----[ 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){
|
DEFPRINT(AST_New, function(self, output){
|
||||||
output.print("new");
|
output.print("new");
|
||||||
output.space();
|
output.space();
|
||||||
@@ -779,15 +788,16 @@ function OutputStream(options) {
|
|||||||
function first_in_statement(output) {
|
function first_in_statement(output) {
|
||||||
var a = output.stack(), i = a.length, node = a[--i], p = a[--i];
|
var a = output.stack(), i = a.length, node = a[--i], p = a[--i];
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
if (p instanceof AST_Statement) return true;
|
if (p instanceof AST_Statement)
|
||||||
if ((p instanceof AST_Seq && p.first === node) ||
|
return true;
|
||||||
(p instanceof AST_Call && p.expression === node) ||
|
if ((p instanceof AST_Seq && p.first === node ) ||
|
||||||
(p instanceof AST_Dot && p.expression === node) ||
|
(p instanceof AST_Call && p.expression === node ) ||
|
||||||
(p instanceof AST_Sub && p.expression === node) ||
|
(p instanceof AST_Dot && p.expression === node ) ||
|
||||||
(p instanceof AST_Conditional && p.condition === node) ||
|
(p instanceof AST_Sub && p.expression === node ) ||
|
||||||
(p instanceof AST_Binary && p.first === node) ||
|
(p instanceof AST_Conditional && p.condition === node ) ||
|
||||||
(p instanceof AST_Assign && p.first === node) ||
|
(p instanceof AST_Binary && p.first === node ) ||
|
||||||
(p instanceof AST_UnaryPostfix && p.expression === node))
|
(p instanceof AST_Assign && p.first === node ) ||
|
||||||
|
(p instanceof AST_UnaryPostfix && p.expression === node ))
|
||||||
{
|
{
|
||||||
node = p;
|
node = p;
|
||||||
p = a[--i];
|
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) {
|
function best_of(a) {
|
||||||
var best = a[0], len = best.length;
|
var best = a[0], len = best.length;
|
||||||
for (var i = 1; i < a.length; ++i) {
|
for (var i = 1; i < a.length; ++i) {
|
||||||
|
|||||||
Reference in New Issue
Block a user