Skip to content

Commit e5da5bb

Browse files
committedNov 2, 2022
feat(check-types): add skipRootChecking option to preferredTypes setting; fixes #863
1 parent 691a414 commit e5da5bb

File tree

4 files changed

+87
-11
lines changed

4 files changed

+87
-11
lines changed
 

‎.README/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ The format of the configuration is as follows:
391391
- a string type to be preferred in its place (and which `fix` mode
392392
can replace)
393393
- `false` (for forbidding the type)
394+
- an optional key `skipRootChecking` (for `check-types`) to allow for this
395+
type in the context of a root (i.e., a parent object of some child type)
394396

395397
Note that the preferred types indicated as targets in
396398
`settings.jsdoc.preferredTypes` map will be assumed to be defined by

‎README.md

+18
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,8 @@ The format of the configuration is as follows:
480480
- a string type to be preferred in its place (and which `fix` mode
481481
can replace)
482482
- `false` (for forbidding the type)
483+
- an optional key `skipRootChecking` (for `check-types`) to allow for this
484+
type in the context of a root (i.e., a parent object of some child type)
483485

484486
Note that the preferred types indicated as targets in
485487
`settings.jsdoc.preferredTypes` map will be assumed to be defined by
@@ -5737,6 +5739,15 @@ function abc(param) {
57375739
return 'abc';
57385740
}
57395741
// Message: Invalid JSDoc @param "param" type "Object"; prefer: "object".
5742+
5743+
/**
5744+
* @param {object} root
5745+
* @param {number} root.a
5746+
* @param {object} b
5747+
*/
5748+
function a () {}
5749+
// Settings: {"jsdoc":{"preferredTypes":{"object":{"skipRootChecking":true}}}}
5750+
// Message: Invalid JSDoc @param "b" type "object".
57405751
````
57415752

57425753
The following patterns are not considered problems:
@@ -6055,6 +6066,13 @@ function foo(spec) {
60556066
}
60566067

60576068
foo()
6069+
6070+
/**
6071+
* @param {object} root
6072+
* @param {number} root.a
6073+
*/
6074+
function a () {}
6075+
// Settings: {"jsdoc":{"preferredTypes":{"object":{"message":"Won't see this message","skipRootChecking":true}}}}
60586076
````
60596077

60606078

‎src/rules/checkTypes.js

+23-11
Original file line numberDiff line numberDiff line change
@@ -237,13 +237,15 @@ export default iterateJsdoc(({
237237
* @param {string} type
238238
* @param {string} value
239239
* @param {string} tagName
240+
* @param {string} nameInTag
241+
* @param {number} idx
240242
* @param {string} property
241243
* @param {import('jsdoc-type-pratt-parser/dist/src/index.d.ts').NonTerminalResult} node
242244
* @param {import('jsdoc-type-pratt-parser/dist/src/index.d.ts').NonTerminalResult} parentNode
243245
* @param {string[]} invalidTypes
244246
* @returns {void}
245247
*/
246-
const getInvalidTypes = (type, value, tagName, property, node, parentNode, invalidTypes) => {
248+
const getInvalidTypes = (type, value, tagName, nameInTag, idx, property, node, parentNode, invalidTypes) => {
247249
let typeNodeName = type === 'JsdocTypeAny' ? '*' : value;
248250

249251
const [
@@ -267,13 +269,17 @@ export default iterateJsdoc(({
267269
invalidTypes.push([
268270
typeNodeName, preferred,
269271
]);
270-
} else if (typeof preferredSetting === 'object') {
271-
preferred = preferredSetting?.replacement;
272-
invalidTypes.push([
273-
typeNodeName,
274-
preferred,
275-
preferredSetting?.message,
276-
]);
272+
} else if (preferredSetting && typeof preferredSetting === 'object') {
273+
const nextItem = preferredSetting.skipRootChecking && jsdocTagsWithPossibleType[idx + 1];
274+
275+
if (!nextItem || !nextItem.name.startsWith(`${nameInTag}.`)) {
276+
preferred = preferredSetting.replacement;
277+
invalidTypes.push([
278+
typeNodeName,
279+
preferred,
280+
preferredSetting.message,
281+
]);
282+
}
277283
} else {
278284
utils.reportSettings(
279285
'Invalid `settings.jsdoc.preferredTypes`. Values must be falsy, a string, or an object.',
@@ -306,7 +312,10 @@ export default iterateJsdoc(({
306312
}
307313
};
308314

309-
for (const jsdocTag of jsdocTagsWithPossibleType) {
315+
for (const [
316+
idx,
317+
jsdocTag,
318+
] of jsdocTagsWithPossibleType.entries()) {
310319
const invalidTypes = [];
311320
let typeAst;
312321

@@ -316,7 +325,10 @@ export default iterateJsdoc(({
316325
continue;
317326
}
318327

319-
const tagName = jsdocTag.tag;
328+
const {
329+
tag: tagName,
330+
name: nameInTag,
331+
} = jsdocTag;
320332

321333
traverse(typeAst, (node, parentNode, property) => {
322334
const {
@@ -329,7 +341,7 @@ export default iterateJsdoc(({
329341
return;
330342
}
331343

332-
getInvalidTypes(type, value, tagName, property, node, parentNode, invalidTypes);
344+
getInvalidTypes(type, value, tagName, nameInTag, idx, property, node, parentNode, invalidTypes);
333345
});
334346

335347
if (invalidTypes.length) {

‎test/rules/assertions/checkTypes.js

+44
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,31 @@ export default {
23962396
}
23972397
`,
23982398
},
2399+
{
2400+
code: `
2401+
/**
2402+
* @param {object} root
2403+
* @param {number} root.a
2404+
* @param {object} b
2405+
*/
2406+
function a () {}
2407+
`,
2408+
errors: [
2409+
{
2410+
line: 5,
2411+
message: 'Invalid JSDoc @param "b" type "object".',
2412+
},
2413+
],
2414+
settings: {
2415+
jsdoc: {
2416+
preferredTypes: {
2417+
object: {
2418+
skipRootChecking: true,
2419+
},
2420+
},
2421+
},
2422+
},
2423+
},
23992424
],
24002425
valid: [
24012426
{
@@ -3057,5 +3082,24 @@ export default {
30573082
foo()
30583083
`,
30593084
},
3085+
{
3086+
code: `
3087+
/**
3088+
* @param {object} root
3089+
* @param {number} root.a
3090+
*/
3091+
function a () {}
3092+
`,
3093+
settings: {
3094+
jsdoc: {
3095+
preferredTypes: {
3096+
object: {
3097+
message: 'Won\'t see this message',
3098+
skipRootChecking: true,
3099+
},
3100+
},
3101+
},
3102+
},
3103+
},
30603104
],
30613105
};

0 commit comments

Comments
 (0)
Please sign in to comment.