Skip to content

Commit

Permalink
finished :(
Browse files Browse the repository at this point in the history
  • Loading branch information
aladdin-add authored and 薛定谔的猫 committed Oct 6, 2017
1 parent 90c85f4 commit 4d28db5
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 22 deletions.
75 changes: 70 additions & 5 deletions docs/rules/multiline-comment-style.md
Expand Up @@ -16,27 +16,92 @@ This rule has a string option, which can have one of the following values:

The rule always ignores directive comments such as `/* eslint-disable */`. Additionally, unless the mode is `"starred-block"`, the rule ignores JSDoc comments.

TODO: Add examples

Examples of **incorrect** code for this rule:

```js

// fill me in
/* eslint multiline-comment-style: ["error", "separate-lines"] */

/* This line
calls foo() */
foo();

/*
* This line
* calls foo()
*/
foo();

/* eslint multiline-comment-style: ["error", "starred-block"] */

// this line
// calls foo()
foo();

/* this line
calls foo() */
foo();

/* this comment
* is missing a newline after /*
*/

/*
* this comment
* is missing a newline at the end */

/*
* the star in this line should have a space before it
*/

/*
* the star on the following line should have a space before it
*/

/* eslint multiline-comment-style: ["error", "bare-block"] */

// this line
// calls foo()
foo();

/*
* this line
* calls foo()
*/
foo();

```

Examples of **correct** code for this rule:

```js
/* eslint multiline-comment-style: ["error", "separate-lines"] */

// This line
// calls foo()
foo();


/* eslint multiline-comment-style: ["error", "starred-block"] */

/*
* this line
* calls foo()
*/
foo();


/* eslint multiline-comment-style: ["error", "bare-block"] */

// fill me in
/* this line
calls foo() */
foo();

```

## When Not To Use It

Give a short description of when it would be appropriate to turn off this rule.
If you don't want to enforce a particular style for multiline comments, you can disable the rule.

## Further Reading

Expand Down
113 changes: 105 additions & 8 deletions lib/rules/multiline-comment-style.js
Expand Up @@ -18,13 +18,20 @@ module.exports = {
recommended: false
},
fixable: "whitespace",
schema: [{ enum: ["starred-block", "separate-lines"] }]
schema: [{ enum: ["starred-block", "separate-lines", "bare-block"] }]
},

create(context) {
const sourceCode = context.getSourceCode();
const option = context.options[0] || "starred-block";

const EXPECTED_BLOCK_ERROR = "Expected a block comment instead of consecutive line comments.";
const START_NEWLINE_ERROR = "Expected a linebreak after '/*'.";
const END_NEWLINE_ERROR = "Expected a linebreak before '*/'.";
const MISSING_STAR_ERROR = "Expected a '*' at the start of this line.";
const ALIGNMENT_ERROR = "Expected this line to be aligned with the start of the comment.";
const EXPECTED_LINES_ERROR = "Expected multiple line comments instead of a block comment.";

//----------------------------------------------------------------------
// Helpers
//----------------------------------------------------------------------
Expand Down Expand Up @@ -56,6 +63,45 @@ module.exports = {
return `\n${starredLines.join("\n")}\n${initialOffset} `;
}

/**
* Converts a comment into separate-line form
* @param {Token} firstComment The first comment of the group being converted
* @param {string[]} commentLinesList A list of lines to appear in the new starred-block comment
* @returns {string} A representation of the comment value in separate-line form
*/
function convertToSeparateLines(firstComment, commentLinesList) {
const initialOffset = sourceCode.text.slice(firstComment.range[0] - firstComment.loc.start.column, firstComment.range[0]);
const separateLines = commentLinesList.map(line => `// ${line.trim()}`);

return separateLines.join(`\n${initialOffset}`);
}

/**
* Converts a comment into bare-block form
* @param {Token} firstComment The first comment of the group being converted
* @param {string[]} commentLinesList A list of lines to appear in the new starred-block comment
* @returns {string} A representation of the comment value in bare-block form
*/
function convertToBlock(firstComment, commentLinesList) {
const initialOffset = sourceCode.text.slice(firstComment.range[0] - firstComment.loc.start.column, firstComment.range[0]);
const blockLines = commentLinesList.map(line => line.trim());

return `/* ${blockLines.join(`\n${initialOffset} `)} */`;
}

/**
* Check a comment is JSDoc form
* @param {Token[]} commentGroup A group of comments, containing either multiple line comments or a single block comment
* @returns {boolean} if commentGroup is JSDoc form, return true
*/
function isJSDoc(commentGroup) {
const lines = commentGroup[0].value.split(astUtils.LINEBREAK_MATCHER);

return commentGroup[0].type === "Block" &&
/^\*\s*$/.test(lines[0]) &&
/^\s*$/.test(lines[lines.length - 1]);
}

/**
* Each method checks a group of comments to see if it's valid according to the given option.
* @param {Token[]} commentGroup A list of comments that appear together. This will either contain a single
Expand All @@ -76,7 +122,7 @@ module.exports = {
start: commentGroup[0].loc.start,
end: commentGroup[commentGroup.length - 1].loc.end
},
message: "Expected a block comment instead of consecutive line comments.",
message: EXPECTED_BLOCK_ERROR,
fix(fixer) {
return fixer.replaceTextRange(
[commentGroup[0].range[0], commentGroup[commentGroup.length - 1].range[1]],
Expand All @@ -97,7 +143,7 @@ module.exports = {
start: block.loc.start,
end: { line: block.loc.start.line, column: block.loc.start.column + 2 }
},
message: "Expected a linebreak after '/*'.",
message: START_NEWLINE_ERROR,
fix: fixer => fixer.insertTextAfterRange([start, start + 2], `\n${expectedLinePrefix}`)
});
}
Expand All @@ -108,7 +154,7 @@ module.exports = {
start: { line: block.loc.end.line, column: block.loc.end.column - 2 },
end: block.loc.end
},
message: "Expected a linebreak before '*/'.",
message: END_NEWLINE_ERROR,
fix: fixer => fixer.replaceTextRange([block.range[1] - 2, block.range[1]], `\n${expectedLinePrefix}/`)
});
}
Expand All @@ -124,8 +170,8 @@ module.exports = {
end: { line: lineNumber, column: sourceCode.lines[lineNumber - 1].length }
},
message: /^\s*\*/.test(lineText)
? "Expected this line to be aligned with the start of the comment."
: "Expected a '*' at the start of this line.",
? ALIGNMENT_ERROR
: MISSING_STAR_ERROR,
fix(fixer) {

// TODO: Make this more readable, possibly by splitting it into two separate cases.
Expand All @@ -140,9 +186,60 @@ module.exports = {
}
}
},
"separate-lines"() {
"separate-lines"(commentGroup) {
if (!isJSDoc(commentGroup) && commentGroup[0].type === "Block") {
const commentLines = getCommentLines(commentGroup);
const block = commentGroup[0];

// TODO
context.report({
loc: {
start: block.loc.start,
end: { line: block.loc.start.line, column: block.loc.start.column + 2 }
},
message: EXPECTED_LINES_ERROR,
fix(fixer) {
return fixer.replaceTextRange(block.range, convertToSeparateLines(block, commentLines.filter(line => line)));
}
});
}
},
"bare-block"(commentGroup) {
if (!isJSDoc(commentGroup)) {
const commentLines = getCommentLines(commentGroup);

// disallows consecutive line comments in favor of using a block comment
if (commentGroup[0].type === "Line" && commentLines.length > 1) {
context.report({
loc: {
start: commentGroup[0].loc.start,
end: commentGroup[commentGroup.length - 1].loc.end
},
message: EXPECTED_BLOCK_ERROR,
fix(fixer) {
return fixer.replaceTextRange([commentGroup[0].range[0], commentGroup[commentGroup.length - 1].range[1]], convertToBlock(commentGroup[0], commentLines.filter(line => line)));
}
});
}

// prohibits block comments from having a * at the beginning of each line.
if (commentGroup[0].type === "Block") {
const block = commentGroup[0];
const lines = block.value.split(astUtils.LINEBREAK_MATCHER).slice(1, -1);

if (lines.length > 0 && lines.every(line => /^\s*\*/.test(line))) {
context.report({
loc: {
start: block.loc.start,
end: { line: block.loc.start.line, column: block.loc.start.column + 2 }
},
message: EXPECTED_BLOCK_ERROR,
fix(fixer) {
return fixer.replaceTextRange(block.range, convertToBlock(block, commentLines.filter(line => line)));
}
});
}
}
}
}
};

Expand Down
53 changes: 44 additions & 9 deletions tests/lib/rules/multiline-comment-style.js
Expand Up @@ -153,6 +153,24 @@ ruleTester.run("multiline-comment-style", rule, {
`,
options: ["separate-lines"]
},
{
code: `
/**
* This is
* a JSDoc comment
*/
`,
options: ["starred-block"]
},
{
code: `
/**
* This is
* a JSDoc comment
*/
`,
options: ["bare-block"]
},
{
code: `
/* This is
Expand All @@ -175,15 +193,6 @@ ruleTester.run("multiline-comment-style", rule, {
`,
options: ["separate-lines"]
},
{
code: `
/**
* This is
* a JSDoc comment
*/
`,
options: ["bare-block"]
},
{
code: `
/* The value of 5
Expand Down Expand Up @@ -339,6 +348,32 @@ ruleTester.run("multiline-comment-style", rule, {
`,
options: ["separate-lines"],
errors: [{ message: EXPECTED_LINES_ERROR, line: 2 }]
},
{
code: `
// foo
// bar
`,
output: `
/* foo
bar */
`,
options: ["bare-block"],
errors: [{ message: EXPECTED_BLOCK_ERROR, line: 2 }]
},
{
code: `
/*
* foo
* bar
*/
`,
output: `
/* foo
bar */
`,
options: ["bare-block"],
errors: [{ message: EXPECTED_BLOCK_ERROR, line: 2 }]
}
]
});

0 comments on commit 4d28db5

Please sign in to comment.