diff --git a/src/parser/comments.js b/src/parser/comments.js index c032e85e07..1f9a2a7031 100644 --- a/src/parser/comments.js +++ b/src/parser/comments.js @@ -43,7 +43,7 @@ pp.processComment = function (node) { const stack = this.state.commentStack; - let lastChild, trailingComments, i, j; + let firstChild, lastChild, trailingComments, i, j; if (this.state.trailingComments.length > 0) { // If the first comment in trailingComments comes after the @@ -71,10 +71,41 @@ pp.processComment = function (node) { } // Eating the stack. + if (stack.length > 0 && last(stack).start >= node.start) { + firstChild = stack.pop(); + } + while (stack.length > 0 && last(stack).start >= node.start) { lastChild = stack.pop(); } + if (!lastChild && firstChild) lastChild = firstChild; + + // Attach comments that follow a trailing comma on the last + // property in an object literal or a trailing comma in function arguments + // as trailing comments + if (firstChild && + (firstChild.type === "ObjectProperty" || + (node.type === "CallExpression")) && + this.state.leadingComments.length > 0) { + const lastComment = last(this.state.leadingComments); + if (lastComment.start >= node.start) { + if (this.state.commentPreviousNode) { + for (j = 0; j < this.state.leadingComments.length; j++) { + if (this.state.leadingComments[j].end < this.state.commentPreviousNode.end) { + this.state.leadingComments.splice(j, 1); + j--; + } + } + + if (this.state.leadingComments.length > 0) { + firstChild.trailingComments = this.state.leadingComments; + this.state.leadingComments = []; + } + } + } + } + if (lastChild) { if (lastChild.leadingComments) { if (lastChild !== node && last(lastChild.leadingComments).end <= node.start) { diff --git a/test/fixtures/comments/basic/function-trailing-comma-shorthand/actual.js b/test/fixtures/comments/basic/function-trailing-comma-shorthand/actual.js new file mode 100644 index 0000000000..0936c59b4e --- /dev/null +++ b/test/fixtures/comments/basic/function-trailing-comma-shorthand/actual.js @@ -0,0 +1 @@ +fn(a, { b }, /* comment */); diff --git a/test/fixtures/comments/basic/function-trailing-comma-shorthand/expected.json b/test/fixtures/comments/basic/function-trailing-comma-shorthand/expected.json new file mode 100644 index 0000000000..95184b49b6 --- /dev/null +++ b/test/fixtures/comments/basic/function-trailing-comma-shorthand/expected.json @@ -0,0 +1,208 @@ +{ + "type": "File", + "start": 0, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 28 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 28 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 28, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 28 + } + }, + "expression": { + "type": "CallExpression", + "start": 0, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 27 + } + }, + "callee": { + "type": "Identifier", + "start": 0, + "end": 2, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 2 + }, + "identifierName": "fn" + }, + "name": "fn" + }, + "arguments": [ + { + "type": "Identifier", + "start": 3, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 4 + }, + "identifierName": "a" + }, + "name": "a" + }, + { + "type": "ObjectExpression", + "start": 6, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 8, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "start": 8, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 9 + }, + "identifierName": "b" + }, + "name": "b" + }, + "value": { + "type": "Identifier", + "start": 8, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 9 + }, + "identifierName": "b" + }, + "name": "b" + }, + "extra": { + "shorthand": true + } + } + ], + "trailingComments": [ + { + "type": "CommentBlock", + "value": " comment ", + "start": 13, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 26 + } + } + } + ] + } + ] + } + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentBlock", + "value": " comment ", + "start": 13, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 26 + } + } + } + ] +} \ No newline at end of file diff --git a/test/fixtures/comments/basic/function-trailing-comma/actual.js b/test/fixtures/comments/basic/function-trailing-comma/actual.js new file mode 100644 index 0000000000..d8611dab0c --- /dev/null +++ b/test/fixtures/comments/basic/function-trailing-comma/actual.js @@ -0,0 +1 @@ +fn(a, b, /* comment */); diff --git a/test/fixtures/comments/basic/function-trailing-comma/expected.json b/test/fixtures/comments/basic/function-trailing-comma/expected.json new file mode 100644 index 0000000000..4f4b3c2604 --- /dev/null +++ b/test/fixtures/comments/basic/function-trailing-comma/expected.json @@ -0,0 +1,153 @@ +{ + "type": "File", + "start": 0, + "end": 24, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 24, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 24, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "expression": { + "type": "CallExpression", + "start": 0, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "callee": { + "type": "Identifier", + "start": 0, + "end": 2, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 2 + }, + "identifierName": "fn" + }, + "name": "fn" + }, + "arguments": [ + { + "type": "Identifier", + "start": 3, + "end": 4, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 4 + }, + "identifierName": "a" + }, + "name": "a" + }, + { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "b" + }, + "name": "b", + "trailingComments": [ + { + "type": "CommentBlock", + "value": " comment ", + "start": 9, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 22 + } + } + } + ] + } + ] + } + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentBlock", + "value": " comment ", + "start": 9, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 22 + } + } + } + ] +} \ No newline at end of file diff --git a/test/fixtures/comments/basic/object-property-trailing-comma/actual.js b/test/fixtures/comments/basic/object-property-trailing-comma/actual.js new file mode 100644 index 0000000000..acd5921a7c --- /dev/null +++ b/test/fixtures/comments/basic/object-property-trailing-comma/actual.js @@ -0,0 +1,5 @@ +var obj = { + a: '1', // comment 1 + b: '2', // comment 2 + c: '3', // comment 3 +}; diff --git a/test/fixtures/comments/basic/object-property-trailing-comma/expected.json b/test/fixtures/comments/basic/object-property-trailing-comma/expected.json new file mode 100644 index 0000000000..3e55ef7129 --- /dev/null +++ b/test/fixtures/comments/basic/object-property-trailing-comma/expected.json @@ -0,0 +1,372 @@ +{ + "type": "File", + "start": 0, + "end": 83, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 83, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "sourceType": "script", + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 83, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 82, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 4, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "obj" + }, + "name": "obj" + }, + "init": { + "type": "ObjectExpression", + "start": 10, + "end": 82, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "properties": [ + { + "type": "ObjectProperty", + "start": 14, + "end": 20, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 8 + } + }, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 14, + "end": 15, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 3 + }, + "identifierName": "a" + }, + "name": "a" + }, + "value": { + "type": "StringLiteral", + "start": 17, + "end": 20, + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 8 + } + }, + "extra": { + "rawValue": "1", + "raw": "'1'" + }, + "value": "1" + } + }, + { + "type": "ObjectProperty", + "start": 37, + "end": 43, + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 8 + } + }, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 37, + "end": 38, + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + }, + "identifierName": "b" + }, + "name": "b", + "leadingComments": null + }, + "value": { + "type": "StringLiteral", + "start": 40, + "end": 43, + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 8 + } + }, + "extra": { + "rawValue": "2", + "raw": "'2'" + }, + "value": "2" + }, + "leadingComments": [ + { + "type": "CommentLine", + "value": " comment 1", + "start": 22, + "end": 34, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 22 + } + } + } + ] + }, + { + "type": "ObjectProperty", + "start": 60, + "end": 66, + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 4, + "column": 8 + } + }, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 60, + "end": 61, + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 4, + "column": 3 + }, + "identifierName": "c" + }, + "name": "c", + "leadingComments": null + }, + "value": { + "type": "StringLiteral", + "start": 63, + "end": 66, + "loc": { + "start": { + "line": 4, + "column": 5 + }, + "end": { + "line": 4, + "column": 8 + } + }, + "extra": { + "rawValue": "3", + "raw": "'3'" + }, + "value": "3" + }, + "leadingComments": [ + { + "type": "CommentLine", + "value": " comment 2", + "start": 45, + "end": 57, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 22 + } + } + } + ], + "trailingComments": [ + { + "type": "CommentLine", + "value": " comment 3", + "start": 68, + "end": 80, + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 4, + "column": 22 + } + } + } + ] + } + ] + } + } + ], + "kind": "var" + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentLine", + "value": " comment 1", + "start": 22, + "end": 34, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 22 + } + } + }, + { + "type": "CommentLine", + "value": " comment 2", + "start": 45, + "end": 57, + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 22 + } + } + }, + { + "type": "CommentLine", + "value": " comment 3", + "start": 68, + "end": 80, + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 4, + "column": 22 + } + } + } + ] +} \ No newline at end of file