• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

satisfactory-dev / ajv-utilities / 26333519053

23 May 2026 01:06PM UTC coverage: 99.237% (+0.05%) from 99.186%
26333519053

push

github

SignpostMarv
updating readme

609 of 626 branches covered (97.28%)

Branch coverage included in aggregate %.

5372 of 5401 relevant lines covered (99.46%)

16572.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.74
/src/TypeScriptify/preprocessors/CollectValidateCalls.ts
1
import type {
1✔
2
} from '@signpostmarv/js-types';
1✔
3

1✔
4
import type {
1✔
5
        BinaryExpression,
1✔
6
        CallExpression,
1✔
7
        ElementAccessExpression,
1✔
8
        Identifier,
1✔
9
        Node,
1✔
10
        NodeArray,
1✔
11
        ObjectLiteralExpression,
1✔
12
        PropertyAccessExpression,
1✔
13
        PropertyAssignment,
1✔
14
        ShorthandPropertyAssignment,
1✔
15
        StringLiteral,
1✔
16
        SyntaxKind,
1✔
17
} from 'typescript';
1✔
18

1✔
19
import {
1✔
20
        ConditionalPreprocessor,
1✔
21
} from '../abstracts.ts';
1✔
22

1✔
23
import type {
1✔
24
        Config,
1✔
25
        specify_type_conditionally_with_nested,
1✔
26
        specify_type_conditionally_without_nested,
1✔
27
        specify_type_nested,
1✔
28
        specify_type_with_nested,
1✔
29
        specify_type_without_nested_but_generic,
1✔
30
        specify_types_config,
1✔
31
        specify_types_instance,
1✔
32
        validate_call_argument_1_match,
1✔
33
} from '../types.ts';
1✔
34

1✔
35
import type {
1✔
36
        prepend_with_imports,
1✔
37
} from '../TypeReferences.ts';
1✔
38
import {
1✔
39
        ConditionalPredicate,
1✔
40
        GenericT,
1✔
41
        to_string,
1✔
42
        Types,
1✔
43
} from '../TypeReferences.ts';
1✔
44

1✔
45
import type {
1✔
46
        ts,
1✔
47
} from '../../TypeScriptify.ts';
1✔
48

1✔
49
type CandidateBinaryExpressionString = (
1✔
50
        & BinaryExpression
1✔
51
        & {
1✔
52
                left: Identifier,
1✔
53
                operatorToken: {
1✔
54
                        kind: SyntaxKind.PlusToken,
1✔
55
                },
1✔
56
                right: StringLiteral,
1✔
57
        }
1✔
58
);
1✔
59

1✔
60
type CandidateBinaryExpressionStringConcat = (
1✔
61
        & BinaryExpression
1✔
62
        & {
1✔
63
                left: CandidateBinaryExpressionString,
1✔
64
                operatorToken: {
1✔
65
                        kind: SyntaxKind.PlusToken,
1✔
66
                },
1✔
67
                right: (
1✔
68
                        | Identifier
1✔
69
                        | PropertyAccessExpression
1✔
70
                        | CallExpression
1✔
71
                ),
1✔
72
        }
1✔
73
);
1✔
74

1✔
75
type instancePath_initializer = (
1✔
76
        | StringLiteral
1✔
77
        | CandidateBinaryExpressionString
1✔
78
        | CandidateBinaryExpressionStringConcat
1✔
79
);
1✔
80

1✔
81
type argument_1_property_instancePath = (
1✔
82
        & (
1✔
83
                | ShorthandPropertyAssignment
1✔
84
                | (
1✔
85
                        & PropertyAssignment
1✔
86
                        & {
1✔
87
                                initializer: instancePath_initializer,
1✔
88
                        }
1✔
89
                )
1✔
90
        )
1✔
91
        & {
1✔
92
                name: (
1✔
93
                        & Identifier
1✔
94
                        & {
1✔
95
                                text: 'instancePath',
1✔
96
                        }
1✔
97
                ),
1✔
98
        }
1✔
99
);
1✔
100

1✔
101
type Candidate = (
1✔
102
        & CallExpression
1✔
103
        & {
1✔
104
                expression: (
1✔
105
                        & Identifier
1✔
106
                        & {
1✔
107
                                text: `validate${number}`,
1✔
108
                        }
1✔
109
                ),
1✔
110
                arguments: (
1✔
111
                        & NodeArray<(
1✔
112
                                | Identifier
1✔
113
                                | PropertyAccessExpression
1✔
114
                                | ObjectLiteralExpression
1✔
115
                                | ElementAccessExpression
1✔
116
                        )>
1✔
117
                        & {
1✔
118
                                length: 2,
1✔
119
                                0: (
1✔
120
                                        | Identifier
1✔
121
                                        | PropertyAccessExpression
1✔
122
                                        | ElementAccessExpression
1✔
123
                                ),
1✔
124
                                1: (
1✔
125
                                        & ObjectLiteralExpression
1✔
126
                                        & {
1✔
127
                                                properties: (
1✔
128
                                                        & NodeArray<PropertyAssignment>
1✔
129
                                                        & {
1✔
130
                                                                length: 5,
1✔
131
                                                                0: argument_1_property_instancePath,
1✔
132
                                                                2: (
1✔
133
                                                                        & PropertyAssignment
1✔
134
                                                                        & {
1✔
135
                                                                                name: (
1✔
136
                                                                                        & Identifier
1✔
137
                                                                                        & {
1✔
138
                                                                                                text: 'parentDataProperty',
1✔
139
                                                                                        }
1✔
140
                                                                                ),
1✔
141
                                                                                initializer: (
1✔
142
                                                                                        | StringLiteral
1✔
143
                                                                                        | Identifier
1✔
144
                                                                                ),
1✔
145
                                                                        }
1✔
146
                                                                ),
1✔
147
                                                        }
1✔
148
                                                ),
1✔
149
                                        }
1✔
150
                                ),
1✔
151
                        }
1✔
152
                ),
1✔
153
        }
1✔
154
);
1✔
155

1✔
156
const unique_id = Symbol('unique_id');
1✔
157

1✔
158
export type ValidateCallInfo = {
1✔
159
        name: string,
1✔
160

1✔
161
        // we're using null here as a placeholder for stuff we're not supporting
1✔
162
        instancePath: (
1✔
163
                | null
1✔
164
                | [string]
1✔
165
                | [string | null, ...(string | null)[]]
1✔
166
        ),
1✔
167

1✔
168
        parentDataProperty: string | null,
1✔
169

1✔
170
        [unique_id]: string,
1✔
171
};
1✔
172

1✔
173
export default class CollectValidateCalls extends ConditionalPreprocessor<
1✔
174
        Candidate
1✔
175
> {
1✔
176
        constructor(
1✔
177
                ts: ts,
26✔
178
                validate_calls: {
26✔
179
                        [key: string]: [
26✔
180
                                ValidateCallInfo,
26✔
181
                                ...ValidateCallInfo[],
26✔
182
                        ],
26✔
183
                },
26✔
184
        ) {
26✔
185
                const {
26✔
186
                        isCallExpression,
26✔
187
                        isElementAccessExpression,
26✔
188
                        isFunctionDeclaration,
26✔
189
                        isIdentifier,
26✔
190
                        isObjectLiteralExpression,
26✔
191
                        isPropertyAccessExpression,
26✔
192
                        isPropertyAssignment,
26✔
193
                        isShorthandPropertyAssignment,
26✔
194
                        isStringLiteral,
26✔
195
                } = ts;
26✔
196

26✔
197
                super(
26✔
198
                        (maybe): maybe is Candidate => (
26✔
199
                                isCallExpression(maybe)
238,767✔
200
                                && isIdentifier(maybe.expression)
238,767✔
201
                                && this.validate_function_name.test(maybe.expression.text)
238,767✔
202
                                && 2 === maybe.arguments.length
238,767✔
203
                                && (
238,767✔
204
                                        isIdentifier(maybe.arguments[0])
21✔
205
                                        || isPropertyAccessExpression(maybe.arguments[0])
21✔
206
                                        || isElementAccessExpression(maybe.arguments[0])
21✔
207
                                )
21✔
208
                                && isObjectLiteralExpression(maybe.arguments[1])
238,767✔
209
                                && 5 === maybe.arguments[1].properties.length
238,767✔
210
                                && (
238,767✔
211
                                        (
21✔
212
                                                isShorthandPropertyAssignment(
21✔
213
                                                        maybe.arguments[1].properties[0],
21✔
214
                                                )
21✔
215
                                                || (
21✔
216
                                                        isPropertyAssignment(
16✔
217
                                                                maybe.arguments[1].properties[0],
16✔
218
                                                        )
16✔
219
                                                        && this.#is_instancePath_initializer(
16✔
220
                                                                ts,
16✔
221
                                                                maybe.arguments[
16✔
222
                                                                        1
16✔
223
                                                                ].properties[
16✔
224
                                                                        0
16✔
225
                                                                ].initializer,
16✔
226
                                                        )
16✔
227
                                                )
16✔
228
                                        )
21✔
229
                                        && isIdentifier(
21✔
230
                                                maybe.arguments[1].properties[0].name,
21✔
231
                                        )
21✔
232
                                        && 'instancePath' === maybe.arguments[
21✔
233
                                                1
21✔
234
                                        ].properties[
21✔
235
                                                0
21✔
236
                                        ].name.text
21✔
237
                                )
21✔
238
                                && (
238,767✔
239
                                        isShorthandPropertyAssignment(
21✔
240
                                                maybe.arguments[1].properties[2],
21✔
241
                                        )
21✔
242
                                        || (
21✔
243
                                                isPropertyAssignment(maybe.arguments[1].properties[2])
16✔
244
                                                && (
16✔
245
                                                        isStringLiteral(
16✔
246
                                                                maybe.arguments[1].properties[2].initializer,
16✔
247
                                                        )
16✔
248
                                                        || isIdentifier(
16✔
249
                                                                maybe.arguments[1].properties[2].initializer,
6✔
250
                                                        )
6✔
251
                                                )
16✔
252
                                        )
16✔
253
                                )
21✔
254
                                && isIdentifier(maybe.arguments[1].properties[2].name)
238,767✔
255
                                && 'parentDataProperty' === (
238,767✔
256
                                        maybe.arguments[1].properties[2].name.text
21✔
257
                                )
21✔
258
                        ),
26✔
259
                        (node) => {
26✔
260
                                let checking: Node | undefined = node.parent;
21✔
261

21✔
262
                                while (checking) {
21✔
263
                                        if (
207✔
264
                                                isFunctionDeclaration(checking)
207✔
265
                                                && !!checking.name
207✔
266
                                                && isIdentifier(checking.name)
207✔
267
                                                && this.validate_function_name.test(
207✔
268
                                                        checking.name.text,
21✔
269
                                                )
21✔
270
                                        ) {
207✔
271
                                                const called_in = checking.name.getText();
21✔
272

21✔
273
                                                let instancePath: ValidateCallInfo['instancePath'];
21✔
274

21✔
275
                                                if (isShorthandPropertyAssignment(
21✔
276
                                                        node.arguments[1].properties[0],
21✔
277
                                                )) {
21✔
278
                                                        instancePath = null;
5✔
279
                                                } else if (isStringLiteral(
21✔
280
                                                        node.arguments[1].properties[0].initializer,
16✔
281
                                                )) {
16!
282
                                                        instancePath = [
×
283
                                                                node.arguments[
×
284
                                                                        1
×
285
                                                                ].properties[
×
286
                                                                        0
×
287
                                                                ].initializer.text,
×
288
                                                        ];
×
289
                                                } else {
16✔
290
                                                        // oxlint-disable-next-line @stylistic/max-len
16✔
291
                                                        instancePath = this.#unpack_CandidateBinaryExpression(
16✔
292
                                                                ts,
16✔
293
                                                                node.arguments[1].properties[0].initializer,
16✔
294
                                                        );
16✔
295
                                                }
16✔
296

21✔
297
                                                const info: Omit<
21✔
298
                                                        ValidateCallInfo,
21✔
299
                                                        typeof unique_id
21✔
300
                                                > = {
21✔
301
                                                        name: node.expression.text,
21✔
302
                                                        instancePath,
21✔
303
                                                        parentDataProperty: (
21✔
304
                                                                (
21✔
305
                                                                        isPropertyAssignment(
21✔
306
                                                                                node.arguments[
21✔
307
                                                                                        1
21✔
308
                                                                                ].properties[
21✔
309
                                                                                        2
21✔
310
                                                                                ],
21✔
311
                                                                        )
21✔
312
                                                                        && isStringLiteral(
21✔
313
                                                                                node.arguments[
16✔
314
                                                                                        1
16✔
315
                                                                                ].properties[
16✔
316
                                                                                        2
16✔
317
                                                                                ].initializer,
16✔
318
                                                                        )
16✔
319
                                                                )
21✔
320
                                                                        ? node.arguments[
21✔
321
                                                                                1
10✔
322
                                                                        ].properties[
10✔
323
                                                                                2
10✔
324
                                                                        ].initializer.text
10✔
325
                                                                        : null
21✔
326
                                                        ),
21✔
327
                                                };
21✔
328

21✔
329
                                                const with_id: ValidateCallInfo = {
21✔
330
                                                        ...info,
21✔
331
                                                        [unique_id]: JSON.stringify(info),
21✔
332
                                                };
21✔
333

21✔
334
                                                if (!(called_in in validate_calls)) {
21✔
335
                                                        validate_calls[called_in] = [with_id];
13✔
336
                                                } else if (!validate_calls[called_in].find((
21✔
337
                                                        maybe,
12✔
338
                                                ) => maybe[unique_id] === with_id[unique_id])) {
8✔
339
                                                        validate_calls[called_in].push(with_id);
8✔
340
                                                }
8✔
341

21✔
342
                                                return true;
21✔
343
                                        }
21✔
344

186✔
345
                                        checking = checking.parent;
186✔
346
                                }
186!
347

×
348
                                return false;
×
349
                        },
26✔
350
                );
26✔
351
        }
26✔
352

1✔
353
        #is_CandidateBinaryExpressionString(
1✔
354
                ts: ts,
30✔
355
                maybe: Node,
30✔
356
        ): maybe is CandidateBinaryExpressionString {
30✔
357
                const {
30✔
358
                        isBinaryExpression,
30✔
359
                        isIdentifier,
30✔
360
                        isStringLiteral,
30✔
361
                        SyntaxKind,
30✔
362
                } = ts;
30✔
363

30✔
364
                return (
30✔
365
                        isBinaryExpression(maybe)
30✔
366
                        && (
30✔
367
                                isIdentifier(maybe.left)
24✔
368
                                || this.#is_CandidateBinaryExpressionStringConcat(
24✔
369
                                        ts,
8✔
370
                                        maybe.left,
8✔
371
                                )
8✔
372
                        )
24✔
373
                        && SyntaxKind.PlusToken === maybe.operatorToken.kind
30✔
374
                        && isStringLiteral(maybe.right)
30✔
375
                );
30✔
376
        }
30✔
377

1✔
378
        #is_CandidateBinaryExpressionStringConcat(
1✔
379
                ts: ts,
14✔
380
                maybe: Node,
14✔
381
        ): maybe is CandidateBinaryExpressionStringConcat {
14✔
382
                const {
14✔
383
                        isBinaryExpression,
14✔
384
                        isCallExpression,
14✔
385
                        isIdentifier,
14✔
386
                        isPropertyAccessExpression,
14✔
387
                        SyntaxKind,
14✔
388
                } = ts;
14✔
389

14✔
390
                return (
14✔
391
                        isBinaryExpression(maybe)
14✔
392
                        && (
14✔
393
                                this.#is_CandidateBinaryExpressionString(ts, maybe.left)
14✔
394
                        )
14✔
395
                        && SyntaxKind.PlusToken === maybe.operatorToken.kind
14✔
396
                        && (
14✔
397
                                isIdentifier(maybe.right)
8✔
398
                                || isPropertyAccessExpression(maybe.right)
8✔
399
                                || isCallExpression(maybe.right)
8✔
400
                        )
8✔
401
                );
14✔
402
        }
14✔
403

1✔
404
        #is_instancePath_initializer(
1✔
405
                ts: ts,
16✔
406
                maybe: Node,
16✔
407
        ): maybe is instancePath_initializer {
16✔
408
                const {
16✔
409
                        isStringLiteral,
16✔
410
                } = ts;
16✔
411

16✔
412
                return (
16✔
413
                        isStringLiteral(maybe)
16✔
414
                        || this.#is_CandidateBinaryExpressionString(ts, maybe)
16✔
415
                        || this.#is_CandidateBinaryExpressionStringConcat(ts, maybe)
16✔
416
                );
16✔
417
        }
16✔
418

1✔
419
        #unpack_CandidateBinaryExpression(
1✔
420
                ts: ts,
26✔
421
                from: (
26✔
422
                        | CandidateBinaryExpressionString
26✔
423
                        | CandidateBinaryExpressionStringConcat
26✔
424
                ),
26✔
425
                current: (null | string)[] = [],
26✔
426
        ): [
26✔
427
                (string | null),
26✔
428
                ...(string | null)[],
26✔
429
        ] {
26✔
430
                const {
26✔
431
                        isIdentifier,
26✔
432
                        isStringLiteral,
26✔
433
                } = ts;
26✔
434

26✔
435
                if (isIdentifier(from.left)) {
26✔
436
                        return [
16✔
437
                                null,
16✔
438
                                (
16✔
439
                                        isStringLiteral(from.right)
16✔
440
                                                ? from.right.text
16✔
441
                                                : null
16!
442
                                ),
16✔
443
                                ...current,
16✔
444
                        ];
16✔
445
                }
16✔
446

10✔
447
                return this.#unpack_CandidateBinaryExpression(ts, from.left, [null]);
10✔
448
        }
26✔
449

1✔
450
        static specify_types_from_collected(
1✔
451
                ts: ts,
3✔
452
                info: {
3✔
453
                        [key: string]: [
3✔
454
                                ValidateCallInfo,
3✔
455
                                ...ValidateCallInfo[],
3✔
456
                        ],
3✔
457
                },
3✔
458
                config: Partial<Config>,
3✔
459
                existing: specify_types_instance,
3✔
460
                prepend_with_imports: prepend_with_imports,
3✔
461
        ) {
3✔
462
                this.#specify_types_from_collected_inside_out(
3✔
463
                        ts,
3✔
464
                        info,
3✔
465
                        config,
3✔
466
                        existing,
3✔
467
                        prepend_with_imports,
3✔
468
                );
3✔
469
                this.#specify_types_from_collected_outside_in(
3✔
470
                        ts,
3✔
471
                        info,
3✔
472
                        config,
3✔
473
                        existing,
3✔
474
                        prepend_with_imports,
3✔
475
                );
3✔
476
        }
3✔
477

1✔
478
        static #specify_types_from_collected_outside_in(
1✔
479
                ts: ts,
3✔
480
                info: {
3✔
481
                        [key: string]: [
3✔
482
                                ValidateCallInfo,
3✔
483
                                ...ValidateCallInfo[],
3✔
484
                        ],
3✔
485
                },
3✔
486
                config: Partial<Config>,
3✔
487
                existing: specify_types_instance,
3✔
488
                prepend_with_imports: prepend_with_imports,
3✔
489
        ) {
3✔
490
                const configurable = Object.entries(config.specify_types || {})
3!
491
                        .filter((maybe): maybe is [
3✔
492
                                string,
4✔
493
                                specify_type_with_nested,
4✔
494
                        ] => 3 === maybe[1].length)
3✔
495
                        .map(([key, not_object]): [
3✔
496
                                string,
2✔
497
                                [
2✔
498
                                        ReturnType<(typeof Types)['toObject']>,
2✔
499
                                        (typeof not_object)[1],
2✔
500
                                        (typeof not_object)[2],
2✔
501
                                        string,
2✔
502
                                ],
2✔
503
                        ] => {
2✔
504
                                const as_object = Types.toObject(ts, not_object[0]);
2✔
505

2✔
506
                                return [
2✔
507
                                        key,
2✔
508
                                        [
2✔
509
                                                as_object,
2✔
510
                                                not_object[1],
2✔
511
                                                not_object[2],
2✔
512
                                                to_string(ts, as_object),
2✔
513
                                        ],
2✔
514
                                ];
2✔
515
                        });
3✔
516

3✔
517
                if (configurable.length < 1) {
3✔
518
                        return;
1✔
519
                }
1✔
520

2✔
521
                const existing_entries = Object.entries(existing);
2✔
522

2✔
523
                for (const [
2✔
524
                        ,
2✔
525
                        [
2✔
526
                                ,,
2✔
527
                                sub_types,
2✔
528
                                as_string,
2✔
529
                        ],
2✔
530
                ] of configurable) {
2✔
531
                        const found = existing_entries.find((maybe) => (
2✔
532
                                to_string(ts, maybe[1]) === as_string
3✔
533
                        ));
2✔
534

2✔
535
                        if (!found) {
2!
536
                                continue;
×
537
                        }
×
538

2✔
539
                        const [function_name] = found;
2✔
540

2✔
541
                        if (!(function_name in info)) {
2!
542
                                continue;
×
543
                        }
×
544

2✔
545
                        this.#specify_types_from_collected_outside_in_deep_dive(
2✔
546
                                ts,
2✔
547
                                info,
2✔
548
                                function_name,
2✔
549
                                sub_types,
2✔
550
                                existing,
2✔
551
                                prepend_with_imports,
2✔
552
                        );
2✔
553
                }
2✔
554
        }
3✔
555

1✔
556
        static #specify_types_from_collected_inside_out(
1✔
557
                ts: ts,
3✔
558
                info: {
3✔
559
                        [key: string]: [
3✔
560
                                ValidateCallInfo,
3✔
561
                                ...ValidateCallInfo[],
3✔
562
                        ],
3✔
563
                },
3✔
564
                config: Partial<Config>,
3✔
565
                existing: specify_types_instance,
3✔
566
                prepend_with_imports: prepend_with_imports,
3✔
567
        ) {
3✔
568
                const configurable = config.specify_types_by_inside_out_match || [];
3✔
569

3✔
570
                if (configurable.length < 1) {
3✔
571
                        return;
1✔
572
                }
1✔
573

2✔
574
                const info_entries = Object.entries(info);
2✔
575

2✔
576
                for (const [
2✔
577
                        sub_type,
2✔
578
                        source,
2✔
579
                        match_with,
2✔
580
                        parent_is,
2✔
581
                ] of configurable) {
2✔
582
                        for (const [parent_function, has_calls] of info_entries) {
2✔
583
                                const checking = this.#filter_info(
12✔
584
                                        match_with,
12✔
585
                                        has_calls,
12✔
586
                                );
12✔
587

12✔
588
                                if (1 === checking.length) {
12✔
589
                                        if (!(source in prepend_with_imports)) {
2!
590
                                                prepend_with_imports[source] = new Types();
×
591
                                        }
×
592

2✔
593
                                        if (!(parent_is[1] in prepend_with_imports)) {
2!
594
                                                prepend_with_imports[parent_is[1]] = new Types();
×
595
                                        }
×
596

2✔
597
                                        existing[checking[0].name] = prepend_with_imports[
2✔
598
                                                source
2✔
599
                                        ].add(ts, sub_type);
2✔
600

2✔
601
                                        existing[parent_function] = prepend_with_imports[
2✔
602
                                                parent_is[1]
2✔
603
                                        ].add(ts, parent_is[0]);
2✔
604
                                }
2✔
605
                        }
12✔
606
                }
2✔
607
        }
3✔
608

1✔
609
        static #filter_info(
1✔
610
                {
24✔
611
                        instancePath,
24✔
612
                        instancePath_partial,
24✔
613
                        parentDataProperty,
24✔
614
                }: validate_call_argument_1_match,
24✔
615
                checking: ValidateCallInfo[],
24✔
616
        ) {
24✔
617
                if (undefined !== instancePath_partial) {
24✔
618
                        checking = checking.filter((maybe) => (
21✔
619
                                maybe.instancePath
43✔
620
                                && maybe.instancePath.includes(
43✔
621
                                        instancePath_partial,
38✔
622
                                )
38✔
623
                        ));
21✔
624
                } else if (undefined !== instancePath) {
24✔
625
                        checking = checking.filter((maybe) => (
3✔
626
                                (
5✔
627
                                        maybe.instancePath
5✔
628
                                        && 1 === maybe.instancePath.length
5!
629
                                        && maybe.instancePath[0] === instancePath
5!
630
                                )
5✔
631
                                || (
5✔
632
                                        maybe.instancePath === null
5✔
633
                                        && instancePath === null
5✔
634
                                )
5✔
635
                        ));
3✔
636
                }
3✔
637

24✔
638
                if (parentDataProperty) {
24✔
639
                        checking = checking.filter((maybe) => (
17✔
640
                                maybe.parentDataProperty === parentDataProperty
7✔
641
                        ));
17✔
642
                }
17✔
643

24✔
644
                return checking;
24✔
645
        }
24✔
646

1✔
647
        static #specify_types_from_collected_outside_in_deep_dive(
1✔
648
                ts: ts,
9✔
649
                info: {
9✔
650
                        [key: string]: [
9✔
651
                                ValidateCallInfo,
9✔
652
                                ...ValidateCallInfo[],
9✔
653
                        ],
9✔
654
                },
9✔
655
                function_name: keyof typeof info,
9✔
656
                sub_types: [specify_type_nested, ...specify_type_nested[]],
9✔
657
                existing: specify_types_instance,
9✔
658
                prepend_with_imports: prepend_with_imports,
9✔
659
        ) {
9✔
660
                for (const sub_type of sub_types) {
9✔
661
                        const match_with = this.#is_conditional(sub_type)
12✔
662
                                ? sub_type[1]
12✔
663
                                : sub_type[2];
12✔
664

12✔
665
                        const checking = this.#filter_info(
12✔
666
                                match_with,
12✔
667
                                info[function_name],
12✔
668
                        ).filter((maybe) => !(maybe.name in existing));
12✔
669

12✔
670
                        if (1 === checking.length) {
12✔
671
                                if (this.#is_generic(sub_type)) {
12✔
672
                                        for (const actual_sub_type of sub_type[1]) {
1✔
673
                                                this.#handle_imports(
2✔
674
                                                        ts,
2✔
675
                                                        existing,
2✔
676
                                                        prepend_with_imports,
2✔
677
                                                        actual_sub_type,
2✔
678
                                                        checking[0].name,
2✔
679
                                                );
2✔
680
                                        }
2✔
681

1✔
682
                                        existing[checking[0].name] = new GenericT(
1✔
683
                                                ts,
1✔
684
                                                sub_type[1].map((e) => (
1✔
685
                                                        'string' === typeof e[0]
2✔
686
                                                                ? e[0]
2✔
687
                                                                : (
2!
688
                                                                        ('as' in e[0] && e[0].as)
×
689
                                                                                ? e[0].as
×
690
                                                                                : e[0].name
×
691
                                                                )
×
692
                                                )),
1✔
693
                                        );
1✔
694
                                } else if (this.#is_conditional(sub_type)) {
12✔
695
                                        for (
1✔
696
                                                const actual_sub_type of Object.values(sub_type[
1✔
697
                                                        0
1✔
698
                                                ].conditionally.parentDataProperty)
1✔
699
                                        ) {
1✔
700
                                                this.#handle_imports(
2✔
701
                                                        ts,
2✔
702
                                                        existing,
2✔
703
                                                        prepend_with_imports,
2✔
704
                                                        actual_sub_type,
2✔
705
                                                        checking[0].name,
2✔
706
                                                );
2✔
707
                                        }
2✔
708

1✔
709
                                        existing[checking[0].name] = new ConditionalPredicate(
1✔
710
                                                ts,
1✔
711
                                                'parentDataProperty',
1✔
712
                                                sub_type[0].conditionally.parentDataProperty,
1✔
713
                                        );
1✔
714
                                } else {
11✔
715
                                        this.#handle_imports(
10✔
716
                                                ts,
10✔
717
                                                existing,
10✔
718
                                                prepend_with_imports,
10✔
719
                                                sub_type,
10✔
720
                                                checking[0].name,
10✔
721
                                        );
10✔
722
                                }
10✔
723

12✔
724
                                if (4 === sub_type.length && checking[0].name in info) {
12✔
725
                                        this.#specify_types_from_collected_outside_in_deep_dive(
6✔
726
                                                ts,
6✔
727
                                                info,
6✔
728
                                                checking[0].name,
6✔
729
                                                sub_type[3],
6✔
730
                                                existing,
6✔
731
                                                prepend_with_imports,
6✔
732
                                        );
6✔
733
                                } else if (
6✔
734
                                        this.#is_conditional(sub_type)
6✔
735
                                        && 3 === sub_type.length
6✔
736
                                        && checking[0].name in info
6✔
737
                                ) {
6✔
738
                                        this.#specify_types_from_collected_outside_in_deep_dive(
1✔
739
                                                ts,
1✔
740
                                                info,
1✔
741
                                                checking[0].name,
1✔
742
                                                sub_type[2],
1✔
743
                                                existing,
1✔
744
                                                prepend_with_imports,
1✔
745
                                        );
1✔
746
                                }
1✔
747
                        } else if (checking.length > 0) {
12!
748
                                throw new Error('Unexpected matches found!');
×
749
                        }
×
750
                }
12✔
751
        }
9✔
752

1✔
753
        static #handle_imports(
1✔
754
                ts: ts,
14✔
755
                existing: specify_types_instance,
14✔
756
                prepend_with_imports: prepend_with_imports,
14✔
757
                sub_type: [
14✔
758
                        specify_types_config,
14✔
759
                        string,
14✔
760
                        ...unknown[],
14✔
761
                ],
14✔
762
                function_name: string,
14✔
763
        ) {
14✔
764
                if (!(sub_type[1] in prepend_with_imports)) {
14!
765
                        prepend_with_imports[sub_type[1]] = new Types();
×
766
                }
×
767

14✔
768
                existing[function_name] = prepend_with_imports[
14✔
769
                        sub_type[1]
14✔
770
                ].add(ts, sub_type[0]);
14✔
771
        }
14✔
772

1✔
773
        static #is_conditional(
1✔
774
                maybe: specify_type_nested,
29✔
775
        ): maybe is (
29✔
776
                | specify_type_conditionally_without_nested
29✔
777
                | specify_type_conditionally_with_nested
29✔
778
        ) {
29✔
779
                return 'string' !== typeof maybe[0] && 'conditionally' in maybe[0];
29✔
780
        }
29✔
781

1✔
782
        static #is_generic(
1✔
783
                maybe: specify_type_nested,
12✔
784
        ): maybe is specify_type_without_nested_but_generic {
12✔
785
                return 'T' === maybe[0];
12✔
786
        }
12✔
787
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc