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

rokucommunity / brighterscript / #13117

01 Oct 2024 08:24AM UTC coverage: 86.842% (-1.4%) from 88.193%
#13117

push

web-flow
Merge abd960cd5 into 3a2dc7282

11537 of 14048 branches covered (82.13%)

Branch coverage included in aggregate %.

6991 of 7582 new or added lines in 100 files covered. (92.21%)

83 existing lines in 18 files now uncovered.

12692 of 13852 relevant lines covered (91.63%)

29478.96 hits per line

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

85.11
/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) {
463,386✔
11
        super(name);
463,386✔
12
        if (parentType) {
463,386✔
13
            this.memberTable.pushParentProvider(() => this.parentType.memberTable);
155,113✔
14
        }
15
    }
16

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

20
        if (hasRoAssociativeArrayAsAncestor) {
1,160✔
21
            return super.getMemberType(memberName, options) ?? DynamicType.instance;
17✔
22
        }
23

24
        return super.getMemberType(memberName, { ...options, fullName: memberName, tableProvider: () => this.memberTable });
1,143✔
25
    }
26

27
    public toString() {
28
        return this.name;
25,302✔
29
    }
30

31
    public toTypeString(): string {
32
        return 'dynamic';
6✔
33
    }
34

35
    protected getAncestorTypeList(): InheritableType[] {
36
        const ancestors = [];
1,221✔
37
        let currentParentType = this.parentType;
1,221✔
38
        while (currentParentType) {
1,221✔
39
            if (isInheritableType(currentParentType)) {
437✔
40
                ancestors.push(currentParentType);
434✔
41
                currentParentType = currentParentType.parentType;
434✔
42
            } else {
43
                break;
3✔
44
            }
45
        }
46
        return ancestors;
1,221✔
47
    }
48

49
    /**
50
     *  Checks if other type is an ancestor of this
51
     */
52
    isTypeAncestor(otherType: BscType) {
53
        if (!isInheritableType(otherType)) {
43!
NEW
54
            return false;
×
55
        }
56
        // Check if targetType is an ancestor of this
57
        const ancestors = this.getAncestorTypeList();
43✔
58
        if (ancestors?.find(ancestorType => ancestorType.isEqual(otherType))) {
43!
59
            return true;
29✔
60
        }
61
        return false;
14✔
62
    }
63

64
    /**
65
     *  Checks if other type is an descendent of this
66
     */
67
    isTypeDescendent(otherType: BscType) {
68
        if (!isInheritableType(otherType)) {
43!
NEW
69
            return false;
×
70
        }
71
        return otherType.isTypeAncestor(this);
43✔
72
    }
73

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

96
    isEqual(targetType: BscType, data: TypeCompatibilityData = {}): boolean {
65✔
97
        if (this === targetType) {
152✔
98
            return true;
6✔
99
        }
100
        if (isReferenceType(targetType)) {
146✔
101
            const lowerTargetName = (targetType.memberKey ?? targetType.fullName).toLowerCase();
59!
102
            const myLowerName = this.name.toLowerCase();
59✔
103

104
            if (myLowerName === lowerTargetName) {
59✔
105
                return true;
19✔
106
            }
107
            //check non-namespaced version
108
            if (myLowerName.split('.').pop() === lowerTargetName) {
40✔
109
                return true;
32✔
110
            }
111
        }
112
        if (!isInheritableType(targetType)) {
95!
NEW
113
            return false;
×
114
        }
115
        if (!targetType) {
95!
NEW
116
            return false;
×
117
        }
118
        if (this === targetType) {
95!
NEW
119
            return true;
×
120
        }
121
        if (this.isAncestorUnresolvedReferenceType() || targetType.isAncestorUnresolvedReferenceType()) {
95✔
122
            return this.name.toLowerCase() === targetType.name?.toLowerCase() &&
2!
123
                this.isParentTypeEqual(targetType, data);
124
        }
125
        return this.name.toLowerCase() === targetType.name?.toLowerCase() &&
93!
126
            this.isParentTypeEqual(targetType, data) &&
127
            this.checkCompatibilityBasedOnMembers(targetType, SymbolTypeFlag.runtime, data) &&
128
            targetType.checkCompatibilityBasedOnMembers(this, SymbolTypeFlag.runtime, data);
129
    }
130

131
    protected isParentTypeEqual(targetType: BscType, data?: TypeCompatibilityData): boolean {
132
        if (isInheritableType(targetType)) {
52!
133
            const targetParent = targetType.parentType;
52✔
134
            if (this.parentType && !targetParent) {
52!
NEW
135
                return false;
×
136
            } else if (!this.parentType && !targetParent) {
52✔
137
                return true;
48✔
138
            } else if (!this.parentType && targetParent) {
4!
NEW
139
                return false;
×
140
            }
141
            if (isReferenceType(targetParent) || isReferenceType(this.parentType)) {
4✔
142
                let thisParentName = isReferenceType(this.parentType) ? this.parentType.memberKey ?? this.parentType.fullName : this.parentType.name;
2!
143
                let targetParentName = isReferenceType(targetParent) ? targetParent.memberKey ?? targetParent.fullName : targetParent.name;
2!
144
                return thisParentName.toLowerCase() === targetParentName.toLowerCase();
2✔
145
            }
146
            return this.parentType.isEqual(targetParent, data);
2✔
147
        }
NEW
148
        return false;
×
149
    }
150

151
    protected isAncestorUnresolvedReferenceType() {
152
        let p = this as InheritableType | ReferenceType;
188✔
153
        while (p) {
188✔
154
            if (isReferenceType(p) && !p.isResolvable()) {
228✔
155
                return true;
2✔
156
            }
157
            p = (p as InheritableType).parentType;
226✔
158

159
        }
160
        return false;
186✔
161
    }
162
}
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