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

rokucommunity / brighterscript / #15221

22 Feb 2026 02:27AM UTC coverage: 87.213% (+0.01%) from 87.199%
#15221

push

web-flow
Merge d0c9a16a7 into 1556715dd

14752 of 17875 branches covered (82.53%)

Branch coverage included in aggregate %.

107 of 117 new or added lines in 19 files covered. (91.45%)

160 existing lines in 15 files now uncovered.

15497 of 16809 relevant lines covered (92.19%)

25606.73 hits per line

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

92.51
/src/types/TypedFunctionType.ts
1
import { isDynamicType, isObjectType, isTypedFunctionType, isTypeStatementType } from '../astUtils/reflection';
1✔
2
import { BaseFunctionType } from './BaseFunctionType';
1✔
3
import type { BscType } from './BscType';
4
import { BscTypeKind } from './BscTypeKind';
1✔
5
import { isUnionTypeCompatible } from './helpers';
1✔
6
import { BuiltInInterfaceAdder } from './BuiltInInterfaceAdder';
1✔
7
import type { TypeCompatibilityData } from '../interfaces';
8

9
export class TypedFunctionType extends BaseFunctionType {
1✔
10
    constructor(
11
        public returnType: BscType
6,961✔
12
    ) {
13
        super();
6,961✔
14
    }
15

16
    public readonly kind = BscTypeKind.TypedFunctionType;
6,961✔
17

18
    /**
19
     * The name of the function for this type. Can be null
20
     */
21
    public name: string;
22

23
    /**
24
     * Determines if this is a sub or not
25
     */
26
    public isSub = false;
6,961✔
27

28
    /**
29
     * Does this function accept more args than just those in this.params
30
     */
31
    public isVariadic = false;
6,961✔
32

33
    public params = [] as Array<{ name: string; type: BscType; isOptional: boolean }>;
6,961✔
34

35
    public setName(name: string) {
36
        this.name = name;
9,618✔
37
        return this;
9,618✔
38
    }
39

40
    public setSub(isSub: boolean) {
41
        this.isSub = isSub;
181✔
42
        return this;
181✔
43
    }
44

45
    public addParameter(name: string, type: BscType, isOptional: boolean) {
46
        this.params.push({
3,843✔
47
            name: name,
48
            type: type,
49
            isOptional: isOptional === true ? true : false
3,843✔
50
        });
51
        return this;
3,843✔
52
    }
53

54
    public isTypeCompatible(targetType: BscType, data: TypeCompatibilityData = {}) {
36✔
55
        data = data || {};
1,860!
56
        if (!data.actualType) {
1,860!
57
            data.actualType = targetType;
1,860✔
58
        }
59
        while (isTypeStatementType(targetType)) {
1,860✔
60
            targetType = targetType.wrappedType;
1✔
61
        }
62
        if (
1,860✔
63
            isDynamicType(targetType) ||
5,578✔
64
            isObjectType(targetType) ||
65
            isUnionTypeCompatible(this, targetType, data)
66
        ) {
67
            return true;
1✔
68
        }
69
        if (isTypedFunctionType(targetType)) {
1,859✔
70
            if (this === targetType) {
1,857✔
71
                return true;
1,727✔
72
            }
73
            return this.checkParamsAndReturnValue(targetType, true, (t1, t2, d) => t1.isTypeCompatible(t2, d), data);
182✔
74
        }
75
        return false;
2✔
76
    }
77

78
    public toString() {
79
        let paramTexts = [];
9,923✔
80
        for (let param of this.params) {
9,923✔
81
            paramTexts.push(`${param.name}${param.isOptional ? '?' : ''} as ${param.type.toString()}`);
11,608✔
82
        }
83
        let variadicText = '';
9,923✔
84
        if (this.isVariadic) {
9,923✔
85
            if (paramTexts.length > 0) {
19✔
86
                variadicText += ', ';
1✔
87
            }
88
            variadicText += '...';
19✔
89
        }
90
        return `${this.isSub ? 'sub' : 'function'} ${this.name ?? ''}(${paramTexts.join(', ')}${variadicText}) as ${this.returnType.toString()}`;
9,923✔
91
    }
92

93
    public toTypeString(): string {
UNCOV
94
        return 'Function';
×
95
    }
96

97
    isEqual(targetType: BscType, data: TypeCompatibilityData = {}) {
94✔
98
        if (isTypedFunctionType(targetType)) {
976✔
99
            const checkNames = data?.allowNameEquality ?? true;
971!
100
            if (checkNames && this.toString().toLowerCase() === targetType.toString().toLowerCase()) {
971✔
101
                // this function has the same param names and types and return type as the target
102
                return true;
832✔
103
            }
104
            return this.checkParamsAndReturnValue(targetType, false, (t1, t2, predData = {}) => {
139!
105
                return t1.isEqual(t2, { ...predData, allowNameEquality: checkNames });
167✔
106
            }, data);
107
        }
108
        return false;
5✔
109
    }
110

111
    private checkParamsAndReturnValue(targetType: TypedFunctionType, allowOptionalParamDifferences: boolean, predicate: (type1: BscType, type2: BscType, data: TypeCompatibilityData) => boolean, data?: TypeCompatibilityData) {
112
        //compare all parameters
113
        let len = Math.max(this.params.length, targetType.params.length);
269✔
114
        for (let i = 0; i < len; i++) {
269✔
115
            let myParam = this.params[i];
167✔
116
            let targetParam = targetType.params[i];
167✔
117
            const paramTypeData: TypeCompatibilityData = {};
167✔
118
            if (allowOptionalParamDifferences && !myParam && targetParam.isOptional) {
167✔
119
                // target func has MORE (optional) params... that's ok
120
                break;
3✔
121
            }
122

123
            if (!myParam || !targetParam || !predicate(myParam.type, targetParam.type, paramTypeData)) {
164✔
124
                data = data ?? {};
56!
125
                data.parameterMismatches = data.parameterMismatches ?? [];
56!
126
                paramTypeData.expectedType = paramTypeData.expectedType ?? myParam?.type;
56!
127
                paramTypeData.actualType = paramTypeData.actualType ?? targetParam?.type;
56!
128
                if (!targetParam || !myParam) {
56✔
129
                    data.expectedParamCount = this.params.length;
26✔
130
                    data.actualParamCount = targetType.params.length;
26✔
131
                }
132
                data.parameterMismatches.push({ index: i, data: paramTypeData });
56✔
133
                data.expectedType = data.expectedType ?? this;
56✔
134
                data.actualType = data.actualType ?? targetType;
56✔
135
                return false;
56✔
136
            }
137
            if ((!allowOptionalParamDifferences && myParam.isOptional !== targetParam.isOptional) ||
108✔
138
                (!myParam.isOptional && targetParam.isOptional)) {
139
                data = data ?? {};
2!
140
                data.parameterMismatches = data.parameterMismatches ?? [];
2!
141
                data.parameterMismatches.push({ index: i, expectedOptional: myParam.isOptional, actualOptional: targetParam.isOptional, data: paramTypeData });
2✔
142
                data.expectedType = this;
2✔
143
                data.actualType = targetType;
2✔
144
                return false;
2✔
145
            }
146
        }
147
        //compare return type
148
        const returnTypeData: TypeCompatibilityData = {};
211✔
149
        if (!this.returnType || !targetType.returnType || !predicate(this.returnType, targetType.returnType, data)) {
211✔
150
            data = data ?? {};
102!
151
            returnTypeData.expectedType = returnTypeData.expectedType ?? this.returnType;
102!
152
            returnTypeData.actualType = returnTypeData.actualType ?? targetType.returnType;
102!
153
            data.returnTypeMismatch = returnTypeData;
102✔
154
            data.expectedType = this;
102✔
155
            data.actualType = targetType;
102✔
156
            return false;
102✔
157
        }
158
        //compare Variadic
159
        if (this.isVariadic !== targetType.isVariadic) {
109✔
160
            data = data ?? {};
1!
161
            data.expectedVariadic = this.isVariadic;
1✔
162
            data.actualVariadic = targetType.isVariadic;
1✔
163
            data.expectedType = data.expectedType ?? this;
1!
164
            data.actualType = data.actualType ?? targetType;
1!
165
            return false;
1✔
166
        }
167
        //made it here, all params and return type pass predicate
168
        return true;
108✔
169
    }
170
}
171

172
BuiltInInterfaceAdder.typedFunctionFactory = (returnType: BscType) => {
1✔
173
    return new TypedFunctionType(returnType);
1,257✔
174
};
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