eslint-plugin-jsdoc 39.3.3 → 39.3.6
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.
- package/README.md +16 -2
- package/dist/iterateJsdoc.js +1 -1
- package/dist/iterateJsdoc.js.map +1 -1
- package/dist/jsdocUtils.js +13 -357
- package/dist/jsdocUtils.js.map +1 -1
- package/dist/utils/hasReturnValue.js +364 -0
- package/dist/utils/hasReturnValue.js.map +1 -0
- package/package.json +1 -1
- package/CONTRIBUTING.md +0 -100
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.hasValueOrExecutorHasNonEmptyResolveValue = exports.hasReturnValue = void 0;
|
|
7
|
+
|
|
8
|
+
/* eslint-disable jsdoc/no-undefined-types */
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Checks if a node is a promise but has no resolve value or an empty value.
|
|
12
|
+
* An `undefined` resolve does not count.
|
|
13
|
+
*
|
|
14
|
+
* @param {object} node
|
|
15
|
+
* @returns {boolean}
|
|
16
|
+
*/
|
|
17
|
+
const isNewPromiseExpression = node => {
|
|
18
|
+
return node && node.type === 'NewExpression' && node.callee.type === 'Identifier' && node.callee.name === 'Promise';
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const isVoidPromise = node => {
|
|
22
|
+
var _node$typeParameters, _node$typeParameters$, _node$typeParameters$2;
|
|
23
|
+
|
|
24
|
+
return (node === null || node === void 0 ? void 0 : (_node$typeParameters = node.typeParameters) === null || _node$typeParameters === void 0 ? void 0 : (_node$typeParameters$ = _node$typeParameters.params) === null || _node$typeParameters$ === void 0 ? void 0 : (_node$typeParameters$2 = _node$typeParameters$[0]) === null || _node$typeParameters$2 === void 0 ? void 0 : _node$typeParameters$2.type) === 'TSVoidKeyword';
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* @callback PromiseFilter
|
|
28
|
+
* @param {object} node
|
|
29
|
+
* @returns {boolean}
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Checks if a node has a return statement. Void return does not count.
|
|
34
|
+
*
|
|
35
|
+
* @param {object} node
|
|
36
|
+
* @param {PromiseFilter} promFilter
|
|
37
|
+
* @returns {boolean|Node}
|
|
38
|
+
*/
|
|
39
|
+
// eslint-disable-next-line complexity
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const hasReturnValue = (node, promFilter) => {
|
|
43
|
+
var _node$returnType, _node$returnType$type;
|
|
44
|
+
|
|
45
|
+
if (!node) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
switch (node.type) {
|
|
50
|
+
case 'TSFunctionType':
|
|
51
|
+
case 'TSMethodSignature':
|
|
52
|
+
return !['TSVoidKeyword', 'TSUndefinedKeyword'].includes(node === null || node === void 0 ? void 0 : (_node$returnType = node.returnType) === null || _node$returnType === void 0 ? void 0 : (_node$returnType$type = _node$returnType.typeAnnotation) === null || _node$returnType$type === void 0 ? void 0 : _node$returnType$type.type);
|
|
53
|
+
|
|
54
|
+
case 'MethodDefinition':
|
|
55
|
+
return hasReturnValue(node.value, promFilter);
|
|
56
|
+
|
|
57
|
+
case 'FunctionExpression':
|
|
58
|
+
case 'FunctionDeclaration':
|
|
59
|
+
case 'ArrowFunctionExpression':
|
|
60
|
+
{
|
|
61
|
+
return node.expression && (!isNewPromiseExpression(node.body) || !isVoidPromise(node.body)) || hasReturnValue(node.body, promFilter);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
case 'BlockStatement':
|
|
65
|
+
{
|
|
66
|
+
return node.body.some(bodyNode => {
|
|
67
|
+
return bodyNode.type !== 'FunctionDeclaration' && hasReturnValue(bodyNode, promFilter);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
case 'LabeledStatement':
|
|
72
|
+
case 'WhileStatement':
|
|
73
|
+
case 'DoWhileStatement':
|
|
74
|
+
case 'ForStatement':
|
|
75
|
+
case 'ForInStatement':
|
|
76
|
+
case 'ForOfStatement':
|
|
77
|
+
case 'WithStatement':
|
|
78
|
+
{
|
|
79
|
+
return hasReturnValue(node.body, promFilter);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
case 'IfStatement':
|
|
83
|
+
{
|
|
84
|
+
return hasReturnValue(node.consequent, promFilter) || hasReturnValue(node.alternate, promFilter);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
case 'TryStatement':
|
|
88
|
+
{
|
|
89
|
+
return hasReturnValue(node.block, promFilter) || hasReturnValue(node.handler && node.handler.body, promFilter) || hasReturnValue(node.finalizer, promFilter);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
case 'SwitchStatement':
|
|
93
|
+
{
|
|
94
|
+
return node.cases.some(someCase => {
|
|
95
|
+
return someCase.consequent.some(nde => {
|
|
96
|
+
return hasReturnValue(nde, promFilter);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
case 'ReturnStatement':
|
|
102
|
+
{
|
|
103
|
+
// void return does not count.
|
|
104
|
+
if (node.argument === null) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (promFilter && isNewPromiseExpression(node.argument)) {
|
|
109
|
+
// Let caller decide how to filter, but this is, at the least,
|
|
110
|
+
// a return of sorts and truthy
|
|
111
|
+
return promFilter(node.argument);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
default:
|
|
118
|
+
{
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Avoids further checking child nodes if a nested function shadows the
|
|
125
|
+
* resolver, but otherwise, if name is used (by call or passed in as an
|
|
126
|
+
* argument to another function), will be considered as non-empty.
|
|
127
|
+
*
|
|
128
|
+
* This could check for redeclaration of the resolver, but as such is
|
|
129
|
+
* unlikely, we avoid the performance cost of checking everywhere for
|
|
130
|
+
* (re)declarations or assignments.
|
|
131
|
+
*
|
|
132
|
+
* @param {AST} node
|
|
133
|
+
* @param {string} resolverName
|
|
134
|
+
* @returns {boolean}
|
|
135
|
+
*/
|
|
136
|
+
// eslint-disable-next-line complexity
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
exports.hasReturnValue = hasReturnValue;
|
|
140
|
+
|
|
141
|
+
const hasNonEmptyResolverCall = (node, resolverName) => {
|
|
142
|
+
if (!node) {
|
|
143
|
+
return false;
|
|
144
|
+
} // Arrow function without block
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
switch (node.type) {
|
|
148
|
+
// istanbul ignore next -- In Babel?
|
|
149
|
+
case 'OptionalCallExpression':
|
|
150
|
+
case 'CallExpression':
|
|
151
|
+
return node.callee.name === resolverName && ( // Implicit or explicit undefined
|
|
152
|
+
node.arguments.length > 1 || node.arguments[0] !== undefined) || node.arguments.some(nde => {
|
|
153
|
+
// Being passed in to another function (which might invoke it)
|
|
154
|
+
return nde.type === 'Identifier' && nde.name === resolverName || // Handle nested items
|
|
155
|
+
hasNonEmptyResolverCall(nde, resolverName);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
case 'ChainExpression':
|
|
159
|
+
case 'Decorator':
|
|
160
|
+
case 'ExpressionStatement':
|
|
161
|
+
return hasNonEmptyResolverCall(node.expression, resolverName);
|
|
162
|
+
|
|
163
|
+
case 'ClassBody':
|
|
164
|
+
case 'BlockStatement':
|
|
165
|
+
return node.body.some(bodyNode => {
|
|
166
|
+
return hasNonEmptyResolverCall(bodyNode, resolverName);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
case 'FunctionExpression':
|
|
170
|
+
case 'FunctionDeclaration':
|
|
171
|
+
case 'ArrowFunctionExpression':
|
|
172
|
+
{
|
|
173
|
+
var _node$params$;
|
|
174
|
+
|
|
175
|
+
// Shadowing
|
|
176
|
+
if (((_node$params$ = node.params[0]) === null || _node$params$ === void 0 ? void 0 : _node$params$.name) === resolverName) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return hasNonEmptyResolverCall(node.body, resolverName);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
case 'LabeledStatement':
|
|
184
|
+
case 'WhileStatement':
|
|
185
|
+
case 'DoWhileStatement':
|
|
186
|
+
case 'ForStatement':
|
|
187
|
+
case 'ForInStatement':
|
|
188
|
+
case 'ForOfStatement':
|
|
189
|
+
case 'WithStatement':
|
|
190
|
+
{
|
|
191
|
+
return hasNonEmptyResolverCall(node.body, resolverName);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
case 'ConditionalExpression':
|
|
195
|
+
case 'IfStatement':
|
|
196
|
+
{
|
|
197
|
+
return hasNonEmptyResolverCall(node.test, resolverName) || hasNonEmptyResolverCall(node.consequent, resolverName) || hasNonEmptyResolverCall(node.alternate, resolverName);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
case 'TryStatement':
|
|
201
|
+
{
|
|
202
|
+
return hasNonEmptyResolverCall(node.block, resolverName) || hasNonEmptyResolverCall(node.handler && node.handler.body, resolverName) || hasNonEmptyResolverCall(node.finalizer, resolverName);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
case 'SwitchStatement':
|
|
206
|
+
{
|
|
207
|
+
return node.cases.some(someCase => {
|
|
208
|
+
return someCase.consequent.some(nde => {
|
|
209
|
+
return hasNonEmptyResolverCall(nde, resolverName);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
case 'ArrayPattern':
|
|
215
|
+
case 'ArrayExpression':
|
|
216
|
+
return node.elements.some(element => {
|
|
217
|
+
return hasNonEmptyResolverCall(element, resolverName);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
case 'AssignmentPattern':
|
|
221
|
+
return hasNonEmptyResolverCall(node.right, resolverName);
|
|
222
|
+
|
|
223
|
+
case 'AssignmentExpression':
|
|
224
|
+
case 'BinaryExpression':
|
|
225
|
+
case 'LogicalExpression':
|
|
226
|
+
{
|
|
227
|
+
return hasNonEmptyResolverCall(node.left, resolverName) || hasNonEmptyResolverCall(node.right, resolverName);
|
|
228
|
+
}
|
|
229
|
+
// Comma
|
|
230
|
+
|
|
231
|
+
case 'SequenceExpression':
|
|
232
|
+
case 'TemplateLiteral':
|
|
233
|
+
return node.expressions.some(subExpression => {
|
|
234
|
+
return hasNonEmptyResolverCall(subExpression, resolverName);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
case 'ObjectPattern':
|
|
238
|
+
case 'ObjectExpression':
|
|
239
|
+
return node.properties.some(property => {
|
|
240
|
+
return hasNonEmptyResolverCall(property, resolverName);
|
|
241
|
+
});
|
|
242
|
+
// istanbul ignore next -- In Babel?
|
|
243
|
+
|
|
244
|
+
case 'ClassMethod':
|
|
245
|
+
case 'MethodDefinition':
|
|
246
|
+
return node.decorators && node.decorators.some(decorator => {
|
|
247
|
+
return hasNonEmptyResolverCall(decorator, resolverName);
|
|
248
|
+
}) || node.computed && hasNonEmptyResolverCall(node.key, resolverName) || hasNonEmptyResolverCall(node.value, resolverName);
|
|
249
|
+
// istanbul ignore next -- In Babel?
|
|
250
|
+
|
|
251
|
+
case 'ObjectProperty':
|
|
252
|
+
/* eslint-disable no-fallthrough */
|
|
253
|
+
// istanbul ignore next -- In Babel?
|
|
254
|
+
|
|
255
|
+
case 'PropertyDefinition': // istanbul ignore next -- In Babel?
|
|
256
|
+
|
|
257
|
+
case 'ClassProperty':
|
|
258
|
+
/* eslint-enable no-fallthrough */
|
|
259
|
+
|
|
260
|
+
case 'Property':
|
|
261
|
+
return node.computed && hasNonEmptyResolverCall(node.key, resolverName) || hasNonEmptyResolverCall(node.value, resolverName);
|
|
262
|
+
// istanbul ignore next -- In Babel?
|
|
263
|
+
|
|
264
|
+
case 'ObjectMethod':
|
|
265
|
+
// istanbul ignore next -- In Babel?
|
|
266
|
+
return node.computed && hasNonEmptyResolverCall(node.key, resolverName) || node.arguments.some(nde => {
|
|
267
|
+
return hasNonEmptyResolverCall(nde, resolverName);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
case 'ClassExpression':
|
|
271
|
+
case 'ClassDeclaration':
|
|
272
|
+
return hasNonEmptyResolverCall(node.body, resolverName);
|
|
273
|
+
|
|
274
|
+
case 'AwaitExpression':
|
|
275
|
+
case 'SpreadElement':
|
|
276
|
+
case 'UnaryExpression':
|
|
277
|
+
case 'YieldExpression':
|
|
278
|
+
return hasNonEmptyResolverCall(node.argument, resolverName);
|
|
279
|
+
|
|
280
|
+
case 'VariableDeclaration':
|
|
281
|
+
{
|
|
282
|
+
return node.declarations.some(nde => {
|
|
283
|
+
return hasNonEmptyResolverCall(nde, resolverName);
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
case 'VariableDeclarator':
|
|
288
|
+
{
|
|
289
|
+
return hasNonEmptyResolverCall(node.id, resolverName) || hasNonEmptyResolverCall(node.init, resolverName);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
case 'TaggedTemplateExpression':
|
|
293
|
+
return hasNonEmptyResolverCall(node.quasi, resolverName);
|
|
294
|
+
// ?.
|
|
295
|
+
// istanbul ignore next -- In Babel?
|
|
296
|
+
|
|
297
|
+
case 'OptionalMemberExpression':
|
|
298
|
+
case 'MemberExpression':
|
|
299
|
+
return hasNonEmptyResolverCall(node.object, resolverName) || hasNonEmptyResolverCall(node.property, resolverName);
|
|
300
|
+
// istanbul ignore next -- In Babel?
|
|
301
|
+
|
|
302
|
+
case 'Import':
|
|
303
|
+
case 'ImportExpression':
|
|
304
|
+
return hasNonEmptyResolverCall(node.source, resolverName);
|
|
305
|
+
|
|
306
|
+
case 'ReturnStatement':
|
|
307
|
+
{
|
|
308
|
+
if (node.argument === null) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return hasNonEmptyResolverCall(node.argument, resolverName);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/*
|
|
316
|
+
// Shouldn't need to parse literals/literal components, etc.
|
|
317
|
+
case 'Identifier':
|
|
318
|
+
case 'TemplateElement':
|
|
319
|
+
case 'Super':
|
|
320
|
+
// Exports not relevant in this context
|
|
321
|
+
*/
|
|
322
|
+
|
|
323
|
+
default:
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
/**
|
|
328
|
+
* Checks if a Promise executor has no resolve value or an empty value.
|
|
329
|
+
* An `undefined` resolve does not count.
|
|
330
|
+
*
|
|
331
|
+
* @param {object} node
|
|
332
|
+
* @param {boolean} anyPromiseAsReturn
|
|
333
|
+
* @returns {boolean}
|
|
334
|
+
*/
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
const hasValueOrExecutorHasNonEmptyResolveValue = (node, anyPromiseAsReturn) => {
|
|
338
|
+
return hasReturnValue(node, prom => {
|
|
339
|
+
if (anyPromiseAsReturn) {
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (isVoidPromise(prom)) {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const [{
|
|
348
|
+
params,
|
|
349
|
+
body
|
|
350
|
+
} = {}] = prom.arguments;
|
|
351
|
+
|
|
352
|
+
if (!(params !== null && params !== void 0 && params.length)) {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const [{
|
|
357
|
+
name: resolverName
|
|
358
|
+
}] = params;
|
|
359
|
+
return hasNonEmptyResolverCall(body, resolverName);
|
|
360
|
+
});
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
exports.hasValueOrExecutorHasNonEmptyResolveValue = hasValueOrExecutorHasNonEmptyResolveValue;
|
|
364
|
+
//# sourceMappingURL=hasReturnValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hasReturnValue.js","names":["isNewPromiseExpression","node","type","callee","name","isVoidPromise","typeParameters","params","hasReturnValue","promFilter","includes","returnType","typeAnnotation","value","expression","body","some","bodyNode","consequent","alternate","block","handler","finalizer","cases","someCase","nde","argument","hasNonEmptyResolverCall","resolverName","arguments","length","undefined","test","elements","element","right","left","expressions","subExpression","properties","property","decorators","decorator","computed","key","declarations","id","init","quasi","object","source","hasValueOrExecutorHasNonEmptyResolveValue","anyPromiseAsReturn","prom"],"sources":["../../src/utils/hasReturnValue.js"],"sourcesContent":["/* eslint-disable jsdoc/no-undefined-types */\n/**\n * Checks if a node is a promise but has no resolve value or an empty value.\n * An `undefined` resolve does not count.\n *\n * @param {object} node\n * @returns {boolean}\n */\nconst isNewPromiseExpression = (node) => {\n return node && node.type === 'NewExpression' && node.callee.type === 'Identifier' &&\n node.callee.name === 'Promise';\n};\n\nconst isVoidPromise = (node) => {\n return node?.typeParameters?.params?.[0]?.type === 'TSVoidKeyword';\n};\n\n/**\n * @callback PromiseFilter\n * @param {object} node\n * @returns {boolean}\n */\n\n/**\n * Checks if a node has a return statement. Void return does not count.\n *\n * @param {object} node\n * @param {PromiseFilter} promFilter\n * @returns {boolean|Node}\n */\n// eslint-disable-next-line complexity\nconst hasReturnValue = (node, promFilter) => {\n if (!node) {\n return false;\n }\n\n switch (node.type) {\n case 'TSFunctionType':\n case 'TSMethodSignature':\n return ![\n 'TSVoidKeyword',\n 'TSUndefinedKeyword',\n ].includes(node?.returnType?.typeAnnotation?.type);\n case 'MethodDefinition':\n return hasReturnValue(node.value, promFilter);\n case 'FunctionExpression':\n case 'FunctionDeclaration':\n case 'ArrowFunctionExpression': {\n return node.expression && (!isNewPromiseExpression(node.body) || !isVoidPromise(node.body)) ||\n hasReturnValue(node.body, promFilter);\n }\n\n case 'BlockStatement': {\n return node.body.some((bodyNode) => {\n return bodyNode.type !== 'FunctionDeclaration' && hasReturnValue(bodyNode, promFilter);\n });\n }\n\n case 'LabeledStatement':\n case 'WhileStatement':\n case 'DoWhileStatement':\n case 'ForStatement':\n case 'ForInStatement':\n case 'ForOfStatement':\n case 'WithStatement': {\n return hasReturnValue(node.body, promFilter);\n }\n\n case 'IfStatement': {\n return hasReturnValue(node.consequent, promFilter) || hasReturnValue(node.alternate, promFilter);\n }\n\n case 'TryStatement': {\n return hasReturnValue(node.block, promFilter) ||\n hasReturnValue(node.handler && node.handler.body, promFilter) ||\n hasReturnValue(node.finalizer, promFilter);\n }\n\n case 'SwitchStatement': {\n return node.cases.some(\n (someCase) => {\n return someCase.consequent.some((nde) => {\n return hasReturnValue(nde, promFilter);\n });\n },\n );\n }\n\n case 'ReturnStatement': {\n // void return does not count.\n if (node.argument === null) {\n return false;\n }\n\n if (promFilter && isNewPromiseExpression(node.argument)) {\n // Let caller decide how to filter, but this is, at the least,\n // a return of sorts and truthy\n return promFilter(node.argument);\n }\n\n return true;\n }\n\n default: {\n return false;\n }\n }\n};\n\n/**\n * Avoids further checking child nodes if a nested function shadows the\n * resolver, but otherwise, if name is used (by call or passed in as an\n * argument to another function), will be considered as non-empty.\n *\n * This could check for redeclaration of the resolver, but as such is\n * unlikely, we avoid the performance cost of checking everywhere for\n * (re)declarations or assignments.\n *\n * @param {AST} node\n * @param {string} resolverName\n * @returns {boolean}\n */\n// eslint-disable-next-line complexity\nconst hasNonEmptyResolverCall = (node, resolverName) => {\n if (!node) {\n return false;\n }\n\n // Arrow function without block\n switch (node.type) {\n // istanbul ignore next -- In Babel?\n case 'OptionalCallExpression':\n case 'CallExpression':\n return node.callee.name === resolverName && (\n\n // Implicit or explicit undefined\n node.arguments.length > 1 || node.arguments[0] !== undefined\n ) ||\n node.arguments.some((nde) => {\n // Being passed in to another function (which might invoke it)\n return nde.type === 'Identifier' && nde.name === resolverName ||\n\n // Handle nested items\n hasNonEmptyResolverCall(nde, resolverName);\n });\n case 'ChainExpression':\n case 'Decorator':\n case 'ExpressionStatement':\n return hasNonEmptyResolverCall(node.expression, resolverName);\n case 'ClassBody':\n case 'BlockStatement':\n return node.body.some((bodyNode) => {\n return hasNonEmptyResolverCall(bodyNode, resolverName);\n });\n case 'FunctionExpression':\n case 'FunctionDeclaration':\n case 'ArrowFunctionExpression': {\n // Shadowing\n if (node.params[0]?.name === resolverName) {\n return false;\n }\n\n return hasNonEmptyResolverCall(node.body, resolverName);\n }\n\n case 'LabeledStatement':\n case 'WhileStatement':\n case 'DoWhileStatement':\n case 'ForStatement':\n case 'ForInStatement':\n case 'ForOfStatement':\n case 'WithStatement': {\n return hasNonEmptyResolverCall(node.body, resolverName);\n }\n\n case 'ConditionalExpression':\n case 'IfStatement': {\n return hasNonEmptyResolverCall(node.test, resolverName) ||\n hasNonEmptyResolverCall(node.consequent, resolverName) ||\n hasNonEmptyResolverCall(node.alternate, resolverName);\n }\n\n case 'TryStatement': {\n return hasNonEmptyResolverCall(node.block, resolverName) ||\n hasNonEmptyResolverCall(node.handler && node.handler.body, resolverName) ||\n hasNonEmptyResolverCall(node.finalizer, resolverName);\n }\n\n case 'SwitchStatement': {\n return node.cases.some(\n (someCase) => {\n return someCase.consequent.some((nde) => {\n return hasNonEmptyResolverCall(nde, resolverName);\n });\n },\n );\n }\n\n case 'ArrayPattern':\n case 'ArrayExpression':\n return node.elements.some((element) => {\n return hasNonEmptyResolverCall(element, resolverName);\n });\n\n case 'AssignmentPattern':\n return hasNonEmptyResolverCall(node.right, resolverName);\n\n case 'AssignmentExpression':\n case 'BinaryExpression':\n case 'LogicalExpression': {\n return hasNonEmptyResolverCall(node.left, resolverName) ||\n hasNonEmptyResolverCall(node.right, resolverName);\n }\n\n // Comma\n case 'SequenceExpression':\n case 'TemplateLiteral':\n return node.expressions.some((subExpression) => {\n return hasNonEmptyResolverCall(subExpression, resolverName);\n });\n\n case 'ObjectPattern':\n case 'ObjectExpression':\n return node.properties.some((property) => {\n return hasNonEmptyResolverCall(property, resolverName);\n });\n // istanbul ignore next -- In Babel?\n case 'ClassMethod':\n case 'MethodDefinition':\n return node.decorators && node.decorators.some((decorator) => {\n return hasNonEmptyResolverCall(decorator, resolverName);\n }) ||\n node.computed && hasNonEmptyResolverCall(node.key, resolverName) ||\n hasNonEmptyResolverCall(node.value, resolverName);\n\n // istanbul ignore next -- In Babel?\n case 'ObjectProperty':\n /* eslint-disable no-fallthrough */\n // istanbul ignore next -- In Babel?\n case 'PropertyDefinition':\n // istanbul ignore next -- In Babel?\n case 'ClassProperty':\n /* eslint-enable no-fallthrough */\n case 'Property':\n return node.computed && hasNonEmptyResolverCall(node.key, resolverName) ||\n hasNonEmptyResolverCall(node.value, resolverName);\n // istanbul ignore next -- In Babel?\n case 'ObjectMethod':\n // istanbul ignore next -- In Babel?\n return node.computed && hasNonEmptyResolverCall(node.key, resolverName) ||\n node.arguments.some((nde) => {\n return hasNonEmptyResolverCall(nde, resolverName);\n });\n\n case 'ClassExpression':\n case 'ClassDeclaration':\n return hasNonEmptyResolverCall(node.body, resolverName);\n\n case 'AwaitExpression':\n case 'SpreadElement':\n case 'UnaryExpression':\n case 'YieldExpression':\n return hasNonEmptyResolverCall(node.argument, resolverName);\n\n case 'VariableDeclaration': {\n return node.declarations.some((nde) => {\n return hasNonEmptyResolverCall(nde, resolverName);\n });\n }\n\n case 'VariableDeclarator': {\n return hasNonEmptyResolverCall(node.id, resolverName) ||\n hasNonEmptyResolverCall(node.init, resolverName);\n }\n\n case 'TaggedTemplateExpression':\n return hasNonEmptyResolverCall(node.quasi, resolverName);\n\n // ?.\n // istanbul ignore next -- In Babel?\n case 'OptionalMemberExpression':\n case 'MemberExpression':\n return hasNonEmptyResolverCall(node.object, resolverName) ||\n hasNonEmptyResolverCall(node.property, resolverName);\n\n // istanbul ignore next -- In Babel?\n case 'Import':\n case 'ImportExpression':\n return hasNonEmptyResolverCall(node.source, resolverName);\n\n case 'ReturnStatement': {\n if (node.argument === null) {\n return false;\n }\n\n return hasNonEmptyResolverCall(node.argument, resolverName);\n }\n\n /*\n // Shouldn't need to parse literals/literal components, etc.\n\n case 'Identifier':\n case 'TemplateElement':\n case 'Super':\n // Exports not relevant in this context\n */\n default:\n return false;\n }\n};\n\n/**\n * Checks if a Promise executor has no resolve value or an empty value.\n * An `undefined` resolve does not count.\n *\n * @param {object} node\n * @param {boolean} anyPromiseAsReturn\n * @returns {boolean}\n */\nconst hasValueOrExecutorHasNonEmptyResolveValue = (node, anyPromiseAsReturn) => {\n return hasReturnValue(node, (prom) => {\n if (anyPromiseAsReturn) {\n return true;\n }\n\n if (isVoidPromise(prom)) {\n return false;\n }\n\n const [\n {\n params,\n body,\n } = {},\n ] = prom.arguments;\n\n if (!params?.length) {\n return false;\n }\n\n const [\n {\n name: resolverName,\n },\n ] = params;\n\n return hasNonEmptyResolverCall(body, resolverName);\n });\n};\n\nexport {\n hasReturnValue,\n hasValueOrExecutorHasNonEmptyResolveValue,\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
package/CONTRIBUTING.md
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# CONTRIBUTING to eslint-plugin-jsdoc
|
|
2
|
-
|
|
3
|
-
## Testing changes locally
|
|
4
|
-
|
|
5
|
-
You might try a TDD approach and add tests within the `test` directory,
|
|
6
|
-
to try different configs you may find it easier to try out changes in
|
|
7
|
-
a separate local directory.
|
|
8
|
-
|
|
9
|
-
You can run [`npm link`](https://docs.npmjs.com/cli/link) for this purpose,
|
|
10
|
-
pointing from your project to this project. For example, while in your project
|
|
11
|
-
root and with `eslint-plugin-jsdoc` as a sibling, run:
|
|
12
|
-
|
|
13
|
-
```shell
|
|
14
|
-
npm link ../eslint-plugin-jsdoc
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Building the project
|
|
18
|
-
|
|
19
|
-
After running `npm install` to get the latest dependencies and devDependencies,
|
|
20
|
-
you can run the following command to update the `dist` files, with `dist/index.js`
|
|
21
|
-
being the `main` entry point from `package.json`:
|
|
22
|
-
|
|
23
|
-
```shell
|
|
24
|
-
npm run build
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Coding standards
|
|
28
|
-
|
|
29
|
-
The project follows ESLint rules from [`canonical`](https://www.npmjs.com/package/eslint-config-canonical)
|
|
30
|
-
and testing follows its subconfig, `canonical/mocha`. You can run
|
|
31
|
-
`npm run lint` to check the linting if your IDE is not already indicating
|
|
32
|
-
items needing fixing.
|
|
33
|
-
|
|
34
|
-
## Documentation building
|
|
35
|
-
|
|
36
|
-
To make changes that are reflected in the README, you will need to
|
|
37
|
-
modify files within the `.README` directory. `.README/README.md` contains the
|
|
38
|
-
main README skeleton and details on the project, its global `settings`, etc.,
|
|
39
|
-
while the documentation for specific rules (that will be pulled into the
|
|
40
|
-
README) ought to be modified within the relevant file within `.README/rules`.
|
|
41
|
-
Once these files are modified, you can run `npm run create-readme` to have
|
|
42
|
-
these files integrated into the main `/README.md`. While you should include
|
|
43
|
-
the built file in your PR, you will not want to make manual changes
|
|
44
|
-
directly to this file, as they will be overwritten.
|
|
45
|
-
|
|
46
|
-
## Testing
|
|
47
|
-
|
|
48
|
-
Tests are expected. Each rule file should be in CamelCase (despite the rule names themselves being hyphenated) and should be added within `test/assertions` and then imported/required by
|
|
49
|
-
`test/rules/index.js`.
|
|
50
|
-
|
|
51
|
-
Each rule file should be an ESM default export of an object that has `valid` and `invalid` array properties containing the tests. Tests of each type should be provided.
|
|
52
|
-
|
|
53
|
-
`parserOptions` will be `ecmaVersion: 6` by default, but tests can override `parserOptions`
|
|
54
|
-
with their own.
|
|
55
|
-
|
|
56
|
-
See ESLint's [RuleTester](https://eslint.org/docs/developer-guide/nodejs-api#ruletester)
|
|
57
|
-
for more on the allowable properties (e.g., `code`, `errors` (for invalid rules),
|
|
58
|
-
`options`, `settings`, etc.).
|
|
59
|
-
|
|
60
|
-
Note that besides `npm test` there is `npm run test-cov`, which shows more
|
|
61
|
-
detailed coverage information. Coverage should be maintained at 100%, and
|
|
62
|
-
if there are a few guards in place for future use, the code block in question
|
|
63
|
-
can be ignored by being preceded by `/* istanbul ignore next */` (including
|
|
64
|
-
for warnings where the block is never passed over (i.e., the block is always
|
|
65
|
-
entered)). If you want to test without coverage at all, you can use
|
|
66
|
-
`npm run test-no-cov`. To only test rules rather than other files, you
|
|
67
|
-
can use `npm run test-index`.
|
|
68
|
-
|
|
69
|
-
To test specific rules, you can supply a comma-separated list with the `--rule`
|
|
70
|
-
flag passed to `test-index`, e.g., for `check-examples` and `require-example`:
|
|
71
|
-
|
|
72
|
-
`npm run test-index --rule=check-examples,require-example`.
|
|
73
|
-
|
|
74
|
-
You can further limit this by providing `--invalid` and/or `--valid` flags
|
|
75
|
-
with a comma-separated list of 0-based indexes that you wish to include (also
|
|
76
|
-
accepts negative offsets from the end, e.g., `-1` for the last item). For
|
|
77
|
-
example, to check the first and third invalid tests of `check-examples`
|
|
78
|
-
along with the second valid test, you can run:
|
|
79
|
-
|
|
80
|
-
`npm run --rule=check-examples --invalid=0,2 --valid=1 test-index`.
|
|
81
|
-
|
|
82
|
-
## Requirements for PRs
|
|
83
|
-
|
|
84
|
-
PRs should be mergeable, [rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)
|
|
85
|
-
first against the latest `master`.
|
|
86
|
-
|
|
87
|
-
The number of commits will ideally be limited unless extra commits
|
|
88
|
-
can better show a progression of features.
|
|
89
|
-
|
|
90
|
-
Commit messages should be worded clearly and the reason for any PR made clear
|
|
91
|
-
by linking to an issue or giving a full description of what it achieves.
|
|
92
|
-
|
|
93
|
-
## Merging
|
|
94
|
-
|
|
95
|
-
We use [semantic-release](https://github.com/semantic-release/semantic-release)
|
|
96
|
-
for preparing releases, so the commit messages (or at least the merge that
|
|
97
|
-
brings them into `master`) must follow the
|
|
98
|
-
[AngularJS commit guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines) with a special format such as `feat: describe new feature`
|
|
99
|
-
for releases to occur and for the described items to be added
|
|
100
|
-
to the release notes.
|