From b2d58f2cfdcde270f750c32505bfca33b678f9b7 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 12 Jun 2020 13:51:29 +0900 Subject: [PATCH 01/19] Handle ternary comments --- src/language-js/comments.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index 1968ad646570..ea6b8928af48 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -67,7 +67,8 @@ function handleOwnLineComment(comment, text, options, ast, isLastComment) { comment, options ) || - handleLabeledStatementComments(enclosingNode, comment) + handleLabeledStatementComments(enclosingNode, comment) || + handleTernaryComment(enclosingNode, precedingNode, comment) ); } @@ -941,6 +942,24 @@ function handleTSMappedTypeComments( return false; } +function handleTernaryComment(enclosingNode, precedingNode, comment) { + const isTernaryTest = (node, ternary) => { + if (!node || !ternary) { + return false; + } + const isTernary = + ternary.type === "ConditionalExpression" || + ternary.type === "TSConditionalType"; + const testField = ternary.test ? "test" : "extendsType"; + return isTernary && node === ternary[testField]; + } + if (isTernaryTest(precedingNode, enclosingNode)) { + addTrailingComment(precedingNode, comment); + return true; + } + return false; +} + function isBlockComment(comment) { return comment.type === "Block" || comment.type === "CommentBlock"; } From 90ba3e54403c7a76430bf493186ac1adde1c3dd8 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 12 Jun 2020 14:25:17 +0900 Subject: [PATCH 02/19] Add indent --- src/language-js/comments.js | 28 ++++++++++++++++++---------- src/language-js/printer-estree.js | 1 + src/main/comments.js | 11 ++++++++++- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index ea6b8928af48..e1862b2764ee 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -943,16 +943,6 @@ function handleTSMappedTypeComments( } function handleTernaryComment(enclosingNode, precedingNode, comment) { - const isTernaryTest = (node, ternary) => { - if (!node || !ternary) { - return false; - } - const isTernary = - ternary.type === "ConditionalExpression" || - ternary.type === "TSConditionalType"; - const testField = ternary.test ? "test" : "extendsType"; - return isTernary && node === ternary[testField]; - } if (isTernaryTest(precedingNode, enclosingNode)) { addTrailingComment(precedingNode, comment); return true; @@ -1037,6 +1027,23 @@ function isTypeCastComment(comment) { ); } +function isTernaryTest(node, ternary) { + if (!node || !ternary) { + return false; + } + const isTernary = + ternary.type === "ConditionalExpression" || + ternary.type === "TSConditionalType"; + const testField = ternary.test ? "test" : "extendsType"; + return isTernary && node === ternary[testField]; +} + +function shouldIndentComment(path) { + const parent = path.getParentNode(); + const parentParent = path.getParentNode(1); + return parent && parentParent && isTernaryTest(parent, parentParent); +} + module.exports = { handleOwnLineComment, handleEndOfLineComment, @@ -1046,4 +1053,5 @@ module.exports = { isTypeCastComment, getGapRegex, getCommentChildNodes, + shouldIndentComment, }; diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 2d2b7588ff4a..930d03b21e3f 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -5396,4 +5396,5 @@ module.exports = { }, getGapRegex: handleComments.getGapRegex, getCommentChildNodes: handleComments.getCommentChildNodes, + shouldIndentComment: handleComments.shouldIndentComment, }; diff --git a/src/main/comments.js b/src/main/comments.js index 127f511985f3..deb97cb97991 100644 --- a/src/main/comments.js +++ b/src/main/comments.js @@ -431,9 +431,18 @@ function printTrailingComment(commentPath, options) { locStart ); - return lineSuffix( + const printed = lineSuffix( concat([hardline, isLineBeforeEmpty ? hardline : "", contents]) ); + + if ( + options.printer.shouldIndentComment && + options.printer.shouldIndentComment(commentPath) + ) { + return indent(printed); + } + + return printed; } let printed = concat([" ", contents]); From e88bf464c26de42ff6f52837d6d400eb624ea139 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 12 Jun 2020 14:26:09 +0900 Subject: [PATCH 03/19] Add comment --- src/language-js/comments.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index e1862b2764ee..d2a475501c37 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -943,6 +943,10 @@ function handleTSMappedTypeComments( } function handleTernaryComment(enclosingNode, precedingNode, comment) { + // test + // // comment + // ? first + // : second if (isTernaryTest(precedingNode, enclosingNode)) { addTrailingComment(precedingNode, comment); return true; From 3d01c8543f5bd49fb4db425b401fb2b47b0e80d1 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 12 Jun 2020 15:55:41 +0900 Subject: [PATCH 04/19] Update tests --- .../__snapshots__/jsfmt.spec.js.snap | 32 +++++++++++++++++-- tests/js/conditional/comments.js | 14 ++++++++ .../__snapshots__/jsfmt.spec.js.snap | 4 +-- .../typescript/conditional-types/comments.ts | 13 ++++++++ 4 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 tests/typescript/conditional-types/comments.ts diff --git a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap index 79e96b2a979d..b1ec01f8f25e 100644 --- a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap @@ -44,6 +44,20 @@ const { configureStore } = process.env.NODE_ENV === "production" ? require("./configureProdStore") // a : require("./configureDevStore"); // b +test + // ? + // comment + ? foo + : bar; + +test + /* comment + comment + comment + comment */ + ? foo + : bar; + =====================================output===================================== var inspect = 4 === util.inspect.length @@ -68,8 +82,8 @@ var inspect = }; const extractTextPluginOptions = shouldUseRelativeAssetPaths - ? // Making sure that the publicPath goes back to to build folder. - { publicPath: Array(cssFilename.split("/").length).join("../") } + // Making sure that the publicPath goes back to to build folder. + ? { publicPath: Array(cssFilename.split("/").length).join("../") } : {}; const extractTextPluginOptions2 = shouldUseRelativeAssetPaths @@ -86,6 +100,20 @@ const { configureStore } = ? require("./configureProdStore") // a : require("./configureDevStore"); // b +test + // ? + // comment + ? foo + : bar; + +test + /* comment + comment + comment + comment */ + ? foo + : bar; + ================================================================================ `; diff --git a/tests/js/conditional/comments.js b/tests/js/conditional/comments.js index da56db4f8a7a..3774f6dee159 100644 --- a/tests/js/conditional/comments.js +++ b/tests/js/conditional/comments.js @@ -35,3 +35,17 @@ const extractTextPluginOptions3 = shouldUseRelativeAssetPaths // Making sure tha const { configureStore } = process.env.NODE_ENV === "production" ? require("./configureProdStore") // a : require("./configureDevStore"); // b + +test + // ? + // comment + ? foo + : bar; + +test + /* comment + comment + comment + comment */ + ? foo + : bar; diff --git a/tests/js/method-chain/__snapshots__/jsfmt.spec.js.snap b/tests/js/method-chain/__snapshots__/jsfmt.spec.js.snap index 8420ce5ba8e8..5144aac33cfd 100644 --- a/tests/js/method-chain/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/method-chain/__snapshots__/jsfmt.spec.js.snap @@ -372,8 +372,8 @@ this.doWriteConfiguration(target, value, options) // queue up writes to prevent ); ret = __DEV__ - ? // $FlowFixMe: this type differs according to the env - vm.runInContext(source, ctx) + // $FlowFixMe: this type differs according to the env + ? vm.runInContext(source, ctx) : a; this.firebase diff --git a/tests/typescript/conditional-types/comments.ts b/tests/typescript/conditional-types/comments.ts new file mode 100644 index 000000000000..058f9ef2c5e8 --- /dev/null +++ b/tests/typescript/conditional-types/comments.ts @@ -0,0 +1,13 @@ +type A = test extends B + // ? + // comment + ? foo + : bar; + +type A = test extends B + /* comment + comment + comment + comment */ + ? foo + : bar; From dac148e2a768d0b7e77200d174e7e09254b521bd Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 12 Jun 2020 16:18:02 +0900 Subject: [PATCH 05/19] Update tests --- .../__snapshots__/jsfmt.spec.js.snap | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap b/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap index 73ab426aba94..88129f35d8ab 100644 --- a/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,43 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`comments.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +type A = test extends B + // ? + // comment + ? foo + : bar; + +type A = test extends B + /* comment + comment + comment + comment */ + ? foo + : bar; + +=====================================output===================================== +type A = test extends B + // ? + // comment + ? foo + : bar; + +type A = test extends B + /* comment + comment + comment + comment */ + ? foo + : bar; + +================================================================================ +`; + exports[`conditonal-types.ts format 1`] = ` ====================================options===================================== parsers: ["typescript"] From 42957666b84934656b0fcc5bb4920d78c92f6026 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 12 Jun 2020 17:52:18 +0900 Subject: [PATCH 06/19] Support dedent --- src/language-js/comments.js | 29 +++++++++++- src/language-js/printer-estree.js | 1 + src/main/comments.js | 10 +++- .../__snapshots__/jsfmt.spec.js.snap | 46 +++++++++++++++++++ tests/js/conditional/comments.js | 23 ++++++++++ .../__snapshots__/jsfmt.spec.js.snap | 46 +++++++++++++++++++ .../typescript/conditional-types/comments.ts | 23 ++++++++++ 7 files changed, 176 insertions(+), 2 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index d2a475501c37..14e764f5205f 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -1045,7 +1045,33 @@ function isTernaryTest(node, ternary) { function shouldIndentComment(path) { const parent = path.getParentNode(); const parentParent = path.getParentNode(1); - return parent && parentParent && isTernaryTest(parent, parentParent); + const parentParentParent = path.getParentNode(2); + const isNestedTernary = + parentParentParent && + (parentParentParent.type === "ConditionalExpression" || + parentParentParent.type === "TSConditionalType") + return ( + parent && + parentParent && + isTernaryTest(parent, parentParent) && + !isNestedTernary + ); +} + +function shouldDedentComment(path) { + const parent = path.getParentNode(); + const parentParent = path.getParentNode(1); + const parentParentParent = path.getParentNode(2); + const isNestedTernary = + parentParentParent && + (parentParentParent.type === "ConditionalExpression" || + parentParentParent.type === "TSConditionalType") + return ( + parent && + parentParent && + isTernaryTest(parent, parentParent) && + isNestedTernary + ); } module.exports = { @@ -1058,4 +1084,5 @@ module.exports = { getGapRegex, getCommentChildNodes, shouldIndentComment, + shouldDedentComment, }; diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 930d03b21e3f..74906288143e 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -5397,4 +5397,5 @@ module.exports = { getGapRegex: handleComments.getGapRegex, getCommentChildNodes: handleComments.getCommentChildNodes, shouldIndentComment: handleComments.shouldIndentComment, + shouldDedentComment: handleComments.shouldDedentComment, }; diff --git a/src/main/comments.js b/src/main/comments.js index deb97cb97991..8dcf4684146d 100644 --- a/src/main/comments.js +++ b/src/main/comments.js @@ -9,6 +9,7 @@ const { indent, lineSuffix, join, + dedent, cursor, } = require("../document").builders; const { @@ -439,7 +440,14 @@ function printTrailingComment(commentPath, options) { options.printer.shouldIndentComment && options.printer.shouldIndentComment(commentPath) ) { - return indent(printed); + return indent(printed); + } + + if ( + options.printer.shouldDedentComment && + options.printer.shouldDedentComment(commentPath) + ) { + return dedent(printed); } return printed; diff --git a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap index b1ec01f8f25e..3082645ef18c 100644 --- a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap @@ -58,6 +58,29 @@ test ? foo : bar; +test + // ? + // comment + ? foo + : test2 + // comment + // comment + ? foo + : bar; + +test + /* comment + comment + comment + comment */ + ? foo + : test + /* comment + comment + comment */ + ? foo + : bar; + =====================================output===================================== var inspect = 4 === util.inspect.length @@ -114,6 +137,29 @@ test ? foo : bar; +test + // ? + // comment + ? foo + : test2 + // comment + // comment + ? foo + : bar; + +test + /* comment + comment + comment + comment */ + ? foo + : test + /* comment + comment + comment */ + ? foo + : bar; + ================================================================================ `; diff --git a/tests/js/conditional/comments.js b/tests/js/conditional/comments.js index 3774f6dee159..6e401358d671 100644 --- a/tests/js/conditional/comments.js +++ b/tests/js/conditional/comments.js @@ -49,3 +49,26 @@ test comment */ ? foo : bar; + +test + // ? + // comment + ? foo + : test2 + // comment + // comment + ? foo + : bar; + +test + /* comment + comment + comment + comment */ + ? foo + : test + /* comment + comment + comment */ + ? foo + : bar; diff --git a/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap b/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap index 88129f35d8ab..a34ad2a3ac5e 100644 --- a/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap @@ -20,6 +20,29 @@ type A = test extends B ? foo : bar; +type A = test extends B + // ? + // comment + ? foo + : test2 extends C + // comment + // comment + ? foo + : bar; + +type B = test extends B + /* comment + comment + comment + comment */ + ? foo + : test2 extends C + /* comment + comment + comment */ + ? foo + : bar; + =====================================output===================================== type A = test extends B // ? @@ -35,6 +58,29 @@ type A = test extends B ? foo : bar; +type A = test extends B + // ? + // comment + ? foo + : test2 extends C + // comment + // comment + ? foo + : bar; + +type B = test extends B + /* comment + comment + comment + comment */ + ? foo + : test2 extends C + /* comment + comment + comment */ + ? foo + : bar; + ================================================================================ `; diff --git a/tests/typescript/conditional-types/comments.ts b/tests/typescript/conditional-types/comments.ts index 058f9ef2c5e8..4e3cdef801f3 100644 --- a/tests/typescript/conditional-types/comments.ts +++ b/tests/typescript/conditional-types/comments.ts @@ -11,3 +11,26 @@ type A = test extends B comment */ ? foo : bar; + +type A = test extends B + // ? + // comment + ? foo + : test2 extends C + // comment + // comment + ? foo + : bar; + +type B = test extends B + /* comment + comment + comment + comment */ + ? foo + : test2 extends C + /* comment + comment + comment */ + ? foo + : bar; From d4e7ad76bcee745dc50ead0e4f35d186ebb5bdbd Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 12 Jun 2020 19:41:30 +0900 Subject: [PATCH 07/19] Refactor --- src/language-js/comments.js | 50 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index 14e764f5205f..be063ea0d1d9 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -1031,46 +1031,44 @@ function isTypeCastComment(comment) { ); } +function isTernaryExpression(node) { + if (!node) { + return false; + } + return ( + node.type === "ConditionalExpression" || node.type === "TSConditionalType" + ); +} + +/** + * Check if node matches the ternary test node + */ function isTernaryTest(node, ternary) { if (!node || !ternary) { return false; } - const isTernary = - ternary.type === "ConditionalExpression" || - ternary.type === "TSConditionalType"; const testField = ternary.test ? "test" : "extendsType"; - return isTernary && node === ternary[testField]; + return isTernaryExpression(ternary) && node === ternary[testField]; +} + +function isCommentParentTernaryTest(commentPath) { + return isTernaryTest( + commentPath.getParentNode(), + commentPath.getParentNode(1) + ); } function shouldIndentComment(path) { - const parent = path.getParentNode(); - const parentParent = path.getParentNode(1); - const parentParentParent = path.getParentNode(2); - const isNestedTernary = - parentParentParent && - (parentParentParent.type === "ConditionalExpression" || - parentParentParent.type === "TSConditionalType") return ( - parent && - parentParent && - isTernaryTest(parent, parentParent) && - !isNestedTernary + isCommentParentTernaryTest(path) && + isTernaryExpression(path.getParentNode(2)) ); } function shouldDedentComment(path) { - const parent = path.getParentNode(); - const parentParent = path.getParentNode(1); - const parentParentParent = path.getParentNode(2); - const isNestedTernary = - parentParentParent && - (parentParentParent.type === "ConditionalExpression" || - parentParentParent.type === "TSConditionalType") return ( - parent && - parentParent && - isTernaryTest(parent, parentParent) && - isNestedTernary + isCommentParentTernaryTest(path) && + !isTernaryExpression(path.getParentNode(2)) ); } From cb097e57d03ecd1fea90e2ffcbd44e906b1937c0 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 12 Jun 2020 22:21:22 +0900 Subject: [PATCH 08/19] Fix --- src/language-js/comments.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index be063ea0d1d9..c46e610c82a2 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -1061,14 +1061,14 @@ function isCommentParentTernaryTest(commentPath) { function shouldIndentComment(path) { return ( isCommentParentTernaryTest(path) && - isTernaryExpression(path.getParentNode(2)) + !isTernaryExpression(path.getParentNode(2)) ); } function shouldDedentComment(path) { return ( isCommentParentTernaryTest(path) && - !isTernaryExpression(path.getParentNode(2)) + isTernaryExpression(path.getParentNode(2)) ); } From 1d7756070844af7098a8013d8ba85485de2330bb Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 14 Jun 2020 13:17:36 +0900 Subject: [PATCH 09/19] Support comment in between "?" and second op --- src/language-js/comments.js | 62 +++++++++++++++++-- src/main/comments.js | 9 ++- .../__snapshots__/jsfmt.spec.js.snap | 42 +++++++++++++ tests/js/conditional/comments.js | 21 +++++++ .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 26 ++++++++ .../typescript/conditional-types/comments.ts | 13 ++++ 7 files changed, 170 insertions(+), 7 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index c46e610c82a2..eea80623bc7a 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -8,7 +8,14 @@ const { getNextNonSpaceNonCommentCharacterIndex, } = require("../common/util-shared"); -function handleOwnLineComment(comment, text, options, ast, isLastComment) { +function handleOwnLineComment( + comment, + text, + options, + ast, + isLastComment, + comments +) { const { precedingNode, enclosingNode, followingNode } = comment; return ( handleLastFunctionArgComments( @@ -68,7 +75,14 @@ function handleOwnLineComment(comment, text, options, ast, isLastComment) { options ) || handleLabeledStatementComments(enclosingNode, comment) || - handleTernaryComment(enclosingNode, precedingNode, comment) + handleTernaryComment( + enclosingNode, + precedingNode, + comment, + comments, + text, + options + ) ); } @@ -942,12 +956,52 @@ function handleTSMappedTypeComments( return false; } -function handleTernaryComment(enclosingNode, precedingNode, comment) { +function hasQuestionInRange(text, start, end, comments, options) { + for (let i = start; i < end; ++i) { + if (text.charAt(i) === "?") { + let hasQuestion = true; + // Ignore "?" in comments + for (const comment of comments) { + const commentStart = options.locStart(comment); + const commentEnd = options.locEnd(comment); + for (let j = commentStart; j < commentEnd; ++j) { + if (j === i) { + hasQuestion = false; + } + } + } + return hasQuestion; + } + } + return false; +} + +function handleTernaryComment( + enclosingNode, + precedingNode, + comment, + comments, + text, + options +) { // test // // comment // ? first // : second - if (isTernaryTest(precedingNode, enclosingNode)) { + if ( + isTernaryTest(precedingNode, enclosingNode) && + // test ? + // // comment + // first + // : second + !hasQuestionInRange( + text, + options.locEnd(precedingNode), + options.locStart(comment), + comments, + options + ) + ) { addTrailingComment(precedingNode, comment); return true; } diff --git a/src/main/comments.js b/src/main/comments.js index 8dcf4684146d..1b339b34a5c7 100644 --- a/src/main/comments.js +++ b/src/main/comments.js @@ -219,7 +219,14 @@ function attach(comments, ast, text, options) { // If a comment exists on its own line, prefer a leading comment. // We also need to check if it's the first line of the file. if ( - pluginHandleOwnLineComment(comment, text, options, ast, isLastComment) + pluginHandleOwnLineComment( + comment, + text, + options, + ast, + isLastComment, + comments + ) ) { // We're good } else if (followingNode) { diff --git a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap index 3082645ef18c..05c3c6953fd0 100644 --- a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap @@ -50,6 +50,19 @@ test ? foo : bar; +test ? + // comment + foo + : bar; + +test ? + // comment + first + : test + // comment + ? first + : second; + test /* comment comment @@ -58,6 +71,14 @@ test ? foo : bar; +test ? + /* comment + comment + comment + comment */ + foo + : bar; + test // ? // comment @@ -129,6 +150,19 @@ test ? foo : bar; +test + ? // comment + foo + : bar; + +test + ? // comment + first + : test + // comment + ? first + : second; + test /* comment comment @@ -137,6 +171,14 @@ test ? foo : bar; +test + ? /* comment + comment + comment + comment */ + foo + : bar; + test // ? // comment diff --git a/tests/js/conditional/comments.js b/tests/js/conditional/comments.js index 6e401358d671..3dbc160874b5 100644 --- a/tests/js/conditional/comments.js +++ b/tests/js/conditional/comments.js @@ -42,6 +42,19 @@ test ? foo : bar; +test ? + // comment + foo + : bar; + +test ? + // comment + first + : test + // comment + ? first + : second; + test /* comment comment @@ -50,6 +63,14 @@ test ? foo : bar; +test ? + /* comment + comment + comment + comment */ + foo + : bar; + test // ? // comment diff --git a/tests/js/method-chain/__snapshots__/jsfmt.spec.js.snap b/tests/js/method-chain/__snapshots__/jsfmt.spec.js.snap index 5144aac33cfd..8420ce5ba8e8 100644 --- a/tests/js/method-chain/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/method-chain/__snapshots__/jsfmt.spec.js.snap @@ -372,8 +372,8 @@ this.doWriteConfiguration(target, value, options) // queue up writes to prevent ); ret = __DEV__ - // $FlowFixMe: this type differs according to the env - ? vm.runInContext(source, ctx) + ? // $FlowFixMe: this type differs according to the env + vm.runInContext(source, ctx) : a; this.firebase diff --git a/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap b/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap index a34ad2a3ac5e..80a46534b9d6 100644 --- a/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap @@ -43,6 +43,19 @@ type B = test extends B ? foo : bar; +type A = B extends test ? + // comment + foo + : bar; + +type A = B extends test ? + // comment + first + : B extends test + // comment + ? first + : second; + =====================================output===================================== type A = test extends B // ? @@ -81,6 +94,19 @@ type B = test extends B ? foo : bar; +type A = B extends test + ? // comment + foo + : bar; + +type A = B extends test + ? // comment + first + : B extends test + // comment + ? first + : second; + ================================================================================ `; diff --git a/tests/typescript/conditional-types/comments.ts b/tests/typescript/conditional-types/comments.ts index 4e3cdef801f3..b6871c9bf9e6 100644 --- a/tests/typescript/conditional-types/comments.ts +++ b/tests/typescript/conditional-types/comments.ts @@ -34,3 +34,16 @@ type B = test extends B comment */ ? foo : bar; + +type A = B extends test ? + // comment + foo + : bar; + +type A = B extends test ? + // comment + first + : B extends test + // comment + ? first + : second; From 8afc04de43127ed5b9da55a980c6091f4acb1795 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 14 Jun 2020 13:31:43 +0900 Subject: [PATCH 10/19] Refactor --- src/language-js/comments.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index eea80623bc7a..06d5ab940e33 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -964,10 +964,8 @@ function hasQuestionInRange(text, start, end, comments, options) { for (const comment of comments) { const commentStart = options.locStart(comment); const commentEnd = options.locEnd(comment); - for (let j = commentStart; j < commentEnd; ++j) { - if (j === i) { - hasQuestion = false; - } + if (commentStart < i && i < commentEnd) { + hasQuestion = false; } } return hasQuestion; From 1feddd4b55a75000c86dfdad5d705f74f401f3ea Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 14 Jun 2020 13:48:02 +0900 Subject: [PATCH 11/19] Refactor --- src/language-js/comments.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index 06d5ab940e33..2ec3a44eca55 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -1084,11 +1084,9 @@ function isTypeCastComment(comment) { } function isTernaryExpression(node) { - if (!node) { - return false; - } return ( - node.type === "ConditionalExpression" || node.type === "TSConditionalType" + node && + (node.type === "ConditionalExpression" || node.type === "TSConditionalType") ); } @@ -1096,11 +1094,11 @@ function isTernaryExpression(node) { * Check if node matches the ternary test node */ function isTernaryTest(node, ternary) { - if (!node || !ternary) { + if (!node || !isTernaryExpression(ternary)) { return false; } const testField = ternary.test ? "test" : "extendsType"; - return isTernaryExpression(ternary) && node === ternary[testField]; + return node === ternary[testField]; } function isCommentParentTernaryTest(commentPath) { From 57da1e1eb1b80a18250fe21f5e91d0f8eef3c238 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 14 Jun 2020 14:29:26 +0900 Subject: [PATCH 12/19] Add changelog --- changelog_unreleased/javascript/pr-8554.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 changelog_unreleased/javascript/pr-8554.md diff --git a/changelog_unreleased/javascript/pr-8554.md b/changelog_unreleased/javascript/pr-8554.md new file mode 100644 index 000000000000..6919d2be5d90 --- /dev/null +++ b/changelog_unreleased/javascript/pr-8554.md @@ -0,0 +1,22 @@ +#### Prefer a trailing comment when comment on between test and consequent on ternary ([#8554](https://github.com/prettier/prettier/pull/8554) by [@sosukesuzuki](https://github.com/sosukesuzuki)) + + +```js +// Input +test + // comment + ? foo + : bar; + +// Prettier (stable) +test + ? // comment + foo + : bar; + +// Prettier (master) +test + // comment + ? foo + : bar; +``` From 74fb69d1b5458e6bae6b63634a0b1bf229a5b9c6 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 14 Jun 2020 18:42:18 +0900 Subject: [PATCH 13/19] Rename --- src/language-js/comments.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index 2ec3a44eca55..da92742dd24f 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -75,7 +75,7 @@ function handleOwnLineComment( options ) || handleLabeledStatementComments(enclosingNode, comment) || - handleTernaryComment( + handleTernaryTrailingComments( enclosingNode, precedingNode, comment, @@ -974,7 +974,7 @@ function hasQuestionInRange(text, start, end, comments, options) { return false; } -function handleTernaryComment( +function handleTernaryTrailingComments( enclosingNode, precedingNode, comment, From 2ed9474bf8cacb79bf5949dcd289c3b01a474992 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 21 Jun 2020 17:24:51 +0900 Subject: [PATCH 14/19] Move functions --- src/language-js/comments.js | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index 5048d740e6fa..6d1259cd5049 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -421,9 +421,7 @@ function handleConditionalExpressionComments( if ( (!precedingNode || !isSameLineAsPrecedingNode) && - enclosingNode && - (enclosingNode.type === "ConditionalExpression" || - enclosingNode.type === "TSConditionalType") && + isTernaryExpression(enclosingNode) && followingNode ) { addLeadingComment(followingNode, comment); @@ -1073,6 +1071,20 @@ function getCommentChildNodes(node, options) { } } +function shouldIndentComment(path) { + return ( + isCommentParentTernaryTest(path) && + !isTernaryExpression(path.getParentNode(2)) + ); +} + +function shouldDedentComment(path) { + return ( + isCommentParentTernaryTest(path) && + isTernaryExpression(path.getParentNode(2)) + ); +} + function isTypeCastComment(comment) { return ( isBlockComment(comment) && @@ -1109,20 +1121,6 @@ function isCommentParentTernaryTest(commentPath) { ); } -function shouldIndentComment(path) { - return ( - isCommentParentTernaryTest(path) && - !isTernaryExpression(path.getParentNode(2)) - ); -} - -function shouldDedentComment(path) { - return ( - isCommentParentTernaryTest(path) && - isTernaryExpression(path.getParentNode(2)) - ); -} - module.exports = { handleOwnLineComment, handleEndOfLineComment, From f2bbf895e7ea1a3c2d60937d4f70d7a2d50ba6ae Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 26 Jun 2020 01:46:52 +0900 Subject: [PATCH 15/19] Refactor with using getNextNonSpaceNonCommentCharacterWithStartIndex --- src/language-js/comments.js | 41 ++++++++----------------------------- src/main/comments.js | 9 +------- 2 files changed, 9 insertions(+), 41 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index 6d1259cd5049..c14c6ad977a6 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -8,14 +8,7 @@ const { getNextNonSpaceNonCommentCharacterIndex, } = require("../common/util-shared"); -function handleOwnLineComment( - comment, - text, - options, - ast, - isLastComment, - comments -) { +function handleOwnLineComment(comment, text, options, ast, isLastComment) { const { precedingNode, enclosingNode, followingNode } = comment; return ( handleLastFunctionArgComments( @@ -79,7 +72,6 @@ function handleOwnLineComment( enclosingNode, precedingNode, comment, - comments, text, options ) @@ -955,29 +947,18 @@ function handleTSMappedTypeComments( return false; } -function hasQuestionInRange(text, start, end, comments, options) { - for (let i = start; i < end; ++i) { - if (text.charAt(i) === "?") { - let hasQuestion = true; - // Ignore "?" in comments - for (const comment of comments) { - const commentStart = options.locStart(comment); - const commentEnd = options.locEnd(comment); - if (commentStart < i && i < commentEnd) { - hasQuestion = false; - } - } - return hasQuestion; - } - } - return false; +function hasQuestionBetweenTestAndComment(testNode, comment, text, options) { + const idx = privateUtil.getNextNonSpaceNonCommentCharacterIndexWithStartIndex( + text, + options.locEnd(testNode) + ); + return idx < options.locStart(comment); } function handleTernaryTrailingComments( enclosingNode, precedingNode, comment, - comments, text, options ) { @@ -991,13 +972,7 @@ function handleTernaryTrailingComments( // // comment // first // : second - !hasQuestionInRange( - text, - options.locEnd(precedingNode), - options.locStart(comment), - comments, - options - ) + !hasQuestionBetweenTestAndComment(precedingNode, comment, text, options) ) { addTrailingComment(precedingNode, comment); return true; diff --git a/src/main/comments.js b/src/main/comments.js index 1b339b34a5c7..8dcf4684146d 100644 --- a/src/main/comments.js +++ b/src/main/comments.js @@ -219,14 +219,7 @@ function attach(comments, ast, text, options) { // If a comment exists on its own line, prefer a leading comment. // We also need to check if it's the first line of the file. if ( - pluginHandleOwnLineComment( - comment, - text, - options, - ast, - isLastComment, - comments - ) + pluginHandleOwnLineComment(comment, text, options, ast, isLastComment) ) { // We're good } else if (followingNode) { From 62290e6224c084aa385dae508c42e19a59e6143c Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sat, 27 Jun 2020 03:10:53 +0900 Subject: [PATCH 16/19] Fix to avoid paren --- src/language-js/comments.js | 2 +- .../__snapshots__/jsfmt.spec.js.snap | 24 +++++++++++++++++++ tests/js/conditional/comments.js | 12 ++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index c14c6ad977a6..d6c51912bd19 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -952,7 +952,7 @@ function hasQuestionBetweenTestAndComment(testNode, comment, text, options) { text, options.locEnd(testNode) ); - return idx < options.locStart(comment); + return text[idx] === "?" && idx < options.locStart(comment); } function handleTernaryTrailingComments( diff --git a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap index 292ad6dc5d32..c81b845ed681 100644 --- a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap @@ -168,6 +168,18 @@ test test ? test /* c c */? foo : bar : bar; +(async () => { + (await test) + // comment + ? + foo : bar; +}); + +(test) +// comment +? +foo : bar; + =====================================output===================================== var inspect = 4 === util.inspect.length @@ -332,6 +344,18 @@ c */ : bar : bar; +async () => { + (await test) + // comment + ? foo + : bar; +}; + +test + // comment + ? foo + : bar; + ================================================================================ `; diff --git a/tests/js/conditional/comments.js b/tests/js/conditional/comments.js index 4cb11e4b9f54..5b359005af1c 100644 --- a/tests/js/conditional/comments.js +++ b/tests/js/conditional/comments.js @@ -159,3 +159,15 @@ test test ? test /* c c */? foo : bar : bar; + +(async () => { + (await test) + // comment + ? + foo : bar; +}); + +(test) +// comment +? +foo : bar; From 776f858c0444f88c21a7325331ea8b88de3124a7 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sat, 27 Jun 2020 03:58:03 +0900 Subject: [PATCH 17/19] Fix --- src/language-js/comments.js | 26 ++++++++++++++++--- .../__snapshots__/jsfmt.spec.js.snap | 18 +++++++++++++ tests/js/conditional/comments.js | 8 ++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index d6c51912bd19..8d34bef59035 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -947,12 +947,32 @@ function handleTSMappedTypeComments( return false; } -function hasQuestionBetweenTestAndComment(testNode, comment, text, options) { +function hasQuestionBetweenTestAndComment( + testNode, + comment, + text, + options, + n = 0 +) { + const testNodeLocEnd = options.locEnd(testNode) + n; + const commentLocStart = options.locStart(comment); const idx = privateUtil.getNextNonSpaceNonCommentCharacterIndexWithStartIndex( text, - options.locEnd(testNode) + testNodeLocEnd ); - return text[idx] === "?" && idx < options.locStart(comment); + if (testNodeLocEnd < commentLocStart) { + if (text[idx] === "?") { + return idx < commentLocStart; + } + return hasQuestionBetweenTestAndComment( + testNode, + comment, + text, + options, + n + 1 + ); + } + return false; } function handleTernaryTrailingComments( diff --git a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap index c81b845ed681..86b5fa8c1629 100644 --- a/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/conditional/__snapshots__/jsfmt.spec.js.snap @@ -180,6 +180,14 @@ c */? foo : bar : bar; ? foo : bar; +(test) ? +// comment +foo : bar; + +test ? +// comment +foo : bar; + =====================================output===================================== var inspect = 4 === util.inspect.length @@ -356,6 +364,16 @@ test ? foo : bar; +test + ? // comment + foo + : bar; + +test + ? // comment + foo + : bar; + ================================================================================ `; diff --git a/tests/js/conditional/comments.js b/tests/js/conditional/comments.js index 5b359005af1c..2813f09d933e 100644 --- a/tests/js/conditional/comments.js +++ b/tests/js/conditional/comments.js @@ -171,3 +171,11 @@ c */? foo : bar : bar; // comment ? foo : bar; + +(test) ? +// comment +foo : bar; + +test ? +// comment +foo : bar; From a5b4a08c7e9fb7b5417d39b0d1cba4f03d712ce4 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 28 Jun 2020 20:13:01 +0900 Subject: [PATCH 18/19] With for loop --- src/language-js/comments.js | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index 8d34bef59035..d03f6e4e13cc 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -947,30 +947,17 @@ function handleTSMappedTypeComments( return false; } -function hasQuestionBetweenTestAndComment( - testNode, - comment, - text, - options, - n = 0 -) { - const testNodeLocEnd = options.locEnd(testNode) + n; +function hasQuestionBetweenTestAndComment(testNode, comment, text, options) { + const testNodeLocEnd = options.locEnd(testNode); const commentLocStart = options.locStart(comment); - const idx = privateUtil.getNextNonSpaceNonCommentCharacterIndexWithStartIndex( - text, - testNodeLocEnd - ); - if (testNodeLocEnd < commentLocStart) { + for (let i = testNodeLocEnd; i < commentLocStart; i++) { + const idx = privateUtil.getNextNonSpaceNonCommentCharacterIndexWithStartIndex( + text, + i + ); if (text[idx] === "?") { return idx < commentLocStart; } - return hasQuestionBetweenTestAndComment( - testNode, - comment, - text, - options, - n + 1 - ); } return false; } From aa4cb495e4223306fca21e458e64b9ce18ce6a2f Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 29 Jun 2020 15:32:01 +0800 Subject: [PATCH 19/19] Try to make loop faster --- src/language-js/comments.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/language-js/comments.js b/src/language-js/comments.js index d03f6e4e13cc..cce25a621a19 100644 --- a/src/language-js/comments.js +++ b/src/language-js/comments.js @@ -951,12 +951,12 @@ function hasQuestionBetweenTestAndComment(testNode, comment, text, options) { const testNodeLocEnd = options.locEnd(testNode); const commentLocStart = options.locStart(comment); for (let i = testNodeLocEnd; i < commentLocStart; i++) { - const idx = privateUtil.getNextNonSpaceNonCommentCharacterIndexWithStartIndex( + i = privateUtil.getNextNonSpaceNonCommentCharacterIndexWithStartIndex( text, i ); - if (text[idx] === "?") { - return idx < commentLocStart; + if (text[i] === "?") { + return i < commentLocStart; } } return false;