From 1cec21f25369e515a1bb642e7d599860de022841 Mon Sep 17 00:00:00 2001 From: Kai Cataldo Date: Fri, 25 Oct 2019 17:30:11 -0400 Subject: [PATCH] Fix starred-block alignment/missing star fixer --- lib/rules/multiline-comment-style.js | 66 ++++++++++++++++------ tests/lib/rules/multiline-comment-style.js | 63 +++++++++++++-------- 2 files changed, 89 insertions(+), 40 deletions(-) diff --git a/lib/rules/multiline-comment-style.js b/lib/rules/multiline-comment-style.js index 17c297fad7e..241f10303c4 100644 --- a/lib/rules/multiline-comment-style.js +++ b/lib/rules/multiline-comment-style.js @@ -42,6 +42,36 @@ module.exports = { // Helpers //---------------------------------------------------------------------- + /** + * Checks if a comment line is starred. + * @param {string} line A string representing a comment line. + * @returns {boolean} Whether or not the comment line is starred. + */ + function isStarredCommentLine(line) { + return /^\s*\*/u.test(line); + } + + /** + * Calculate the column that should be used to align other lines. + * @param {string[]} lines An array of strings that represent each comment line. + * @returns {number} The column to align with. + */ + function getColumnToAlignWith(lines) { + let columnToAlignWith = Infinity; + + for (const line of lines) { + const [, prefix = null] = line.match(isStarredCommentLine(line) ? /^(\s*\*\s*)\S+/u : /^(\s*)\S+/u) || []; + + if (prefix) { + if (prefix.length < columnToAlignWith) { + columnToAlignWith = prefix.length; + } + } + } + + return columnToAlignWith; + } + /** * Checks if a comment group is in starred-block form. * @param {Token[]} commentGroup A group of comments, containing either multiple line comments or a single block comment. @@ -271,32 +301,36 @@ module.exports = { }); } + const columnToAlignWith = getColumnToAlignWith(sourceCode.lines.slice(firstComment.loc.start.line, lines.length)); + for (let lineNumber = firstComment.loc.start.line + 1; lineNumber <= firstComment.loc.end.line; lineNumber++) { const lineText = sourceCode.lines[lineNumber - 1]; + const errorType = isStarredCommentLine(lineText) + ? "alignment" + : "missingStar"; if (!lineText.startsWith(expectedLinePrefix)) { context.report({ loc: { start: { line: lineNumber, column: 0 }, - end: { line: lineNumber, column: sourceCode.lines[lineNumber - 1].length } + end: { line: lineNumber, column: lineText.length } }, - messageId: /^\s*\*/u.test(lineText) - ? "alignment" - : "missingStar", + messageId: errorType, fix(fixer) { const lineStartIndex = sourceCode.getIndexFromLoc({ line: lineNumber, column: 0 }); - const [linePrefix, whitespaceBefore, whitespaceAfter] = lineText.match(/^(\s*)\*?(\s*)/u); - const leadingWhitespace = whitespaceAfter.length && whitespaceAfter || ` ${ - whitespaceBefore.startsWith(expectedLeadingWhitespace) - ? whitespaceBefore.replace(expectedLeadingWhitespace, "") - : "" - }`; - const replacementText = lineNumber === firstComment.loc.end.line || lineText.length === linePrefix.length - ? expectedLinePrefix - : `${expectedLinePrefix}${leadingWhitespace}`; - const commentStartIndex = lineStartIndex + linePrefix.length; - - return fixer.replaceTextRange([lineStartIndex, commentStartIndex], replacementText); + + if (errorType === "alignment") { + const [, commentTextPrefix = ""] = lineText.match(/^(\s*\*)/u) || []; + const commentTextStartIndex = lineStartIndex + commentTextPrefix.length; + + return fixer.replaceTextRange([lineStartIndex, commentTextStartIndex], expectedLinePrefix); + } + + const [, commentTextPrefix = ""] = lineText.match(/^(\s*)/u) || []; + const commentTextStartIndex = lineStartIndex + commentTextPrefix.length; + const offset = commentTextPrefix.slice(columnToAlignWith); + + return fixer.replaceTextRange([lineStartIndex, commentTextStartIndex], `${expectedLinePrefix}${offset}`); } }); } diff --git a/tests/lib/rules/multiline-comment-style.js b/tests/lib/rules/multiline-comment-style.js index 047e4e4f0c7..8f509022dd8 100644 --- a/tests/lib/rules/multiline-comment-style.js +++ b/tests/lib/rules/multiline-comment-style.js @@ -471,7 +471,7 @@ ruleTester.run("multiline-comment-style", rule, { code: ` /* * the following line - is missing a '*' at the start + is missing a '*' at the start */ `, output: ` @@ -492,7 +492,22 @@ ruleTester.run("multiline-comment-style", rule, { output: ` /* * the following line - * is missing a '*' at the start + *is missing a '*' at the start + */ + `, + errors: [{ messageId: "missingStar", line: 4 }] + }, + { + code: ` + /* + * the following line + is missing a '*' at the start + */ + `, + output: ` + /* + * the following line + *is missing a '*' at the start */ `, errors: [{ messageId: "missingStar", line: 4 }] @@ -784,10 +799,10 @@ ruleTester.run("multiline-comment-style", rule, { `, output: ` /* - * { - * "foo": 1, - * "bar": 2 - * } + *{ + * "foo": 1, + * "bar": 2 + *} */ `, errors: [ @@ -809,10 +824,10 @@ ruleTester.run("multiline-comment-style", rule, { `, output: ` /* - * { - * \t"foo": 1, - * \t"bar": 2 - * } + *{ + *\t"foo": 1, + *\t"bar": 2 + *} */ `, errors: [ @@ -834,10 +849,10 @@ ruleTester.run("multiline-comment-style", rule, { `, output: ` /* - * { - * \t "foo": 1, - * \t "bar": 2 - * } + *{ + *\t "foo": 1, + *\t "bar": 2 + *} */ `, errors: [ @@ -859,10 +874,10 @@ ruleTester.run("multiline-comment-style", rule, { `, output: ` /* - * { - * "foo": 1, - * "bar": 2 - * } + *{ + *"foo": 1, + *"bar": 2 + *} */ `, errors: [ @@ -884,10 +899,10 @@ ruleTester.run("multiline-comment-style", rule, { `, output: ` \t /* - \t * { - \t * "foo": 1, - \t * "bar": 2 - \t * } + \t * \t { + \t * \t "foo": 1, + \t *\t "bar": 2 + \t *} \t */ `, errors: [ @@ -1291,7 +1306,7 @@ ${" "} /* * foo * - * bar + * bar${" "} */ `, options: ["starred-block"], @@ -1312,7 +1327,7 @@ ${" "} /* * foo * - * bar + * bar${" "} */ `, options: ["starred-block"],