diff --git a/.README/rules/check-template-names.md b/.README/rules/check-template-names.md index 34aaef77..64492c09 100644 --- a/.README/rules/check-template-names.md +++ b/.README/rules/check-template-names.md @@ -1,7 +1,7 @@ # `check-template-names` Checks that any `@template` names are actually used in the connected -`@typedef` or type alias. +`@typedef`, `@callback`, `@function` or type structure. Currently checks `ClassDeclaration`, `FunctionDeclaration`, `TSInterfaceDeclaration` or `TSTypeAliasDeclaration` such as: diff --git a/docs/rules/check-template-names.md b/docs/rules/check-template-names.md index 996895d0..f7ce1ca0 100644 --- a/docs/rules/check-template-names.md +++ b/docs/rules/check-template-names.md @@ -3,7 +3,7 @@ # check-template-names Checks that any `@template` names are actually used in the connected -`@typedef` or type alias. +`@typedef`, `@callback`, `@function` or type structure. Currently checks `ClassDeclaration`, `FunctionDeclaration`, `TSInterfaceDeclaration` or `TSTypeAliasDeclaration` such as: @@ -190,6 +190,30 @@ export default class { add: (x: NumType, y: NumType) => NumType; } // Message: @template D not in use + +/** + * @template D + * @template V + * @callback + * @returns {[X, Y | undefined]} + */ +// Message: @template D not in use + +/** + * @template D + * @template V + * @function + * @returns {[X, Y | undefined]} + */ +// Message: @template D not in use + +/** + * @template D + * @template V + * @function + * @param {[X, Y | undefined]} someParam + */ +// Message: @template D not in use ```` @@ -327,5 +351,26 @@ export default class { */ export function mapGroupBy(array, callbackFn) { } + +/** + * @template D + * @template V + * @callback + * @returns {[D, V | undefined]} + */ + +/** + * @template D + * @template V + * @function + * @returns {[D, V | undefined]} + */ + +/** + * @template D + * @template V + * @function + * @param {[D, V | undefined]} someParam + */ ```` diff --git a/src/rules/checkTemplateNames.js b/src/rules/checkTemplateNames.js index 28b2c180..df38316b 100644 --- a/src/rules/checkTemplateNames.js +++ b/src/rules/checkTemplateNames.js @@ -43,6 +43,36 @@ export default iterateJsdoc(({ }); }; + const checkParamsAndReturnsTags = () => { + const paramName = /** @type {string} */ (utils.getPreferredTagName({ + tagName: 'param', + })); + const paramTags = utils.getTags(paramName); + for (const paramTag of paramTags) { + checkForUsedTypes(paramTag.type); + } + + const returnsName = /** @type {string} */ (utils.getPreferredTagName({ + tagName: 'returns', + })); + const returnsTags = utils.getTags(returnsName); + for (const returnsTag of returnsTags) { + checkForUsedTypes(returnsTag.type); + } + }; + + const checkTemplateTags = () => { + for (const tag of templateTags) { + const {name} = tag; + const names = name.split(/,\s*/); + for (const name of names) { + if (!usedNames.has(name)) { + report(`@template ${name} not in use`, null, tag); + } + } + } + }; + /** * @param {import('@typescript-eslint/types').TSESTree.FunctionDeclaration| * import('@typescript-eslint/types').TSESTree.ClassDeclaration| @@ -57,31 +87,10 @@ export default iterateJsdoc(({ usedNames.add(name); } if (checkParamsAndReturns) { - const paramName = /** @type {string} */ (utils.getPreferredTagName({ - tagName: 'param', - })); - const paramTags = utils.getTags(paramName); - for (const paramTag of paramTags) { - checkForUsedTypes(paramTag.type); - } - - const returnsName = /** @type {string} */ (utils.getPreferredTagName({ - tagName: 'returns', - })); - const returnsTags = utils.getTags(returnsName); - for (const returnsTag of returnsTags) { - checkForUsedTypes(returnsTag.type); - } - } - for (const tag of templateTags) { - const {name} = tag; - const names = name.split(/,\s*/); - for (const name of names) { - if (!usedNames.has(name)) { - report(`@template ${name} not in use`, null, tag); - } - } + checkParamsAndReturnsTags(); } + + checkTemplateTags(); }; const handleTypeAliases = () => { @@ -116,6 +125,14 @@ export default iterateJsdoc(({ } }; + const callbackTags = utils.getTags('callback'); + const functionTags = utils.getTags('function'); + if (callbackTags.length || functionTags.length) { + checkParamsAndReturnsTags(); + checkTemplateTags(); + return; + } + const typedefTags = utils.getTags('typedef'); if (!typedefTags.length || typedefTags.length >= 2) { handleTypeAliases(); diff --git a/test/rules/assertions/checkTemplateNames.js b/test/rules/assertions/checkTemplateNames.js index 639448ad..98dc1827 100644 --- a/test/rules/assertions/checkTemplateNames.js +++ b/test/rules/assertions/checkTemplateNames.js @@ -402,6 +402,66 @@ export default { parser: typescriptEslintParser }, }, + { + code: ` + /** + * @template D + * @template V + * @callback + * @returns {[X, Y | undefined]} + */ + `, + errors: [ + { + line: 3, + message: '@template D not in use', + }, + { + line: 4, + message: '@template V not in use', + }, + ], + }, + { + code: ` + /** + * @template D + * @template V + * @function + * @returns {[X, Y | undefined]} + */ + `, + errors: [ + { + line: 3, + message: '@template D not in use', + }, + { + line: 4, + message: '@template V not in use', + }, + ], + }, + { + code: ` + /** + * @template D + * @template V + * @function + * @param {[X, Y | undefined]} someParam + */ + `, + errors: [ + { + line: 3, + message: '@template D not in use', + }, + { + line: 4, + message: '@template V not in use', + }, + ], + }, ], valid: [ { @@ -624,5 +684,35 @@ export default { parser: typescriptEslintParser }, }, + { + code: ` + /** + * @template D + * @template V + * @callback + * @returns {[D, V | undefined]} + */ + `, + }, + { + code: ` + /** + * @template D + * @template V + * @function + * @returns {[D, V | undefined]} + */ + `, + }, + { + code: ` + /** + * @template D + * @template V + * @function + * @param {[D, V | undefined]} someParam + */ + `, + }, ], };