Skip to content

Commit

Permalink
Fix edge case with trailing comments in arrow chains (#10543)
Browse files Browse the repository at this point in the history
* Fix edge case with trailing comments in arrow chains

* Remove handling of args.needsSemi from printComments
  • Loading branch information
thorn0 committed Mar 16, 2021
1 parent 68fd9db commit 13744df
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 27 deletions.
2 changes: 1 addition & 1 deletion changelog_unreleased/javascript/9992.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#### Refine formatting of curried arrow functions (#9992 by @sosukesuzuki and @thorn0)
#### Refine formatting of curried arrow functions (#9992, #10543 by @sosukesuzuki & @thorn0)

<!-- prettier-ignore -->
```js
Expand Down
22 changes: 16 additions & 6 deletions src/language-js/print/function.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
"use strict";

/** @typedef {import("../../document/doc-builders").Doc} Doc */

/** @type {import("assert")} */
const assert = require("assert");
const { printDanglingComments, printComments } = require("../../main/comments");
const {
printDanglingComments,
printCommentsSeparately,
} = require("../../main/comments");
const {
getNextNonSpaceNonCommentCharacterIndex,
} = require("../../common/util");
Expand Down Expand Up @@ -246,15 +251,20 @@ function printArrowChain(

function printArrowFunctionExpression(path, options, print, args) {
let node = path.getValue();
/** @type {Doc[]} */
const signatures = [];
let body;
const body = [];
let chainShouldBreak = false;

(function rec(path) {
const doc = printArrowFunctionSignature(path, options, print, args);
signatures.push(
signatures.length === 0 ? doc : printComments(path, doc, options)
);
if (signatures.length === 0) {
signatures.push(doc);
} else {
const { leading, trailing } = printCommentsSeparately(path, options);
signatures.push([leading, doc]);
body.unshift(trailing);
}

chainShouldBreak =
chainShouldBreak ||
Expand All @@ -267,7 +277,7 @@ function printArrowFunctionExpression(path, options, print, args) {
node.body.type !== "ArrowFunctionExpression" ||
(args && args.expandLastArg)
) {
body = path.call((bodyPath) => print(bodyPath, args), "body");
body.unshift(path.call((bodyPath) => print(bodyPath, args), "body"));
} else {
node = node.body;
path.call(rec, "body");
Expand Down
6 changes: 3 additions & 3 deletions src/language-js/printer-estree.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,18 @@ function genericPrint(path, options, print, args) {
}

const printedDecorators = printDecorators(path, options, print);
// Nodes with decorators can't have parentheses
// Nodes with decorators can't have parentheses and don't need leading semicolons
if (printedDecorators) {
return group([...printedDecorators, printed]);
}

const needsParens = pathNeedsParens(path, options);

if (!needsParens) {
return printed;
return args && args.needsSemi ? [";", printed] : printed;
}

const parts = ["(", printed];
const parts = [args && args.needsSemi ? ";(" : "(", printed];

if (hasFlowShorthandAnnotationComment(node)) {
const [comment] = node.trailingComments;
Expand Down
2 changes: 1 addition & 1 deletion src/main/ast-to-doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function printAstToDoc(ast, options, alignmentSize = 0) {
) {
// printComments will call the plugin print function and check for
// comments to print
doc = printComments(path, doc, options, args && args.needsSemi);
doc = printComments(path, doc, options);
}

if (shouldCache) {
Expand Down
38 changes: 22 additions & 16 deletions src/main/comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -540,23 +540,18 @@ function printDanglingComments(path, options, sameIndent, filter) {
return indent([hardline, join(hardline, parts)]);
}

function prependCursorPlaceholder(path, options, printed) {
if (path.getNode() === options.cursorNode && path.getValue()) {
return [cursor, printed, cursor];
}
return printed;
}

function printComments(path, printed, options, needsSemi) {
function printCommentsSeparately(path, options) {
const value = path.getValue();
const comments = value && value.comments;
const hasComments = isNonEmptyArray(value && value.comments);
const isCursorNode = Boolean(value && value === options.cursorNode);

if (!isNonEmptyArray(comments)) {
return prependCursorPlaceholder(path, options, printed);
if (!hasComments) {
const maybeCursor = isCursorNode ? cursor : "";
return { leading: maybeCursor, trailing: maybeCursor };
}

const leadingParts = [];
const trailingParts = [needsSemi ? ";" : "", printed];
const trailingParts = [];

path.each((commentPath) => {
const comment = commentPath.getValue();
Expand All @@ -583,10 +578,20 @@ function printComments(path, printed, options, needsSemi) {
}
}, "comments");

return prependCursorPlaceholder(path, options, [
...leadingParts,
...trailingParts,
]);
if (isCursorNode) {
leadingParts.unshift(cursor);
trailingParts.push(cursor);
}

return { leading: leadingParts, trailing: trailingParts };
}

function printComments(path, doc, options) {
const { leading, trailing } = printCommentsSeparately(path, options);
if (!leading && !trailing) {
return doc;
}
return [leading, doc, trailing];
}

function ensureAllCommentsPrinted(astComments) {
Expand All @@ -609,6 +614,7 @@ function ensureAllCommentsPrinted(astComments) {
module.exports = {
attach,
printComments,
printCommentsSeparately,
printDanglingComments,
getSortedChildNodes,
ensureAllCommentsPrinted,
Expand Down
76 changes: 76 additions & 0 deletions tests/js/arrows/__snapshots__/jsfmt.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,82 @@ a = b => {
================================================================================
`;

exports[`arrow-chain-with-trailing-comments.js - {"arrowParens":"always"} format 1`] = `
====================================options=====================================
arrowParens: "always"
parsers: ["babel", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
x = (bifornCringerMoshedPerplexSawder) => ((askTrovenaBeenaDependsRowans, glimseGlyphsHazardNoopsTieTie) => (f00) => {
averredBathersBoxroomBuggyNurl();
} // BOOM
)
x2 = (a) => ((askTrovenaBeenaDependsRowans1, askTrovenaBeenaDependsRowans2, askTrovenaBeenaDependsRowans3) => {
c();
} /* ! */ // KABOOM
)
=====================================output=====================================
x =
(bifornCringerMoshedPerplexSawder) =>
(askTrovenaBeenaDependsRowans, glimseGlyphsHazardNoopsTieTie) =>
(f00) => {
averredBathersBoxroomBuggyNurl();
}; // BOOM
x2 =
(a) =>
(
askTrovenaBeenaDependsRowans1,
askTrovenaBeenaDependsRowans2,
askTrovenaBeenaDependsRowans3
) => {
c();
} /* ! */; // KABOOM
================================================================================
`;

exports[`arrow-chain-with-trailing-comments.js - {"arrowParens":"avoid"} format 1`] = `
====================================options=====================================
arrowParens: "avoid"
parsers: ["babel", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
x = (bifornCringerMoshedPerplexSawder) => ((askTrovenaBeenaDependsRowans, glimseGlyphsHazardNoopsTieTie) => (f00) => {
averredBathersBoxroomBuggyNurl();
} // BOOM
)
x2 = (a) => ((askTrovenaBeenaDependsRowans1, askTrovenaBeenaDependsRowans2, askTrovenaBeenaDependsRowans3) => {
c();
} /* ! */ // KABOOM
)
=====================================output=====================================
x =
bifornCringerMoshedPerplexSawder =>
(askTrovenaBeenaDependsRowans, glimseGlyphsHazardNoopsTieTie) =>
f00 => {
averredBathersBoxroomBuggyNurl();
}; // BOOM
x2 =
a =>
(
askTrovenaBeenaDependsRowans1,
askTrovenaBeenaDependsRowans2,
askTrovenaBeenaDependsRowans3
) => {
c();
} /* ! */; // KABOOM
================================================================================
`;

exports[`assignment-chain-with-arrow-chain.js - {"arrowParens":"always"} format 1`] = `
====================================options=====================================
arrowParens: "always"
Expand Down
9 changes: 9 additions & 0 deletions tests/js/arrows/arrow-chain-with-trailing-comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
x = (bifornCringerMoshedPerplexSawder) => ((askTrovenaBeenaDependsRowans, glimseGlyphsHazardNoopsTieTie) => (f00) => {
averredBathersBoxroomBuggyNurl();
} // BOOM
)

x2 = (a) => ((askTrovenaBeenaDependsRowans1, askTrovenaBeenaDependsRowans2, askTrovenaBeenaDependsRowans3) => {
c();
} /* ! */ // KABOOM
)

0 comments on commit 13744df

Please sign in to comment.