eslint-plugin-jsdoc 48.0.0 → 48.0.1

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.
Files changed (64) hide show
  1. package/package.json +1 -1
  2. package/src/WarnSettings.js +34 -0
  3. package/src/alignTransform.js +356 -0
  4. package/src/defaultTagOrder.js +168 -0
  5. package/src/exportParser.js +957 -0
  6. package/src/getDefaultTagStructureForMode.js +969 -0
  7. package/src/index.js +266 -0
  8. package/src/iterateJsdoc.js +2555 -0
  9. package/src/jsdocUtils.js +1693 -0
  10. package/src/rules/checkAccess.js +45 -0
  11. package/src/rules/checkAlignment.js +63 -0
  12. package/src/rules/checkExamples.js +594 -0
  13. package/src/rules/checkIndentation.js +75 -0
  14. package/src/rules/checkLineAlignment.js +364 -0
  15. package/src/rules/checkParamNames.js +404 -0
  16. package/src/rules/checkPropertyNames.js +152 -0
  17. package/src/rules/checkSyntax.js +30 -0
  18. package/src/rules/checkTagNames.js +314 -0
  19. package/src/rules/checkTypes.js +535 -0
  20. package/src/rules/checkValues.js +220 -0
  21. package/src/rules/emptyTags.js +88 -0
  22. package/src/rules/implementsOnClasses.js +64 -0
  23. package/src/rules/importsAsDependencies.js +131 -0
  24. package/src/rules/informativeDocs.js +182 -0
  25. package/src/rules/matchDescription.js +286 -0
  26. package/src/rules/matchName.js +147 -0
  27. package/src/rules/multilineBlocks.js +333 -0
  28. package/src/rules/noBadBlocks.js +109 -0
  29. package/src/rules/noBlankBlockDescriptions.js +69 -0
  30. package/src/rules/noBlankBlocks.js +53 -0
  31. package/src/rules/noDefaults.js +85 -0
  32. package/src/rules/noMissingSyntax.js +195 -0
  33. package/src/rules/noMultiAsterisks.js +134 -0
  34. package/src/rules/noRestrictedSyntax.js +91 -0
  35. package/src/rules/noTypes.js +73 -0
  36. package/src/rules/noUndefinedTypes.js +328 -0
  37. package/src/rules/requireAsteriskPrefix.js +189 -0
  38. package/src/rules/requireDescription.js +161 -0
  39. package/src/rules/requireDescriptionCompleteSentence.js +333 -0
  40. package/src/rules/requireExample.js +118 -0
  41. package/src/rules/requireFileOverview.js +154 -0
  42. package/src/rules/requireHyphenBeforeParamDescription.js +178 -0
  43. package/src/rules/requireJsdoc.js +629 -0
  44. package/src/rules/requireParam.js +592 -0
  45. package/src/rules/requireParamDescription.js +89 -0
  46. package/src/rules/requireParamName.js +55 -0
  47. package/src/rules/requireParamType.js +89 -0
  48. package/src/rules/requireProperty.js +48 -0
  49. package/src/rules/requirePropertyDescription.js +25 -0
  50. package/src/rules/requirePropertyName.js +25 -0
  51. package/src/rules/requirePropertyType.js +25 -0
  52. package/src/rules/requireReturns.js +238 -0
  53. package/src/rules/requireReturnsCheck.js +141 -0
  54. package/src/rules/requireReturnsDescription.js +59 -0
  55. package/src/rules/requireReturnsType.js +51 -0
  56. package/src/rules/requireThrows.js +111 -0
  57. package/src/rules/requireYields.js +216 -0
  58. package/src/rules/requireYieldsCheck.js +208 -0
  59. package/src/rules/sortTags.js +557 -0
  60. package/src/rules/tagLines.js +359 -0
  61. package/src/rules/textEscaping.js +146 -0
  62. package/src/rules/validTypes.js +368 -0
  63. package/src/tagNames.js +234 -0
  64. package/src/utils/hasReturnValue.js +549 -0
@@ -0,0 +1,957 @@
1
+ import {
2
+ findJSDocComment,
3
+ } from '@es-joy/jsdoccomment';
4
+ import debugModule from 'debug';
5
+
6
+ const debug = debugModule('requireExportJsdoc');
7
+
8
+ /**
9
+ * @typedef {{
10
+ * value: string
11
+ * }} ValueObject
12
+ */
13
+
14
+ /**
15
+ * @typedef {{
16
+ * type?: string,
17
+ * value?: ValueObject|import('eslint').Rule.Node,
18
+ * props: {
19
+ * [key: string]: CreatedNode|null,
20
+ * },
21
+ * special?: true,
22
+ * globalVars?: CreatedNode,
23
+ * exported?: boolean,
24
+ * ANONYMOUS_DEFAULT?: import('eslint').Rule.Node
25
+ * }} CreatedNode
26
+ */
27
+
28
+ /**
29
+ * @returns {CreatedNode}
30
+ */
31
+ const createNode = function () {
32
+ return {
33
+ props: {},
34
+ };
35
+ };
36
+
37
+ /**
38
+ * @param {CreatedNode|null} symbol
39
+ * @returns {string|null}
40
+ */
41
+ const getSymbolValue = function (symbol) {
42
+ /* c8 ignore next 3 */
43
+ if (!symbol) {
44
+ return null;
45
+ }
46
+
47
+ /* c8 ignore else */
48
+ if (symbol.type === 'literal') {
49
+ return /** @type {ValueObject} */ (symbol.value).value;
50
+ }
51
+ /* c8 ignore next */
52
+ return null;
53
+ };
54
+
55
+ /**
56
+ *
57
+ * @param {import('estree').Identifier} node
58
+ * @param {CreatedNode} globals
59
+ * @param {CreatedNode} scope
60
+ * @param {SymbolOptions} opts
61
+ * @returns {CreatedNode|null}
62
+ */
63
+ const getIdentifier = function (node, globals, scope, opts) {
64
+ if (opts.simpleIdentifier) {
65
+ // Type is Identier for noncomputed properties
66
+ const identifierLiteral = createNode();
67
+ identifierLiteral.type = 'literal';
68
+ identifierLiteral.value = {
69
+ value: node.name,
70
+ };
71
+
72
+ return identifierLiteral;
73
+ }
74
+
75
+ /* c8 ignore next */
76
+ const block = scope || globals;
77
+
78
+ // As scopes are not currently supported, they are not traversed upwards recursively
79
+ if (block.props[node.name]) {
80
+ return block.props[node.name];
81
+ }
82
+
83
+ // Seems this will only be entered once scopes added and entered
84
+ /* c8 ignore next 3 */
85
+ if (globals.props[node.name]) {
86
+ return globals.props[node.name];
87
+ }
88
+
89
+ return null;
90
+ };
91
+
92
+ /**
93
+ * @callback CreateSymbol
94
+ * @param {import('eslint').Rule.Node|null} node
95
+ * @param {CreatedNode} globals
96
+ * @param {import('eslint').Rule.Node|null} value
97
+ * @param {CreatedNode} [scope]
98
+ * @param {boolean|SymbolOptions} [isGlobal]
99
+ * @returns {CreatedNode|null}
100
+ */
101
+
102
+ /** @type {CreateSymbol} */
103
+ let createSymbol; // eslint-disable-line prefer-const
104
+
105
+ /* eslint-disable complexity -- Temporary */
106
+
107
+ /**
108
+ * @typedef {{
109
+ * simpleIdentifier?: boolean
110
+ * }} SymbolOptions
111
+ */
112
+
113
+ /**
114
+ *
115
+ * @param {import('eslint').Rule.Node} node
116
+ * @param {CreatedNode} globals
117
+ * @param {CreatedNode} scope
118
+ * @param {SymbolOptions} [opt]
119
+ * @returns {CreatedNode|null}
120
+ */
121
+ const getSymbol = function (node, globals, scope, opt) {
122
+ /* eslint-enable complexity -- Temporary */
123
+ const opts = opt || {};
124
+ /* c8 ignore next */
125
+ switch (node.type) {
126
+ case 'Identifier': {
127
+ return getIdentifier(node, globals, scope, opts);
128
+ }
129
+
130
+ case 'MemberExpression': {
131
+ const obj = getSymbol(
132
+ /** @type {import('eslint').Rule.Node} */
133
+ (node.object),
134
+ globals,
135
+ scope,
136
+ opts,
137
+ );
138
+ const propertySymbol = getSymbol(
139
+ /** @type {import('eslint').Rule.Node} */
140
+ (node.property),
141
+ globals,
142
+ scope,
143
+ {
144
+ simpleIdentifier: !node.computed,
145
+ },
146
+ );
147
+ const propertyValue = getSymbolValue(propertySymbol);
148
+
149
+ /* c8 ignore else */
150
+ if (obj && propertyValue && obj.props[propertyValue]) {
151
+ const block = obj.props[propertyValue];
152
+
153
+ return block;
154
+ }
155
+ /* c8 ignore next 10 */
156
+ /*
157
+ if (opts.createMissingProps && propertyValue) {
158
+ obj.props[propertyValue] = createNode();
159
+
160
+ return obj.props[propertyValue];
161
+ }
162
+ */
163
+ debug(`MemberExpression: Missing property ${
164
+ /** @type {import('estree').PrivateIdentifier} */ (node.property).name
165
+ }`);
166
+ /* c8 ignore next 2 */
167
+ return null;
168
+ }
169
+
170
+ case 'ClassExpression': {
171
+ return getSymbol(
172
+ /** @type {import('eslint').Rule.Node} */
173
+ (node.body),
174
+ globals,
175
+ scope,
176
+ opts,
177
+ );
178
+ }
179
+
180
+ /* c8 ignore next 7 -- No longer needed? */
181
+ // @ts-expect-error TS OK
182
+ case 'TSTypeAliasDeclaration':
183
+ // @ts-expect-error TS OK
184
+ // Fallthrough
185
+ case 'TSEnumDeclaration':
186
+ // @ts-expect-error TS OK
187
+ case 'TSInterfaceDeclaration':
188
+ case 'ClassDeclaration':
189
+ case 'FunctionExpression': case 'FunctionDeclaration':
190
+ case 'ArrowFunctionExpression': {
191
+ const val = createNode();
192
+ val.props.prototype = createNode();
193
+ val.props.prototype.type = 'object';
194
+ val.type = 'object';
195
+ val.value = node;
196
+
197
+ return val;
198
+ }
199
+
200
+ case 'AssignmentExpression': {
201
+ return createSymbol(
202
+ /** @type {import('eslint').Rule.Node} */
203
+ (node.left),
204
+ globals,
205
+ /** @type {import('eslint').Rule.Node} */
206
+ (node.right),
207
+ scope,
208
+ opts,
209
+ );
210
+ }
211
+
212
+ case 'ClassBody': {
213
+ const val = createNode();
214
+ for (const method of node.body) {
215
+ val.props[
216
+ /** @type {import('estree').Identifier} */ (
217
+ /** @type {import('estree').MethodDefinition} */ (
218
+ method
219
+ ).key
220
+ ).name
221
+ ] = createNode();
222
+ /** @type {{[key: string]: CreatedNode}} */ (val.props)[
223
+ /** @type {import('estree').Identifier} */ (
224
+ /** @type {import('estree').MethodDefinition} */ (
225
+ method
226
+ ).key
227
+ ).name
228
+ ].type = 'object';
229
+ /** @type {{[key: string]: CreatedNode}} */ (val.props)[
230
+ /** @type {import('estree').Identifier} */ (
231
+ /** @type {import('estree').MethodDefinition} */ (
232
+ method
233
+ ).key
234
+ ).name
235
+ ].value = /** @type {import('eslint').Rule.Node} */ (
236
+ /** @type {import('estree').MethodDefinition} */ (method).value
237
+ );
238
+ }
239
+
240
+ val.type = 'object';
241
+ val.value = node.parent;
242
+
243
+ return val;
244
+ }
245
+
246
+ case 'ObjectExpression': {
247
+ const val = createNode();
248
+ val.type = 'object';
249
+ for (const prop of node.properties) {
250
+ if ([
251
+ // @typescript-eslint/parser, espree, acorn, etc.
252
+ 'SpreadElement',
253
+
254
+ // @babel/eslint-parser
255
+ 'ExperimentalSpreadProperty',
256
+ ].includes(prop.type)) {
257
+ continue;
258
+ }
259
+
260
+ const propVal = getSymbol(
261
+ /** @type {import('eslint').Rule.Node} */ (
262
+ /** @type {import('estree').Property} */
263
+ (prop).value
264
+ ),
265
+ globals,
266
+ scope,
267
+ opts,
268
+ );
269
+ /* c8 ignore next 8 */
270
+ if (propVal) {
271
+ val.props[
272
+ /** @type {import('estree').PrivateIdentifier} */
273
+ (
274
+ /** @type {import('estree').Property} */ (prop).key
275
+ ).name
276
+ ] = propVal;
277
+ }
278
+ }
279
+
280
+ return val;
281
+ }
282
+
283
+ case 'Literal': {
284
+ const val = createNode();
285
+ val.type = 'literal';
286
+ val.value = node;
287
+
288
+ return val;
289
+ }
290
+ }
291
+ /* c8 ignore next */
292
+ return null;
293
+ };
294
+
295
+ /**
296
+ *
297
+ * @param {CreatedNode} block
298
+ * @param {string} name
299
+ * @param {CreatedNode|null} value
300
+ * @param {CreatedNode} globals
301
+ * @param {boolean|SymbolOptions|undefined} isGlobal
302
+ * @returns {void}
303
+ */
304
+ const createBlockSymbol = function (block, name, value, globals, isGlobal) {
305
+ block.props[name] = value;
306
+ if (isGlobal && globals.props.window && globals.props.window.special) {
307
+ globals.props.window.props[name] = value;
308
+ }
309
+ };
310
+
311
+ createSymbol = function (node, globals, value, scope, isGlobal) {
312
+ const block = scope || globals;
313
+ /* c8 ignore next 3 */
314
+ if (!node) {
315
+ return null;
316
+ }
317
+
318
+ let symbol;
319
+ switch (node.type) {
320
+ case 'FunctionDeclaration':
321
+ /* c8 ignore next */
322
+ // @ts-expect-error TS OK
323
+ // Fall through
324
+ case 'TSEnumDeclaration': case 'TSInterfaceDeclaration':
325
+ /* c8 ignore next */
326
+ // @ts-expect-error TS OK
327
+ // Fall through
328
+ case 'TSTypeAliasDeclaration': case 'ClassDeclaration': {
329
+ const nde = /** @type {import('estree').ClassDeclaration} */ (node);
330
+ /* c8 ignore else */
331
+ if (nde.id && nde.id.type === 'Identifier') {
332
+ return createSymbol(
333
+ /** @type {import('eslint').Rule.Node} */ (nde.id),
334
+ globals,
335
+ node,
336
+ globals,
337
+ );
338
+ }
339
+ /* c8 ignore next 2 */
340
+ break;
341
+ }
342
+
343
+ case 'Identifier': {
344
+ const nde = /** @type {import('estree').Identifier} */ (node);
345
+ if (value) {
346
+ const valueSymbol = getSymbol(value, globals, block);
347
+ /* c8 ignore else */
348
+ if (valueSymbol) {
349
+ createBlockSymbol(block, nde.name, valueSymbol, globals, isGlobal);
350
+
351
+ return block.props[nde.name];
352
+ }
353
+ /* c8 ignore next */
354
+ debug('Identifier: Missing value symbol for %s', nde.name);
355
+ } else {
356
+ createBlockSymbol(block, nde.name, createNode(), globals, isGlobal);
357
+
358
+ return block.props[nde.name];
359
+ }
360
+ /* c8 ignore next 2 */
361
+ break;
362
+ }
363
+
364
+ case 'MemberExpression': {
365
+ const nde = /** @type {import('estree').MemberExpression} */ (node);
366
+ symbol = getSymbol(
367
+ /** @type {import('eslint').Rule.Node} */ (nde.object), globals, block,
368
+ );
369
+
370
+ const propertySymbol = getSymbol(
371
+ /** @type {import('eslint').Rule.Node} */ (nde.property),
372
+ globals,
373
+ block,
374
+ {
375
+ simpleIdentifier: !nde.computed,
376
+ },
377
+ );
378
+ const propertyValue = getSymbolValue(propertySymbol);
379
+ if (symbol && propertyValue) {
380
+ createBlockSymbol(symbol, propertyValue, getSymbol(
381
+ /** @type {import('eslint').Rule.Node} */
382
+ (value), globals, block,
383
+ ), globals, isGlobal);
384
+ return symbol.props[propertyValue];
385
+ }
386
+
387
+ debug(
388
+ 'MemberExpression: Missing symbol: %s',
389
+ /** @type {import('estree').Identifier} */ (
390
+ nde.property
391
+ ).name,
392
+ );
393
+ break;
394
+ }
395
+ }
396
+
397
+ return null;
398
+ };
399
+
400
+ /**
401
+ * Creates variables from variable definitions
402
+ * @param {import('eslint').Rule.Node} node
403
+ * @param {CreatedNode} globals
404
+ * @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opts
405
+ * @returns {void}
406
+ */
407
+ const initVariables = function (node, globals, opts) {
408
+ switch (node.type) {
409
+ case 'Program': {
410
+ for (const childNode of node.body) {
411
+ initVariables(
412
+ /** @type {import('eslint').Rule.Node} */
413
+ (childNode),
414
+ globals,
415
+ opts,
416
+ );
417
+ }
418
+
419
+ break;
420
+ }
421
+
422
+ case 'ExpressionStatement': {
423
+ initVariables(
424
+ /** @type {import('eslint').Rule.Node} */
425
+ (node.expression),
426
+ globals,
427
+ opts,
428
+ );
429
+ break;
430
+ }
431
+
432
+ case 'VariableDeclaration': {
433
+ for (const declaration of node.declarations) {
434
+ // let and const
435
+ const symbol = createSymbol(
436
+ /** @type {import('eslint').Rule.Node} */
437
+ (declaration.id),
438
+ globals,
439
+ null,
440
+ globals,
441
+ );
442
+ if (opts.initWindow && node.kind === 'var' && globals.props.window) {
443
+ // If var, also add to window
444
+ globals.props.window.props[
445
+ /** @type {import('estree').Identifier} */
446
+ (declaration.id).name
447
+ ] = symbol;
448
+ }
449
+ }
450
+
451
+ break;
452
+ }
453
+
454
+ case 'ExportNamedDeclaration': {
455
+ if (node.declaration) {
456
+ initVariables(
457
+ /** @type {import('eslint').Rule.Node} */
458
+ (node.declaration),
459
+ globals,
460
+ opts,
461
+ );
462
+ }
463
+
464
+ break;
465
+ }
466
+ }
467
+ };
468
+
469
+ /* eslint-disable complexity -- Temporary */
470
+
471
+ /**
472
+ * Populates variable maps using AST
473
+ * @param {import('eslint').Rule.Node} node
474
+ * @param {CreatedNode} globals
475
+ * @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opt
476
+ * @param {true} [isExport]
477
+ * @returns {boolean}
478
+ */
479
+ const mapVariables = function (node, globals, opt, isExport) {
480
+ /* eslint-enable complexity -- Temporary */
481
+ /* c8 ignore next */
482
+ const opts = opt || {};
483
+ /* c8 ignore next */
484
+ switch (node.type) {
485
+ case 'Program': {
486
+ if (opts.ancestorsOnly) {
487
+ return false;
488
+ }
489
+
490
+ for (const childNode of node.body) {
491
+ mapVariables(
492
+ /** @type {import('eslint').Rule.Node} */
493
+ (childNode),
494
+ globals,
495
+ opts,
496
+ );
497
+ }
498
+
499
+ break;
500
+ }
501
+
502
+ case 'ExpressionStatement': {
503
+ mapVariables(
504
+ /** @type {import('eslint').Rule.Node} */
505
+ (node.expression),
506
+ globals,
507
+ opts,
508
+ );
509
+ break;
510
+ }
511
+
512
+ case 'AssignmentExpression': {
513
+ createSymbol(
514
+ /** @type {import('eslint').Rule.Node} */
515
+ (node.left),
516
+ globals,
517
+ /** @type {import('eslint').Rule.Node} */
518
+ (node.right),
519
+ );
520
+ break;
521
+ }
522
+
523
+ case 'VariableDeclaration': {
524
+ for (const declaration of node.declarations) {
525
+ const isGlobal = Boolean(opts.initWindow && node.kind === 'var' && globals.props.window);
526
+ const symbol = createSymbol(
527
+ /** @type {import('eslint').Rule.Node} */
528
+ (declaration.id),
529
+ globals,
530
+ /** @type {import('eslint').Rule.Node} */
531
+ (declaration.init),
532
+ globals,
533
+ isGlobal,
534
+ );
535
+ if (symbol && isExport) {
536
+ symbol.exported = true;
537
+ }
538
+ }
539
+
540
+ break;
541
+ }
542
+
543
+ case 'FunctionDeclaration': {
544
+ /* c8 ignore next 10 */
545
+ if (/** @type {import('estree').Identifier} */ (node.id).type === 'Identifier') {
546
+ createSymbol(
547
+ /** @type {import('eslint').Rule.Node} */
548
+ (node.id),
549
+ globals,
550
+ node,
551
+ globals,
552
+ true,
553
+ );
554
+ }
555
+
556
+ break;
557
+ }
558
+
559
+ case 'ExportDefaultDeclaration': {
560
+ const symbol = createSymbol(
561
+ /** @type {import('eslint').Rule.Node} */
562
+ (node.declaration),
563
+ globals,
564
+ /** @type {import('eslint').Rule.Node} */
565
+ (node.declaration),
566
+ );
567
+ if (symbol) {
568
+ symbol.exported = true;
569
+ /* c8 ignore next 6 */
570
+ } else {
571
+ // if (!node.id) {
572
+ globals.ANONYMOUS_DEFAULT = /** @type {import('eslint').Rule.Node} */ (
573
+ node.declaration
574
+ );
575
+ }
576
+
577
+ break;
578
+ }
579
+
580
+ case 'ExportNamedDeclaration': {
581
+ if (node.declaration) {
582
+ if (node.declaration.type === 'VariableDeclaration') {
583
+ mapVariables(
584
+ /** @type {import('eslint').Rule.Node} */
585
+ (node.declaration),
586
+ globals,
587
+ opts,
588
+ true,
589
+ );
590
+ } else {
591
+ const symbol = createSymbol(
592
+ /** @type {import('eslint').Rule.Node} */
593
+ (node.declaration),
594
+ globals,
595
+ /** @type {import('eslint').Rule.Node} */
596
+ (node.declaration),
597
+ );
598
+ /* c8 ignore next 3 */
599
+ if (symbol) {
600
+ symbol.exported = true;
601
+ }
602
+ }
603
+ }
604
+
605
+ for (const specifier of node.specifiers) {
606
+ mapVariables(
607
+ /** @type {import('eslint').Rule.Node} */
608
+ (specifier),
609
+ globals,
610
+ opts,
611
+ );
612
+ }
613
+
614
+ break;
615
+ }
616
+
617
+ case 'ExportSpecifier': {
618
+ const symbol = getSymbol(
619
+ /** @type {import('eslint').Rule.Node} */
620
+ (node.local),
621
+ globals,
622
+ globals,
623
+ );
624
+ /* c8 ignore next 3 */
625
+ if (symbol) {
626
+ symbol.exported = true;
627
+ }
628
+
629
+ break;
630
+ }
631
+
632
+ case 'ClassDeclaration': {
633
+ createSymbol(
634
+ /** @type {import('eslint').Rule.Node|null} */ (node.id),
635
+ globals,
636
+ /** @type {import('eslint').Rule.Node} */ (node.body),
637
+ globals,
638
+ );
639
+ break;
640
+ }
641
+
642
+ default: {
643
+ /* c8 ignore next */
644
+ return false;
645
+ }
646
+ }
647
+
648
+ return true;
649
+ };
650
+
651
+ /**
652
+ *
653
+ * @param {import('eslint').Rule.Node} node
654
+ * @param {CreatedNode|ValueObject|string|undefined|
655
+ * import('eslint').Rule.Node} block
656
+ * @param {(CreatedNode|ValueObject|string|
657
+ * import('eslint').Rule.Node)[]} [cache]
658
+ * @returns {boolean}
659
+ */
660
+ const findNode = function (node, block, cache) {
661
+ let blockCache = cache || [];
662
+ if (!block || blockCache.includes(block)) {
663
+ return false;
664
+ }
665
+
666
+ blockCache = blockCache.slice();
667
+ blockCache.push(block);
668
+
669
+ if (
670
+ typeof block === 'object' &&
671
+ 'type' in block &&
672
+ (block.type === 'object' || block.type === 'MethodDefinition') &&
673
+ block.value === node
674
+ ) {
675
+ return true;
676
+ }
677
+
678
+ if (typeof block !== 'object') {
679
+ return false;
680
+ }
681
+
682
+ const props = ('props' in block && block.props) || ('body' in block && block.body);
683
+ for (const propval of Object.values(props || {})) {
684
+ if (Array.isArray(propval)) {
685
+ /* c8 ignore next 5 */
686
+ if (propval.some((val) => {
687
+ return findNode(node, val, blockCache);
688
+ })) {
689
+ return true;
690
+ }
691
+ } else if (findNode(node, propval, blockCache)) {
692
+ return true;
693
+ }
694
+ }
695
+
696
+ return false;
697
+ };
698
+
699
+ const exportTypes = new Set([
700
+ 'ExportNamedDeclaration', 'ExportDefaultDeclaration',
701
+ ]);
702
+ const ignorableNestedTypes = new Set([
703
+ 'FunctionDeclaration', 'ArrowFunctionExpression', 'FunctionExpression',
704
+ ]);
705
+
706
+ /**
707
+ * @param {import('eslint').Rule.Node} nde
708
+ * @returns {import('eslint').Rule.Node|false}
709
+ */
710
+ const getExportAncestor = function (nde) {
711
+ let node = nde;
712
+ let idx = 0;
713
+ const ignorableIfDeep = ignorableNestedTypes.has(nde?.type);
714
+ while (node) {
715
+ // Ignore functions nested more deeply than say `export default function () {}`
716
+ if (idx >= 2 && ignorableIfDeep) {
717
+ break;
718
+ }
719
+
720
+ if (exportTypes.has(node.type)) {
721
+ return node;
722
+ }
723
+
724
+ node = node.parent;
725
+ idx++;
726
+ }
727
+
728
+ return false;
729
+ };
730
+
731
+ const canBeExportedByAncestorType = new Set([
732
+ 'TSPropertySignature',
733
+ 'TSMethodSignature',
734
+ 'ClassProperty',
735
+ 'PropertyDefinition',
736
+ 'Method',
737
+ ]);
738
+
739
+ const canExportChildrenType = new Set([
740
+ 'TSInterfaceBody',
741
+ 'TSInterfaceDeclaration',
742
+ 'TSTypeLiteral',
743
+ 'TSTypeAliasDeclaration',
744
+ 'ClassDeclaration',
745
+ 'ClassBody',
746
+ 'ClassDefinition',
747
+ 'ClassExpression',
748
+ 'Program',
749
+ ]);
750
+
751
+ /**
752
+ * @param {import('eslint').Rule.Node} nde
753
+ * @returns {false|import('eslint').Rule.Node}
754
+ */
755
+ const isExportByAncestor = function (nde) {
756
+ if (!canBeExportedByAncestorType.has(nde.type)) {
757
+ return false;
758
+ }
759
+
760
+ let node = nde.parent;
761
+ while (node) {
762
+ if (exportTypes.has(node.type)) {
763
+ return node;
764
+ }
765
+
766
+ if (!canExportChildrenType.has(node.type)) {
767
+ return false;
768
+ }
769
+
770
+ node = node.parent;
771
+ }
772
+
773
+ return false;
774
+ };
775
+
776
+ /**
777
+ *
778
+ * @param {CreatedNode} block
779
+ * @param {import('eslint').Rule.Node} node
780
+ * @param {CreatedNode[]} [cache] Currently unused
781
+ * @returns {boolean}
782
+ */
783
+ const findExportedNode = function (block, node, cache) {
784
+ /* c8 ignore next 3 */
785
+ if (block === null) {
786
+ return false;
787
+ }
788
+
789
+ const blockCache = cache || [];
790
+ const {
791
+ props,
792
+ } = block;
793
+ for (const propval of Object.values(props)) {
794
+ const pval = /** @type {CreatedNode} */ (propval);
795
+ blockCache.push(pval);
796
+ if (pval.exported && (node === pval.value || findNode(node, pval.value))) {
797
+ return true;
798
+ }
799
+
800
+ // No need to check `propval` for exported nodes as ESM
801
+ // exports are only global
802
+ }
803
+
804
+ return false;
805
+ };
806
+
807
+ /**
808
+ *
809
+ * @param {import('eslint').Rule.Node} node
810
+ * @param {CreatedNode} globals
811
+ * @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opt
812
+ * @returns {boolean}
813
+ */
814
+ const isNodeExported = function (node, globals, opt) {
815
+ const moduleExports = globals.props.module?.props?.exports;
816
+ if (
817
+ opt.initModuleExports && moduleExports && findNode(node, moduleExports)
818
+ ) {
819
+ return true;
820
+ }
821
+
822
+ if (opt.initWindow && globals.props.window && findNode(node, globals.props.window)) {
823
+ return true;
824
+ }
825
+
826
+ if (opt.esm && findExportedNode(globals, node)) {
827
+ return true;
828
+ }
829
+
830
+ return false;
831
+ };
832
+
833
+ /**
834
+ *
835
+ * @param {import('eslint').Rule.Node} node
836
+ * @param {CreatedNode} globalVars
837
+ * @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opts
838
+ * @returns {boolean}
839
+ */
840
+ const parseRecursive = function (node, globalVars, opts) {
841
+ // Iterate from top using recursion - stop at first processed node from top
842
+ if (node.parent && parseRecursive(node.parent, globalVars, opts)) {
843
+ return true;
844
+ }
845
+
846
+ return mapVariables(node, globalVars, opts);
847
+ };
848
+
849
+ /**
850
+ *
851
+ * @param {import('eslint').Rule.Node} ast
852
+ * @param {import('eslint').Rule.Node} node
853
+ * @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opt
854
+ * @returns {CreatedNode}
855
+ */
856
+ const parse = function (ast, node, opt) {
857
+ /* c8 ignore next 6 */
858
+ const opts = opt || {
859
+ ancestorsOnly: false,
860
+ esm: true,
861
+ initModuleExports: true,
862
+ initWindow: true,
863
+ };
864
+
865
+ const globalVars = createNode();
866
+ if (opts.initModuleExports) {
867
+ globalVars.props.module = createNode();
868
+ globalVars.props.module.props.exports = createNode();
869
+ globalVars.props.exports = globalVars.props.module.props.exports;
870
+ }
871
+
872
+ if (opts.initWindow) {
873
+ globalVars.props.window = createNode();
874
+ globalVars.props.window.special = true;
875
+ }
876
+
877
+ if (opts.ancestorsOnly) {
878
+ parseRecursive(node, globalVars, opts);
879
+ } else {
880
+ initVariables(ast, globalVars, opts);
881
+ mapVariables(ast, globalVars, opts);
882
+ }
883
+
884
+ return {
885
+ globalVars,
886
+ props: {},
887
+ };
888
+ };
889
+
890
+ const accessibilityNodes = new Set([
891
+ 'PropertyDefinition',
892
+ 'MethodDefinition',
893
+ ]);
894
+
895
+ /**
896
+ *
897
+ * @param {import('eslint').Rule.Node} node
898
+ * @returns {boolean}
899
+ */
900
+ const hasAccessibility = (node) => {
901
+ return accessibilityNodes.has(node.type) && 'accessibility' in node &&
902
+ node.accessibility !== 'public' && node.accessibility !== undefined;
903
+ };
904
+
905
+ /**
906
+ *
907
+ * @param {import('eslint').Rule.Node} node
908
+ * @param {import('eslint').SourceCode} sourceCode
909
+ * @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opt
910
+ * @param {import('./iterateJsdoc.js').Settings} settings
911
+ * @returns {boolean}
912
+ */
913
+ const isUncommentedExport = function (node, sourceCode, opt, settings) {
914
+ // console.log({node});
915
+ // Optimize with ancestor check for esm
916
+ if (opt.esm) {
917
+ if (hasAccessibility(node) ||
918
+ node.parent && hasAccessibility(node.parent)) {
919
+ return false;
920
+ }
921
+
922
+ const exportNode = getExportAncestor(node);
923
+
924
+ // Is export node comment
925
+ if (exportNode && !findJSDocComment(exportNode, sourceCode, settings)) {
926
+ return true;
927
+ }
928
+
929
+ /**
930
+ * Some typescript types are not in variable map, but inherit exported (interface property and method)
931
+ */
932
+ if (
933
+ isExportByAncestor(node) &&
934
+ !findJSDocComment(node, sourceCode, settings)
935
+ ) {
936
+ return true;
937
+ }
938
+ }
939
+
940
+ const ast = /** @type {unknown} */ (sourceCode.ast);
941
+
942
+ const parseResult = parse(
943
+ /** @type {import('eslint').Rule.Node} */
944
+ (ast),
945
+ node,
946
+ opt,
947
+ );
948
+
949
+ return isNodeExported(
950
+ node, /** @type {CreatedNode} */ (parseResult.globalVars), opt,
951
+ );
952
+ };
953
+
954
+ export default {
955
+ isUncommentedExport,
956
+ parse,
957
+ };