From 909de737f115af69a5fd10ec64810a0f42f834e0 Mon Sep 17 00:00:00 2001 From: Brett Zamir Date: Wed, 25 Sep 2024 18:39:53 +0800 Subject: [PATCH] fix(`require-jsdoc`): allow `TSTypeAliasDeclaration` to be detected for export; fixes #1319 --- docs/rules/require-jsdoc.md | 8 ++++ src/exportParser.js | 18 ++++----- test/rules/assertions/requireJsdoc.js | 53 ++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/docs/rules/require-jsdoc.md b/docs/rules/require-jsdoc.md index 411f596f..627b97db 100644 --- a/docs/rules/require-jsdoc.md +++ b/docs/rules/require-jsdoc.md @@ -1020,6 +1020,14 @@ export type LoginOptions = CmdOptions<{ }>; // "jsdoc/require-jsdoc": ["error"|"warn", {"publicOnly":{"ancestorsOnly":true},"contexts":["TSTypeAliasDeclaration","TSInterfaceDeclaration","TSMethodSignature","TSPropertySignature"]}] // Message: Missing JSDoc comment. + +type Props = { + variant: string +} + +export type { Props as ComponentProps }; +// "jsdoc/require-jsdoc": ["error"|"warn", {"publicOnly":{"esm":true},"require":{"FunctionDeclaration":true,"FunctionExpression":true,"ArrowFunctionExpression":true,"ClassDeclaration":true,"ClassExpression":true,"MethodDefinition":true},"contexts":["VariableDeclaration","TSTypeAliasDeclaration","TSPropertySignature","TSInterfaceDeclaration","TSMethodSignature","TSEnumDeclaration"],"enableFixer":true}] +// Message: Missing JSDoc comment. ```` diff --git a/src/exportParser.js b/src/exportParser.js index b9dff88c..85957e54 100644 --- a/src/exportParser.js +++ b/src/exportParser.js @@ -14,7 +14,7 @@ const debug = debugModule('requireExportJsdoc'); /** * @typedef {{ * type?: string, - * value?: ValueObject|import('eslint').Rule.Node, + * value?: ValueObject|import('eslint').Rule.Node|import('@typescript-eslint/types').TSESTree.Node, * props: { * [key: string]: CreatedNode|null, * }, @@ -93,7 +93,7 @@ const getIdentifier = function (node, globals, scope, opts) { * @callback CreateSymbol * @param {import('eslint').Rule.Node|null} node * @param {CreatedNode} globals - * @param {import('eslint').Rule.Node|null} value + * @param {import('eslint').Rule.Node|import('@typescript-eslint/types').TSESTree.Node|null} value * @param {CreatedNode} [scope] * @param {boolean|SymbolOptions} [isGlobal] * @returns {CreatedNode|null} @@ -112,7 +112,7 @@ let createSymbol; // eslint-disable-line prefer-const /** * - * @param {import('eslint').Rule.Node} node + * @param {import('eslint').Rule.Node|import('@typescript-eslint/types').TSESTree.Node} node * @param {CreatedNode} globals * @param {CreatedNode} scope * @param {SymbolOptions} [opt] @@ -177,13 +177,10 @@ const getSymbol = function (node, globals, scope, opt) { ); } - /* c8 ignore next 7 -- No longer needed? */ - // @ts-expect-error TS OK + /* c8 ignore next 4 -- No longer needed? */ case 'TSTypeAliasDeclaration': - // @ts-expect-error TS OK // Fallthrough case 'TSEnumDeclaration': - // @ts-expect-error TS OK case 'TSInterfaceDeclaration': case 'ClassDeclaration': case 'FunctionExpression': case 'FunctionDeclaration': @@ -473,7 +470,7 @@ const initVariables = function (node, globals, opts) { /** * Populates variable maps using AST - * @param {import('eslint').Rule.Node} node + * @param {import('eslint').Rule.Node|import('@typescript-eslint/types').TSESTree.Node} node * @param {CreatedNode} globals * @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opt * @param {true} [isExport] @@ -543,6 +540,7 @@ const mapVariables = function (node, globals, opt, isExport) { break; } + case 'TSTypeAliasDeclaration': case 'FunctionDeclaration': { /* c8 ignore next 10 */ if (/** @type {import('estree').Identifier} */ (node.id).type === 'Identifier') { @@ -655,9 +653,9 @@ const mapVariables = function (node, globals, opt, isExport) { * * @param {import('eslint').Rule.Node} node * @param {CreatedNode|ValueObject|string|undefined| - * import('eslint').Rule.Node} block + * import('eslint').Rule.Node|import('@typescript-eslint/types').TSESTree.Node} block * @param {(CreatedNode|ValueObject|string| - * import('eslint').Rule.Node)[]} [cache] + * import('eslint').Rule.Node|import('@typescript-eslint/types').TSESTree.Node)[]} [cache] * @returns {boolean} */ const findNode = function (node, block, cache) { diff --git a/test/rules/assertions/requireJsdoc.js b/test/rules/assertions/requireJsdoc.js index e8ab9b0f..9991abf9 100644 --- a/test/rules/assertions/requireJsdoc.js +++ b/test/rules/assertions/requireJsdoc.js @@ -4196,6 +4196,57 @@ function quux (foo) { parser: typescriptEslintParser, }, }, + { + code: ` + type Props = { + variant: string + } + + export type { Props as ComponentProps }; + `, + errors: [ + { + line: 2, + message: 'Missing JSDoc comment.', + }, + ], + languageOptions: { + parser: typescriptEslintParser, + }, + options: [ + { + publicOnly: { esm: true }, + require: { + FunctionDeclaration: true, + FunctionExpression: true, + ArrowFunctionExpression: true, + ClassDeclaration: true, + ClassExpression: true, + MethodDefinition: true, + }, + contexts: [ + "VariableDeclaration", + "TSTypeAliasDeclaration", + // Encourage documenting React prop types + "TSPropertySignature", + "TSInterfaceDeclaration", + "TSMethodSignature", + "TSEnumDeclaration" + ], + enableFixer: true, + }, + ], + output: ` + /** + * + */ + type Props = { + variant: string + } + + export type { Props as ComponentProps }; + `, + }, ], valid: [ { @@ -6312,6 +6363,6 @@ function quux (foo) { } } ], - } + }, ], };