diff --git a/.github/workflows/feature.yaml b/.github/workflows/feature.yaml index 85dd75ae0..db380e999 100644 --- a/.github/workflows/feature.yaml +++ b/.github/workflows/feature.yaml @@ -3,7 +3,7 @@ jobs: runs-on: ubuntu-latest name: Lint steps: - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: latest - name: setup repository @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest name: Test (Node.js ${{ matrix.node_js_version }}) steps: - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: latest - name: setup repository @@ -46,7 +46,7 @@ jobs: runs-on: ubuntu-latest name: Build steps: - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: latest - name: setup repository diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index da2a9412f..27d56a17b 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -4,7 +4,7 @@ jobs: environment: release name: Release steps: - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: latest - name: setup repository diff --git a/src/jsdocUtils.js b/src/jsdocUtils.js index 4b9c67280..f9272c5f5 100644 --- a/src/jsdocUtils.js +++ b/src/jsdocUtils.js @@ -436,7 +436,10 @@ const getFunctionParameterNames = ( name: /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */ ( /** @type {import('@typescript-eslint/types').TSESTree.RestElement} */ ( param - ).argument).name, + // @ts-expect-error Ok + ).argument).name ?? param?.argument?.elements?.map(({name}) => { + return name; + }), restElement: true, }; } diff --git a/src/rules/checkParamNames.js b/src/rules/checkParamNames.js index b1b8cd9ec..54ac72b9c 100644 --- a/src/rules/checkParamNames.js +++ b/src/rules/checkParamNames.js @@ -87,6 +87,24 @@ const validateParameterNames = ( return true; } + if ( + typeof functionParameterName === 'object' && + 'name' in functionParameterName && + Array.isArray(functionParameterName.name) + ) { + const actualName = tag.name.trim(); + const expectedName = functionParameterName.name[index]; + if (actualName === expectedName) { + thisOffset--; + return false; + } + report( + `Expected @${targetTagName} name to be "${expectedName}". Got "${actualName}".`, + null, + tag, + ); + return true; + } if (Array.isArray(functionParameterName)) { if (!checkDestructured) { @@ -236,6 +254,7 @@ const validateParameterNames = ( ]) => { return name.trim(); }); + const expectedNames = functionParameterNames.map((item, idx) => { if (/** * @type {[string|undefined, (import('../jsdocUtils.js').FlattendRootInfo & { @@ -260,7 +279,15 @@ const validateParameterNames = ( } report( - `Expected @${targetTagName} names to be "${expectedNames.join(', ')}". Got "${actualNames.join(', ')}".`, + `Expected @${targetTagName} names to be "${ + expectedNames.map((expectedName) => { + return typeof expectedName === 'object' && + 'name' in expectedName && + expectedName.restElement + ? '...' + expectedName.name + : expectedName; + }).join(', ') + }". Got "${actualNames.join(', ')}".`, null, tag, ); @@ -352,6 +379,7 @@ export default iterateJsdoc(({ } const functionParameterNames = utils.getFunctionParameterNames(useDefaultObjectProperties); + const targetTagName = /** @type {string} */ (utils.getPreferredTagName({ tagName: 'param', })); diff --git a/test/rules/assertions/checkParamNames.js b/test/rules/assertions/checkParamNames.js index 851f5df59..7804b499b 100644 --- a/test/rules/assertions/checkParamNames.js +++ b/test/rules/assertions/checkParamNames.js @@ -1276,7 +1276,46 @@ export default { parser: typescriptEslintParser, sourceType: 'module', }, - } + }, + { + code: ` + interface A { + /** + * @param params Values for the placeholders + */ + getText(key: string, ...params: string[]): string + } + `, + errors: [ + { + line: 4, + message: 'Expected @param names to be "key, ...params". Got "params".', + }, + ], + languageOptions: { + parser: typescriptEslintParser, + }, + }, + { + code: ` + /** + * @param arg Arg + */ + export function fn(...[type, arg]: FnArgs): void { + // ... + } + `, + errors: [ + { + line: 3, + message: 'Expected @param name to be "type". Got "arg".', + }, + ], + languageOptions: { + parser: typescriptEslintParser, + sourceType: 'module', + }, + }, ], valid: [ { @@ -1961,5 +2000,20 @@ export default { }, ], }, + { + code: ` + /** + * @param type Type + * @param arg Arg + */ + export function fn(...[type, arg]: FnArgs): void { + // ... + } + `, + languageOptions: { + parser: typescriptEslintParser, + sourceType: 'module', + }, + }, ], };