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

rokucommunity / brighterscript / #14386

09 May 2025 11:44AM UTC coverage: 87.026% (-2.0%) from 89.017%
#14386

push

web-flow
Merge a194c3925 into 489231ac7

13731 of 16677 branches covered (82.33%)

Branch coverage included in aggregate %.

8175 of 8874 new or added lines in 103 files covered. (92.12%)

85 existing lines in 22 files now uncovered.

14603 of 15881 relevant lines covered (91.95%)

20322.22 hits per line

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

91.26
/src/types/ComponentType.ts
1
import type { BscSymbol, GetSymbolTypeOptions, SymbolTableProvider } from '../SymbolTable';
2
import { SymbolTypeFlag } from '../SymbolTypeFlag';
1✔
3
import { SymbolTable } from '../SymbolTable';
1✔
4
import { isAnyReferenceType, isComponentType, isDynamicType, isInvalidType, isObjectType, isPrimitiveType, isReferenceType, isTypedFunctionType } from '../astUtils/reflection';
1✔
5
import type { ExtraSymbolData, TypeCompatibilityData } from '../interfaces';
6
import type { BaseFunctionType } from './BaseFunctionType';
7
import type { BscType } from './BscType';
8
import { BscTypeKind } from './BscTypeKind';
1✔
9
import { BuiltInInterfaceAdder } from './BuiltInInterfaceAdder';
1✔
10
import { InheritableType } from './InheritableType';
1✔
11
import { addAssociatedTypesTableAsSiblingToMemberTable, isUnionTypeCompatible } from './helpers';
1✔
12
import util from '../util';
1✔
13

14
export class ComponentType extends InheritableType {
1✔
15

16
    constructor(public name: string, superComponent?: ComponentType) {
194,632✔
17
        super(name, superComponent);
194,632✔
18
        this.callFuncMemberTable = new SymbolTable(`${this.name}: CallFunc`, () => this.parentComponent?.callFuncMemberTable);
194,632✔
19
        this.callFuncAssociatedTypesTable = new SymbolTable(`${this.name}: CallFuncAssociatedTypes`, () => this.parentComponent?.callFuncAssociatedTypesTable);
194,632!
20
    }
21

22
    public readonly kind = BscTypeKind.ComponentType;
194,632✔
23

24
    public get parentComponent() {
25
        return this.parentType as ComponentType;
2,285✔
26
    }
27

28
    public isTypeCompatible(targetType: BscType, data?: TypeCompatibilityData) {
29
        if (this.isEqual(targetType)) {
2,547✔
30
            return true;
2,538✔
31
        } else if (isInvalidType(targetType) ||
9✔
32
            isDynamicType(targetType) ||
33
            isObjectType(targetType) ||
34
            isUnionTypeCompatible(this, targetType, data)) {
35
            return true;
1✔
36
        } else if (isComponentType(targetType)) {
8!
37
            return this.isTypeDescendent(targetType);
8✔
38
        }
NEW
39
        return false;
×
40
    }
41

42
    public static instance = new ComponentType('Node');
1✔
43

44
    isEqual(targetType: BscType, data: TypeCompatibilityData = {}): boolean {
2,585✔
45
        if (isReferenceType(targetType) && targetType.isResolvable()) {
3,282✔
46
            targetType = targetType.getTarget?.() ?? targetType;
2,921!
47
        }
48
        if (this === targetType) {
3,282✔
49
            return true;
3,085✔
50
        }
51
        if (!isComponentType(targetType)) {
197✔
52
            return false;
1✔
53
        }
54

55
        const thisNameLower = this.name.toLowerCase();
196✔
56
        const targetNameLower = targetType.name.toLowerCase();
196✔
57
        if (thisNameLower !== targetNameLower) {
196✔
58
            return false;
48✔
59
        }
60
        if (this.isBuiltIn && targetType.isBuiltIn) {
148✔
61
            return true;
2✔
62
        }
63

64
        if (!this.isParentTypeEqual(targetType, data)) {
146!
NEW
65
            return false;
×
66
        }
67
        if (!this.checkCompatibilityBasedOnMembers(targetType, SymbolTypeFlag.runtime, data) ||
146✔
68
            !targetType.checkCompatibilityBasedOnMembers(this, SymbolTypeFlag.runtime, data)) {
69
            return false;
5✔
70
        }
71
        if (!this.checkCompatibilityBasedOnMembers(targetType, SymbolTypeFlag.runtime, data, this.callFuncMemberTable, targetType.callFuncMemberTable) ||
141✔
72
            !targetType.checkCompatibilityBasedOnMembers(this, SymbolTypeFlag.runtime, data, targetType.callFuncMemberTable, this.callFuncMemberTable)) {
73
            return false;
3✔
74
        }
75

76
        return true;
138✔
77
    }
78

79
    public toString() {
80
        return util.getSgNodeTypeName(this.name);
680✔
81
    }
82

83
    private builtInMemberTable: SymbolTable;
84

85
    getBuiltInMemberTable(): SymbolTable {
86
        if (!this.parentType) {
194,630✔
87
            if (this.builtInMemberTable) {
14,035!
NEW
88
                return this.builtInMemberTable;
×
89
            }
90
            this.builtInMemberTable = new SymbolTable(`${this.__identifier} Built-in Members`);
14,035✔
91
            this.pushMemberProvider(() => this.builtInMemberTable);
23,566✔
92
            return this.builtInMemberTable;
14,035✔
93
        }
94
    }
95

96
    private hasStartedAddingBuiltInInterfaces = false;
194,632✔
97

98
    addBuiltInInterfaces() {
99
        if (!this.hasAddedBuiltInInterfaces && !this.hasStartedAddingBuiltInInterfaces) {
377,093✔
100
            this.hasStartedAddingBuiltInInterfaces = true;
194,630✔
101
            if (this.parentType) {
194,630✔
102
                this.parentType.addBuiltInInterfaces();
180,595✔
103
            }
104
            BuiltInInterfaceAdder.addBuiltInInterfacesToType(this);
194,630✔
105
        }
106
        this.hasAddedBuiltInInterfaces = true;
377,093✔
107
        this.addBuiltInFields();
377,093✔
108
    }
109

110
    private hasAddedBuiltInFields = false;
194,632✔
111
    private hasStartedAddingBuiltInFields = false;
194,632✔
112

113

114
    addBuiltInFields() {
115
        if (!this.hasAddedBuiltInFields && !this.hasStartedAddingBuiltInFields) {
557,665✔
116
            this.hasStartedAddingBuiltInFields = true;
194,630✔
117
            if (isComponentType(this.parentType)) {
194,630✔
118
                this.parentType.addBuiltInFields();
180,572✔
119
            }
120
            BuiltInInterfaceAdder.addBuiltInFieldsToNodeType(this);
194,630✔
121
        }
122
        this.hasAddedBuiltInFields = true;
557,665✔
123
    }
124

125
    public readonly callFuncMemberTable: SymbolTable;
126
    public readonly callFuncAssociatedTypesTable: SymbolTable;
127

128
    /**
129
     * Adds a function to the call func member table
130
     * Also adds any associated custom types to its own table, so they can be used through a callfunc
131
     */
132
    addCallFuncMember(name: string, data: ExtraSymbolData, funcType: BaseFunctionType, flags: SymbolTypeFlag, associatedTypesTableProvider?: SymbolTableProvider) {
133
        const originalTypesToCheck = new Set<BscType>();
69✔
134
        if (isTypedFunctionType(funcType)) {
69✔
135
            const paramTypes = (funcType.params ?? []).map(p => p.type);
68!
136
            for (const paramType of paramTypes) {
65✔
137
                originalTypesToCheck.add(paramType);
68✔
138
            }
139
        }
140
        if (funcType.returnType) {
69!
141
            originalTypesToCheck.add(funcType.returnType);
69✔
142
        }
143
        const additionalTypesToCheck = new Set<BscType>();
69✔
144

145
        for (const type of originalTypesToCheck) {
69✔
146
            if (!type.isBuiltIn) {
100✔
147
                util.getCustomTypesInSymbolTree(additionalTypesToCheck, type, (subSymbol: BscSymbol) => {
9✔
148
                    return !originalTypesToCheck.has(subSymbol.type);
3✔
149
                });
150
            }
151
        }
152

153
        for (const type of [...originalTypesToCheck.values(), ...additionalTypesToCheck.values()]) {
69✔
154
            if (!isPrimitiveType(type) && type.isResolvable()) {
103✔
155
                // This type is a reference type, but was able to be resolved here
156
                // add it to the table of associated types, so it can be used through a callfunc
157
                const extraData = {};
49✔
158
                if (associatedTypesTableProvider) {
49!
159
                    associatedTypesTableProvider().getSymbolType(type.toString(), { flags: SymbolTypeFlag.typetime, data: extraData });
49✔
160
                }
161
                let targetType = isAnyReferenceType(type) ? type.getTarget?.() : type;
49!
162

163
                this.callFuncAssociatedTypesTable.addSymbol(type.toString(), { ...extraData, isFromCallFunc: true }, targetType, SymbolTypeFlag.typetime);
49✔
164
            }
165
        }
166

167
        // add this function to be available through callfunc
168
        this.callFuncMemberTable.addSymbol(name, data, funcType, flags);
69✔
169
    }
170

171
    getCallFuncTable() {
172
        return this.callFuncMemberTable;
3✔
173
    }
174

175
    getCallFuncType(name: string, options: GetSymbolTypeOptions) {
176
        const callFuncType = this.callFuncMemberTable.getSymbolType(name, options);
275✔
177

178
        if (isTypedFunctionType(callFuncType)) {
272✔
179
            const typesToCheck = [...callFuncType.params.map(p => p.type), callFuncType.returnType];
256✔
180

181
            for (const type of typesToCheck) {
256✔
182
                addAssociatedTypesTableAsSiblingToMemberTable(type, this.callFuncAssociatedTypesTable, SymbolTypeFlag.runtime);
462✔
183
            }
184
        }
185

186
        return callFuncType;
272✔
187
    }
188
}
189

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