From 6a2217bb3f11b07aba8a33f56bc9959f3d0cb8f9 Mon Sep 17 00:00:00 2001 From: Eli Skeggs Date: Fri, 13 Dec 2019 17:00:53 -0800 Subject: [PATCH] feat: add check-prefix rule This rule checks that each line of the jsdoc comment starts with an asterisk. For composability with other rules, this does not check the alignment or indentation of the comment content. fix #199 --- .README/README.md | 2 + .README/rules/check-prefix.md | 8 +++ README.md | 12 ++++ src/index.js | 3 + src/rules/checkPrefix.js | 41 +++++++++++++ test/rules/assertions/checkPrefix.js | 91 ++++++++++++++++++++++++++++ test/rules/index.js | 1 + 7 files changed, 158 insertions(+) create mode 100644 .README/rules/check-prefix.md create mode 100644 src/rules/checkPrefix.js create mode 100644 test/rules/assertions/checkPrefix.js 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',