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

rokucommunity / brighterscript / #13231

24 Oct 2024 01:02PM UTC coverage: 86.866% (-1.3%) from 88.214%
#13231

push

web-flow
Merge cc3491b40 into 7cfaaa047

11613 of 14131 branches covered (82.18%)

Branch coverage included in aggregate %.

7028 of 7618 new or added lines in 100 files covered. (92.26%)

87 existing lines in 18 files now uncovered.

12732 of 13895 relevant lines covered (91.63%)

30018.29 hits per line

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

85.71
/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) {
472,430✔
11
        super(name);
472,430✔
12
        if (parentType) {
472,430✔
13
            this.memberTable.pushParentProvider(() => this.parentType.memberTable);
158,139✔
14
        }
15
    }
16

17
    changeUnknownMemberToDynamic = false;
472,430✔
18

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

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

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

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

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

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

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

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

71
    /**
72
     *  Checks if other type is an descendent of this
73
     */
74
    isTypeDescendent(otherType: BscType) {
75
        if (!isInheritableType(otherType)) {
43!
NEW
76
            return false;
×
77
        }
78
        return otherType.isTypeAncestor(this);
43✔
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 {
65✔
104
        if (this === targetType) {
156✔
105
            return true;
6✔
106
        }
107
        if (isReferenceType(targetType)) {
150✔
108
            const lowerTargetName = (targetType.memberKey ?? targetType.fullName).toLowerCase();
63!
109
            const myLowerName = this.name.toLowerCase();
63✔
110

111
            if (myLowerName === lowerTargetName) {
63✔
112
                return true;
23✔
113
            }
114
            //check non-namespaced version
115
            if (myLowerName.split('.').pop() === lowerTargetName) {
40✔
116
                return true;
32✔
117
            }
118
        }
119
        if (!isInheritableType(targetType)) {
95!
NEW
120
            return false;
×
121
        }
122
        if (!targetType) {
95!
NEW
123
            return false;
×
124
        }
125
        if (this === targetType) {
95!
NEW
126
            return true;
×
127
        }
128
        if (this.isAncestorUnresolvedReferenceType() || targetType.isAncestorUnresolvedReferenceType()) {
95✔
129
            return this.name.toLowerCase() === targetType.name?.toLowerCase() &&
2!
130
                this.isParentTypeEqual(targetType, data);
131
        }
132
        return this.name.toLowerCase() === targetType.name?.toLowerCase() &&
93!
133
            this.isParentTypeEqual(targetType, data) &&
134
            this.checkCompatibilityBasedOnMembers(targetType, SymbolTypeFlag.runtime, data) &&
135
            targetType.checkCompatibilityBasedOnMembers(this, SymbolTypeFlag.runtime, data);
136
    }
137

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

158
    protected isAncestorUnresolvedReferenceType() {
159
        let p = this as InheritableType | ReferenceType;
188✔
160
        while (p) {
188✔
161
            if (isReferenceType(p) && !p.isResolvable()) {
228✔
162
                return true;
2✔
163
            }
164
            p = (p as InheritableType).parentType;
226✔
165

166
        }
167
        return false;
186✔
168
    }
169
}
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