From 6f1b50b57106df18ece93a68bb9bc15b1364aaa2 Mon Sep 17 00:00:00 2001 From: Brett Zamir Date: Fri, 8 Sep 2023 09:59:33 -0700 Subject: [PATCH] feat(`informative-docs`): add `excludedTags`; fixes #1153 Also: - fix(`informative-docs`): proper `aliases` schema - test(`informative-docs`): check `uselessWords` - test(`require-jsdoc`): example for Vue components --- .README/rules/informative-docs.md | 2 +- docs/rules/informative-docs.md | 22 ++++++++-- docs/rules/require-jsdoc.md | 22 ++++++++++ src/rules/informativeDocs.js | 17 +++++++- test/rules/assertions/informativeDocs.js | 54 +++++++++++++++++++++++- test/rules/assertions/requireJsdoc.js | 33 +++++++++++++++ 6 files changed, 143 insertions(+), 7 deletions(-) diff --git a/.README/rules/informative-docs.md b/.README/rules/informative-docs.md index 1e02f5a32..5aa44948b 100644 --- a/.README/rules/informative-docs.md +++ b/.README/rules/informative-docs.md @@ -60,7 +60,7 @@ The default `uselessWords` option is: |Tags|any| |Recommended|false| |Settings|| -|Options|`aliases`, `uselessWords`| +|Options|`aliases`, `excludedTags`, `uselessWords`| ## Failing examples diff --git a/docs/rules/informative-docs.md b/docs/rules/informative-docs.md index 571428c09..bce9290bf 100644 --- a/docs/rules/informative-docs.md +++ b/docs/rules/informative-docs.md @@ -76,7 +76,7 @@ The default `uselessWords` option is: |Tags|any| |Recommended|false| |Settings|| -|Options|`aliases`, `uselessWords`| +|Options|`aliases`, `excludedTags`, `uselessWords`| @@ -249,6 +249,11 @@ function takesOne(param) {} */ function takesOne(param) {} // Message: This description only repeats the name it describes. + +/** A smiley/winkey. */ +let emoji; +// "jsdoc/informative-docs": ["error"|"warn", {"aliases":{"emoji":["smiley","winkey"]}}] +// Message: This description only repeats the name it describes. ```` @@ -391,10 +396,21 @@ function takesOne(param) {} function takesOne(param) {} /** - * @class + * @class * * @param {number} value - Some useful text - */ + */ function MyAmazingThing(value) {} + +/** + * My option. + * @default {} + */ +// "jsdoc/informative-docs": ["error"|"warn", {"excludedTags":["default"]}] + +/** + * The + */ +// "jsdoc/informative-docs": ["error"|"warn", {"uselessWords":["an"]}] ```` diff --git a/docs/rules/require-jsdoc.md b/docs/rules/require-jsdoc.md index 8ed3e8885..e40c04933 100644 --- a/docs/rules/require-jsdoc.md +++ b/docs/rules/require-jsdoc.md @@ -1857,5 +1857,27 @@ export default class Test { } } // "jsdoc/require-jsdoc": ["error"|"warn", {"publicOnly":true,"require":{"ArrowFunctionExpression":false,"ClassDeclaration":false,"ClassExpression":false,"FunctionDeclaration":false,"FunctionExpression":false,"MethodDefinition":true}}] + +export default { + created() { + this.getData(); + }, + + beforeUpdate() {}, + + watch: { + someValue(val) {} + }, + + computed: { + loaded() {}, + selection() {} + }, + + methods: { + getData(id) {} + } +}; +// "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":["ExportDefaultDeclaration > ObjectExpression > Property[key.name!=/^(created|beforeUpdate)$/] > FunctionExpression","ExportDefaultDeclaration > ObjectExpression > Property[key.name!=/^(watch|computed|methods)$/] > ObjectExpression > Property > FunctionExpression"]}] ```` diff --git a/src/rules/informativeDocs.js b/src/rules/informativeDocs.js index 6bd6eb23f..03bd4c4ca 100644 --- a/src/rules/informativeDocs.js +++ b/src/rules/informativeDocs.js @@ -91,8 +91,9 @@ export default iterateJsdoc(({ report, utils, }) => { - const { + const /** @type {{aliases: {[key: string]: string[]}, excludedTags: string[], uselessWords: string[]}} */ { aliases = defaultAliases, + excludedTags = [], uselessWords = defaultUselessWords, } = context.options[0] || {}; const nodeNames = getNamesFromNode(node); @@ -119,6 +120,10 @@ export default iterateJsdoc(({ let descriptionReported = false; for (const tag of jsdoc.tags) { + if (excludedTags.includes(tag.tag)) { + continue; + } + if (descriptionIsRedundant(tag.description, tag.name)) { utils.reportJSDoc( 'This tag description only repeats the name it describes.', @@ -147,6 +152,16 @@ export default iterateJsdoc(({ additionalProperties: false, properties: { aliases: { + patternProperties: { + '.*': { + items: { + type: 'string', + }, + type: 'array', + }, + }, + }, + excludedTags: { items: { type: 'string', }, diff --git a/test/rules/assertions/informativeDocs.js b/test/rules/assertions/informativeDocs.js index bbdfbfa17..3b33641fe 100644 --- a/test/rules/assertions/informativeDocs.js +++ b/test/rules/assertions/informativeDocs.js @@ -476,6 +476,27 @@ export default { }, ], }, + { + code: ` + /** A smiley/winkey. */ + let emoji; + `, + errors: [ + { + line: 2, + message: 'This description only repeats the name it describes.', + }, + ], + options: [ + { + aliases: { + emoji: [ + 'smiley', 'winkey', + ], + }, + }, + ], + }, ], valid: [ { @@ -752,12 +773,41 @@ export default { { code: ` /** - * @class + * @class * * @param {number} value - Some useful text - */ + */ function MyAmazingThing(value) {} `, }, + { + code: ` + /** + * My option. + * @default {} + */ + `, + options: [ + { + excludedTags: [ + 'default', + ], + }, + ], + }, + { + code: ` + /** + * The + */ + `, + options: [ + { + uselessWords: [ + 'an', + ], + }, + ], + }, ], }; diff --git a/test/rules/assertions/requireJsdoc.js b/test/rules/assertions/requireJsdoc.js index 079227561..772f63219 100644 --- a/test/rules/assertions/requireJsdoc.js +++ b/test/rules/assertions/requireJsdoc.js @@ -6202,5 +6202,38 @@ function quux (foo) { sourceType: 'module', }, }, + { + code: ` + export default { + created() { + this.getData(); + }, + + beforeUpdate() {}, + + watch: { + someValue(val) {} + }, + + computed: { + loaded() {}, + selection() {} + }, + + methods: { + getData(id) {} + } + }; + `, + options: [ + { + contexts: [ + 'ExportDefaultDeclaration > ObjectExpression > Property[key.name!=/^(created|beforeUpdate)$/] > FunctionExpression', + 'ExportDefaultDeclaration > ObjectExpression > Property[key.name!=/^(watch|computed|methods)$/] > ObjectExpression > Property > FunctionExpression', + ], + }, + ], + parser: require.resolve('@typescript-eslint/parser'), + }, ], };