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

rokucommunity / brighterscript / #14385

09 May 2025 11:44AM UTC coverage: 87.032% (-2.0%) from 89.017%
#14385

push

web-flow
Merge a194c3925 into 489231ac7

13732 of 16677 branches covered (82.34%)

Branch coverage included in aggregate %.

8175 of 8874 new or added lines in 103 files covered. (92.12%)

84 existing lines in 22 files now uncovered.

14604 of 15881 relevant lines covered (91.96%)

20324.31 hits per line

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

92.42
/src/types/TypedFunctionType.ts
1
import { isDynamicType, isObjectType, isTypedFunctionType } 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,052✔
12
    ) {
13
        super();
6,052✔
14
    }
15

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

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

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

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

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

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

54
    public isTypeCompatible(targetType: BscType, data: TypeCompatibilityData = {}) {
26✔
55
        if (
20,826✔
56
            isDynamicType(targetType) ||
62,476✔
57
            isObjectType(targetType) ||
58
            isUnionTypeCompatible(this, targetType, data)
59
        ) {
60
            return true;
1✔
61
        }
62
        if (isTypedFunctionType(targetType)) {
20,825✔
63
            return this.checkParamsAndReturnValue(targetType, true, (t1, t2, d) => t1.isTypeCompatible(t2, d), data);
40,927✔
64
        }
65
        return false;
2✔
66
    }
67

68
    public toString() {
69
        let paramTexts = [];
8,414✔
70
        for (let param of this.params) {
8,414✔
71
            paramTexts.push(`${param.name}${param.isOptional ? '?' : ''} as ${param.type.toString()}`);
10,766✔
72
        }
73
        let variadicText = '';
8,414✔
74
        if (this.isVariadic) {
8,414✔
75
            if (paramTexts.length > 0) {
11✔
76
                variadicText += ', ';
1✔
77
            }
78
            variadicText += '...';
11✔
79
        }
80
        return `${this.isSub ? 'sub' : 'function'} ${this.name ?? ''}(${paramTexts.join(', ')}${variadicText}) as ${this.returnType.toString()}`;
8,414✔
81
    }
82

83
    public toTypeString(): string {
NEW
84
        return 'Function';
×
85
    }
86

87
    isEqual(targetType: BscType, data: TypeCompatibilityData = {}) {
24✔
88
        if (isTypedFunctionType(targetType)) {
290!
89
            const checkNames = data?.allowNameEquality ?? true;
290!
90
            if (checkNames && this.toString().toLowerCase() === targetType.toString().toLowerCase()) {
290✔
91
                // this function has the same param names and types and return type as the target
92
                return true;
182✔
93
            }
94
            return this.checkParamsAndReturnValue(targetType, false, (t1, t2, predData = {}) => {
108!
95
                return t1.isEqual(t2, { ...predData, allowNameEquality: checkNames });
128✔
96
            }, data);
97
        }
NEW
98
        return false;
×
99
    }
100

101
    private checkParamsAndReturnValue(targetType: TypedFunctionType, allowOptionalParamDifferences: boolean, predicate: (type1: BscType, type2: BscType, data: TypeCompatibilityData) => boolean, data?: TypeCompatibilityData) {
102
        //compare all parameters
103
        let len = Math.max(this.params.length, targetType.params.length);
20,931✔
104
        for (let i = 0; i < len; i++) {
20,931✔
105
            let myParam = this.params[i];
20,181✔
106
            let targetParam = targetType.params[i];
20,181✔
107
            const paramTypeData: TypeCompatibilityData = {};
20,181✔
108
            if (allowOptionalParamDifferences && !myParam && targetParam.isOptional) {
20,181✔
109
                // target func has MORE (optional) params... that's ok
110
                break;
1✔
111
            }
112

113
            if (!myParam || !targetParam || !predicate(myParam.type, targetParam.type, paramTypeData)) {
20,180✔
114
                data = data ?? {};
38!
115
                data.parameterMismatches = data.parameterMismatches ?? [];
38!
116
                paramTypeData.expectedType = paramTypeData.expectedType ?? myParam?.type;
38!
117
                paramTypeData.actualType = paramTypeData.actualType ?? targetParam?.type;
38!
118
                if (!targetParam || !myParam) {
38✔
119
                    data.expectedParamCount = this.params.filter(p => !p.isOptional).length;
20✔
120
                    data.actualParamCount = targetType.params.filter(p => !p.isOptional).length;
16✔
121
                }
122
                data.parameterMismatches.push({ index: i, data: paramTypeData });
38✔
123
                data.expectedType = this;
38✔
124
                data.actualType = targetType;
38✔
125
                return false;
38✔
126
            }
127
            if ((!allowOptionalParamDifferences && myParam.isOptional !== targetParam.isOptional) ||
20,142✔
128
                (!myParam.isOptional && targetParam.isOptional)) {
129
                data = data ?? {};
2!
130
                data.parameterMismatches = data.parameterMismatches ?? [];
2!
131
                data.parameterMismatches.push({ index: i, expectedOptional: myParam.isOptional, actualOptional: targetParam.isOptional, data: paramTypeData });
2✔
132
                data.expectedType = this;
2✔
133
                data.actualType = targetType;
2✔
134
                return false;
2✔
135
            }
136
        }
137
        //compare return type
138
        const returnTypeData: TypeCompatibilityData = {};
20,891✔
139
        if (!this.returnType || !targetType.returnType || !predicate(this.returnType, targetType.returnType, data)) {
20,891✔
140
            data = data ?? {};
75!
141
            returnTypeData.expectedType = returnTypeData.expectedType ?? this.returnType;
75!
142
            returnTypeData.actualType = returnTypeData.actualType ?? targetType.returnType;
75!
143
            data.returnTypeMismatch = returnTypeData;
75✔
144
            data.expectedType = this;
75✔
145
            data.actualType = targetType;
75✔
146
            return false;
75✔
147
        }
148
        //compare Variadic
149
        if (this.isVariadic !== targetType.isVariadic) {
20,816✔
150
            data = data ?? {};
1!
151
            data.expectedVariadic = this.isVariadic;
1✔
152
            data.actualVariadic = targetType.isVariadic;
1✔
153
            data.expectedType = this;
1✔
154
            data.actualType = targetType;
1✔
155
            return false;
1✔
156
        }
157
        //made it here, all params and return type pass predicate
158
        return true;
20,815✔
159
    }
160
}
161

162
BuiltInInterfaceAdder.typedFunctionFactory = (returnType: BscType) => {
1✔
163
    return new TypedFunctionType(returnType);
1,113✔
164
};
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