diff --git a/changelog_unreleased/typescript/pr-7798.md b/changelog_unreleased/typescript/pr-7798.md new file mode 100644 index 000000000000..49ba31742c80 --- /dev/null +++ b/changelog_unreleased/typescript/pr-7798.md @@ -0,0 +1,32 @@ +#### Fix `prettier-ignore` in union types ([#7798](https://github.com/prettier/prettier/pull/7798) by [@thorn0](https://github.com/thorn0)) + + +```ts +// Input +export type a = + // foo + | foo1&foo2 + // prettier-ignore + | bar1&bar2 + // baz + | baz1&baz2; + +// Prettier stable +export type a = + // foo + | foo1&foo2 + // prettier-ignore + // prettier-ignore + | (bar1 & bar2) + // baz + | (baz1 & baz2); + +// Prettier master +export type a = + // foo + | (foo1 & foo2) + // prettier-ignore + | bar1&bar2 + // baz + | (baz1 & baz2); +``` diff --git a/cspell.json b/cspell.json index 5c36c994029c..eabba62c51e6 100644 --- a/cspell.json +++ b/cspell.json @@ -381,6 +381,7 @@ "unaries", "uncheck", "uncook", + "unignore", "uniqby", "unist", "unmount", diff --git a/src/common/util.js b/src/common/util.js index 18cab0454970..51ab3a1dce40 100644 --- a/src/common/util.js +++ b/src/common/util.js @@ -749,12 +749,19 @@ function hasIgnoreComment(path) { function hasNodeIgnoreComment(node) { return ( node && - node.comments && - node.comments.length > 0 && - node.comments.some((comment) => comment.value.trim() === "prettier-ignore") + ((node.comments && + node.comments.length > 0 && + node.comments.some( + (comment) => isNodeIgnoreComment(comment) && !comment.unignore + )) || + node.prettierIgnore) ); } +function isNodeIgnoreComment(comment) { + return comment.value.trim() === "prettier-ignore"; +} + function addCommentHelper(node, comment) { const comments = node.comments || (node.comments = []); comments.push(comment); @@ -850,6 +857,7 @@ module.exports = { printNumber, hasIgnoreComment, hasNodeIgnoreComment, + isNodeIgnoreComment, makeString, addLeadingComment, addDanglingComment, diff --git a/src/language-js/comments.js b/src/language-js/comments.js index fcc9f8a34f57..50aa34987355 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -722,9 +722,27 @@ function handleUnionTypeComments( (enclosingNode.type === "UnionTypeAnnotation" || enclosingNode.type === "TSUnionType") ) { - addTrailingComment(precedingNode, comment); - return true; + if (privateUtil.isNodeIgnoreComment(comment)) { + followingNode.prettierIgnore = true; + comment.unignore = true; + } + if (precedingNode) { + addTrailingComment(precedingNode, comment); + return true; + } + return false; } + + if ( + followingNode && + (followingNode.type === "UnionTypeAnnotation" || + followingNode.type === "TSUnionType") && + privateUtil.isNodeIgnoreComment(comment) + ) { + followingNode.types[0].prettierIgnore = true; + comment.unignore = true; + } + return false; } diff --git a/src/language-js/postprocess.js b/src/language-js/postprocess.js index e35279825ff3..5b1cff5bb8bc 100644 --- a/src/language-js/postprocess.js +++ b/src/language-js/postprocess.js @@ -60,13 +60,13 @@ function postprocess(ast, options) { } // remove redundant TypeScript nodes case "TSParenthesizedType": { - return node.typeAnnotation; + return { ...node.typeAnnotation, ...composeLoc(node) }; } case "TSUnionType": case "TSIntersectionType": if (node.types.length === 1) { // override loc, so that comments are attached properly - return { ...node.types[0], loc: node.loc, range: node.range }; + return { ...node.types[0], ...composeLoc(node) }; } break; case "TSTypeParameter": diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 2f7118520490..81752b18f837 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -6089,7 +6089,9 @@ function willPrintOwnComments(path /*, options */) { ((parent.type === "ClassDeclaration" || parent.type === "ClassExpression") && parent.superClass === node)))) && - !hasIgnoreComment(path) + (!hasIgnoreComment(path) || + parent.type === "UnionTypeAnnotation" || + parent.type === "TSUnionType") ); } diff --git a/src/main/core.js b/src/main/core.js index 6e9dc42ec2bb..8d35eab40673 100644 --- a/src/main/core.js +++ b/src/main/core.js @@ -34,7 +34,7 @@ function ensureAllCommentsPrinted(astComments) { } for (let i = 0; i < astComments.length; ++i) { - if (astComments[i].value.trim() === "prettier-ignore") { + if (privateUtil.isNodeIgnoreComment(astComments[i])) { // If there's a prettier-ignore, we're not printing that sub-tree so we // don't know if the comments was printed or not. return; diff --git a/tests/typescript_union/__snapshots__/jsfmt.spec.js.snap b/tests/typescript_union/__snapshots__/jsfmt.spec.js.snap index 7349aea3c9cb..33ccf96dbb43 100644 --- a/tests/typescript_union/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typescript_union/__snapshots__/jsfmt.spec.js.snap @@ -94,6 +94,134 @@ type T8 = number | ((arg: any) => void); ================================================================================ `; +exports[`prettier-ignore.ts 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +export type a = + // foo + | foo1&foo2 + // bar + | bar1&bar2 + // prettier-ignore + | qux1&qux2; + +export type a = + // foo + | foo1&foo2 + // bar + | bar1&bar2 + // prettier-ignore + | qux1&qux2 + // baz + | baz1&baz2; + +export type a = + // prettier-ignore + | foo1&foo2 + // bar + | bar1&bar2 + // qux + | qux1&qux2; + +=====================================output===================================== +export type a = + // foo + | (foo1 & foo2) + // bar + | (bar1 & bar2) + // prettier-ignore + | qux1&qux2; + +export type a = + // foo + | (foo1 & foo2) + // bar + | (bar1 & bar2) + // prettier-ignore + | qux1&qux2 + // baz + | (baz1 & baz2); + +export type a = + // prettier-ignore + | foo1&foo2 + // bar + | (bar1 & bar2) + // qux + | (qux1 & qux2); + +================================================================================ +`; + +exports[`prettier-ignore-nested-unions.ts 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +export type a = + // foo + | foo1&foo2 + // bar + | bar1&bar2 + // prettier-ignore + | ( + | aaaaaaaaaaaaa&1 + // b + | bbbbbbbbbbbbb&2 + ) + // baz + | baz1&baz2; + +export type b = + // foo + | foo1&foo2 + // bar + | bar1&bar2 + | ( + // prettier-ignore + | aaaaaaaaaaaaa&1 + // b + | bbbbbbbbbbbbb&2 + ) + // baz + | baz1&baz2; + +=====================================output===================================== +export type a = + // foo + | (foo1 & foo2) + // bar + | (bar1 & bar2) + // prettier-ignore + | ( + | aaaaaaaaaaaaa&1 + // b + | bbbbbbbbbbbbb&2 + ) + // baz + | (baz1 & baz2); + +export type b = + // foo + | (foo1 & foo2) + // bar + | (bar1 & bar2) + | ( + | // prettier-ignore + aaaaaaaaaaaaa&1 + // b + | (bbbbbbbbbbbbb & 2) + ) + // baz + | (baz1 & baz2); + +================================================================================ +`; + exports[`union-parens.ts 1`] = ` ====================================options===================================== parsers: ["typescript"] diff --git a/tests/typescript_union/prettier-ignore-nested-unions.ts b/tests/typescript_union/prettier-ignore-nested-unions.ts new file mode 100644 index 000000000000..335379e3a205 --- /dev/null +++ b/tests/typescript_union/prettier-ignore-nested-unions.ts @@ -0,0 +1,27 @@ +export type a = + // foo + | foo1&foo2 + // bar + | bar1&bar2 + // prettier-ignore + | ( + | aaaaaaaaaaaaa&1 + // b + | bbbbbbbbbbbbb&2 + ) + // baz + | baz1&baz2; + +export type b = + // foo + | foo1&foo2 + // bar + | bar1&bar2 + | ( + // prettier-ignore + | aaaaaaaaaaaaa&1 + // b + | bbbbbbbbbbbbb&2 + ) + // baz + | baz1&baz2; diff --git a/tests/typescript_union/prettier-ignore.ts b/tests/typescript_union/prettier-ignore.ts new file mode 100644 index 000000000000..786b59686337 --- /dev/null +++ b/tests/typescript_union/prettier-ignore.ts @@ -0,0 +1,25 @@ +export type a = + // foo + | foo1&foo2 + // bar + | bar1&bar2 + // prettier-ignore + | qux1&qux2; + +export type a = + // foo + | foo1&foo2 + // bar + | bar1&bar2 + // prettier-ignore + | qux1&qux2 + // baz + | baz1&baz2; + +export type a = + // prettier-ignore + | foo1&foo2 + // bar + | bar1&bar2 + // qux + | qux1&qux2;