diff --git a/.README/README.md b/.README/README.md index 9a0b13bff..9fb23310a 100644 --- a/.README/README.md +++ b/.README/README.md @@ -44,6 +44,7 @@ Finally, enable all of the rules that you would like to use. "jsdoc/check-examples": 1, "jsdoc/check-indentation": 1, "jsdoc/check-param-names": 1, // Recommended + "jsdoc/check-prefix": 1, "jsdoc/check-syntax": 1, "jsdoc/check-tag-names": 1, // Recommended "jsdoc/check-types": 1, // Recommended @@ -327,6 +328,7 @@ only (e.g., to match `Array` if the type is `Array` vs. `Array.`). {"gitdown": "include", "file": "./rules/check-examples.md"} {"gitdown": "include", "file": "./rules/check-indentation.md"} {"gitdown": "include", "file": "./rules/check-param-names.md"} +{"gitdown": "include", "file": "./rules/check-prefix.md"} {"gitdown": "include", "file": "./rules/check-syntax.md"} {"gitdown": "include", "file": "./rules/check-tag-names.md"} {"gitdown": "include", "file": "./rules/check-types.md"} diff --git a/.README/rules/check-prefix.md b/.README/rules/check-prefix.md new file mode 100644 index 000000000..536958ccf --- /dev/null +++ b/.README/rules/check-prefix.md @@ -0,0 +1,8 @@ +### `check-prefix` + +Ensures that each JSDoc line starts with an `*`. + +||| +|---|---| +|Context|everywhere| +|Tags|N/a| diff --git a/README.md b/README.md index d0e276efe..a3fffbd0e 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ JSDoc linting rules for ESLint. * [`check-examples`](#eslint-plugin-jsdoc-rules-check-examples) * [`check-indentation`](#eslint-plugin-jsdoc-rules-check-indentation) * [`check-param-names`](#eslint-plugin-jsdoc-rules-check-param-names) + * [`check-prefix`](#eslint-plugin-jsdoc-rules-check-prefix) * [`check-syntax`](#eslint-plugin-jsdoc-rules-check-syntax) * [`check-tag-names`](#eslint-plugin-jsdoc-rules-check-tag-names) * [`check-types`](#eslint-plugin-jsdoc-rules-check-types) @@ -87,6 +88,7 @@ Finally, enable all of the rules that you would like to use. "jsdoc/check-examples": 1, "jsdoc/check-indentation": 1, "jsdoc/check-param-names": 1, // Recommended + "jsdoc/check-prefix": 1, "jsdoc/check-syntax": 1, "jsdoc/check-tag-names": 1, // Recommended "jsdoc/check-types": 1, // Recommended @@ -1642,6 +1644,16 @@ function quux ({ Likewise for the pattern `[a, b]` which is an [`ArrayPattern`](https://github.com/estree/estree/blob/master/es2015.md#arraypattern). + +### check-prefix + +Ensures that each JSDoc line starts with an `*`. + +||| +|---|---| +|Context|everywhere| +|Tags|N/a| + ### check-syntax diff --git a/src/index.js b/src/index.js index d91180a37..b5e44b031 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,7 @@ import checkAlignment from './rules/checkAlignment'; import checkExamples from './rules/checkExamples'; import checkIndentation from './rules/checkIndentation'; import checkParamNames from './rules/checkParamNames'; +import checkPrefix from './rules/checkPrefix'; import checkSyntax from './rules/checkSyntax'; import checkTagNames from './rules/checkTagNames'; import checkTypes from './rules/checkTypes'; @@ -39,6 +40,7 @@ export default { 'jsdoc/check-examples': 'off', 'jsdoc/check-indentation': 'off', 'jsdoc/check-param-names': 'warn', + 'jsdoc/check-prefix': 'off', 'jsdoc/check-syntax': 'off', 'jsdoc/check-tag-names': 'warn', 'jsdoc/check-types': 'warn', @@ -72,6 +74,7 @@ export default { 'check-examples': checkExamples, 'check-indentation': checkIndentation, 'check-param-names': checkParamNames, + 'check-prefix': checkPrefix, 'check-syntax': checkSyntax, 'check-tag-names': checkTagNames, 'check-types': checkTypes, diff --git a/src/rules/checkPrefix.js b/src/rules/checkPrefix.js new file mode 100644 index 000000000..5bd4f63f1 --- /dev/null +++ b/src/rules/checkPrefix.js @@ -0,0 +1,41 @@ +import iterateJsdoc from '../iterateJsdoc'; + +const prefixMatch = /^(\s+)(?:\*( ?))?/u; +const validPrefix = /^\s+\*(?:\/?$| )/u; + +export default iterateJsdoc(({ + sourceCode, + jsdocNode, + report, +}) => { + const fix = (fixer) => { + const replacement = sourceCode.getText(jsdocNode).split('\n') + .map((line, index) => { + return index && !validPrefix.test(line) ? line.replace(prefixMatch, (_, $1, $2) => { + return `${$1}*${$2 || ' '}`; + }) : line; + }) + .join('\n'); + + return fixer.replaceText(jsdocNode, replacement); + }; + + sourceCode.getText(jsdocNode).split('\n').some((line, index) => { + const lineNum = parseInt(index, 10); + if (lineNum && !validPrefix.test(line)) { + report('Expected JSDoc block to have the prefix.', fix, { + line: lineNum, + }); + + return true; + } + + return false; + }); +}, { + iterateAllJsdocs: true, + meta: { + fixable: 'code', + type: 'layout', + }, +}); diff --git a/test/rules/assertions/checkPrefix.js b/test/rules/assertions/checkPrefix.js new file mode 100644 index 000000000..8d363687d --- /dev/null +++ b/test/rules/assertions/checkPrefix.js @@ -0,0 +1,91 @@ +export default { + invalid: [ + { + code: ` + + /** + @param {Number} foo + */ + function quux (foo) { + // with spaces + } + `, + errors: [ + { + line: 4, + message: 'Expected JSDoc block to have the prefix.', + }, + ], + output: ` + + /** + * @param {Number} foo + */ + function quux (foo) { + // with spaces + } + `, + }, + { + code: ` + /** + @param {Number} foo + */function quux (foo) { + // with spaces + } + `, + errors: [ + { + line: 3, + message: 'Expected JSDoc block to have the prefix.', + }, + ], + output: ` + /** + * @param {Number} foo + */function quux (foo) { + // with spaces + } + `, + }, + ], + valid: [ + { + code: ` + /** + * Desc + * + * @param {Number} foo + * This is more comment. + */ + function quux (foo) { + + } + `, + }, + { + code: ` + /** + * Desc + * + * @param {{ + * foo: Bar, + * bar: Baz + * }} foo + * + */ + function quux (foo) { + + } + `, + }, + { + code: ` + /* <- JSDoc must start with 2 stars. + So this is unchecked. + */ + function quux (foo) {} + `, + }, + ], +}; diff --git a/test/rules/index.js b/test/rules/index.js index 57d114389..cf571a7ef 100644 --- a/test/rules/index.js +++ b/test/rules/index.js @@ -13,6 +13,7 @@ const ruleTester = new RuleTester(); 'check-examples', 'check-indentation', 'check-param-names', + 'check-prefix', 'check-syntax', 'check-tag-names', 'check-types',