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

rokucommunity / brighterscript / #15093

13 Jan 2026 11:32PM UTC coverage: 87.166% (+0.01%) from 87.154%
#15093

push

web-flow
Merge 5e648aa9b into 3a7dcf6e8

14584 of 17684 branches covered (82.47%)

Branch coverage included in aggregate %.

288 of 337 new or added lines in 16 files covered. (85.46%)

206 existing lines in 10 files now uncovered.

15341 of 16647 relevant lines covered (92.15%)

24484.44 hits per line

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

84.3
/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) {
577,209✔
11
        super(name);
577,209✔
12
        if (parentType) {
577,209✔
13
            this.memberTable.pushParentProvider(() => this.parentType.memberTable);
193,853✔
14
        }
15
    }
16

17
    changeUnknownMemberToDynamic = false;
577,209✔
18

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

22
        if (hasRoAssociativeArrayAsAncestor) {
2,242✔
23
            return super.getMemberType(memberName, options) ?? (!options?.ignoreDefaultDynamicMembers ? DynamicType.instance : undefined);
125!
24
        }
25

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

28
        if (this.changeUnknownMemberToDynamic && !resultType.isResolvable()) {
2,117✔
29
            if (options.ignoreDefaultDynamicMembers) {
5!
NEW
30
                return resultType;
×
31
            }
32
            return DynamicType.instance;
5✔
33
        }
34
        return resultType;
2,112✔
35
    }
36

37
    public toString() {
38
        return this.name;
1,921✔
39
    }
40

41
    public toTypeString(): string {
42
        return 'dynamic';
9✔
43
    }
44

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

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

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

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

106
    isEqual(targetType: BscType, data: TypeCompatibilityData = {}): boolean {
21✔
107
        if (this === targetType) {
144!
UNCOV
108
            return true;
×
109
        }
110
        if (isReferenceType(targetType)) {
144✔
111
            const lowerTargetName = (targetType.memberKey ?? targetType.fullName).toLowerCase();
26!
112
            const myLowerName = this.name.toLowerCase();
26✔
113

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

140
        if (this.isAncestorUnresolvedReferenceType() || targetType.isAncestorUnresolvedReferenceType()) {
107✔
141
            return this.name.toLowerCase() === targetType.name?.toLowerCase() &&
2!
142
                this.isParentTypeEqual(targetType, data);
143
        }
144
        return this.name.toLowerCase() === targetType.name?.toLowerCase() &&
105!
145
            this.isParentTypeEqual(targetType, data) &&
146
            this.checkCompatibilityBasedOnMembers(targetType, SymbolTypeFlag.runtime, data) &&
147
            targetType.checkCompatibilityBasedOnMembers(this, SymbolTypeFlag.runtime, data);
148
    }
149

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

170
    protected isAncestorUnresolvedReferenceType() {
171
        let p = this as InheritableType | ReferenceType;
212✔
172
        while (p) {
212✔
173
            if (isReferenceType(p) && !p.isResolvable()) {
252✔
174
                return true;
2✔
175
            }
176
            p = (p as InheritableType).parentType;
250✔
177

178
        }
179
        return false;
210✔
180
    }
181
}
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