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

rokucommunity / brighterscript / #15215

22 Feb 2026 02:08AM UTC coverage: 87.151% (-0.07%) from 87.225%
#15215

push

web-flow
Merge f6ff8a6fa into 1556715dd

14734 of 17873 branches covered (82.44%)

Branch coverage included in aggregate %.

104 of 115 new or added lines in 19 files covered. (90.43%)

2 existing lines in 1 file now uncovered.

15490 of 16807 relevant lines covered (92.16%)

25562.64 hits per line

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

91.93
/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,898✔
12
    ) {
13
        super();
6,898✔
14
    }
15

16
    public readonly kind = BscTypeKind.TypedFunctionType;
6,898✔
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,898✔
27

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

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

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

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

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

54
    public isTypeCompatible(targetType: BscType, data: TypeCompatibilityData = {}) {
36✔
55
        data = data || {};
1,855!
56
        if (!data.actualType) {
1,855!
57
            data.actualType = targetType;
1,855✔
58
        }
59
        while (isTypeStatementType(targetType)) {
1,855✔
NEW
60
            targetType = targetType.wrappedType;
×
61
        }
62
        if (
1,855✔
63
            isDynamicType(targetType) ||
5,563✔
64
            isObjectType(targetType) ||
65
            isUnionTypeCompatible(this, targetType, data)
66
        ) {
67
            return true;
1✔
68
        }
69
        if (isTypedFunctionType(targetType)) {
1,854✔
70
            return this.checkParamsAndReturnValue(targetType, true, (t1, t2, d) => t1.isTypeCompatible(t2, d), data);
3,512✔
71
        }
72
        return false;
2✔
73
    }
74

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

90
    public toTypeString(): string {
91
        return 'Function';
×
92
    }
93

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

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

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

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