eslint-plugin-jsdoc 48.8.2 → 48.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -71,23 +71,36 @@ var _default = exports.default = (0, _iterateJsdoc.default)(({
71
71
  handleTypeAliases();
72
72
  return;
73
73
  }
74
- const potentialType = typedefTags[0].type;
75
- let parsedType;
76
- try {
77
- parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialType) : (0, _jsdoccomment.parse)( /** @type {string} */potentialType, mode);
78
- } catch {
79
- // Todo: Should handle types in @prop/erty
80
- return;
81
- }
82
- (0, _jsdoccomment.traverse)(parsedType, nde => {
83
- const {
84
- type,
85
- value
86
- } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
87
- if (type === 'JsdocTypeName' && /^[A-Z]$/.test(value)) {
88
- usedNames.add(value);
74
+
75
+ /**
76
+ * @param {string} potentialType
77
+ */
78
+ const checkForUsedTypes = potentialType => {
79
+ let parsedType;
80
+ try {
81
+ parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialType) : (0, _jsdoccomment.parse)( /** @type {string} */potentialType, mode);
82
+ } catch {
83
+ return;
89
84
  }
85
+ (0, _jsdoccomment.traverse)(parsedType, nde => {
86
+ const {
87
+ type,
88
+ value
89
+ } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
90
+ if (type === 'JsdocTypeName' && /^[A-Z]$/.test(value)) {
91
+ usedNames.add(value);
92
+ }
93
+ });
94
+ };
95
+ const potentialTypedefType = typedefTags[0].type;
96
+ checkForUsedTypes(potentialTypedefType);
97
+ const tagName = /** @type {string} */utils.getPreferredTagName({
98
+ tagName: 'property'
90
99
  });
100
+ const propertyTags = utils.getTags(tagName);
101
+ for (const propertyTag of propertyTags) {
102
+ checkForUsedTypes(propertyTag.type);
103
+ }
91
104
  for (const tag of templateTags) {
92
105
  const {
93
106
  name
@@ -1 +1 @@
1
- {"version":3,"file":"checkTemplateNames.cjs","names":["_jsdoccomment","require","_iterateJsdoc","_interopRequireDefault","e","__esModule","default","_default","exports","iterateJsdoc","context","utils","node","settings","report","mode","templateTags","getTags","usedNames","Set","checkParameters","aliasDeclaration","params","typeParameters","name","add","tag","names","split","has","handleTypeAliases","_nde$declaration","nde","type","declaration","typedefTags","length","potentialType","parsedType","tryParseType","parseType","traverse","value","test","iterateAllJsdocs","meta","docs","description","url","schema","module"],"sources":["../../src/rules/checkTemplateNames.js"],"sourcesContent":["import {\n parse as parseType,\n traverse,\n tryParse as tryParseType,\n} from '@es-joy/jsdoccomment';\nimport iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n utils,\n node,\n settings,\n report,\n}) => {\n const {\n mode\n } = settings;\n\n const templateTags = utils.getTags('template');\n\n const usedNames = new Set();\n /**\n * @param {import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration\n */\n const checkParameters = (aliasDeclaration) => {\n /* c8 ignore next -- Guard */\n const {params} = aliasDeclaration.typeParameters ?? {params: []};\n for (const {name: {name}} of params) {\n usedNames.add(name);\n }\n for (const tag of templateTags) {\n const {name} = tag;\n const names = name.split(/,\\s*/);\n for (const name of names) {\n if (!usedNames.has(name)) {\n report(`@template ${name} not in use`, null, tag);\n }\n }\n }\n };\n\n const handleTypeAliases = () => {\n const nde = /** @type {import('@typescript-eslint/types').TSESTree.Node} */ (\n node\n );\n if (!nde) {\n return;\n }\n switch (nde.type) {\n case 'ExportNamedDeclaration':\n if (nde.declaration?.type === 'TSTypeAliasDeclaration') {\n checkParameters(nde.declaration);\n }\n break;\n case 'TSTypeAliasDeclaration':\n checkParameters(nde);\n break;\n }\n };\n\n const typedefTags = utils.getTags('typedef');\n if (!typedefTags.length || typedefTags.length >= 2) {\n handleTypeAliases();\n return;\n }\n\n const potentialType = typedefTags[0].type;\n\n let parsedType;\n try {\n parsedType = mode === 'permissive' ?\n tryParseType(/** @type {string} */ (potentialType)) :\n parseType(/** @type {string} */ (potentialType), mode)\n } catch {\n // Todo: Should handle types in @prop/erty\n return;\n }\n\n traverse(parsedType, (nde) => {\n const {\n type,\n value,\n } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);\n if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {\n usedNames.add(value);\n }\n });\n\n for (const tag of templateTags) {\n const {name} = tag;\n const names = name.split(/,\\s*/);\n for (const name of names) {\n if (!usedNames.has(name)) {\n report(`@template ${name} not in use`, null, tag);\n }\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Checks that any `@template` names are actually used in the connected `@typedef` or type alias.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-template.md#repos-sticky-header',\n },\n schema: [],\n type: 'suggestion',\n },\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"checkTemplateNames.cjs","names":["_jsdoccomment","require","_iterateJsdoc","_interopRequireDefault","e","__esModule","default","_default","exports","iterateJsdoc","context","utils","node","settings","report","mode","templateTags","getTags","usedNames","Set","checkParameters","aliasDeclaration","params","typeParameters","name","add","tag","names","split","has","handleTypeAliases","_nde$declaration","nde","type","declaration","typedefTags","length","checkForUsedTypes","potentialType","parsedType","tryParseType","parseType","traverse","value","test","potentialTypedefType","tagName","getPreferredTagName","propertyTags","propertyTag","iterateAllJsdocs","meta","docs","description","url","schema","module"],"sources":["../../src/rules/checkTemplateNames.js"],"sourcesContent":["import {\n parse as parseType,\n traverse,\n tryParse as tryParseType,\n} from '@es-joy/jsdoccomment';\nimport iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n utils,\n node,\n settings,\n report,\n}) => {\n const {\n mode\n } = settings;\n\n const templateTags = utils.getTags('template');\n\n const usedNames = new Set();\n /**\n * @param {import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration\n */\n const checkParameters = (aliasDeclaration) => {\n /* c8 ignore next -- Guard */\n const {params} = aliasDeclaration.typeParameters ?? {params: []};\n for (const {name: {name}} of params) {\n usedNames.add(name);\n }\n for (const tag of templateTags) {\n const {name} = tag;\n const names = name.split(/,\\s*/);\n for (const name of names) {\n if (!usedNames.has(name)) {\n report(`@template ${name} not in use`, null, tag);\n }\n }\n }\n };\n\n const handleTypeAliases = () => {\n const nde = /** @type {import('@typescript-eslint/types').TSESTree.Node} */ (\n node\n );\n if (!nde) {\n return;\n }\n switch (nde.type) {\n case 'ExportNamedDeclaration':\n if (nde.declaration?.type === 'TSTypeAliasDeclaration') {\n checkParameters(nde.declaration);\n }\n break;\n case 'TSTypeAliasDeclaration':\n checkParameters(nde);\n break;\n }\n };\n\n const typedefTags = utils.getTags('typedef');\n if (!typedefTags.length || typedefTags.length >= 2) {\n handleTypeAliases();\n return;\n }\n\n /**\n * @param {string} potentialType\n */\n const checkForUsedTypes = (potentialType) => {\n let parsedType;\n try {\n parsedType = mode === 'permissive' ?\n tryParseType(/** @type {string} */ (potentialType)) :\n parseType(/** @type {string} */ (potentialType), mode);\n } catch {\n return;\n }\n\n traverse(parsedType, (nde) => {\n const {\n type,\n value,\n } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);\n if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {\n usedNames.add(value);\n }\n });\n };\n\n const potentialTypedefType = typedefTags[0].type;\n checkForUsedTypes(potentialTypedefType);\n\n const tagName = /** @type {string} */ (utils.getPreferredTagName({\n tagName: 'property',\n }));\n const propertyTags = utils.getTags(tagName);\n for (const propertyTag of propertyTags) {\n checkForUsedTypes(propertyTag.type);\n }\n\n for (const tag of templateTags) {\n const {name} = tag;\n const names = name.split(/,\\s*/);\n for (const name of names) {\n if (!usedNames.has(name)) {\n report(`@template ${name} not in use`, null, tag);\n }\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Checks that any `@template` names are actually used in the connected `@typedef` or type alias.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-template.md#repos-sticky-header',\n },\n schema: [],\n type: 'suggestion',\n },\n});\n"],"mappings":"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","ignoreList":[]}
@@ -83,28 +83,45 @@ var _default = exports.default = (0, _iterateJsdoc.default)(({
83
83
  handleTypeAliases();
84
84
  return;
85
85
  }
86
- const potentialType = typedefTags[0].type;
87
- let parsedType;
88
- try {
89
- parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialType) : (0, _jsdoccomment.parse)( /** @type {string} */potentialType, mode);
90
- } catch {
91
- // Todo: Should handle types in @prop/erty
92
- return;
93
- }
94
- (0, _jsdoccomment.traverse)(parsedType, nde => {
95
- const {
96
- type,
97
- value
98
- } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
99
- if (type === 'JsdocTypeName' && /^[A-Z]$/.test(value)) {
100
- usedNames.add(value);
86
+ const usedNameToTag = new Map();
87
+
88
+ /**
89
+ * @param {import('comment-parser').Spec} potentialTag
90
+ */
91
+ const checkForUsedTypes = potentialTag => {
92
+ let parsedType;
93
+ try {
94
+ parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialTag.type) : (0, _jsdoccomment.parse)( /** @type {string} */potentialTag.type, mode);
95
+ } catch {
96
+ return;
101
97
  }
98
+ (0, _jsdoccomment.traverse)(parsedType, nde => {
99
+ const {
100
+ type,
101
+ value
102
+ } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
103
+ if (type === 'JsdocTypeName' && /^[A-Z]$/.test(value)) {
104
+ usedNames.add(value);
105
+ if (!usedNameToTag.has(value)) {
106
+ usedNameToTag.set(value, potentialTag);
107
+ }
108
+ }
109
+ });
110
+ };
111
+ const potentialTypedef = typedefTags[0];
112
+ checkForUsedTypes(potentialTypedef);
113
+ const tagName = /** @type {string} */utils.getPreferredTagName({
114
+ tagName: 'property'
102
115
  });
116
+ const propertyTags = utils.getTags(tagName);
117
+ for (const propertyTag of propertyTags) {
118
+ checkForUsedTypes(propertyTag);
119
+ }
103
120
 
104
121
  // Could check against whitelist/blacklist
105
122
  for (const usedName of usedNames) {
106
123
  if (!templateNames.includes(usedName)) {
107
- report(`Missing @template ${usedName}`, null, typedefTags[0]);
124
+ report(`Missing @template ${usedName}`, null, usedNameToTag.get(usedName));
108
125
  }
109
126
  }
110
127
  }, {
@@ -1 +1 @@
1
- {"version":3,"file":"requireTemplate.cjs","names":["_jsdoccomment","require","_iterateJsdoc","_interopRequireDefault","e","__esModule","default","_default","exports","iterateJsdoc","context","utils","node","settings","report","requireSeparateTemplates","options","mode","usedNames","Set","templateTags","getTags","templateNames","flatMap","name","split","tag","names","length","checkParameters","aliasDeclaration","params","typeParameters","add","usedName","includes","handleTypeAliases","_nde$declaration","nde","type","declaration","typedefTags","potentialType","parsedType","tryParseType","parseType","traverse","value","test","iterateAllJsdocs","meta","docs","description","url","schema","additionalProperties","properties","module"],"sources":["../../src/rules/requireTemplate.js"],"sourcesContent":["import {\n parse as parseType,\n traverse,\n tryParse as tryParseType,\n} from '@es-joy/jsdoccomment';\nimport iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n utils,\n node,\n settings,\n report,\n}) => {\n const {\n requireSeparateTemplates = false,\n } = context.options[0] || {};\n\n const {\n mode\n } = settings;\n\n const usedNames = new Set();\n const templateTags = utils.getTags('template');\n const templateNames = templateTags.flatMap(({name}) => {\n return name.split(/,\\s*/);\n });\n\n for (const tag of templateTags) {\n const {name} = tag;\n const names = name.split(/,\\s*/);\n if (requireSeparateTemplates && names.length > 1) {\n report(`Missing separate @template for ${names[1]}`, null, tag);\n }\n }\n\n /**\n * @param {import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration\n */\n const checkParameters = (aliasDeclaration) => {\n /* c8 ignore next -- Guard */\n const {params} = aliasDeclaration.typeParameters ?? {params: []};\n for (const {name: {name}} of params) {\n usedNames.add(name);\n }\n for (const usedName of usedNames) {\n if (!templateNames.includes(usedName)) {\n report(`Missing @template ${usedName}`);\n }\n }\n };\n\n const handleTypeAliases = () => {\n const nde = /** @type {import('@typescript-eslint/types').TSESTree.Node} */ (\n node\n );\n if (!nde) {\n return;\n }\n switch (nde.type) {\n case 'ExportNamedDeclaration':\n if (nde.declaration?.type === 'TSTypeAliasDeclaration') {\n checkParameters(nde.declaration);\n }\n break;\n case 'TSTypeAliasDeclaration':\n checkParameters(nde);\n break;\n }\n };\n\n const typedefTags = utils.getTags('typedef');\n if (!typedefTags.length || typedefTags.length >= 2) {\n handleTypeAliases();\n return;\n }\n\n const potentialType = typedefTags[0].type;\n\n let parsedType;\n try {\n parsedType = mode === 'permissive' ?\n tryParseType(/** @type {string} */ (potentialType)) :\n parseType(/** @type {string} */ (potentialType), mode)\n } catch {\n // Todo: Should handle types in @prop/erty\n return;\n }\n\n traverse(parsedType, (nde) => {\n const {\n type,\n value,\n } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);\n if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {\n usedNames.add(value);\n }\n });\n\n // Could check against whitelist/blacklist\n for (const usedName of usedNames) {\n if (!templateNames.includes(usedName)) {\n report(`Missing @template ${usedName}`, null, typedefTags[0]);\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Requires template tags for each generic type parameter',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-template.md#repos-sticky-header',\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n requireSeparateTemplates: {\n type: 'boolean'\n }\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"requireTemplate.cjs","names":["_jsdoccomment","require","_iterateJsdoc","_interopRequireDefault","e","__esModule","default","_default","exports","iterateJsdoc","context","utils","node","settings","report","requireSeparateTemplates","options","mode","usedNames","Set","templateTags","getTags","templateNames","flatMap","name","split","tag","names","length","checkParameters","aliasDeclaration","params","typeParameters","add","usedName","includes","handleTypeAliases","_nde$declaration","nde","type","declaration","typedefTags","usedNameToTag","Map","checkForUsedTypes","potentialTag","parsedType","tryParseType","parseType","traverse","value","test","has","set","potentialTypedef","tagName","getPreferredTagName","propertyTags","propertyTag","get","iterateAllJsdocs","meta","docs","description","url","schema","additionalProperties","properties","module"],"sources":["../../src/rules/requireTemplate.js"],"sourcesContent":["import {\n parse as parseType,\n traverse,\n tryParse as tryParseType,\n} from '@es-joy/jsdoccomment';\nimport iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n utils,\n node,\n settings,\n report,\n}) => {\n const {\n requireSeparateTemplates = false,\n } = context.options[0] || {};\n\n const {\n mode\n } = settings;\n\n const usedNames = new Set();\n const templateTags = utils.getTags('template');\n const templateNames = templateTags.flatMap(({name}) => {\n return name.split(/,\\s*/);\n });\n\n for (const tag of templateTags) {\n const {name} = tag;\n const names = name.split(/,\\s*/);\n if (requireSeparateTemplates && names.length > 1) {\n report(`Missing separate @template for ${names[1]}`, null, tag);\n }\n }\n\n /**\n * @param {import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration\n */\n const checkParameters = (aliasDeclaration) => {\n /* c8 ignore next -- Guard */\n const {params} = aliasDeclaration.typeParameters ?? {params: []};\n for (const {name: {name}} of params) {\n usedNames.add(name);\n }\n for (const usedName of usedNames) {\n if (!templateNames.includes(usedName)) {\n report(`Missing @template ${usedName}`);\n }\n }\n };\n\n const handleTypeAliases = () => {\n const nde = /** @type {import('@typescript-eslint/types').TSESTree.Node} */ (\n node\n );\n if (!nde) {\n return;\n }\n switch (nde.type) {\n case 'ExportNamedDeclaration':\n if (nde.declaration?.type === 'TSTypeAliasDeclaration') {\n checkParameters(nde.declaration);\n }\n break;\n case 'TSTypeAliasDeclaration':\n checkParameters(nde);\n break;\n }\n };\n\n const typedefTags = utils.getTags('typedef');\n if (!typedefTags.length || typedefTags.length >= 2) {\n handleTypeAliases();\n return;\n }\n\n const usedNameToTag = new Map();\n\n /**\n * @param {import('comment-parser').Spec} potentialTag\n */\n const checkForUsedTypes = (potentialTag) => {\n let parsedType;\n try {\n parsedType = mode === 'permissive' ?\n tryParseType(/** @type {string} */ (potentialTag.type)) :\n parseType(/** @type {string} */ (potentialTag.type), mode)\n } catch {\n return;\n }\n\n traverse(parsedType, (nde) => {\n const {\n type,\n value,\n } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);\n if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {\n usedNames.add(value);\n if (!usedNameToTag.has(value)) {\n usedNameToTag.set(value, potentialTag);\n }\n }\n });\n };\n\n const potentialTypedef = typedefTags[0];\n checkForUsedTypes(potentialTypedef);\n\n const tagName = /** @type {string} */ (utils.getPreferredTagName({\n tagName: 'property',\n }));\n const propertyTags = utils.getTags(tagName);\n for (const propertyTag of propertyTags) {\n checkForUsedTypes(propertyTag);\n }\n\n // Could check against whitelist/blacklist\n for (const usedName of usedNames) {\n if (!templateNames.includes(usedName)) {\n report(`Missing @template ${usedName}`, null, usedNameToTag.get(usedName));\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Requires template tags for each generic type parameter',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-template.md#repos-sticky-header',\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n requireSeparateTemplates: {\n type: 'boolean'\n }\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -144,5 +144,5 @@
144
144
  "test-cov": "cross-env TIMING=1 c8 --reporter text npm run test-no-cov",
145
145
  "test-index": "npm run test-no-cov -- test/rules/index.js"
146
146
  },
147
- "version": "48.8.2"
147
+ "version": "48.8.3"
148
148
  }
@@ -64,27 +64,40 @@ export default iterateJsdoc(({
64
64
  return;
65
65
  }
66
66
 
67
- const potentialType = typedefTags[0].type;
67
+ /**
68
+ * @param {string} potentialType
69
+ */
70
+ const checkForUsedTypes = (potentialType) => {
71
+ let parsedType;
72
+ try {
73
+ parsedType = mode === 'permissive' ?
74
+ tryParseType(/** @type {string} */ (potentialType)) :
75
+ parseType(/** @type {string} */ (potentialType), mode);
76
+ } catch {
77
+ return;
78
+ }
68
79
 
69
- let parsedType;
70
- try {
71
- parsedType = mode === 'permissive' ?
72
- tryParseType(/** @type {string} */ (potentialType)) :
73
- parseType(/** @type {string} */ (potentialType), mode)
74
- } catch {
75
- // Todo: Should handle types in @prop/erty
76
- return;
77
- }
80
+ traverse(parsedType, (nde) => {
81
+ const {
82
+ type,
83
+ value,
84
+ } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);
85
+ if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {
86
+ usedNames.add(value);
87
+ }
88
+ });
89
+ };
78
90
 
79
- traverse(parsedType, (nde) => {
80
- const {
81
- type,
82
- value,
83
- } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);
84
- if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {
85
- usedNames.add(value);
86
- }
87
- });
91
+ const potentialTypedefType = typedefTags[0].type;
92
+ checkForUsedTypes(potentialTypedefType);
93
+
94
+ const tagName = /** @type {string} */ (utils.getPreferredTagName({
95
+ tagName: 'property',
96
+ }));
97
+ const propertyTags = utils.getTags(tagName);
98
+ for (const propertyTag of propertyTags) {
99
+ checkForUsedTypes(propertyTag.type);
100
+ }
88
101
 
89
102
  for (const tag of templateTags) {
90
103
  const {name} = tag;
@@ -75,32 +75,50 @@ export default iterateJsdoc(({
75
75
  return;
76
76
  }
77
77
 
78
- const potentialType = typedefTags[0].type;
78
+ const usedNameToTag = new Map();
79
79
 
80
- let parsedType;
81
- try {
82
- parsedType = mode === 'permissive' ?
83
- tryParseType(/** @type {string} */ (potentialType)) :
84
- parseType(/** @type {string} */ (potentialType), mode)
85
- } catch {
86
- // Todo: Should handle types in @prop/erty
87
- return;
88
- }
89
-
90
- traverse(parsedType, (nde) => {
91
- const {
92
- type,
93
- value,
94
- } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);
95
- if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {
96
- usedNames.add(value);
80
+ /**
81
+ * @param {import('comment-parser').Spec} potentialTag
82
+ */
83
+ const checkForUsedTypes = (potentialTag) => {
84
+ let parsedType;
85
+ try {
86
+ parsedType = mode === 'permissive' ?
87
+ tryParseType(/** @type {string} */ (potentialTag.type)) :
88
+ parseType(/** @type {string} */ (potentialTag.type), mode)
89
+ } catch {
90
+ return;
97
91
  }
98
- });
92
+
93
+ traverse(parsedType, (nde) => {
94
+ const {
95
+ type,
96
+ value,
97
+ } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);
98
+ if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {
99
+ usedNames.add(value);
100
+ if (!usedNameToTag.has(value)) {
101
+ usedNameToTag.set(value, potentialTag);
102
+ }
103
+ }
104
+ });
105
+ };
106
+
107
+ const potentialTypedef = typedefTags[0];
108
+ checkForUsedTypes(potentialTypedef);
109
+
110
+ const tagName = /** @type {string} */ (utils.getPreferredTagName({
111
+ tagName: 'property',
112
+ }));
113
+ const propertyTags = utils.getTags(tagName);
114
+ for (const propertyTag of propertyTags) {
115
+ checkForUsedTypes(propertyTag);
116
+ }
99
117
 
100
118
  // Could check against whitelist/blacklist
101
119
  for (const usedName of usedNames) {
102
120
  if (!templateNames.includes(usedName)) {
103
- report(`Missing @template ${usedName}`, null, typedefTags[0]);
121
+ report(`Missing @template ${usedName}`, null, usedNameToTag.get(usedName));
104
122
  }
105
123
  }
106
124
  }, {