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

rokucommunity / brighterscript / #13311

22 Nov 2024 08:22PM UTC coverage: 86.806%. Remained the same
#13311

push

web-flow
Merge a320d9302 into 2a6afd921

11836 of 14421 branches covered (82.07%)

Branch coverage included in aggregate %.

192 of 206 new or added lines in 26 files covered. (93.2%)

200 existing lines in 18 files now uncovered.

12869 of 14039 relevant lines covered (91.67%)

32035.86 hits per line

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

74.54
/src/types/ReferenceType.ts
1
import type { GetTypeOptions, TypeChainEntry, TypeCompatibilityData } from '../interfaces';
2
import type { GetSymbolTypeOptions, SymbolTable, SymbolTableProvider, SymbolTypeGetterProvider } from '../SymbolTable';
3
import type { SymbolTypeFlag } from '../SymbolTypeFlag';
4
import { isAnyReferenceType, isArrayDefaultTypeReferenceType, isArrayType, isBinaryOperatorReferenceType, isComponentType, isDynamicType, isReferenceType, isTypePropertyReferenceType } from '../astUtils/reflection';
1✔
5
import { BscType } from './BscType';
1✔
6
import { DynamicType } from './DynamicType';
1✔
7
import { BscTypeKind } from './BscTypeKind';
1✔
8
import type { Token } from '../lexer/Token';
9

10
export type AnyReferenceType = ReferenceType | TypePropertyReferenceType | BinaryOperatorReferenceType | ArrayDefaultTypeReferenceType;
11

12
export function referenceTypeFactory(memberKey: string, fullName, flags: SymbolTypeFlag, tableProvider: SymbolTypeGetterProvider) {
1✔
13
    return new ReferenceType(memberKey, fullName, flags, tableProvider);
210,665✔
14
}
15

16
export class ReferenceType extends BscType {
1✔
17

18
    /**
19
     * ReferenceTypes are used when the actual type may be resolved later from a Symbol table
20
     * @param memberKey which key do we use to look up this type in the given table?
21
     * @param fullName the full/display name for this type
22
     * @param flags is this type available at typetime, runtime, etc.
23
     * @param tableProvider function that returns a SymbolTable that we use for the lookup.
24
     */
25
    constructor(public memberKey: string, public fullName, public flags: SymbolTypeFlag, public tableProvider: SymbolTypeGetterProvider) {
211,969✔
26
        super(memberKey);
211,969✔
27
        // eslint-disable-next-line no-constructor-return
28
        return new Proxy(this, {
211,969✔
29
            get: (target, propName, receiver) => {
30

31
                if (propName === '__reflection') {
480,174✔
32
                    // Cheeky way to get `isReferenceType` reflection to work
33
                    return this.__reflection;
435,208✔
34
                }
35
                if (propName === '__identifier') {
44,966✔
36
                    // Cheeky way to get `isReferenceType` reflection to work
37
                    return this.__identifier;
38✔
38
                }
39
                if (propName === 'fullName') {
44,928✔
40
                    return this.fullName;
730✔
41
                }
42
                if (propName === 'isResolvable') {
44,198✔
43
                    return () => {
3,988✔
44
                        let resultSoFar = this.resolve();
3,988✔
45
                        while (resultSoFar && isReferenceType(resultSoFar)) {
3,988✔
46
                            resultSoFar = (resultSoFar as any).getTarget?.();
×
47
                        }
48
                        return !!resultSoFar;
3,988✔
49
                    };
50
                }
51
                if (propName === 'getTarget') {
40,210✔
52
                    return () => {
6,549✔
53
                        return this.resolve();
6,549✔
54
                    };
55
                }
56
                if (propName === 'tableProvider') {
33,661✔
57
                    return this.tableProvider;
22✔
58
                }
59
                if (propName === 'isEqual') {
33,639✔
60
                    //Need to be able to check equality without resolution, because resolution need to check equality
61
                    //To see if you need to make a UnionType
62
                    return (targetType: BscType, data?: TypeCompatibilityData) => {
63✔
63
                        if (!targetType) {
63!
64
                            return false;
×
65
                        }
66
                        const resolvedType = this.resolve();
63✔
67
                        let equal = false;
63✔
68
                        if (resolvedType && !isReferenceType(resolvedType)) {
63✔
69
                            equal = resolvedType.isEqual(targetType, data);
31✔
70
                        } else if (isReferenceType(targetType)) {
32✔
71
                            equal = this.fullName.toLowerCase() === targetType.fullName.toLowerCase() &&
28!
72
                                (this.tableProvider === targetType.tableProvider ||
73
                                    this.tableProvider().name === targetType.tableProvider().name);
74
                        } else {
75
                            equal = targetType.isEqual(this, data);
4✔
76
                        }
77
                        return equal;
63✔
78
                    };
79
                }
80
                if (propName === 'isTypeCompatible') {
33,576✔
81
                    //Need to be able to check equality without resolution, because resolution need to check equality
82
                    //To see if you need to make a UnionType
83
                    return (targetType: BscType, data?: TypeCompatibilityData) => {
87✔
84
                        if (!targetType) {
87!
85
                            return false;
×
86
                        }
87
                        if (isDynamicType(targetType)) {
87✔
88
                            return true;
1✔
89
                        }
90
                        const resolvedType = this.resolve();
86✔
91
                        if (resolvedType && !isReferenceType(resolvedType)) {
86✔
92
                            return resolvedType.isTypeCompatible(targetType, data);
85✔
93
                        } else if (isReferenceType(targetType)) {
1!
94
                            return this.fullName.toLowerCase() === targetType.fullName.toLowerCase() &&
×
95
                                this.tableProvider === targetType.tableProvider;
96
                        }
97
                        return targetType.isTypeCompatible(this, data);
1✔
98
                    };
99
                }
100

101
                //There may be some need to specifically get members on ReferenceType in the future
102
                // eg: if (Reflect.has(target, name)) {
103
                //   return Reflect.get(target, propName, receiver);
104

105
                let innerType = this.resolve();
33,489✔
106

107
                if (!innerType) {
33,489✔
108
                    // No real BscType found - we may need to handle some specific cases
109

110
                    if (propName === 'getMemberType') {
24,092✔
111
                        // We're looking for a member of a reference type
112
                        // Since we don't know what type this is, yet, return ReferenceType
113
                        return (memberName: string, options: GetTypeOptions) => {
951✔
114
                            const resolvedType = this.resolve();
951✔
115
                            if (resolvedType) {
951!
116
                                return resolvedType.getMemberType(memberName, options);
×
117
                            }
118
                            const refLookUp = `${memberName.toLowerCase()}-${options?.flags}`;
951!
119
                            let memberTypeReference = this.memberTypeReferences.get(refLookUp);
951✔
120
                            if (memberTypeReference) {
951✔
121
                                return memberTypeReference;
26✔
122

123
                            }
124
                            memberTypeReference = new ReferenceType(memberName, this.makeMemberFullName(memberName), options.flags, this.futureMemberTableProvider);
925✔
125
                            this.memberTypeReferences.set(refLookUp, memberTypeReference);
925✔
126
                            return memberTypeReference;
925✔
127
                        };
128
                    } else if (propName === 'getCallFuncType') {
23,141✔
129
                        // We're looking for a callfunc member of a reference type
130
                        // Since we don't know what type this is, yet, return ReferenceType
131
                        return (memberName: string, options: GetTypeOptions) => {
13✔
132
                            const resolvedType = this.resolve();
13✔
133
                            if (isComponentType(resolvedType)) {
13!
134
                                return resolvedType.getCallFuncType(memberName, options);
×
135
                            }
136
                            const refLookUp = `${memberName.toLowerCase()}-${options.flags}-callfunc`;
13✔
137
                            let callFuncMemberTypeReference = this.callFuncMemberTypeReferences.get(refLookUp);
12✔
138
                            if (callFuncMemberTypeReference) {
12!
139
                                return callFuncMemberTypeReference;
×
140

141
                            }
142
                            callFuncMemberTypeReference = new ReferenceType(memberName, this.makeMemberFullName(memberName), options.flags, this.futureCallFuncMemberTableProvider);
12✔
143
                            this.callFuncMemberTypeReferences.set(refLookUp, callFuncMemberTypeReference);
12✔
144
                            return callFuncMemberTypeReference;
12✔
145
                        };
146
                    } else if (propName === 'toString') {
23,128✔
147
                        // This type was never found
148
                        // For diagnostics, we should return the expected name of of the type
149
                        return () => this.fullName;
5,571✔
150
                    } else if (propName === 'toTypeString') {
17,557!
151
                        // For transpilation, we should 'dynamic'
152
                        return () => 'dynamic';
×
153
                    } else if (propName === 'returnType') {
17,557✔
154
                        let propRefType = this.propertyTypeReference.get(propName);
70✔
155
                        if (!propRefType) {
70✔
156
                            propRefType = new TypePropertyReferenceType(this, propName);
30✔
157
                            this.propertyTypeReference.set(propName, propRefType);
30✔
158
                        }
159
                        return propRefType;
70✔
160
                    } else if (propName === 'memberTable') {
17,487✔
161
                        return this.memberTable;
10✔
162
                    } else if (propName === 'getMemberTable') {
17,477✔
163
                        return () => {
6✔
164
                            return this.memberTable;
6✔
165
                        };
166
                    } else if (propName === 'callFuncTable') {
17,471!
167
                        return (this as any).callFuncMemberTable;
×
168
                    } else if (propName === 'getCallFuncTable') {
17,471!
169
                        return () => {
×
170
                            return (this as any).callFuncMemberTable;
×
171
                        };
172
                    } else if (propName === 'isTypeCompatible') {
17,471!
173
                        return (targetType: BscType) => {
×
174
                            return isDynamicType(targetType);
×
175
                        };
176
                    } else if (propName === 'isEqual') {
17,471!
177
                        return (targetType: BscType) => {
×
178
                            if (isReferenceType(targetType)) {
×
179
                                return this.fullName.toLowerCase() === targetType.toString().toLowerCase() &&
×
180
                                    this.tableProvider() === targetType.tableProvider();
181
                            }
182
                            return false;
×
183
                        };
184
                    } else if (propName === 'addBuiltInInterfaces') {
17,471✔
185
                        // this is an unknown type. There is no use in adding built in interfaces
186
                        // return no-op function
187
                        return () => { };
21✔
188
                    } else if (propName === 'hasAddedBuiltInInterfaces') {
17,450!
189
                        // this is an unknown type. There is no use in adding built in interfaces
190
                        return true;
×
191
                    } else if (propName === 'isBuiltIn') {
17,450✔
192
                        return false;
1✔
193
                    }
194
                }
195

196
                if (!innerType) {
26,846✔
197
                    innerType = DynamicType.instance;
17,449✔
198
                }
199
                const result = Reflect.get(innerType, propName, innerType);
26,846✔
200
                return result;
26,846✔
201
            },
202
            set: (target, name, value, receiver) => {
203
                //There may be some need to specifically set members on ReferenceType in the future
204
                // eg: if (Reflect.has(target, name)) {
205
                //   return Reflect.set(target, name, value, receiver);
206

207
                let innerType = this.resolve();
616✔
208

209
                // Look for circular references
210
                if (!innerType || this.referenceChain.has(innerType)) {
616!
NEW
211
                    console.log(`Proxy set error`, name, value, innerType);
×
NEW
212
                    const error = new Error();
×
NEW
213
                    console.log(error.stack);
×
UNCOV
214
                    return false;
×
215
                }
216
                const result = Reflect.set(innerType, name, value, innerType);
616✔
217
                this.referenceChain.clear();
616✔
218
                return result;
616✔
219
            }
220
        });
221
    }
222

223
    public readonly kind = BscTypeKind.ReferenceType;
211,969✔
224

225
    getTarget: () => BscType;
226

227
    /**
228
     * Resolves the type based on the original name and the table provider
229
     */
230
    private resolve(): BscType {
231
        const symbolTable = this.tableProvider();
56,923✔
232
        if (!symbolTable) {
56,923✔
233
            return;
10✔
234
        }
235
        // Look for circular references
236
        let resolvedType = symbolTable.getSymbolType(this.memberKey, { flags: this.flags, onlyCacheResolvedTypes: true });
56,913✔
237
        if (!resolvedType) {
56,913✔
238
            // could not find this member
239
            return;
36,926✔
240
        }
241
        if (isAnyReferenceType(resolvedType)) {
19,987✔
242
            // If this is a referenceType, keep digging down until we have a non reference Type.
243
            while (resolvedType && isAnyReferenceType(resolvedType)) {
723✔
244
                if (this.referenceChain.has(resolvedType)) {
723✔
245
                    // this is a circular reference
246
                    this.circRefCount++;
39✔
247
                }
248
                if (this.circRefCount > 1) {
723✔
249
                    //It is possible that we could properly resolve the case that one reference points to itself
250
                    //see test: '[Scope][symbolTable lookups with enhanced typing][finds correct class field type with default value enums are used]
251
                    return;
33✔
252
                }
253
                this.referenceChain.add(resolvedType);
690✔
254
                resolvedType = (resolvedType as any).getTarget?.();
690!
255
            }
256
            this.tableProvider().setCachedType(this.memberKey, { type: resolvedType }, { flags: this.flags });
690✔
257
        }
258

259
        if (resolvedType && !isAnyReferenceType(resolvedType)) {
19,954✔
260
            this.circRefCount = 0;
19,267✔
261
            this.referenceChain.clear();
19,267✔
262
        }
263
        return resolvedType;
19,954✔
264
    }
265

266
    get __reflection() {
267
        return { name: 'ReferenceType' };
435,302✔
268
    }
269

270
    makeMemberFullName(memberName: string) {
271
        return this.fullName + '.' + memberName;
937✔
272
    }
273
    private circRefCount = 0;
211,969✔
274

275
    private referenceChain = new Set<BscType>();
211,969✔
276

277
    private propertyTypeReference = new Map<string, TypePropertyReferenceType>();
211,969✔
278

279
    private memberTypeReferences = new Map<string, ReferenceType>();
211,969✔
280
    private callFuncMemberTypeReferences = new Map<string, ReferenceType>();
211,969✔
281

282
    private futureMemberTableProvider = () => {
211,969✔
283
        return {
10,904✔
284
            name: `FutureMemberTableProvider: '${this.__identifier}'`,
285
            getSymbolType: (innerName: string, innerOptions: GetTypeOptions) => {
286
                const resolvedType = this.resolve();
10,226✔
287
                if (resolvedType) {
10,226✔
288
                    return resolvedType.getMemberType(innerName, innerOptions);
6,937✔
289
                }
290
            },
291
            setCachedType: (innerName: string, innerResolvedTypeCacheEntry: TypeChainEntry, options: GetSymbolTypeOptions) => {
292
                const resolvedType = this.resolve();
678✔
293
                if (resolvedType) {
678!
294
                    resolvedType.memberTable.setCachedType(innerName, innerResolvedTypeCacheEntry, options);
678✔
295
                }
296
            },
297
            addSibling: (symbolTable: SymbolTable) => {
NEW
298
                const resolvedType = this.resolve();
×
NEW
299
                if (resolvedType) {
×
NEW
300
                    resolvedType.memberTable?.addSibling?.(symbolTable);
×
301
                }
302
            }
303
        };
304
    };
305

306
    private futureCallFuncMemberTableProvider = () => {
211,969✔
307
        return {
264✔
308
            name: `FutureCallFuncMemberTableProvider: '${this.__identifier}'`,
309
            getSymbolType: (innerName: string, innerOptions: GetTypeOptions) => {
310
                const resolvedType = this.resolve();
264✔
311
                if (isComponentType(resolvedType)) {
264✔
312
                    return resolvedType.getCallFuncType(innerName, innerOptions);
204✔
313
                }
314
            },
315
            setCachedType: (innerName: string, innerResolvedTypeCacheEntry: TypeChainEntry, options: GetSymbolTypeOptions) => {
UNCOV
316
                const resolvedType = this.resolve();
×
UNCOV
317
                if (isComponentType(resolvedType)) {
×
UNCOV
318
                    resolvedType.getCallFuncTable().setCachedType(innerName, innerResolvedTypeCacheEntry, options);
×
319
                }
320
            },
321
            addSibling: (symbolTable: SymbolTable) => {
NEW
322
                const resolvedType = this.resolve();
×
NEW
323
                if (isComponentType(resolvedType)) {
×
NEW
324
                    resolvedType.getCallFuncTable()?.addSibling?.(symbolTable);
×
325
                }
326
            }
327
        };
328
    };
329
}
330

331
/**
332
 * Use this class for when you need to reference a property of a BscType, and that property is also a BscType,
333
 * Especially when the instance with the property may not have been instantiated/discovered yet
334
 *
335
 * For Example, FunctionType.returnType --- if the FunctionExpression has not been walked yet, it will be a ReferenceType
336
 * if we just access .returnType on a ReferenceType that doesn't have access to an actual FunctionType yet, .returnType will be undefined
337
 * So when we use this class, it maintains that reference to a potential ReferenceType, and this class will change from
338
 * returning undefined to the ACTUAL .returnType when the ReferenceType can be resolved.
339
 *
340
 * This is really cool. It's like programming with time-travel.
341
 */
342
export class TypePropertyReferenceType extends BscType {
1✔
343
    constructor(public outerType: BscType, public propertyName: string) {
86✔
344
        super(propertyName);
86✔
345
        // eslint-disable-next-line no-constructor-return
346
        return new Proxy(this, {
86✔
347
            get: (target, propName, receiver) => {
348

349
                if (propName === '__reflection') {
538✔
350
                    // Cheeky way to get `isTypePropertyReferenceType` reflection to work
351
                    return { name: 'TypePropertyReferenceType' };
116✔
352
                }
353

354
                if (propName === 'outerType') {
422!
UNCOV
355
                    return outerType;
×
356
                }
357

358
                if (isAnyReferenceType(this.outerType) && !this.outerType.isResolvable()) {
422✔
359
                    if (propName === 'getMemberType') {
52✔
360
                        //If we're calling `getMemberType()`, we need it to proxy to using the actual symbol table
361
                        //So if that symbol is ever populated, the correct type is passed through
362
                        return (memberName: string, options: GetSymbolTypeOptions) => {
16✔
363
                            const fullMemberName = this.outerType.toString() + '.' + memberName;
16✔
364
                            return new ReferenceType(memberName, fullMemberName, options.flags, () => {
16✔
365
                                return {
36✔
366
                                    name: `TypePropertyReferenceType : '${fullMemberName}'`,
367
                                    getSymbolType: (innerName: string, innerOptions: GetTypeOptions) => {
368
                                        return this.outerType?.[this.propertyName]?.getMemberType(innerName, innerOptions);
36!
369
                                    },
370
                                    setCachedType: (innerName: string, innerTypeCacheEntry: TypeChainEntry, innerOptions: GetTypeOptions) => {
UNCOV
371
                                        return this.outerType?.[this.propertyName]?.memberTable.setCachedType(innerName, innerTypeCacheEntry, innerOptions);
×
372
                                    },
373
                                    addSibling: (symbolTable: SymbolTable) => {
NEW
374
                                        return this.outerType?.[this.propertyName]?.memberTable?.addSibling?.(symbolTable);
×
375
                                    }
376
                                };
377
                            });
378
                        };
379
                    }
380
                    if (propName === 'isResolvable') {
36✔
381
                        return () => false;
8✔
382
                    }
383
                }
384
                let inner = this.outerType?.[this.propertyName];
398✔
385

386
                if (!inner) {
398✔
387
                    inner = DynamicType.instance;
95✔
388
                }
389

390
                if (inner) {
398!
391
                    const result = Reflect.get(inner, propName, inner);
398✔
392
                    return result;
398✔
393
                }
394
            },
395
            set: (target, name, value, receiver) => {
396
                //There may be some need to specifically set members on ReferenceType in the future
397
                // eg: if (Reflect.has(target, name)) {
398
                //   return Reflect.set(target, name, value, receiver);
399

400
                let inner = this.outerType[this.propertyName];
29✔
401

402
                if (inner) {
29!
403
                    const result = Reflect.set(inner, name, value, inner);
29✔
404
                    return result;
29✔
405
                }
406
            }
407
        });
408
    }
409

410
    getTarget: () => BscType;
411

412
    tableProvider: SymbolTableProvider;
413
}
414

415

416
/**
417
 * Use this class for when there is a binary operator and either the left hand side and/or the right hand side
418
 * are ReferenceTypes
419
 */
420
export class BinaryOperatorReferenceType extends BscType {
1✔
421
    cachedType: BscType;
422

423
    constructor(public leftType: BscType, public operator: Token, public rightType: BscType, binaryOpResolver: (lType: BscType, operator: Token, rType: BscType) => BscType) {
31✔
424
        super(operator.text);
31✔
425
        // eslint-disable-next-line no-constructor-return
426
        return new Proxy(this, {
31✔
427
            get: (target, propName, receiver) => {
428

429
                if (propName === '__reflection') {
130✔
430
                    // Cheeky way to get `BinaryOperatorReferenceType` reflection to work
431
                    return { name: 'BinaryOperatorReferenceType' };
78✔
432
                }
433

434
                if (propName === 'leftType') {
52✔
435
                    return leftType;
6✔
436
                }
437

438
                if (propName === 'rightType') {
46✔
439
                    return rightType;
6✔
440
                }
441

442
                let resultType: BscType = this.cachedType ?? DynamicType.instance;
40✔
443
                if (!this.cachedType) {
40✔
444
                    if ((isAnyReferenceType(this.leftType) && !this.leftType.isResolvable()) ||
26✔
445
                        (isAnyReferenceType(this.rightType) && !this.rightType.isResolvable())
446
                    ) {
447
                        if (propName === 'isResolvable') {
24✔
448
                            return () => false;
13✔
449
                        }
450
                        if (propName === 'getTarget') {
11✔
451
                            return () => undefined;
2✔
452
                        }
453
                    } else {
454
                        resultType = binaryOpResolver(this.leftType, this.operator, this.rightType);
2✔
455
                        this.cachedType = resultType;
2✔
456
                    }
457

458
                }
459
                if (resultType) {
25!
460
                    const result = Reflect.get(resultType, propName, resultType);
25✔
461
                    return result;
25✔
462
                }
463
            }
464
        });
465
    }
466

467
    getTarget: () => BscType;
468

469
    tableProvider: SymbolTableProvider;
470
}
471

472

473
/**
474
 * Use this class for when there is a presumable array type that is a referenceType
475
 */
476
export class ArrayDefaultTypeReferenceType extends BscType {
1✔
477
    cachedType: BscType;
478

479
    constructor(public objType: BscType) {
2✔
480
        super('ArrayDefaultType');
2✔
481
        // eslint-disable-next-line no-constructor-return
482
        return new Proxy(this, {
2✔
483
            get: (target, propName, receiver) => {
484

485
                if (propName === '__reflection') {
30✔
486
                    // Cheeky way to get `ArrayDefaultTypeReferenceType` reflection to work
487
                    return { name: 'ArrayDefaultTypeReferenceType' };
19✔
488
                }
489

490
                if (propName === 'objType') {
11!
UNCOV
491
                    return objType;
×
492
                }
493

494
                let resultType: BscType = this.cachedType ?? DynamicType.instance;
11✔
495
                if (!this.cachedType) {
11✔
496
                    if ((isAnyReferenceType(this.objType) && !this.objType.isResolvable())
4✔
497
                    ) {
498
                        if (propName === 'isResolvable') {
2✔
499
                            return () => false;
1✔
500
                        }
501
                        if (propName === 'getTarget') {
1!
UNCOV
502
                            return () => undefined;
×
503
                        }
504
                    } else {
505
                        if (isArrayType(this.objType)) {
2!
506
                            resultType = this.objType.defaultType;
2✔
507
                        } else {
UNCOV
508
                            resultType = DynamicType.instance;
×
509
                        }
510
                        this.cachedType = resultType;
2✔
511
                    }
512

513
                }
514
                if (resultType) {
10!
515
                    const result = Reflect.get(resultType, propName, resultType);
10✔
516
                    return result;
10✔
517
                }
518
            }
519
        });
520
    }
521

522
    getTarget: () => BscType;
523

524
    tableProvider: SymbolTableProvider;
525
}
526

527
/**
528
 * Gives an array of all the symbol names that need to be resolved to make the given reference type be resolved
529
 */
530
export function getAllRequiredSymbolNames(refType: BscType, namespaceLower?: string): Array<{ name: string; namespacedName?: string }> {
1✔
531
    if (refType.isResolvable()) {
75✔
532
        return [];
8✔
533
    }
534
    if (isReferenceType(refType)) {
67✔
535
        return [{ name: refType.fullName, namespacedName: namespaceLower ? `${namespaceLower}.${refType.fullName}` : null }];
61✔
536
    }
537
    if (isTypePropertyReferenceType(refType)) {
6!
UNCOV
538
        const outer = refType.outerType;
×
UNCOV
539
        if (isAnyReferenceType(outer)) {
×
UNCOV
540
            return getAllRequiredSymbolNames(outer);
×
541
        } else {
542
            return [];
×
543
        }
544

545
    }
546
    if (isArrayDefaultTypeReferenceType(refType)) {
6!
UNCOV
547
        const objType = refType.objType;
×
UNCOV
548
        if (isAnyReferenceType(objType)) {
×
UNCOV
549
            return getAllRequiredSymbolNames(objType);
×
550
        } else {
UNCOV
551
            return [];
×
552
        }
553
    }
554
    if (isBinaryOperatorReferenceType(refType)) {
6!
555
        const left = refType.leftType;
6✔
556
        const right = refType.rightType;
6✔
557
        const result = [];
6✔
558
        if (isAnyReferenceType(left)) {
6✔
559
            result.push(...getAllRequiredSymbolNames(left, namespaceLower));
4✔
560
        }
561
        if (isAnyReferenceType(right)) {
6!
562
            result.push(...getAllRequiredSymbolNames(right, namespaceLower));
6✔
563

564
        }
565
        return result;
6✔
566
    }
UNCOV
567
    return [];
×
568
}
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

© 2025 Coveralls, Inc