Skip to content

Commit

Permalink
feat(check-types): check settings.jsdoc.structuredTags for an arr…
Browse files Browse the repository at this point in the history
…ay of permissible types, reporting if not present; fixes #695
  • Loading branch information
brettz9 committed Feb 23, 2021
1 parent 1cfdeb4 commit 9dad3e0
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 5 deletions.
1 change: 1 addition & 0 deletions .README/README.md
Expand Up @@ -428,6 +428,7 @@ values are objects with the following optional properties:
might use this with `@throws` to suggest that only free form text
is being input or with `@augments` (for jsdoc mode) to disallow
Closure-style bracketed usage along with a required namepath.
- (An array of strings) - A list of permissible types.
- `required` - Array of one of the following (defaults to an empty array,
meaning none are required):
- One or both of the following strings (if both are included, then both
Expand Down
3 changes: 2 additions & 1 deletion .README/rules/check-types.md
Expand Up @@ -122,7 +122,8 @@ String | **string** | **string** | `("test") instanceof String` -> **`false`**

If you define your own tags and don't wish their bracketed portions checked
for types, you can use `settings.jsdoc.structuredTags` with a tag `type` of
`false`.
`false`. If you set their `type` to an array, only those values will be
permitted.

|||
|---|---|
Expand Down
20 changes: 19 additions & 1 deletion README.md
Expand Up @@ -497,6 +497,7 @@ values are objects with the following optional properties:
might use this with `@throws` to suggest that only free form text
is being input or with `@augments` (for jsdoc mode) to disallow
Closure-style bracketed usage along with a required namepath.
- (An array of strings) - A list of permissible types.
- `required` - Array of one of the following (defaults to an empty array,
meaning none are required):
- One or both of the following strings (if both are included, then both
Expand Down Expand Up @@ -4449,7 +4450,8 @@ String | **string** | **string** | `("test") instanceof String` -> **`false`**

If you define your own tags and don't wish their bracketed portions checked
for types, you can use `settings.jsdoc.structuredTags` with a tag `type` of
`false`.
`false`. If you set their `type` to an array, only those values will be
permitted.

|||
|---|---|
Expand Down Expand Up @@ -5039,6 +5041,12 @@ function b () {}
*/
// Settings: {"jsdoc":{"structuredTags":{"aCustomTag":{"type":true}}}}
// Message: Invalid JSDoc @aCustomTag "foo" type "Number"; prefer: "number".

/**
* @aCustomTag {Number} foo
*/
// Settings: {"jsdoc":{"structuredTags":{"aCustomTag":{"type":["otherType","anotherType"]}}}}
// Message: Invalid JSDoc @aCustomTag "foo" type "Number"; prefer: ["otherType","anotherType"].
````

The following patterns are not considered problems:
Expand Down Expand Up @@ -5308,6 +5316,16 @@ function b () {}
* @aCustomTag {Number} foo
*/
// Settings: {"jsdoc":{"structuredTags":{"aCustomTag":{"type":false}}}}

/**
* @aCustomTag {otherType} foo
*/
// Settings: {"jsdoc":{"structuredTags":{"aCustomTag":{"type":["otherType","anotherType"]}}}}

/**
* @aCustomTag {anotherType|otherType} foo
*/
// Settings: {"jsdoc":{"structuredTags":{"aCustomTag":{"type":["otherType","anotherType"]}}}}
````


Expand Down
15 changes: 12 additions & 3 deletions src/rules/checkTypes.js
Expand Up @@ -71,7 +71,7 @@ export default iterateJsdoc(({
return utils.tagMightHaveTypePosition(tag.tag);
});

const {preferredTypes, mode} = settings;
const {preferredTypes, structuredTags, mode} = settings;
const {
noDefaults,
unifyParentAndChildTypeChecks,
Expand Down Expand Up @@ -138,6 +138,7 @@ export default iterateJsdoc(({
} catch {
return;
}
const tagName = jsdocTag.tag;

traverse(typeAst, (node, parentName, parentNode) => {
const {type, name} = node;
Expand All @@ -149,6 +150,7 @@ export default iterateJsdoc(({
const [hasMatchingPreferredType, typeName, isGenericMatch] = getPreferredTypeInfo(type, nodeName, parentName, parentNode);

let preferred;
let types;
if (hasMatchingPreferredType) {
const preferredSetting = preferredTypes[typeName];
nodeName = typeName === '[]' ? typeName : nodeName;
Expand All @@ -172,6 +174,14 @@ export default iterateJsdoc(({

return;
}
} else if (Object.entries(structuredTags).some(([tag, {type: typs}]) => {
types = typs;

return tag === tagName &&
Array.isArray(types) &&
!types.includes(nodeName);
})) {
invalidTypes.push([nodeName, types]);
} else if (!noDefaults && type === 'NAME') {
for (const strictNativeType of strictNativeTypes) {
if (strictNativeType === 'object' && mode === 'typescript') {
Expand Down Expand Up @@ -199,7 +209,6 @@ export default iterateJsdoc(({
if (invalidTypes.length) {
const fixedType = publish(typeAst);

const tagName = jsdocTag.tag;
invalidTypes.forEach(([badType, preferredType = '', message]) => {
const fix = (fixer) => {
return fixer.replaceText(
Expand All @@ -223,7 +232,7 @@ export default iterateJsdoc(({
message ||
`Invalid JSDoc @${tagName}${tagValue} type "${badType}"` +
(preferredType ? '; ' : '.') +
(preferredType ? `prefer: "${preferredType}".` : ''),
(preferredType ? `prefer: ${JSON.stringify(preferredType)}.` : ''),
preferredType ? fix : null,
jsdocTag,
message ? {
Expand Down
54 changes: 54 additions & 0 deletions test/rules/assertions/checkTypes.js
Expand Up @@ -1989,6 +1989,28 @@ export default {
},
},
},
{
code: `
/**
* @aCustomTag {Number} foo
*/
`,
errors: [
{
line: 3,
message: 'Invalid JSDoc @aCustomTag "foo" type "Number"; prefer: ["otherType","anotherType"].',
},
],
settings: {
jsdoc: {
structuredTags: {
aCustomTag: {
type: ['otherType', 'anotherType'],
},
},
},
},
},
],
valid: [
{
Expand Down Expand Up @@ -2526,5 +2548,37 @@ export default {
},
},
},
{
code: `
/**
* @aCustomTag {otherType} foo
*/
`,
settings: {
jsdoc: {
structuredTags: {
aCustomTag: {
type: ['otherType', 'anotherType'],
},
},
},
},
},
{
code: `
/**
* @aCustomTag {anotherType|otherType} foo
*/
`,
settings: {
jsdoc: {
structuredTags: {
aCustomTag: {
type: ['otherType', 'anotherType'],
},
},
},
},
},
],
};

0 comments on commit 9dad3e0

Please sign in to comment.