diff --git a/changelog_unreleased/typescript/10457.md b/changelog_unreleased/typescript/10457.md new file mode 100644 index 000000000000..8587da5a2472 --- /dev/null +++ b/changelog_unreleased/typescript/10457.md @@ -0,0 +1,13 @@ +#### Fix misplaced comments in unions and intersections (#10457 by @thorn0) + + +```ts +// Input +type Foo = "1" | "2" /* two */ | "3"; + +// Prettier stable +type Foo = "1" | "2" | /* two */ "3"; + +// Prettier main +type Foo = "1" | "2" /* two */ | "3"; +``` diff --git a/src/language-js/clean.js b/src/language-js/clean.js index 60be0872ff59..903988eb6f72 100644 --- a/src/language-js/clean.js +++ b/src/language-js/clean.js @@ -197,6 +197,14 @@ function clean(ast, newObj, parent) { if (ast.type === "InterpreterDirective") { newObj.value = newObj.value.trimEnd(); } + + // Prettier removes degenerate union and intersection types with only one member. + if ( + (ast.type === "TSIntersectionType" || ast.type === "TSUnionType") && + ast.types.length === 1 + ) { + return newObj.types[0]; + } } clean.ignoredProperties = ignoredProperties; diff --git a/src/language-js/comments.js b/src/language-js/comments.js index 944672998ec6..d40b113e4fd3 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -886,22 +886,6 @@ function isRealFunctionLikeNode(node) { ); } -/** - * @param {Node} enclosingNode - * @returns {RegExp | void} - */ -function getGapRegex(enclosingNode) { - if ( - enclosingNode && - enclosingNode.type !== "BinaryExpression" && - enclosingNode.type !== "LogicalExpression" - ) { - // Support degenerate single-element unions and intersections. - // E.g.: `type A = /* 1 */ & B` - return /^[\s&(|]*$/; - } -} - /** * @param {any} node * @returns {Node[] | void} @@ -980,7 +964,6 @@ module.exports = { handleEndOfLineComment, handleRemainingComment, isTypeCastComment, - getGapRegex, getCommentChildNodes, willPrintOwnComments, }; diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 7a2fb10c809d..f897421e5b6e 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -405,8 +405,10 @@ function needsParens(path, options) { case "TSUnionType": case "TSIntersectionType": if ( - parent.type === "TSUnionType" || - parent.type === "TSIntersectionType" + (parent.type === "TSUnionType" || + parent.type === "TSIntersectionType") && + parent.types.length > 1 && + (!node.types || node.types.length > 1) ) { return true; } diff --git a/src/language-js/parse-postprocess.js b/src/language-js/parse-postprocess.js index be9dcd9ddf42..2a9b4fbaeb58 100644 --- a/src/language-js/parse-postprocess.js +++ b/src/language-js/parse-postprocess.js @@ -129,15 +129,6 @@ function postprocess(ast, options) { node.typeAnnotation.range = [locStart(node), locEnd(node)]; return node.typeAnnotation; } - case "TSUnionType": - case "TSIntersectionType": - if (node.types.length === 1) { - const [firstType] = node.types; - // override loc, so that comments are attached properly - firstType.range = [locStart(node), locEnd(node)]; - return firstType; - } - break; case "TSTypeParameter": // babel-ts if (typeof node.name === "string") { diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 502f5651d4d4..a12301870e43 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -1088,6 +1088,5 @@ module.exports = { endOfLine: handleComments.handleEndOfLineComment, remaining: handleComments.handleRemainingComment, }, - getGapRegex: handleComments.getGapRegex, getCommentChildNodes: handleComments.getCommentChildNodes, }; diff --git a/tests/typescript/union/__snapshots__/jsfmt.spec.js.snap b/tests/typescript/union/__snapshots__/jsfmt.spec.js.snap index 55a2716f71ee..3ab365a493df 100644 --- a/tests/typescript/union/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typescript/union/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,37 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`comments.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +type A1 = a /* 1 */ | b; +type A2 = a | /* 1 */ b; +type A3 = (a /* 1 */) | b; +type A4 = a | (/* 1 */ b); +type A5 = (a) /* 1 */ | b; +type A6 = a | /* 1 */ (b); + +type B1 = a /* 1 */ /* 2 */ | b; +type B2 = a /* 1 */ | /* 2 */ b; +type B3 = a | /* 1 */ /* 2 */ b; + +=====================================output===================================== +type A1 = a /* 1 */ | b; +type A2 = a | /* 1 */ b; +type A3 = a /* 1 */ | b; +type A4 = a | /* 1 */ b; +type A5 = a /* 1 */ | b; +type A6 = a | /* 1 */ b; + +type B1 = a /* 1 */ /* 2 */ | b; +type B2 = a /* 1 */ | /* 2 */ b; +type B3 = a | /* 1 */ /* 2 */ b; + +================================================================================ +`; + exports[`inlining.ts format 1`] = ` ====================================options===================================== parsers: ["typescript"] diff --git a/tests/typescript/union/comments.ts b/tests/typescript/union/comments.ts new file mode 100644 index 000000000000..d3f32ddd12d9 --- /dev/null +++ b/tests/typescript/union/comments.ts @@ -0,0 +1,10 @@ +type A1 = a /* 1 */ | b; +type A2 = a | /* 1 */ b; +type A3 = (a /* 1 */) | b; +type A4 = a | (/* 1 */ b); +type A5 = (a) /* 1 */ | b; +type A6 = a | /* 1 */ (b); + +type B1 = a /* 1 */ /* 2 */ | b; +type B2 = a /* 1 */ | /* 2 */ b; +type B3 = a | /* 1 */ /* 2 */ b;