eslint-plugin-jsdoc 48.10.1 → 48.11.0

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.
@@ -19,13 +19,64 @@ var _default = exports.default = (0, _iterateJsdoc.default)(({
19
19
  } = settings;
20
20
  const templateTags = utils.getTags('template');
21
21
  const usedNames = new Set();
22
+ /**
23
+ * @param {string} potentialType
24
+ */
25
+ const checkForUsedTypes = potentialType => {
26
+ let parsedType;
27
+ try {
28
+ parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialType) : (0, _jsdoccomment.parse)( /** @type {string} */potentialType, mode);
29
+ } catch {
30
+ return;
31
+ }
32
+ (0, _jsdoccomment.traverse)(parsedType, nde => {
33
+ const {
34
+ type,
35
+ value
36
+ } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
37
+ if (type === 'JsdocTypeName' && /^[A-Z]$/.test(value)) {
38
+ usedNames.add(value);
39
+ }
40
+ });
41
+ };
42
+ const checkParamsAndReturnsTags = () => {
43
+ const paramName = /** @type {string} */utils.getPreferredTagName({
44
+ tagName: 'param'
45
+ });
46
+ const paramTags = utils.getTags(paramName);
47
+ for (const paramTag of paramTags) {
48
+ checkForUsedTypes(paramTag.type);
49
+ }
50
+ const returnsName = /** @type {string} */utils.getPreferredTagName({
51
+ tagName: 'returns'
52
+ });
53
+ const returnsTags = utils.getTags(returnsName);
54
+ for (const returnsTag of returnsTags) {
55
+ checkForUsedTypes(returnsTag.type);
56
+ }
57
+ };
58
+ const checkTemplateTags = () => {
59
+ for (const tag of templateTags) {
60
+ const {
61
+ name
62
+ } = tag;
63
+ const names = name.split(/,\s*/);
64
+ for (const name of names) {
65
+ if (!usedNames.has(name)) {
66
+ report(`@template ${name} not in use`, null, tag);
67
+ }
68
+ }
69
+ }
70
+ };
71
+
22
72
  /**
23
73
  * @param {import('@typescript-eslint/types').TSESTree.FunctionDeclaration|
24
74
  * import('@typescript-eslint/types').TSESTree.ClassDeclaration|
25
75
  * import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|
26
76
  * import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration
77
+ * @param {boolean} [checkParamsAndReturns]
27
78
  */
28
- const checkParameters = aliasDeclaration => {
79
+ const checkParameters = (aliasDeclaration, checkParamsAndReturns) => {
29
80
  /* c8 ignore next -- Guard */
30
81
  const {
31
82
  params
@@ -39,17 +90,10 @@ var _default = exports.default = (0, _iterateJsdoc.default)(({
39
90
  } of params) {
40
91
  usedNames.add(name);
41
92
  }
42
- for (const tag of templateTags) {
43
- const {
44
- name
45
- } = tag;
46
- const names = name.split(/,\s*/);
47
- for (const name of names) {
48
- if (!usedNames.has(name)) {
49
- report(`@template ${name} not in use`, null, tag);
50
- }
51
- }
93
+ if (checkParamsAndReturns) {
94
+ checkParamsAndReturnsTags();
52
95
  }
96
+ checkTemplateTags();
53
97
  };
54
98
  const handleTypeAliases = () => {
55
99
  var _nde$declaration;
@@ -62,54 +106,44 @@ var _default = exports.default = (0, _iterateJsdoc.default)(({
62
106
  case 'ExportDefaultDeclaration':
63
107
  case 'ExportNamedDeclaration':
64
108
  switch ((_nde$declaration = nde.declaration) === null || _nde$declaration === void 0 ? void 0 : _nde$declaration.type) {
65
- case 'ClassDeclaration':
66
109
  case 'FunctionDeclaration':
110
+ checkParameters(nde.declaration, true);
111
+ break;
112
+ case 'ClassDeclaration':
67
113
  case 'TSTypeAliasDeclaration':
68
114
  case 'TSInterfaceDeclaration':
69
115
  checkParameters(nde.declaration);
70
116
  break;
71
117
  }
72
118
  break;
73
- case 'ClassDeclaration':
74
119
  case 'FunctionDeclaration':
120
+ checkParameters(nde, true);
121
+ break;
122
+ case 'ClassDeclaration':
75
123
  case 'TSTypeAliasDeclaration':
76
124
  case 'TSInterfaceDeclaration':
77
125
  checkParameters(nde);
78
126
  break;
79
127
  }
80
128
  };
129
+ const callbackTags = utils.getTags('callback');
130
+ const functionTags = utils.getTags('function');
131
+ if (callbackTags.length || functionTags.length) {
132
+ checkParamsAndReturnsTags();
133
+ checkTemplateTags();
134
+ return;
135
+ }
81
136
  const typedefTags = utils.getTags('typedef');
82
137
  if (!typedefTags.length || typedefTags.length >= 2) {
83
138
  handleTypeAliases();
84
139
  return;
85
140
  }
86
-
87
- /**
88
- * @param {string} potentialType
89
- */
90
- const checkForUsedTypes = potentialType => {
91
- let parsedType;
92
- try {
93
- parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialType) : (0, _jsdoccomment.parse)( /** @type {string} */potentialType, mode);
94
- } catch {
95
- return;
96
- }
97
- (0, _jsdoccomment.traverse)(parsedType, nde => {
98
- const {
99
- type,
100
- value
101
- } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
102
- if (type === 'JsdocTypeName' && /^[A-Z]$/.test(value)) {
103
- usedNames.add(value);
104
- }
105
- });
106
- };
107
141
  const potentialTypedefType = typedefTags[0].type;
108
142
  checkForUsedTypes(potentialTypedefType);
109
- const tagName = /** @type {string} */utils.getPreferredTagName({
143
+ const propertyName = /** @type {string} */utils.getPreferredTagName({
110
144
  tagName: 'property'
111
145
  });
112
- const propertyTags = utils.getTags(tagName);
146
+ const propertyTags = utils.getTags(propertyName);
113
147
  for (const propertyTag of propertyTags) {
114
148
  checkForUsedTypes(propertyTag.type);
115
149
  }
@@ -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","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.FunctionDeclaration|\n * import('@typescript-eslint/types').TSESTree.ClassDeclaration|\n * import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|\n * 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 'ExportDefaultDeclaration':\n case 'ExportNamedDeclaration':\n switch (nde.declaration?.type) {\n case 'ClassDeclaration':\n case 'FunctionDeclaration':\n case 'TSTypeAliasDeclaration':\n case 'TSInterfaceDeclaration':\n checkParameters(nde.declaration);\n break;\n }\n break;\n case 'ClassDeclaration':\n case 'FunctionDeclaration':\n case 'TSTypeAliasDeclaration':\n case 'TSInterfaceDeclaration':\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":";;;;;;AAAA,IAAAA,aAAA,GAAAC,OAAA;AAKA,IAAAC,aAAA,GAAAC,sBAAA,CAAAF,OAAA;AAA8C,SAAAE,uBAAAC,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,OAAO;EACPC,KAAK;EACLC,IAAI;EACJC,QAAQ;EACRC;AACF,CAAC,KAAK;EACJ,MAAM;IACJC;EACF,CAAC,GAAGF,QAAQ;EAEZ,MAAMG,YAAY,GAAGL,KAAK,CAACM,OAAO,CAAC,UAAU,CAAC;EAE9C,MAAMC,SAAS,GAAG,IAAIC,GAAG,CAAC,CAAC;EAC3B;AACF;AACA;AACA;AACA;AACA;EACE,MAAMC,eAAe,GAAIC,gBAAgB,IAAK;IAC5C;IACA,MAAM;MAACC;IAAM,CAAC,GAAGD,gBAAgB,CAACE,cAAc,IAAI;MAACD,MAAM,EAAE;IAAE,CAAC;IAChE,KAAK,MAAM;MAACE,IAAI,EAAE;QAACA;MAAI;IAAC,CAAC,IAAIF,MAAM,EAAE;MACnCJ,SAAS,CAACO,GAAG,CAACD,IAAI,CAAC;IACrB;IACA,KAAK,MAAME,GAAG,IAAIV,YAAY,EAAE;MAC9B,MAAM;QAACQ;MAAI,CAAC,GAAGE,GAAG;MAClB,MAAMC,KAAK,GAAGH,IAAI,CAACI,KAAK,CAAC,MAAM,CAAC;MAChC,KAAK,MAAMJ,IAAI,IAAIG,KAAK,EAAE;QACxB,IAAI,CAACT,SAAS,CAACW,GAAG,CAACL,IAAI,CAAC,EAAE;UACxBV,MAAM,CAAC,aAAaU,IAAI,aAAa,EAAE,IAAI,EAAEE,GAAG,CAAC;QACnD;MACF;IACF;EACF,CAAC;EAED,MAAMI,iBAAiB,GAAGA,CAAA,KAAM;IAAA,IAAAC,gBAAA;IAC9B,MAAMC,GAAG,GAAG;IACVpB,IACD;IACD,IAAI,CAACoB,GAAG,EAAE;MACR;IACF;IACA,QAAQA,GAAG,CAACC,IAAI;MAChB,KAAK,0BAA0B;MAC/B,KAAK,wBAAwB;QAC3B,SAAAF,gBAAA,GAAQC,GAAG,CAACE,WAAW,cAAAH,gBAAA,uBAAfA,gBAAA,CAAiBE,IAAI;UAC3B,KAAK,kBAAkB;UACvB,KAAK,qBAAqB;UAC1B,KAAK,wBAAwB;UAC7B,KAAK,wBAAwB;YAC3Bb,eAAe,CAACY,GAAG,CAACE,WAAW,CAAC;YAChC;QACJ;QACA;MACF,KAAK,kBAAkB;MACvB,KAAK,qBAAqB;MAC1B,KAAK,wBAAwB;MAC7B,KAAK,wBAAwB;QAC3Bd,eAAe,CAACY,GAAG,CAAC;QACpB;IACF;EACF,CAAC;EAED,MAAMG,WAAW,GAAGxB,KAAK,CAACM,OAAO,CAAC,SAAS,CAAC;EAC5C,IAAI,CAACkB,WAAW,CAACC,MAAM,IAAID,WAAW,CAACC,MAAM,IAAI,CAAC,EAAE;IAClDN,iBAAiB,CAAC,CAAC;IACnB;EACF;;EAEA;AACF;AACA;EACE,MAAMO,iBAAiB,GAAIC,aAAa,IAAK;IAC3C,IAAIC,UAAU;IACd,IAAI;MACFA,UAAU,GAAGxB,IAAI,KAAK,YAAY,GAChC,IAAAyB,sBAAY,GAAC,qBAAuBF,aAAc,CAAC,GACnD,IAAAG,mBAAS,GAAC,qBAAuBH,aAAa,EAAGvB,IAAI,CAAC;IAC1D,CAAC,CAAC,MAAM;MACN;IACF;IAEA,IAAA2B,sBAAQ,EAACH,UAAU,EAAGP,GAAG,IAAK;MAC5B,MAAM;QACJC,IAAI;QACJU;MACF,CAAC,GAAG,2DAA6DX,GAAI;MACrE,IAAIC,IAAI,KAAK,eAAe,IAAK,SAAS,CAAEW,IAAI,CAACD,KAAK,CAAC,EAAE;QACvDzB,SAAS,CAACO,GAAG,CAACkB,KAAK,CAAC;MACtB;IACF,CAAC,CAAC;EACJ,CAAC;EAED,MAAME,oBAAoB,GAAGV,WAAW,CAAC,CAAC,CAAC,CAACF,IAAI;EAChDI,iBAAiB,CAACQ,oBAAoB,CAAC;EAEvC,MAAMC,OAAO,GAAG,qBAAuBnC,KAAK,CAACoC,mBAAmB,CAAC;IAC/DD,OAAO,EAAE;EACX,CAAC,CAAE;EACH,MAAME,YAAY,GAAGrC,KAAK,CAACM,OAAO,CAAC6B,OAAO,CAAC;EAC3C,KAAK,MAAMG,WAAW,IAAID,YAAY,EAAE;IACtCX,iBAAiB,CAACY,WAAW,CAAChB,IAAI,CAAC;EACrC;EAEA,KAAK,MAAMP,GAAG,IAAIV,YAAY,EAAE;IAC9B,MAAM;MAACQ;IAAI,CAAC,GAAGE,GAAG;IAClB,MAAMC,KAAK,GAAGH,IAAI,CAACI,KAAK,CAAC,MAAM,CAAC;IAChC,KAAK,MAAMJ,IAAI,IAAIG,KAAK,EAAE;MACxB,IAAI,CAACT,SAAS,CAACW,GAAG,CAACL,IAAI,CAAC,EAAE;QACxBV,MAAM,CAAC,aAAaU,IAAI,aAAa,EAAE,IAAI,EAAEE,GAAG,CAAC;MACnD;IACF;EACF;AACF,CAAC,EAAE;EACDwB,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,gGAAgG;MAC7GC,GAAG,EAAE;IACP,CAAC;IACDC,MAAM,EAAE,EAAE;IACVtB,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAuB,MAAA,CAAAhD,OAAA,GAAAA,OAAA,CAAAF,OAAA","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","checkForUsedTypes","potentialType","parsedType","tryParseType","parseType","traverse","nde","type","value","test","add","checkParamsAndReturnsTags","paramName","getPreferredTagName","tagName","paramTags","paramTag","returnsName","returnsTags","returnsTag","checkTemplateTags","tag","name","names","split","has","checkParameters","aliasDeclaration","checkParamsAndReturns","params","typeParameters","handleTypeAliases","_nde$declaration","declaration","callbackTags","functionTags","length","typedefTags","potentialTypedefType","propertyName","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 {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 checkParamsAndReturnsTags = () => {\n const paramName = /** @type {string} */ (utils.getPreferredTagName({\n tagName: 'param',\n }));\n const paramTags = utils.getTags(paramName);\n for (const paramTag of paramTags) {\n checkForUsedTypes(paramTag.type);\n }\n\n const returnsName = /** @type {string} */ (utils.getPreferredTagName({\n tagName: 'returns',\n }));\n const returnsTags = utils.getTags(returnsName);\n for (const returnsTag of returnsTags) {\n checkForUsedTypes(returnsTag.type);\n }\n };\n\n const checkTemplateTags = () => {\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 /**\n * @param {import('@typescript-eslint/types').TSESTree.FunctionDeclaration|\n * import('@typescript-eslint/types').TSESTree.ClassDeclaration|\n * import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|\n * import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration\n * @param {boolean} [checkParamsAndReturns]\n */\n const checkParameters = (aliasDeclaration, checkParamsAndReturns) => {\n /* c8 ignore next -- Guard */\n const {params} = aliasDeclaration.typeParameters ?? {params: []};\n for (const {name: {name}} of params) {\n usedNames.add(name);\n }\n if (checkParamsAndReturns) {\n checkParamsAndReturnsTags();\n }\n\n checkTemplateTags();\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 'ExportDefaultDeclaration':\n case 'ExportNamedDeclaration':\n switch (nde.declaration?.type) {\n case 'FunctionDeclaration':\n checkParameters(nde.declaration, true);\n break;\n case 'ClassDeclaration':\n case 'TSTypeAliasDeclaration':\n case 'TSInterfaceDeclaration':\n checkParameters(nde.declaration);\n break;\n }\n break;\n case 'FunctionDeclaration':\n checkParameters(nde, true);\n break;\n case 'ClassDeclaration':\n case 'TSTypeAliasDeclaration':\n case 'TSInterfaceDeclaration':\n checkParameters(nde);\n break;\n }\n };\n\n const callbackTags = utils.getTags('callback');\n const functionTags = utils.getTags('function');\n if (callbackTags.length || functionTags.length) {\n checkParamsAndReturnsTags();\n checkTemplateTags();\n return;\n }\n\n const typedefTags = utils.getTags('typedef');\n if (!typedefTags.length || typedefTags.length >= 2) {\n handleTypeAliases();\n return;\n }\n\n const potentialTypedefType = typedefTags[0].type;\n checkForUsedTypes(potentialTypedefType);\n\n const propertyName = /** @type {string} */ (utils.getPreferredTagName({\n tagName: 'property',\n }));\n const propertyTags = utils.getTags(propertyName);\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":[]}
@@ -98,11 +98,6 @@ var _default = exports.default = (0, _iterateJsdoc.default)(({
98
98
  break;
99
99
  }
100
100
  };
101
- const typedefTags = utils.getTags('typedef');
102
- if (!typedefTags.length || typedefTags.length >= 2) {
103
- handleTypes();
104
- return;
105
- }
106
101
  const usedNameToTag = new Map();
107
102
 
108
103
  /**
@@ -128,22 +123,42 @@ var _default = exports.default = (0, _iterateJsdoc.default)(({
128
123
  }
129
124
  });
130
125
  };
131
- const potentialTypedef = typedefTags[0];
132
- checkForUsedTypes(potentialTypedef);
133
- const tagName = /** @type {string} */utils.getPreferredTagName({
134
- tagName: 'property'
135
- });
136
- const propertyTags = utils.getTags(tagName);
137
- for (const propertyTag of propertyTags) {
138
- checkForUsedTypes(propertyTag);
139
- }
140
126
 
141
- // Could check against whitelist/blacklist
142
- for (const usedName of usedNames) {
143
- if (!templateNames.includes(usedName)) {
144
- report(`Missing @template ${usedName}`, null, usedNameToTag.get(usedName));
127
+ /**
128
+ * @param {string[]} tagNames
129
+ */
130
+ const checkTagsAndTemplates = tagNames => {
131
+ for (const tagName of tagNames) {
132
+ const preferredTagName = /** @type {string} */utils.getPreferredTagName({
133
+ tagName
134
+ });
135
+ const matchingTags = utils.getTags(preferredTagName);
136
+ for (const matchingTag of matchingTags) {
137
+ checkForUsedTypes(matchingTag);
138
+ }
139
+ }
140
+
141
+ // Could check against whitelist/blacklist
142
+ for (const usedName of usedNames) {
143
+ if (!templateNames.includes(usedName)) {
144
+ report(`Missing @template ${usedName}`, null, usedNameToTag.get(usedName));
145
+ }
145
146
  }
147
+ };
148
+ const callbackTags = utils.getTags('callback');
149
+ const functionTags = utils.getTags('function');
150
+ if (callbackTags.length || functionTags.length) {
151
+ checkTagsAndTemplates(['param', 'returns']);
152
+ return;
146
153
  }
154
+ const typedefTags = utils.getTags('typedef');
155
+ if (!typedefTags.length || typedefTags.length >= 2) {
156
+ handleTypes();
157
+ return;
158
+ }
159
+ const potentialTypedef = typedefTags[0];
160
+ checkForUsedTypes(potentialTypedef);
161
+ checkTagsAndTemplates(['property']);
147
162
  }, {
148
163
  iterateAllJsdocs: true,
149
164
  meta: {
@@ -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","checkTypeParams","aliasDeclaration","params","typeParameters","add","usedName","includes","handleTypes","_nde$declaration","_nde$declaration2","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.FunctionDeclaration|\n * import('@typescript-eslint/types').TSESTree.ClassDeclaration|\n * import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|\n * import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration\n */\n const checkTypeParams = (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 handleTypes = () => {\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 'ExportDefaultDeclaration':\n switch (nde.declaration?.type) {\n case 'ClassDeclaration':\n case 'FunctionDeclaration':\n case 'TSInterfaceDeclaration':\n checkTypeParams(nde.declaration);\n break;\n }\n break;\n case 'ExportNamedDeclaration':\n switch (nde.declaration?.type) {\n case 'ClassDeclaration':\n case 'FunctionDeclaration':\n case 'TSTypeAliasDeclaration':\n case 'TSInterfaceDeclaration':\n checkTypeParams(nde.declaration);\n break;\n }\n break;\n case 'ClassDeclaration':\n case 'FunctionDeclaration':\n case 'TSTypeAliasDeclaration':\n case 'TSInterfaceDeclaration':\n checkTypeParams(nde);\n break;\n }\n };\n\n const typedefTags = utils.getTags('typedef');\n if (!typedefTags.length || typedefTags.length >= 2) {\n handleTypes();\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":[]}
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","checkTypeParams","aliasDeclaration","params","typeParameters","add","usedName","includes","handleTypes","_nde$declaration","_nde$declaration2","nde","type","declaration","usedNameToTag","Map","checkForUsedTypes","potentialTag","parsedType","tryParseType","parseType","traverse","value","test","has","set","checkTagsAndTemplates","tagNames","tagName","preferredTagName","getPreferredTagName","matchingTags","matchingTag","get","callbackTags","functionTags","typedefTags","potentialTypedef","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.FunctionDeclaration|\n * import('@typescript-eslint/types').TSESTree.ClassDeclaration|\n * import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|\n * import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration\n */\n const checkTypeParams = (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 handleTypes = () => {\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 'ExportDefaultDeclaration':\n switch (nde.declaration?.type) {\n case 'ClassDeclaration':\n case 'FunctionDeclaration':\n case 'TSInterfaceDeclaration':\n checkTypeParams(nde.declaration);\n break;\n }\n break;\n case 'ExportNamedDeclaration':\n switch (nde.declaration?.type) {\n case 'ClassDeclaration':\n case 'FunctionDeclaration':\n case 'TSTypeAliasDeclaration':\n case 'TSInterfaceDeclaration':\n checkTypeParams(nde.declaration);\n break;\n }\n break;\n case 'ClassDeclaration':\n case 'FunctionDeclaration':\n case 'TSTypeAliasDeclaration':\n case 'TSInterfaceDeclaration':\n checkTypeParams(nde);\n break;\n }\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 /**\n * @param {string[]} tagNames\n */\n const checkTagsAndTemplates = (tagNames) => {\n for (const tagName of tagNames) {\n const preferredTagName = /** @type {string} */ (utils.getPreferredTagName({\n tagName,\n }));\n const matchingTags = utils.getTags(preferredTagName);\n for (const matchingTag of matchingTags) {\n checkForUsedTypes(matchingTag);\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, usedNameToTag.get(usedName));\n }\n }\n };\n\n const callbackTags = utils.getTags('callback');\n const functionTags = utils.getTags('function');\n if (callbackTags.length || functionTags.length) {\n checkTagsAndTemplates(['param', 'returns']);\n return;\n }\n\n const typedefTags = utils.getTags('typedef');\n if (!typedefTags.length || typedefTags.length >= 2) {\n handleTypes();\n return;\n }\n\n const potentialTypedef = typedefTags[0];\n checkForUsedTypes(potentialTypedef);\n\n checkTagsAndTemplates(['property']);\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
@@ -152,5 +152,5 @@
152
152
  "test-cov": "cross-env TIMING=1 c8 --reporter text npm run test-no-cov",
153
153
  "test-index": "npm run test-no-cov -- test/rules/index.js"
154
154
  },
155
- "version": "48.10.1"
155
+ "version": "48.11.0"
156
156
  }
@@ -20,17 +20,48 @@ export default iterateJsdoc(({
20
20
 
21
21
  const usedNames = new Set();
22
22
  /**
23
- * @param {import('@typescript-eslint/types').TSESTree.FunctionDeclaration|
24
- * import('@typescript-eslint/types').TSESTree.ClassDeclaration|
25
- * import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|
26
- * import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration
23
+ * @param {string} potentialType
27
24
  */
28
- const checkParameters = (aliasDeclaration) => {
29
- /* c8 ignore next -- Guard */
30
- const {params} = aliasDeclaration.typeParameters ?? {params: []};
31
- for (const {name: {name}} of params) {
32
- usedNames.add(name);
25
+ const checkForUsedTypes = (potentialType) => {
26
+ let parsedType;
27
+ try {
28
+ parsedType = mode === 'permissive' ?
29
+ tryParseType(/** @type {string} */ (potentialType)) :
30
+ parseType(/** @type {string} */ (potentialType), mode);
31
+ } catch {
32
+ return;
33
33
  }
34
+
35
+ traverse(parsedType, (nde) => {
36
+ const {
37
+ type,
38
+ value,
39
+ } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);
40
+ if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {
41
+ usedNames.add(value);
42
+ }
43
+ });
44
+ };
45
+
46
+ const checkParamsAndReturnsTags = () => {
47
+ const paramName = /** @type {string} */ (utils.getPreferredTagName({
48
+ tagName: 'param',
49
+ }));
50
+ const paramTags = utils.getTags(paramName);
51
+ for (const paramTag of paramTags) {
52
+ checkForUsedTypes(paramTag.type);
53
+ }
54
+
55
+ const returnsName = /** @type {string} */ (utils.getPreferredTagName({
56
+ tagName: 'returns',
57
+ }));
58
+ const returnsTags = utils.getTags(returnsName);
59
+ for (const returnsTag of returnsTags) {
60
+ checkForUsedTypes(returnsTag.type);
61
+ }
62
+ };
63
+
64
+ const checkTemplateTags = () => {
34
65
  for (const tag of templateTags) {
35
66
  const {name} = tag;
36
67
  const names = name.split(/,\s*/);
@@ -42,6 +73,26 @@ export default iterateJsdoc(({
42
73
  }
43
74
  };
44
75
 
76
+ /**
77
+ * @param {import('@typescript-eslint/types').TSESTree.FunctionDeclaration|
78
+ * import('@typescript-eslint/types').TSESTree.ClassDeclaration|
79
+ * import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|
80
+ * import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration
81
+ * @param {boolean} [checkParamsAndReturns]
82
+ */
83
+ const checkParameters = (aliasDeclaration, checkParamsAndReturns) => {
84
+ /* c8 ignore next -- Guard */
85
+ const {params} = aliasDeclaration.typeParameters ?? {params: []};
86
+ for (const {name: {name}} of params) {
87
+ usedNames.add(name);
88
+ }
89
+ if (checkParamsAndReturns) {
90
+ checkParamsAndReturnsTags();
91
+ }
92
+
93
+ checkTemplateTags();
94
+ };
95
+
45
96
  const handleTypeAliases = () => {
46
97
  const nde = /** @type {import('@typescript-eslint/types').TSESTree.Node} */ (
47
98
  node
@@ -53,16 +104,20 @@ export default iterateJsdoc(({
53
104
  case 'ExportDefaultDeclaration':
54
105
  case 'ExportNamedDeclaration':
55
106
  switch (nde.declaration?.type) {
56
- case 'ClassDeclaration':
57
107
  case 'FunctionDeclaration':
108
+ checkParameters(nde.declaration, true);
109
+ break;
110
+ case 'ClassDeclaration':
58
111
  case 'TSTypeAliasDeclaration':
59
112
  case 'TSInterfaceDeclaration':
60
113
  checkParameters(nde.declaration);
61
114
  break;
62
115
  }
63
116
  break;
64
- case 'ClassDeclaration':
65
117
  case 'FunctionDeclaration':
118
+ checkParameters(nde, true);
119
+ break;
120
+ case 'ClassDeclaration':
66
121
  case 'TSTypeAliasDeclaration':
67
122
  case 'TSInterfaceDeclaration':
68
123
  checkParameters(nde);
@@ -70,43 +125,27 @@ export default iterateJsdoc(({
70
125
  }
71
126
  };
72
127
 
128
+ const callbackTags = utils.getTags('callback');
129
+ const functionTags = utils.getTags('function');
130
+ if (callbackTags.length || functionTags.length) {
131
+ checkParamsAndReturnsTags();
132
+ checkTemplateTags();
133
+ return;
134
+ }
135
+
73
136
  const typedefTags = utils.getTags('typedef');
74
137
  if (!typedefTags.length || typedefTags.length >= 2) {
75
138
  handleTypeAliases();
76
139
  return;
77
140
  }
78
141
 
79
- /**
80
- * @param {string} potentialType
81
- */
82
- const checkForUsedTypes = (potentialType) => {
83
- let parsedType;
84
- try {
85
- parsedType = mode === 'permissive' ?
86
- tryParseType(/** @type {string} */ (potentialType)) :
87
- parseType(/** @type {string} */ (potentialType), mode);
88
- } catch {
89
- return;
90
- }
91
-
92
- traverse(parsedType, (nde) => {
93
- const {
94
- type,
95
- value,
96
- } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);
97
- if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {
98
- usedNames.add(value);
99
- }
100
- });
101
- };
102
-
103
142
  const potentialTypedefType = typedefTags[0].type;
104
143
  checkForUsedTypes(potentialTypedefType);
105
144
 
106
- const tagName = /** @type {string} */ (utils.getPreferredTagName({
145
+ const propertyName = /** @type {string} */ (utils.getPreferredTagName({
107
146
  tagName: 'property',
108
147
  }));
109
- const propertyTags = utils.getTags(tagName);
148
+ const propertyTags = utils.getTags(propertyName);
110
149
  for (const propertyTag of propertyTags) {
111
150
  checkForUsedTypes(propertyTag.type);
112
151
  }
@@ -89,12 +89,6 @@ export default iterateJsdoc(({
89
89
  }
90
90
  };
91
91
 
92
- const typedefTags = utils.getTags('typedef');
93
- if (!typedefTags.length || typedefTags.length >= 2) {
94
- handleTypes();
95
- return;
96
- }
97
-
98
92
  const usedNameToTag = new Map();
99
93
 
100
94
  /**
@@ -124,23 +118,45 @@ export default iterateJsdoc(({
124
118
  });
125
119
  };
126
120
 
127
- const potentialTypedef = typedefTags[0];
128
- checkForUsedTypes(potentialTypedef);
121
+ /**
122
+ * @param {string[]} tagNames
123
+ */
124
+ const checkTagsAndTemplates = (tagNames) => {
125
+ for (const tagName of tagNames) {
126
+ const preferredTagName = /** @type {string} */ (utils.getPreferredTagName({
127
+ tagName,
128
+ }));
129
+ const matchingTags = utils.getTags(preferredTagName);
130
+ for (const matchingTag of matchingTags) {
131
+ checkForUsedTypes(matchingTag);
132
+ }
133
+ }
134
+
135
+ // Could check against whitelist/blacklist
136
+ for (const usedName of usedNames) {
137
+ if (!templateNames.includes(usedName)) {
138
+ report(`Missing @template ${usedName}`, null, usedNameToTag.get(usedName));
139
+ }
140
+ }
141
+ };
129
142
 
130
- const tagName = /** @type {string} */ (utils.getPreferredTagName({
131
- tagName: 'property',
132
- }));
133
- const propertyTags = utils.getTags(tagName);
134
- for (const propertyTag of propertyTags) {
135
- checkForUsedTypes(propertyTag);
143
+ const callbackTags = utils.getTags('callback');
144
+ const functionTags = utils.getTags('function');
145
+ if (callbackTags.length || functionTags.length) {
146
+ checkTagsAndTemplates(['param', 'returns']);
147
+ return;
136
148
  }
137
149
 
138
- // Could check against whitelist/blacklist
139
- for (const usedName of usedNames) {
140
- if (!templateNames.includes(usedName)) {
141
- report(`Missing @template ${usedName}`, null, usedNameToTag.get(usedName));
142
- }
150
+ const typedefTags = utils.getTags('typedef');
151
+ if (!typedefTags.length || typedefTags.length >= 2) {
152
+ handleTypes();
153
+ return;
143
154
  }
155
+
156
+ const potentialTypedef = typedefTags[0];
157
+ checkForUsedTypes(potentialTypedef);
158
+
159
+ checkTagsAndTemplates(['property']);
144
160
  }, {
145
161
  iterateAllJsdocs: true,
146
162
  meta: {