Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2092,6 +2092,33 @@ function quux ({a, b}) {

}

/**
* @param foo
* @param foo.a
* @param foo.b
*/
function quux ({"a": A, b}) {

}

/**
* @param foo
* @param foo."a"
* @param foo.b
*/
function quux ({a: A, b}) {

}

/**
* @param foo
* @param foo."a-b"
* @param foo.b
*/
function quux ({"a-b": A, b}) {

}

/**
* @param foo
* @param foo.bar
Expand Down
8 changes: 8 additions & 0 deletions src/jsdocUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ const getFunctionParameterNames = (functionNode : Object) : Array<T> => {
if (param.key.type === 'Identifier') {
return param.key.name;
}

// The key of an object could also be a string or number
/* istanbul ignore else */
if (param.key.type === 'Literal') {
return param.key.raw ||
// istanbul ignore next -- `raw` may not be present in all parsers
param.key.value;
}
}

if (param.type === 'ArrayPattern' || param.left?.type === 'ArrayPattern') {
Expand Down
25 changes: 23 additions & 2 deletions src/rules/checkParamNames.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
import iterateJsdoc from '../iterateJsdoc';

/**
* Since path segments may be unquoted (if matching a reserved word,
* identifier or numeric literal) or single or double quoted, in either
* the `@param` or in source, we need to strip the quotes to give a fair
* comparison.
*
* @param {string} str
* @returns {string}
*/
const dropPathSegmentQuotes = (str) => {
return str.replace(/\.(['"])(.*)\1/gu, '.$2');
};

const comparePaths = (name) => {
return (otherPathName) => {
return otherPathName === name ||
dropPathSegmentQuotes(otherPathName) === dropPathSegmentQuotes(name);
};
};

const validateParameterNames = (
targetTagName : string,
allowExtraTrailingParamDocs: boolean,
Expand Down Expand Up @@ -76,8 +96,9 @@ const validateParameterNames = (
});

const missingProperties = [];

expectedNames.forEach((name, idx) => {
if (!actualNames.includes(name)) {
if (!actualNames.some(comparePaths(name))) {
if (!checkRestProperty && rests[idx]) {
return;
}
Expand All @@ -89,7 +110,7 @@ const validateParameterNames = (
if (!hasPropertyRest || checkRestProperty) {
actualNames.forEach((name, idx) => {
const match = name.startsWith(tag.name.trim() + '.');
if (match && !expectedNames.includes(name) && name !== tag.name) {
if (match && !expectedNames.some(comparePaths(name)) && name !== tag.name) {
extraProperties.push([name, paramTags[idx][1]]);
}
});
Expand Down
51 changes: 46 additions & 5 deletions test/rules/assertions/checkParamNames.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ export default {
errors: [
{
line: 3,
message: '@param path declaration ("Foo.Bar") appears before any real parameter.',
message:
'@param path declaration ("Foo.Bar") appears before any real parameter.',
},
],
},
Expand All @@ -90,7 +91,8 @@ export default {
errors: [
{
line: 4,
message: '@param path declaration ("Foo.Bar") root node name ("Foo") does not match previous real parameter name ("foo").',
message:
'@param path declaration ("Foo.Bar") root node name ("Foo") does not match previous real parameter name ("foo").',
},
],
},
Expand All @@ -108,7 +110,8 @@ export default {
errors: [
{
line: 4,
message: '@param path declaration ("employees[].name") appears before any real parameter.',
message:
'@param path declaration ("employees[].name") appears before any real parameter.',
},
],
},
Expand Down Expand Up @@ -175,7 +178,8 @@ export default {
errors: [
{
line: 4,
message: '@param "bar" does not match an existing function parameter.',
message:
'@param "bar" does not match an existing function parameter.',
},
],
},
Expand Down Expand Up @@ -661,7 +665,8 @@ export default {
errors: [
{
line: 4,
message: 'Expected @param names to be "error, cde". Got "error, code".',
message:
'Expected @param names to be "error, cde". Got "error, code".',
},
],
},
Expand Down Expand Up @@ -925,6 +930,42 @@ export default {
}
`,
},
{
code: `
/**
* @param foo
* @param foo.a
* @param foo.b
*/
function quux ({"a": A, b}) {

}
`,
},
{
code: `
/**
* @param foo
* @param foo."a"
* @param foo.b
*/
function quux ({a: A, b}) {

}
`,
},
{
code: `
/**
* @param foo
* @param foo."a-b"
* @param foo.b
*/
function quux ({"a-b": A, b}) {

}
`,
},
{
code: `
/**
Expand Down