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

rokucommunity / brighterscript / #15079

13 Jan 2026 06:21PM UTC coverage: 87.299% (+0.1%) from 87.152%
#15079

push

web-flow
Merge 0c7d51295 into 2ea4d2108

14409 of 17439 branches covered (82.63%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

209 existing lines in 11 files now uncovered.

15091 of 16353 relevant lines covered (92.28%)

24237.03 hits per line

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

84.98
/src/types/InheritableType.ts
1
import type { GetTypeOptions, TypeCompatibilityData } from '../interfaces';
2
import { isInheritableType, isReferenceType } from '../astUtils/reflection';
1✔
3
import { SymbolTypeFlag } from '../SymbolTypeFlag';
1✔
4
import { BscType } from './BscType';
1✔
5
import type { ReferenceType } from './ReferenceType';
6
import { DynamicType } from './DynamicType';
1✔
7

8
export abstract class InheritableType extends BscType {
1✔
9

10
    constructor(public name: string, public readonly parentType?: InheritableType | ReferenceType) {
568,736✔
11
        super(name);
568,736✔
12
        if (parentType) {
568,736✔
13
            this.memberTable.pushParentProvider(() => this.parentType.memberTable);
191,057✔
14
        }
15
    }
16

17
    changeUnknownMemberToDynamic = false;
568,736✔
18

19
    getMemberType(memberName: string, options: GetTypeOptions) {
20
        let hasRoAssociativeArrayAsAncestor = this.name.toLowerCase() === 'roassociativearray' || this.getAncestorTypeList()?.find(ancestorType => ancestorType.name.toLowerCase() === 'roassociativearray');
1,587!
21

22
        if (hasRoAssociativeArrayAsAncestor) {
1,587✔
23
            return super.getMemberType(memberName, options) ?? DynamicType.instance;
20✔
24
        }
25

26
        const resultType = super.getMemberType(memberName, { ...options, fullName: memberName, tableProvider: () => this.memberTable });
1,880✔
27

28
        if (this.changeUnknownMemberToDynamic && !resultType.isResolvable()) {
1,567✔
29
            return DynamicType.instance;
5✔
30
        }
31
        return resultType;
1,562✔
32
    }
33

34
    public toString() {
35
        return this.name;
1,378✔
36
    }
37

38
    public toTypeString(): string {
39
        return 'dynamic';
9✔
40
    }
41

42
    protected getAncestorTypeList(): InheritableType[] {
43
        const ancestors = [];
1,674✔
44
        let currentParentType = this.parentType;
1,674✔
45
        while (currentParentType) {
1,674✔
46
            if (isInheritableType(currentParentType)) {
552✔
47
                ancestors.push(currentParentType);
547✔
48
                currentParentType = currentParentType.parentType;
547✔
49
            } else {
50
                break;
5✔
51
            }
52
        }
53
        return ancestors;
1,674✔
54
    }
55

56
    /**
57
     *  Checks if other type is an ancestor of this
58
     */
59
    isTypeAncestor(otherType: BscType) {
60
        if (!isInheritableType(otherType)) {
59!
UNCOV
61
            return false;
×
62
        }
63
        // Check if targetType is an ancestor of this
64
        const ancestors = this.getAncestorTypeList();
59✔
65
        if (ancestors?.find(ancestorType => ancestorType.isEqual(otherType))) {
62!
66
            return true;
29✔
67
        }
68
        return false;
30✔
69
    }
70

71
    /**
72
     *  Checks if other type is an descendent of this
73
     */
74
    isTypeDescendent(otherType: BscType) {
75
        if (!isInheritableType(otherType)) {
59!
UNCOV
76
            return false;
×
77
        }
78
        return otherType.isTypeAncestor(this);
59✔
79
    }
80

81
    /**
82
     * Gets a string representation of the Interface that looks like javascript
83
     * Useful for debugging
84
     */
85
    private toJSString() {
86
        // eslint-disable-next-line no-bitwise
87
        const flags = 3 as SymbolTypeFlag; //SymbolTypeFlags.runtime | SymbolTypeFlags.typetime;
5✔
88
        let result = '{';
5✔
89
        const memberSymbols = (this.memberTable?.getAllSymbols(flags) || []).sort((a, b) => a.name.localeCompare(b.name));
5!
90
        for (const symbol of memberSymbols) {
5✔
91
            let symbolTypeString = symbol.type.toString();
6✔
92
            if (isInheritableType(symbol.type)) {
6✔
93
                symbolTypeString = symbol.type.toJSString();
1✔
94
            }
95
            result += ' ' + symbol.name + ': ' + symbolTypeString + ';';
6✔
96
        }
97
        if (memberSymbols.length > 0) {
5✔
98
            result += ' ';
4✔
99
        }
100
        return result + '}';
5✔
101
    }
102

103
    isEqual(targetType: BscType, data: TypeCompatibilityData = {}): boolean {
17✔
104
        if (this === targetType) {
137!
UNCOV
105
            return true;
×
106
        }
107
        if (isReferenceType(targetType)) {
137✔
108
            const lowerTargetName = (targetType.memberKey ?? targetType.fullName).toLowerCase();
22!
109
            const myLowerName = this.name.toLowerCase();
22✔
110

111
            if (myLowerName === lowerTargetName) {
22✔
112
                return true;
12✔
113
            }
114
            //check non-namespaced version
115
            if (myLowerName.split('.').pop() === lowerTargetName) {
10✔
116
                return true;
8✔
117
            }
118
        }
119
        if (!isInheritableType(targetType)) {
117!
UNCOV
120
            return false;
×
121
        }
122
        if (!targetType) {
117!
123
            return false;
×
124
        }
125
        if (this === targetType) {
117!
126
            return true;
×
127
        }
128
        if (data?.allowNameEquality) {
117!
129
            const thisKind = (this as any).kind;
40✔
130
            if (thisKind && thisKind === (targetType as any).kind) {
40!
131
                if (this.toString().toLowerCase() === targetType.toString().toLowerCase()) {
40✔
132
                    return true;
18✔
133
                }
134
            }
135
        }
136

137
        if (this.isAncestorUnresolvedReferenceType() || targetType.isAncestorUnresolvedReferenceType()) {
99✔
138
            return this.name.toLowerCase() === targetType.name?.toLowerCase() &&
2!
139
                this.isParentTypeEqual(targetType, data);
140
        }
141
        return this.name.toLowerCase() === targetType.name?.toLowerCase() &&
97!
142
            this.isParentTypeEqual(targetType, data) &&
143
            this.checkCompatibilityBasedOnMembers(targetType, SymbolTypeFlag.runtime, data) &&
144
            targetType.checkCompatibilityBasedOnMembers(this, SymbolTypeFlag.runtime, data);
145
    }
146

147
    protected isParentTypeEqual(targetType: BscType, data?: TypeCompatibilityData): boolean {
148
        if (isInheritableType(targetType)) {
61!
149
            const targetParent = targetType.parentType;
61✔
150
            if (this.parentType && !targetParent) {
61!
UNCOV
151
                return false;
×
152
            } else if (!this.parentType && !targetParent) {
61✔
153
                return true;
46✔
154
            } else if (!this.parentType && targetParent) {
15!
UNCOV
155
                return false;
×
156
            }
157
            if (isReferenceType(targetParent) || isReferenceType(this.parentType)) {
15✔
158
                let thisParentName = isReferenceType(this.parentType) ? this.parentType.memberKey ?? this.parentType.fullName : this.parentType.name;
2!
159
                let targetParentName = isReferenceType(targetParent) ? targetParent.memberKey ?? targetParent.fullName : targetParent.name;
2!
160
                return thisParentName.toLowerCase() === targetParentName.toLowerCase();
2✔
161
            }
162
            return this.parentType.isEqual(targetParent, data);
13✔
163
        }
UNCOV
164
        return false;
×
165
    }
166

167
    protected isAncestorUnresolvedReferenceType() {
168
        let p = this as InheritableType | ReferenceType;
196✔
169
        while (p) {
196✔
170
            if (isReferenceType(p) && !p.isResolvable()) {
236✔
171
                return true;
2✔
172
            }
173
            p = (p as InheritableType).parentType;
234✔
174

175
        }
176
        return false;
194✔
177
    }
178
}
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