Skip to content

Commit

Permalink
wip.
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 19eee79
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 19 deletions.
71 changes: 69 additions & 2 deletions docs/rules/multiline-comment-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,82 @@ 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();

```

Expand Down
116 changes: 108 additions & 8 deletions lib/rules/multiline-comment-style.js
Original file line number Diff line number Diff line change
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,44 @@ 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 {string[]} commentLinesList A list of lines to appear in the block comment
* @returns {boolean} if commentLinesList is JSDoc, return true
*/
function isJSDoc(commentLinesList) {
const lines = commentLinesList[0].value.split(astUtils.LINEBREAK_MATCHER);

return /^\*\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 +121,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 +142,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 +153,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 +169,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 +185,64 @@ module.exports = {
}
}
},
"separate-lines"() {
"separate-lines"(commentGroup) {

const commentLines = getCommentLines(commentGroup);

// TODO
if (commentGroup[0].type === "Block" && !isJSDoc(commentGroup)) {
const block = commentGroup[0];

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) {
const commentLines = getCommentLines(commentGroup);

if (!isJSDoc(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)));
}
});
}

// TODO: clean up.
// 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
55 changes: 46 additions & 9 deletions tests/lib/rules/multiline-comment-style.js
Original file line number Diff line number Diff line change
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,34 @@ ruleTester.run("multiline-comment-style", rule, {
`,
options: ["separate-lines"],
errors: [{ message: EXPECTED_LINES_ERROR, line: 2 }]
},

// TODO: add "bare-block" option
{
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 19eee79

Please sign in to comment.