Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #365 #425

Closed
wants to merge 12 commits into from
114 changes: 101 additions & 13 deletions escodegen.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,60 @@
return len && esutils.code.isLineTerminator(str.charCodeAt(len - 1));
}

function removeComments(str) {
// https://stackoverflow.com/a/59094308
return str.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
}

function removeTrailingWhiteSpaces(str) {
return str.replace(/\S(\s+)$/g, '');
}

function isParenthesized(str, leftPar, rightPar) {
str = removeComments(str);
str = removeTrailingWhiteSpaces(str);
var counter = 0;
for (var i = 0; i < str.length; ++i) {
if (str[i] == leftPar) {
counter++;
}
else if (str[i] == rightPar) {
if (counter == 0) {
return false;
}
counter--;
}
}
return counter == 0 && str[str.length-1] == rightPar;
}

function isParenthesizedByAnyBracketKind(str) {
return isParenthesized(str, '(', ')') ||
isParenthesized(str, '{', '}') ||
isParenthesized(str, '[', ']');
}

function shouldParenthesize(str, parent) {
if (!hasLineTerminator(str)) {
return false;
}
if (parent !== undefined && (
parent.type == Syntax.ObjectExpression ||
parent.type == Syntax.ArrayExpression ||
parent.type == Syntax.Property
)) {
return false;
}
if (!isParenthesizedByAnyBracketKind(str)) {
return true;
}

str = removeComments(str);
var firstNewlineIdx = str.indexOf(newline);
var firstParenthesisIdx = str.match(/[\(\[\{)]/).index;
return firstNewlineIdx < firstParenthesisIdx;
}

function merge(target, override) {
var key;
for (key in override) {
Expand Down Expand Up @@ -570,6 +624,18 @@
return [base, stmt];
}

function addMultiLineIndent(stmt) {
var str = base + flattenToString(stmt);
var split = str.split(/\n/g);
var suffix = '';
// do not replace the last newline
if (split[split.length-1].length == 0) {
split = split.slice(0, split.length-1);
suffix = newline;
}
return split.join(newline + base) + suffix;
}

function withIndent(fn) {
var previousBase;
previousBase = base;
Expand Down Expand Up @@ -659,7 +725,7 @@
return '/*' + comment.value + '*/';
}

function addComments(stmt, result) {
function addComments(stmt, result, parent) {
var i, len, comment, save, tailingToStatement, specialBase, fragment,
extRange, range, prevRange, prefix, infix, suffix, count;

Expand Down Expand Up @@ -703,10 +769,12 @@
} else {
comment = stmt.leadingComments[0];
result = [];

if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) {
result.push('\n');
}
result.push(generateComment(comment));

if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
result.push('\n');
}
Expand All @@ -721,7 +789,26 @@
}
}

result.push(addIndent(save));
if (!isExpression(stmt)) {
result.push(addIndent(save));
} else {
var text = toSourceNodeWhenNeeded(result).toString();
if (shouldParenthesize(text, parent)) {
withIndent(function () {
result = addMultiLineIndent(result);
});

result = ['(', newline, result];

withIndent(function () {
result.push(addMultiLineIndent(save));
});

result.push([newline, base, ')']);
} else {
result.push(addIndent(save));
}
}
}

if (stmt.trailingComments) {
Expand Down Expand Up @@ -977,14 +1064,14 @@
return result;
};

CodeGenerator.prototype.generatePropertyKey = function (expr, computed) {
CodeGenerator.prototype.generatePropertyKey = function (expr, computed, parent) {
var result = [];

if (computed) {
result.push('[');
}

result.push(this.generateExpression(expr, Precedence.Assignment, E_TTT));
result.push(this.generateExpression(expr, Precedence.Assignment, E_TTT, parent));

if (computed) {
result.push(']');
Expand Down Expand Up @@ -2095,7 +2182,7 @@
}
} else {
result.push(multiline ? indent : '');
result.push(that.generateExpression(expr.elements[i], Precedence.Assignment, E_TTT));
result.push(that.generateExpression(expr.elements[i], Precedence.Assignment, E_TTT, expr));
}
if (i + 1 < iz) {
result.push(',' + (multiline ? newline : space));
Expand Down Expand Up @@ -2155,7 +2242,7 @@
if (expr.kind === 'get' || expr.kind === 'set') {
return [
expr.kind, noEmptySpace(),
this.generatePropertyKey(expr.key, expr.computed),
this.generatePropertyKey(expr.key, expr.computed, expr),
this.generateFunctionBody(expr.value)
];
}
Expand All @@ -2164,19 +2251,19 @@
if (expr.value.type === "AssignmentPattern") {
return this.AssignmentPattern(expr.value, Precedence.Sequence, E_TTT);
}
return this.generatePropertyKey(expr.key, expr.computed);
return this.generatePropertyKey(expr.key, expr.computed, expr);
}

if (expr.method) {
return [
generateMethodPrefix(expr),
this.generatePropertyKey(expr.key, expr.computed),
this.generatePropertyKey(expr.key, expr.computed, expr),
this.generateFunctionBody(expr.value)
];
}

return [
this.generatePropertyKey(expr.key, expr.computed),
this.generatePropertyKey(expr.key, expr.computed, expr),
':' + space,
this.generateExpression(expr.value, Precedence.Assignment, E_TTT)
];
Expand All @@ -2191,7 +2278,7 @@
multiline = expr.properties.length > 1;

withIndent(function () {
fragment = that.generateExpression(expr.properties[0], Precedence.Sequence, E_TTT);
fragment = that.generateExpression(expr.properties[0], Precedence.Sequence, E_TTT, expr);
});

if (!multiline) {
Expand All @@ -2216,7 +2303,7 @@
result.push(',' + newline);
for (i = 1, iz = expr.properties.length; i < iz; ++i) {
result.push(indent);
result.push(that.generateExpression(expr.properties[i], Precedence.Sequence, E_TTT));
result.push(that.generateExpression(expr.properties[i], Precedence.Sequence, E_TTT, expr));
if (i + 1 < iz) {
result.push(',' + newline);
}
Expand Down Expand Up @@ -2484,7 +2571,7 @@

merge(CodeGenerator.prototype, CodeGenerator.Expression);

CodeGenerator.prototype.generateExpression = function (expr, precedence, flags) {
CodeGenerator.prototype.generateExpression = function (expr, precedence, flags, parent) {
var result, type;

type = expr.type || Syntax.Property;
Expand All @@ -2497,8 +2584,9 @@


if (extra.comment) {
result = addComments(expr, result);
result = addComments(expr, result, parent);
}

return toSourceNodeWhenNeeded(result, expr);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
let variable = (
// comment
3 + 3
);
let variable = (
// comment
3 + 3
);
let variable = (
/* comment */
3 + 3
);
let variable = (
/* comment
comment
comment
*/
3 + 3
);
let variable = (
// comment
/* comment */
// comment
3 + 3
);
let variable = (
// comment
3 + 3
);
let variable = (
// one
3 + 3
) - (
// two
(1 + 1)
);
function foo(a, b, c) {
return (
// comment
a >= b && a <= c || a === 42 || a === 666
);
}
function foo(a, b, c) {
return (
// comment
a >= b && a <= c
) || a === 42 || a === 666;
}
function foo(a, b, c) {
throw (
// comment
a >= b && a <= c || a === 42 || a === 666
);
}
let arrowFn = () => (
// comment
{
a: 1,
b: 2
}
);
var test = [
/**
* Test 2
*/
a,
/*
* Test 1
*/
2,
// Test 3
3 + 3
];
87 changes: 87 additions & 0 deletions test/comment/comment-as-first-element-in-parenthesis-expression.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
let variable = (
// comment
3+3
);

let variable = ( // comment
3+3
);

let variable = ( /* comment */
3+3
);

let variable = ( /* comment
comment
comment
*/
3+3
);

let variable = (
// comment
/* comment */
// comment
3+3
);

let variable = /* comment */ (
// comment
3+3
);

let variable = (
(
// one
3+3
) -
(
// two
1+1
)
);

function foo(a, b, c) {
return (
// comment
(a >= b && a <= c)
|| a === 42 || a === 666
);
}

function foo(a, b, c) {
return (
( // comment
a >= b &&
a <= c)
|| a === 42 || a === 666
);
}

function foo(a, b, c) {
throw (
// comment
(a >= b && a <= c)
|| a === 42 || a === 666
);
}

let arrowFn = () => (
// comment
{
a: 1, b: 2
}
);

var test = [
/**
* Test 2
*/
a,
/*
* Test 1
*/
2,
// Test 3
3+3
];