eslint-plugin-jsdoc 48.0.0 → 48.0.2

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 +2 -2
  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,592 @@
1
+ import iterateJsdoc from '../iterateJsdoc.js';
2
+
3
+ /**
4
+ * @typedef {[string, boolean, () => RootNamerReturn]} RootNamerReturn
5
+ */
6
+
7
+ /**
8
+ * @param {string[]} desiredRoots
9
+ * @param {number} currentIndex
10
+ * @returns {RootNamerReturn}
11
+ */
12
+ const rootNamer = (desiredRoots, currentIndex) => {
13
+ /** @type {string} */
14
+ let name;
15
+ let idx = currentIndex;
16
+ const incremented = desiredRoots.length <= 1;
17
+ if (incremented) {
18
+ const base = desiredRoots[0];
19
+ const suffix = idx++;
20
+ name = `${base}${suffix}`;
21
+ } else {
22
+ name = /** @type {string} */ (desiredRoots.shift());
23
+ }
24
+
25
+ return [
26
+ name,
27
+ incremented,
28
+ () => {
29
+ return rootNamer(desiredRoots, idx);
30
+ },
31
+ ];
32
+ };
33
+
34
+ /* eslint-disable complexity -- Temporary */
35
+ export default iterateJsdoc(({
36
+ jsdoc,
37
+ utils,
38
+ context,
39
+ }) => {
40
+ /* eslint-enable complexity -- Temporary */
41
+ if (utils.avoidDocs()) {
42
+ return;
43
+ }
44
+
45
+ // Param type is specified by type in @type
46
+ if (utils.hasTag('type')) {
47
+ return;
48
+ }
49
+
50
+ const {
51
+ autoIncrementBase = 0,
52
+ checkRestProperty = false,
53
+ checkDestructured = true,
54
+ checkDestructuredRoots = true,
55
+ checkTypesPattern = '/^(?:[oO]bject|[aA]rray|PlainObject|Generic(?:Object|Array))$/',
56
+ enableFixer = true,
57
+ enableRootFixer = true,
58
+ enableRestElementFixer = true,
59
+ unnamedRootBase = [
60
+ 'root',
61
+ ],
62
+ useDefaultObjectProperties = false,
63
+ } = context.options[0] || {};
64
+
65
+ const preferredTagName = /** @type {string} */ (utils.getPreferredTagName({
66
+ tagName: 'param',
67
+ }));
68
+ if (!preferredTagName) {
69
+ return;
70
+ }
71
+
72
+ const functionParameterNames = utils.getFunctionParameterNames(useDefaultObjectProperties);
73
+ if (!functionParameterNames.length) {
74
+ return;
75
+ }
76
+
77
+ const jsdocParameterNames =
78
+ /**
79
+ * @type {{
80
+ * idx: import('../iterateJsdoc.js').Integer;
81
+ * name: string;
82
+ * type: string;
83
+ * }[]}
84
+ */ (utils.getJsdocTagsDeep(preferredTagName));
85
+
86
+ const shallowJsdocParameterNames = jsdocParameterNames.filter((tag) => {
87
+ return !tag.name.includes('.');
88
+ }).map((tag, idx) => {
89
+ return {
90
+ ...tag,
91
+ idx,
92
+ };
93
+ });
94
+
95
+ const checkTypesRegex = utils.getRegexFromString(checkTypesPattern);
96
+
97
+ /**
98
+ * @type {{
99
+ * functionParameterIdx: import('../iterateJsdoc.js').Integer,
100
+ * functionParameterName: string,
101
+ * inc: boolean|undefined,
102
+ * remove?: true,
103
+ * type?: string|undefined
104
+ * }[]}
105
+ */
106
+ const missingTags = [];
107
+ const flattenedRoots = utils.flattenRoots(functionParameterNames).names;
108
+
109
+ /**
110
+ * @type {{
111
+ * [key: string]: import('../iterateJsdoc.js').Integer
112
+ * }}
113
+ */
114
+ const paramIndex = {};
115
+
116
+ /**
117
+ * @param {string} cur
118
+ * @returns {boolean}
119
+ */
120
+ const hasParamIndex = (cur) => {
121
+ return utils.dropPathSegmentQuotes(String(cur)) in paramIndex;
122
+ };
123
+
124
+ /**
125
+ *
126
+ * @param {string|number|undefined} cur
127
+ * @returns {import('../iterateJsdoc.js').Integer}
128
+ */
129
+ const getParamIndex = (cur) => {
130
+ return paramIndex[utils.dropPathSegmentQuotes(String(cur))];
131
+ };
132
+
133
+ /**
134
+ *
135
+ * @param {string} cur
136
+ * @param {import('../iterateJsdoc.js').Integer} idx
137
+ * @returns {void}
138
+ */
139
+ const setParamIndex = (cur, idx) => {
140
+ paramIndex[utils.dropPathSegmentQuotes(String(cur))] = idx;
141
+ };
142
+
143
+ for (const [
144
+ idx,
145
+ cur,
146
+ ] of flattenedRoots.entries()) {
147
+ setParamIndex(cur, idx);
148
+ }
149
+
150
+ /**
151
+ *
152
+ * @param {(import('@es-joy/jsdoccomment').JsdocTagWithInline & {
153
+ * newAdd?: boolean
154
+ * })[]} jsdocTags
155
+ * @param {import('../iterateJsdoc.js').Integer} indexAtFunctionParams
156
+ * @returns {import('../iterateJsdoc.js').Integer}
157
+ */
158
+ const findExpectedIndex = (jsdocTags, indexAtFunctionParams) => {
159
+ const remainingRoots = functionParameterNames.slice(indexAtFunctionParams || 0);
160
+ const foundIndex = jsdocTags.findIndex(({
161
+ name,
162
+ newAdd,
163
+ }) => {
164
+ return !newAdd && remainingRoots.some((remainingRoot) => {
165
+ if (Array.isArray(remainingRoot)) {
166
+ return (
167
+ /**
168
+ * @type {import('../jsdocUtils.js').FlattendRootInfo & {
169
+ * annotationParamName?: string|undefined;
170
+ * }}
171
+ */ (remainingRoot[1]).names.includes(name)
172
+ );
173
+ }
174
+
175
+ if (typeof remainingRoot === 'object') {
176
+ return name === remainingRoot.name;
177
+ }
178
+
179
+ return name === remainingRoot;
180
+ });
181
+ });
182
+
183
+ const tags = foundIndex > -1 ?
184
+ jsdocTags.slice(0, foundIndex) :
185
+ jsdocTags.filter(({
186
+ tag,
187
+ }) => {
188
+ return tag === preferredTagName;
189
+ });
190
+
191
+ let tagLineCount = 0;
192
+ for (const {
193
+ source,
194
+ } of tags) {
195
+ for (const {
196
+ tokens: {
197
+ end,
198
+ },
199
+ } of source) {
200
+ if (!end) {
201
+ tagLineCount++;
202
+ }
203
+ }
204
+ }
205
+
206
+ return tagLineCount;
207
+ };
208
+
209
+ let [
210
+ nextRootName,
211
+ incremented,
212
+ namer,
213
+ ] = rootNamer([
214
+ ...unnamedRootBase,
215
+ ], autoIncrementBase);
216
+
217
+ for (const [
218
+ functionParameterIdx,
219
+ functionParameterName,
220
+ ] of functionParameterNames.entries()) {
221
+ let inc;
222
+ if (Array.isArray(functionParameterName)) {
223
+ const matchedJsdoc = shallowJsdocParameterNames[functionParameterIdx] ||
224
+ jsdocParameterNames[functionParameterIdx];
225
+
226
+ /** @type {string} */
227
+ let rootName;
228
+ if (functionParameterName[0]) {
229
+ rootName = functionParameterName[0];
230
+ } else if (matchedJsdoc && matchedJsdoc.name) {
231
+ rootName = matchedJsdoc.name;
232
+ if (matchedJsdoc.type && matchedJsdoc.type.search(checkTypesRegex) === -1) {
233
+ continue;
234
+ }
235
+ } else {
236
+ rootName = nextRootName;
237
+ inc = incremented;
238
+ [
239
+ nextRootName,
240
+ incremented,
241
+ namer,
242
+ ] = namer();
243
+ }
244
+
245
+ const {
246
+ hasRestElement,
247
+ hasPropertyRest,
248
+ rests,
249
+ names,
250
+ } = /**
251
+ * @type {import('../jsdocUtils.js').FlattendRootInfo & {
252
+ * annotationParamName?: string | undefined;
253
+ * }}
254
+ */ (functionParameterName[1]);
255
+ const notCheckingNames = [];
256
+ if (!enableRestElementFixer && hasRestElement) {
257
+ continue;
258
+ }
259
+
260
+ if (!checkDestructuredRoots) {
261
+ continue;
262
+ }
263
+
264
+ for (const [
265
+ idx,
266
+ paramName,
267
+ ] of names.entries()) {
268
+ // Add root if the root name is not in the docs (and is not already
269
+ // in the tags to be fixed)
270
+ if (!jsdocParameterNames.find(({
271
+ name,
272
+ }) => {
273
+ return name === rootName;
274
+ }) && !missingTags.find(({
275
+ functionParameterName: fpn,
276
+ }) => {
277
+ return fpn === rootName;
278
+ })) {
279
+ const emptyParamIdx = jsdocParameterNames.findIndex(({
280
+ name,
281
+ }) => {
282
+ return !name;
283
+ });
284
+
285
+ if (emptyParamIdx > -1) {
286
+ missingTags.push({
287
+ functionParameterIdx: emptyParamIdx,
288
+ functionParameterName: rootName,
289
+ inc,
290
+ remove: true,
291
+ });
292
+ } else {
293
+ missingTags.push({
294
+ functionParameterIdx: hasParamIndex(rootName) ?
295
+ getParamIndex(rootName) :
296
+ getParamIndex(paramName),
297
+ functionParameterName: rootName,
298
+ inc,
299
+ });
300
+ }
301
+ }
302
+
303
+ if (!checkDestructured) {
304
+ continue;
305
+ }
306
+
307
+ if (!checkRestProperty && rests[idx]) {
308
+ continue;
309
+ }
310
+
311
+ const fullParamName = `${rootName}.${paramName}`;
312
+
313
+ const notCheckingName = jsdocParameterNames.find(({
314
+ name,
315
+ type: paramType,
316
+ }) => {
317
+ return utils.comparePaths(name)(fullParamName) && paramType.search(checkTypesRegex) === -1 && paramType !== '';
318
+ });
319
+
320
+ if (notCheckingName !== undefined) {
321
+ notCheckingNames.push(notCheckingName.name);
322
+ }
323
+
324
+ if (notCheckingNames.find((name) => {
325
+ return fullParamName.startsWith(name);
326
+ })) {
327
+ continue;
328
+ }
329
+
330
+ if (jsdocParameterNames && !jsdocParameterNames.find(({
331
+ name,
332
+ }) => {
333
+ return utils.comparePaths(name)(fullParamName);
334
+ })) {
335
+ missingTags.push({
336
+ functionParameterIdx: getParamIndex(
337
+ functionParameterName[0] ? fullParamName : paramName,
338
+ ),
339
+ functionParameterName: fullParamName,
340
+ inc,
341
+ type: hasRestElement && !hasPropertyRest ? '{...any}' : undefined,
342
+ });
343
+ }
344
+ }
345
+
346
+ continue;
347
+ }
348
+
349
+ /** @type {string} */
350
+ let funcParamName;
351
+ let type;
352
+ if (typeof functionParameterName === 'object') {
353
+ if (!enableRestElementFixer && functionParameterName.restElement) {
354
+ continue;
355
+ }
356
+
357
+ funcParamName = /** @type {string} */ (functionParameterName.name);
358
+ type = '{...any}';
359
+ } else {
360
+ funcParamName = /** @type {string} */ (functionParameterName);
361
+ }
362
+
363
+ if (jsdocParameterNames && !jsdocParameterNames.find(({
364
+ name,
365
+ }) => {
366
+ return name === funcParamName;
367
+ }) && funcParamName !== 'this') {
368
+ missingTags.push({
369
+ functionParameterIdx: getParamIndex(funcParamName),
370
+ functionParameterName: funcParamName,
371
+ inc,
372
+ type,
373
+ });
374
+ }
375
+ }
376
+
377
+ /**
378
+ *
379
+ * @param {{
380
+ * functionParameterIdx: import('../iterateJsdoc.js').Integer,
381
+ * functionParameterName: string,
382
+ * remove?: true,
383
+ * inc?: boolean,
384
+ * type?: string
385
+ * }} cfg
386
+ */
387
+ const fix = ({
388
+ functionParameterIdx,
389
+ functionParameterName,
390
+ remove,
391
+ inc,
392
+ type,
393
+ }) => {
394
+ if (inc && !enableRootFixer) {
395
+ return;
396
+ }
397
+
398
+ /**
399
+ *
400
+ * @param {import('../iterateJsdoc.js').Integer} tagIndex
401
+ * @param {import('../iterateJsdoc.js').Integer} sourceIndex
402
+ * @param {import('../iterateJsdoc.js').Integer} spliceCount
403
+ * @returns {void}
404
+ */
405
+ const createTokens = (tagIndex, sourceIndex, spliceCount) => {
406
+ // console.log(sourceIndex, tagIndex, jsdoc.tags, jsdoc.source);
407
+ const tokens = {
408
+ number: sourceIndex + 1,
409
+ source: '',
410
+ tokens: {
411
+ delimiter: '*',
412
+ description: '',
413
+ end: '',
414
+ lineEnd: '',
415
+ name: functionParameterName,
416
+ newAdd: true,
417
+ postDelimiter: ' ',
418
+ postName: '',
419
+ postTag: ' ',
420
+ postType: type ? ' ' : '',
421
+ start: jsdoc.source[sourceIndex].tokens.start,
422
+ tag: `@${preferredTagName}`,
423
+ type: type ?? '',
424
+ },
425
+ };
426
+
427
+ /**
428
+ * @type {(import('@es-joy/jsdoccomment').JsdocTagWithInline & {
429
+ * newAdd?: true
430
+ * })[]}
431
+ */ (jsdoc.tags).splice(tagIndex, spliceCount, {
432
+ description: '',
433
+ inlineTags: [],
434
+ name: functionParameterName,
435
+ newAdd: true,
436
+ optional: false,
437
+ problems: [],
438
+ source: [
439
+ tokens,
440
+ ],
441
+ tag: preferredTagName,
442
+ type: type ?? '',
443
+ });
444
+ const firstNumber = jsdoc.source[0].number;
445
+ jsdoc.source.splice(sourceIndex, spliceCount, tokens);
446
+ for (const [
447
+ idx,
448
+ src,
449
+ ] of jsdoc.source.slice(sourceIndex).entries()) {
450
+ src.number = firstNumber + sourceIndex + idx;
451
+ }
452
+ };
453
+
454
+ const offset = jsdoc.source.findIndex(({
455
+ tokens: {
456
+ tag,
457
+ end,
458
+ },
459
+ }) => {
460
+ return tag || end;
461
+ });
462
+ if (remove) {
463
+ createTokens(functionParameterIdx, offset + functionParameterIdx, 1);
464
+ } else {
465
+ const expectedIdx = findExpectedIndex(jsdoc.tags, functionParameterIdx);
466
+ createTokens(expectedIdx, offset + expectedIdx, 0);
467
+ }
468
+ };
469
+
470
+ /**
471
+ * @returns {void}
472
+ */
473
+ const fixer = () => {
474
+ for (const missingTag of missingTags) {
475
+ fix(missingTag);
476
+ }
477
+ };
478
+
479
+ if (missingTags.length && jsdoc.source.length === 1) {
480
+ utils.makeMultiline();
481
+ }
482
+
483
+ for (const {
484
+ functionParameterName,
485
+ } of missingTags) {
486
+ utils.reportJSDoc(
487
+ `Missing JSDoc @${preferredTagName} "${functionParameterName}" declaration.`,
488
+ null,
489
+ enableFixer ? fixer : null,
490
+ );
491
+ }
492
+ }, {
493
+ contextDefaults: true,
494
+ meta: {
495
+ docs: {
496
+ description: 'Requires that all function parameters are documented.',
497
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param.md#repos-sticky-header',
498
+ },
499
+ fixable: 'code',
500
+ schema: [
501
+ {
502
+ additionalProperties: false,
503
+ properties: {
504
+ autoIncrementBase: {
505
+ default: 0,
506
+ type: 'integer',
507
+ },
508
+ checkConstructors: {
509
+ default: true,
510
+ type: 'boolean',
511
+ },
512
+ checkDestructured: {
513
+ default: true,
514
+ type: 'boolean',
515
+ },
516
+ checkDestructuredRoots: {
517
+ default: true,
518
+ type: 'boolean',
519
+ },
520
+ checkGetters: {
521
+ default: false,
522
+ type: 'boolean',
523
+ },
524
+ checkRestProperty: {
525
+ default: false,
526
+ type: 'boolean',
527
+ },
528
+ checkSetters: {
529
+ default: false,
530
+ type: 'boolean',
531
+ },
532
+ checkTypesPattern: {
533
+ type: 'string',
534
+ },
535
+ contexts: {
536
+ items: {
537
+ anyOf: [
538
+ {
539
+ type: 'string',
540
+ },
541
+ {
542
+ additionalProperties: false,
543
+ properties: {
544
+ comment: {
545
+ type: 'string',
546
+ },
547
+ context: {
548
+ type: 'string',
549
+ },
550
+ },
551
+ type: 'object',
552
+ },
553
+ ],
554
+ },
555
+ type: 'array',
556
+ },
557
+ enableFixer: {
558
+ type: 'boolean',
559
+ },
560
+ enableRestElementFixer: {
561
+ type: 'boolean',
562
+ },
563
+ enableRootFixer: {
564
+ type: 'boolean',
565
+ },
566
+ exemptedBy: {
567
+ items: {
568
+ type: 'string',
569
+ },
570
+ type: 'array',
571
+ },
572
+ unnamedRootBase: {
573
+ items: {
574
+ type: 'string',
575
+ },
576
+ type: 'array',
577
+ },
578
+ useDefaultObjectProperties: {
579
+ type: 'boolean',
580
+ },
581
+ },
582
+ type: 'object',
583
+ },
584
+ ],
585
+ type: 'suggestion',
586
+ },
587
+
588
+ // We cannot cache comment nodes as the contexts may recur with the
589
+ // same comment node but a different JS node, and we may need the different
590
+ // JS node to ensure we iterate its context
591
+ noTracking: true,
592
+ });
@@ -0,0 +1,89 @@
1
+ import iterateJsdoc from '../iterateJsdoc.js';
2
+
3
+ export default iterateJsdoc(({
4
+ context,
5
+ report,
6
+ settings,
7
+ utils,
8
+ }) => {
9
+ const {
10
+ defaultDestructuredRootDescription = 'The root object',
11
+ setDefaultDestructuredRootDescription = false,
12
+ } = context.options[0] || {};
13
+
14
+ const functionParameterNames = utils.getFunctionParameterNames();
15
+
16
+ let rootCount = -1;
17
+ utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {
18
+ rootCount += jsdocParameter.name.includes('.') ? 0 : 1;
19
+ if (!jsdocParameter.description.trim()) {
20
+ if (Array.isArray(functionParameterNames[rootCount])) {
21
+ if (settings.exemptDestructuredRootsFromChecks) {
22
+ return;
23
+ }
24
+
25
+ if (setDefaultDestructuredRootDescription) {
26
+ utils.reportJSDoc(`Missing root description for @${targetTagName}.`, jsdocParameter, () => {
27
+ utils.changeTag(jsdocParameter, {
28
+ description: defaultDestructuredRootDescription,
29
+ postName: ' ',
30
+ });
31
+ });
32
+ return;
33
+ }
34
+ }
35
+
36
+ report(
37
+ `Missing JSDoc @${targetTagName} "${jsdocParameter.name}" description.`,
38
+ null,
39
+ jsdocParameter,
40
+ );
41
+ }
42
+ });
43
+ }, {
44
+ contextDefaults: true,
45
+ meta: {
46
+ docs: {
47
+ description: 'Requires that each `@param` tag has a `description` value.',
48
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param-description.md#repos-sticky-header',
49
+ },
50
+ fixable: 'code',
51
+ schema: [
52
+ {
53
+ additionalProperties: false,
54
+ properties: {
55
+ contexts: {
56
+ items: {
57
+ anyOf: [
58
+ {
59
+ type: 'string',
60
+ },
61
+ {
62
+ additionalProperties: false,
63
+ properties: {
64
+ comment: {
65
+ type: 'string',
66
+ },
67
+ context: {
68
+ type: 'string',
69
+ },
70
+ },
71
+ type: 'object',
72
+ },
73
+ ],
74
+ },
75
+ type: 'array',
76
+ },
77
+ defaultDestructuredRootDescription: {
78
+ type: 'string',
79
+ },
80
+ setDefaultDestructuredRootDescription: {
81
+ type: 'boolean',
82
+ },
83
+ },
84
+ type: 'object',
85
+ },
86
+ ],
87
+ type: 'suggestion',
88
+ },
89
+ });