brighterscript 0.66.0-alpha.2 → 0.66.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/README.md +0 -6
- package/dist/BsConfig.d.ts +0 -5
- package/dist/BusyStatusTracker.d.ts +31 -0
- package/dist/BusyStatusTracker.js +83 -0
- package/dist/BusyStatusTracker.js.map +1 -0
- package/dist/Cache.js +3 -3
- package/dist/Cache.js.map +1 -1
- package/dist/CodeActionUtil.d.ts +2 -2
- package/dist/DiagnosticCollection.js +8 -5
- package/dist/DiagnosticCollection.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +6 -1
- package/dist/DiagnosticMessages.js +5 -0
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/FunctionScope.d.ts +1 -1
- package/dist/LanguageServer.d.ts +22 -1
- package/dist/LanguageServer.js +124 -51
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.d.ts +3 -2
- package/dist/Logger.js +10 -2
- package/dist/Logger.js.map +1 -1
- package/dist/Program.d.ts +1 -3
- package/dist/Program.js +14 -16
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.js +1 -1
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +11 -6
- package/dist/Scope.js +77 -93
- package/dist/Scope.js.map +1 -1
- package/dist/SymbolTable.d.ts +11 -5
- package/dist/SymbolTable.js +21 -8
- package/dist/SymbolTable.js.map +1 -1
- package/dist/Throttler.d.ts +12 -0
- package/dist/Throttler.js +39 -0
- package/dist/Throttler.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +4 -0
- package/dist/astUtils/reflection.js +9 -1
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/bscPlugin/hover/HoverProcessor.d.ts +5 -0
- package/dist/bscPlugin/hover/HoverProcessor.js +108 -77
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +83 -29
- package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +0 -4
- package/dist/bscPlugin/validation/BrsFileValidator.js +10 -16
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +4 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +77 -42
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.spec.js +715 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
- package/dist/cli.js +103 -13
- package/dist/cli.js.map +1 -1
- package/dist/deferred.d.ts +1 -1
- package/dist/deferred.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +5 -0
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +1 -11
- package/dist/files/BrsFile.js +9 -101
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +3 -267
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/globalCallables.js +87 -79
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +11 -5
- package/dist/interfaces.js.map +1 -1
- package/dist/parser/Expression.d.ts +4 -3
- package/dist/parser/Expression.js +32 -9
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/SGParser.d.ts +2 -2
- package/dist/parser/Statement.d.ts +11 -6
- package/dist/parser/Statement.js +54 -21
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +2 -2
- package/dist/types/BaseFunctionType.d.ts +8 -0
- package/dist/types/BaseFunctionType.js +25 -0
- package/dist/types/BaseFunctionType.js.map +1 -0
- package/dist/types/BooleanType.d.ts +3 -0
- package/dist/types/BooleanType.js +7 -1
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BscTypeKind.d.ts +1 -0
- package/dist/types/BscTypeKind.js +1 -0
- package/dist/types/BscTypeKind.js.map +1 -1
- package/dist/types/ClassType.js +1 -1
- package/dist/types/ClassType.js.map +1 -1
- package/dist/types/DoubleType.d.ts +3 -0
- package/dist/types/DoubleType.js +6 -0
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/EnumType.d.ts +23 -4
- package/dist/types/EnumType.js +18 -2
- package/dist/types/EnumType.js.map +1 -1
- package/dist/types/FloatType.d.ts +3 -0
- package/dist/types/FloatType.js +6 -0
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FunctionType.d.ts +6 -19
- package/dist/types/FunctionType.js +12 -44
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/IntegerType.d.ts +3 -0
- package/dist/types/IntegerType.js +6 -0
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/InterfaceType.js +3 -3
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InvalidType.d.ts +1 -0
- package/dist/types/InvalidType.js +3 -1
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +3 -0
- package/dist/types/LongIntegerType.js +6 -0
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/ObjectType.js +2 -9
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ReferenceType.spec.js +6 -6
- package/dist/types/ReferenceType.spec.js.map +1 -1
- package/dist/types/StringType.d.ts +3 -0
- package/dist/types/StringType.js +9 -1
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +27 -0
- package/dist/types/TypedFunctionType.js +69 -0
- package/dist/types/TypedFunctionType.js.map +1 -0
- package/dist/types/TypedFunctionType.spec.d.ts +1 -0
- package/dist/types/TypedFunctionType.spec.js +23 -0
- package/dist/types/TypedFunctionType.spec.js.map +1 -0
- package/dist/types/UnionType.js +1 -1
- package/dist/types/UnionType.js.map +1 -1
- package/dist/types/VoidType.js +2 -1
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/util.d.ts +22 -6
- package/dist/util.js +248 -82
- package/dist/util.js.map +1 -1
- package/package.json +4 -2
- package/dist/types/FunctionType.spec.js +0 -23
- package/dist/types/FunctionType.spec.js.map +0 -1
- /package/dist/{types/FunctionType.spec.d.ts → bscPlugin/validation/ScopeValidator.spec.d.ts} +0 -0
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const sinonImport = require("sinon");
|
|
4
|
+
const DiagnosticMessages_1 = require("../../DiagnosticMessages");
|
|
5
|
+
const Program_1 = require("../../Program");
|
|
6
|
+
const testHelpers_spec_1 = require("../../testHelpers.spec");
|
|
7
|
+
const chai_1 = require("chai");
|
|
8
|
+
describe('ScopeValidator', () => {
|
|
9
|
+
let sinon = sinonImport.createSandbox();
|
|
10
|
+
let rootDir = process.cwd();
|
|
11
|
+
let program;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
program = new Program_1.Program({
|
|
14
|
+
rootDir: rootDir
|
|
15
|
+
});
|
|
16
|
+
program.createSourceScope();
|
|
17
|
+
});
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
sinon.restore();
|
|
20
|
+
program.dispose();
|
|
21
|
+
});
|
|
22
|
+
describe('mismatchArgumentCount', () => {
|
|
23
|
+
it('detects calling functions with too many arguments', () => {
|
|
24
|
+
program.setFile('source/file.brs', `
|
|
25
|
+
sub a()
|
|
26
|
+
end sub
|
|
27
|
+
sub b()
|
|
28
|
+
a(1)
|
|
29
|
+
end sub
|
|
30
|
+
`);
|
|
31
|
+
program.validate();
|
|
32
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
33
|
+
DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(0, 1).message
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
it('detects calling class constructors with too many arguments', () => {
|
|
37
|
+
program.setFile('source/main.bs', `
|
|
38
|
+
function noop0()
|
|
39
|
+
end function
|
|
40
|
+
|
|
41
|
+
function noop1(p1)
|
|
42
|
+
end function
|
|
43
|
+
|
|
44
|
+
sub main()
|
|
45
|
+
noop0(1)
|
|
46
|
+
noop1(1,2)
|
|
47
|
+
noop1()
|
|
48
|
+
end sub
|
|
49
|
+
`);
|
|
50
|
+
program.validate();
|
|
51
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
52
|
+
DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(0, 1),
|
|
53
|
+
DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 2),
|
|
54
|
+
DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 0)
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
it('detects calling functions with too few arguments', () => {
|
|
58
|
+
program.setFile('source/file.brs', `
|
|
59
|
+
sub a(name)
|
|
60
|
+
end sub
|
|
61
|
+
sub b()
|
|
62
|
+
a()
|
|
63
|
+
end sub
|
|
64
|
+
`);
|
|
65
|
+
program.validate();
|
|
66
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
67
|
+
DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 0)
|
|
68
|
+
]);
|
|
69
|
+
});
|
|
70
|
+
it('allows skipping optional parameter', () => {
|
|
71
|
+
program.setFile('source/file.brs', `
|
|
72
|
+
sub a(name="Bob")
|
|
73
|
+
end sub
|
|
74
|
+
sub b()
|
|
75
|
+
a()
|
|
76
|
+
end sub
|
|
77
|
+
`);
|
|
78
|
+
program.validate();
|
|
79
|
+
//should have an error
|
|
80
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
81
|
+
});
|
|
82
|
+
it('shows expected parameter range in error message', () => {
|
|
83
|
+
program.setFile('source/file.brs', `
|
|
84
|
+
sub a(age, name="Bob")
|
|
85
|
+
end sub
|
|
86
|
+
sub b()
|
|
87
|
+
a()
|
|
88
|
+
end sub
|
|
89
|
+
`);
|
|
90
|
+
program.validate();
|
|
91
|
+
//should have an error
|
|
92
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
93
|
+
DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount('1-2', 0)
|
|
94
|
+
]);
|
|
95
|
+
});
|
|
96
|
+
it('handles expressions as arguments to a function', () => {
|
|
97
|
+
program.setFile('source/file.brs', `
|
|
98
|
+
sub a(age, name="Bob")
|
|
99
|
+
end sub
|
|
100
|
+
sub b()
|
|
101
|
+
a("cat" + "dog" + "mouse")
|
|
102
|
+
end sub
|
|
103
|
+
`);
|
|
104
|
+
program.validate();
|
|
105
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
106
|
+
});
|
|
107
|
+
it('Catches extra arguments for expressions as arguments to a function', () => {
|
|
108
|
+
program.setFile('source/file.brs', `
|
|
109
|
+
sub a(age)
|
|
110
|
+
end sub
|
|
111
|
+
sub b()
|
|
112
|
+
a(m.lib.movies[0], 1)
|
|
113
|
+
end sub
|
|
114
|
+
`);
|
|
115
|
+
program.validate();
|
|
116
|
+
//should have an error
|
|
117
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
118
|
+
DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(1, 2)
|
|
119
|
+
]);
|
|
120
|
+
});
|
|
121
|
+
it('allows any number of parameters in a function used as an argument', () => {
|
|
122
|
+
program.setFile('source/file.brs', `
|
|
123
|
+
sub tryManyParams(someFunc as function)
|
|
124
|
+
someFunc(1, 2, "hello", "world")
|
|
125
|
+
end sub
|
|
126
|
+
`);
|
|
127
|
+
program.validate();
|
|
128
|
+
//should have no errors
|
|
129
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('argumentTypeMismatch', () => {
|
|
133
|
+
it('param `as object` supports all known types', () => {
|
|
134
|
+
program.setFile('source/file.bs', `
|
|
135
|
+
sub main()
|
|
136
|
+
consoleLog(Direction.up)
|
|
137
|
+
consoleLog(true)
|
|
138
|
+
consoleLog(main)
|
|
139
|
+
consoleLog(1.2)
|
|
140
|
+
consoleLog({} as Video)
|
|
141
|
+
consoleLog("test")
|
|
142
|
+
end sub
|
|
143
|
+
|
|
144
|
+
sub consoleLog(thing as object)
|
|
145
|
+
print thing
|
|
146
|
+
end sub
|
|
147
|
+
|
|
148
|
+
interface Video
|
|
149
|
+
url as string
|
|
150
|
+
end interface
|
|
151
|
+
enum Direction
|
|
152
|
+
up = "up"
|
|
153
|
+
down = "down"
|
|
154
|
+
end enum
|
|
155
|
+
`);
|
|
156
|
+
program.validate();
|
|
157
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
158
|
+
});
|
|
159
|
+
it('`as object` var can be passed to various param types', () => {
|
|
160
|
+
program.setFile('source/file.bs', `
|
|
161
|
+
sub main()
|
|
162
|
+
obj = {} as object
|
|
163
|
+
|
|
164
|
+
printBoolean(obj)
|
|
165
|
+
printClass(obj)
|
|
166
|
+
printDouble(obj)
|
|
167
|
+
printEnum(obj)
|
|
168
|
+
printFloat(obj)
|
|
169
|
+
printFunction(obj)
|
|
170
|
+
printInteger(obj)
|
|
171
|
+
printInterface(obj)
|
|
172
|
+
printLongInteger(obj)
|
|
173
|
+
printString(obj)
|
|
174
|
+
end sub
|
|
175
|
+
|
|
176
|
+
sub printBoolean(value as boolean)
|
|
177
|
+
print value
|
|
178
|
+
end sub
|
|
179
|
+
|
|
180
|
+
class Person
|
|
181
|
+
name as string
|
|
182
|
+
end class
|
|
183
|
+
|
|
184
|
+
sub printClass(value as Person)
|
|
185
|
+
print value
|
|
186
|
+
end sub
|
|
187
|
+
|
|
188
|
+
sub printDouble(value as double)
|
|
189
|
+
print value
|
|
190
|
+
end sub
|
|
191
|
+
|
|
192
|
+
enum Direction
|
|
193
|
+
up = "up"
|
|
194
|
+
end enum
|
|
195
|
+
|
|
196
|
+
sub printEnum(value as Direction)
|
|
197
|
+
print value
|
|
198
|
+
end sub
|
|
199
|
+
|
|
200
|
+
sub printFloat(value as float)
|
|
201
|
+
print value
|
|
202
|
+
end sub
|
|
203
|
+
|
|
204
|
+
sub printFunction(value as function)
|
|
205
|
+
print value
|
|
206
|
+
print value(1)
|
|
207
|
+
end sub
|
|
208
|
+
|
|
209
|
+
interface Video
|
|
210
|
+
url as string
|
|
211
|
+
end interface
|
|
212
|
+
|
|
213
|
+
sub printInterface(value as Video)
|
|
214
|
+
print value
|
|
215
|
+
end sub
|
|
216
|
+
|
|
217
|
+
sub printInteger(value as integer)
|
|
218
|
+
print value
|
|
219
|
+
end sub
|
|
220
|
+
|
|
221
|
+
sub printLongInteger(value as LongInteger)
|
|
222
|
+
print value
|
|
223
|
+
end sub
|
|
224
|
+
|
|
225
|
+
sub printString(value as string)
|
|
226
|
+
print value
|
|
227
|
+
end sub
|
|
228
|
+
`);
|
|
229
|
+
program.validate();
|
|
230
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
231
|
+
});
|
|
232
|
+
it('treats string enums as strings when assigned to string vars', () => {
|
|
233
|
+
program.setFile('source/file.bs', `
|
|
234
|
+
sub main()
|
|
235
|
+
printDirection(Direction.up)
|
|
236
|
+
end sub
|
|
237
|
+
|
|
238
|
+
sub printDirection(theDirection as string)
|
|
239
|
+
print theDirection
|
|
240
|
+
end sub
|
|
241
|
+
|
|
242
|
+
enum Direction
|
|
243
|
+
up = "up"
|
|
244
|
+
down = "down"
|
|
245
|
+
end enum
|
|
246
|
+
`);
|
|
247
|
+
program.validate();
|
|
248
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
249
|
+
});
|
|
250
|
+
it('does not treat strings as a string enum', () => {
|
|
251
|
+
program.setFile('source/file.bs', `
|
|
252
|
+
sub main()
|
|
253
|
+
printDirection("up")
|
|
254
|
+
end sub
|
|
255
|
+
|
|
256
|
+
sub printDirection(theDirection as Direction)
|
|
257
|
+
print theDirection
|
|
258
|
+
end sub
|
|
259
|
+
|
|
260
|
+
enum Direction
|
|
261
|
+
up = "up"
|
|
262
|
+
down = "down"
|
|
263
|
+
end enum
|
|
264
|
+
|
|
265
|
+
`);
|
|
266
|
+
program.validate();
|
|
267
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
268
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'Direction')
|
|
269
|
+
]);
|
|
270
|
+
});
|
|
271
|
+
it('supports passing enum type as enum type', () => {
|
|
272
|
+
program.setFile('source/file.bs', `
|
|
273
|
+
sub test(theDirection as Direction)
|
|
274
|
+
printDirection(theDirection)
|
|
275
|
+
end sub
|
|
276
|
+
|
|
277
|
+
sub printDirection(theDirection as Direction)
|
|
278
|
+
print theDirection
|
|
279
|
+
end sub
|
|
280
|
+
|
|
281
|
+
enum Direction
|
|
282
|
+
up = "up"
|
|
283
|
+
down = "down"
|
|
284
|
+
end enum
|
|
285
|
+
`);
|
|
286
|
+
program.validate();
|
|
287
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, []);
|
|
288
|
+
});
|
|
289
|
+
it('Catches argument type mismatches on function calls', () => {
|
|
290
|
+
program.setFile('source/file.brs', `
|
|
291
|
+
sub a(age as integer)
|
|
292
|
+
end sub
|
|
293
|
+
sub b()
|
|
294
|
+
a("hello")
|
|
295
|
+
end sub
|
|
296
|
+
`);
|
|
297
|
+
program.validate();
|
|
298
|
+
//should have an error
|
|
299
|
+
(0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
|
|
300
|
+
});
|
|
301
|
+
it('Catches argument type mismatches on function calls for functions defined in another file', () => {
|
|
302
|
+
program.setFile('source/file.brs', `
|
|
303
|
+
sub a(age as integer)
|
|
304
|
+
end sub
|
|
305
|
+
`);
|
|
306
|
+
program.setFile('source/file2.brs', `
|
|
307
|
+
sub b()
|
|
308
|
+
a("hello")
|
|
309
|
+
foo = "foo"
|
|
310
|
+
a(foo)
|
|
311
|
+
end sub
|
|
312
|
+
`);
|
|
313
|
+
program.validate();
|
|
314
|
+
//should have an error
|
|
315
|
+
(0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
|
|
316
|
+
});
|
|
317
|
+
it('catches argument type mismatches on function calls within namespaces', () => {
|
|
318
|
+
program.setFile('source/file.bs', `
|
|
319
|
+
namespace Name.Space
|
|
320
|
+
sub a(param as integer)
|
|
321
|
+
print param
|
|
322
|
+
end sub
|
|
323
|
+
|
|
324
|
+
sub b()
|
|
325
|
+
a("hello")
|
|
326
|
+
foo = "foo"
|
|
327
|
+
a(foo)
|
|
328
|
+
end sub
|
|
329
|
+
end namespace
|
|
330
|
+
`);
|
|
331
|
+
program.validate();
|
|
332
|
+
//should have an error
|
|
333
|
+
(0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
|
|
334
|
+
});
|
|
335
|
+
it('catches argument type mismatches on function calls as arguments', () => {
|
|
336
|
+
program.setFile('source/file1.bs', `
|
|
337
|
+
sub a(param as string)
|
|
338
|
+
print param
|
|
339
|
+
end sub
|
|
340
|
+
|
|
341
|
+
function getNum() as integer
|
|
342
|
+
return 1
|
|
343
|
+
end function
|
|
344
|
+
|
|
345
|
+
sub b()
|
|
346
|
+
a(getNum())
|
|
347
|
+
end sub
|
|
348
|
+
`);
|
|
349
|
+
program.validate();
|
|
350
|
+
//should have an error
|
|
351
|
+
(0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message);
|
|
352
|
+
});
|
|
353
|
+
it('catches argument type mismatches on function calls within namespaces across files', () => {
|
|
354
|
+
program.setFile('source/file1.bs', `
|
|
355
|
+
namespace Name.Space
|
|
356
|
+
function getNum() as integer
|
|
357
|
+
return 1
|
|
358
|
+
end function
|
|
359
|
+
|
|
360
|
+
function getStr() as string
|
|
361
|
+
return "hello"
|
|
362
|
+
end function
|
|
363
|
+
end namespace
|
|
364
|
+
`);
|
|
365
|
+
program.setFile('source/file2.bs', `
|
|
366
|
+
namespace Name.Space
|
|
367
|
+
sub needsInt(param as integer)
|
|
368
|
+
print param
|
|
369
|
+
end sub
|
|
370
|
+
|
|
371
|
+
sub someFunc()
|
|
372
|
+
needsInt(getStr())
|
|
373
|
+
needsInt(getNum())
|
|
374
|
+
end sub
|
|
375
|
+
end namespace
|
|
376
|
+
`);
|
|
377
|
+
program.validate();
|
|
378
|
+
//should have an error
|
|
379
|
+
(0, chai_1.expect)(program.getDiagnostics().length).to.equal(1);
|
|
380
|
+
(0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message);
|
|
381
|
+
});
|
|
382
|
+
it('correctly validates correct parameters that are class members', () => {
|
|
383
|
+
program.setFile('source/main.bs', `
|
|
384
|
+
class PiHolder
|
|
385
|
+
pi = 3.14
|
|
386
|
+
function getPi() as float
|
|
387
|
+
return m.pi
|
|
388
|
+
end function
|
|
389
|
+
end class
|
|
390
|
+
|
|
391
|
+
sub takesFloat(fl as float)
|
|
392
|
+
end sub
|
|
393
|
+
|
|
394
|
+
sub someFunc()
|
|
395
|
+
holder = new PiHolder()
|
|
396
|
+
takesFloat(holder.pi)
|
|
397
|
+
takesFloat(holder.getPI())
|
|
398
|
+
end sub`);
|
|
399
|
+
program.validate();
|
|
400
|
+
//should have no error
|
|
401
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
402
|
+
});
|
|
403
|
+
it('correctly validates wrong parameters that are class members', () => {
|
|
404
|
+
program.setFile('source/main.bs', `
|
|
405
|
+
class PiHolder
|
|
406
|
+
pi = 3.14
|
|
407
|
+
name = "hello"
|
|
408
|
+
function getPi() as float
|
|
409
|
+
return m.pi
|
|
410
|
+
end function
|
|
411
|
+
end class
|
|
412
|
+
|
|
413
|
+
sub takesFloat(fl as float)
|
|
414
|
+
end sub
|
|
415
|
+
|
|
416
|
+
sub someFunc()
|
|
417
|
+
holder = new PiHolder()
|
|
418
|
+
takesFloat(holder.name)
|
|
419
|
+
takesFloat(Str(holder.getPI()))
|
|
420
|
+
end sub`);
|
|
421
|
+
program.validate();
|
|
422
|
+
//should have error: holder.name is string
|
|
423
|
+
(0, chai_1.expect)(program.getDiagnostics().length).to.equal(2);
|
|
424
|
+
(0, chai_1.expect)(program.getDiagnostics().map(x => x.message)).to.include(DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'float').message);
|
|
425
|
+
});
|
|
426
|
+
it('correctly validates correct parameters that are interface members', () => {
|
|
427
|
+
program.setFile('source/main.bs', `
|
|
428
|
+
interface IPerson
|
|
429
|
+
height as float
|
|
430
|
+
name as string
|
|
431
|
+
function getWeight() as float
|
|
432
|
+
function getAddress() as string
|
|
433
|
+
end interface
|
|
434
|
+
|
|
435
|
+
sub takesFloat(fl as float)
|
|
436
|
+
end sub
|
|
437
|
+
|
|
438
|
+
sub someFunc(person as IPerson)
|
|
439
|
+
takesFloat(person.height)
|
|
440
|
+
takesFloat(person.getWeight())
|
|
441
|
+
end sub`);
|
|
442
|
+
program.validate();
|
|
443
|
+
//should have no error
|
|
444
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
445
|
+
});
|
|
446
|
+
it('correctly validates wrong parameters that are interface members', () => {
|
|
447
|
+
program.setFile('source/main.bs', `
|
|
448
|
+
interface IPerson
|
|
449
|
+
isAlive as boolean
|
|
450
|
+
function getAddress() as string
|
|
451
|
+
end interface
|
|
452
|
+
|
|
453
|
+
sub takesFloat(fl as float)
|
|
454
|
+
end sub
|
|
455
|
+
|
|
456
|
+
sub someFunc(person as IPerson)
|
|
457
|
+
takesFloat(person.isAlive)
|
|
458
|
+
takesFloat(person.getAddress())
|
|
459
|
+
end sub
|
|
460
|
+
`);
|
|
461
|
+
program.validate();
|
|
462
|
+
//should have 2 errors: person.name is string (not float) and person.getAddress() is object (not float)
|
|
463
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
464
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('boolean', 'float').message,
|
|
465
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'float').message
|
|
466
|
+
]);
|
|
467
|
+
});
|
|
468
|
+
it('`as object` param allows all types', () => {
|
|
469
|
+
program.setFile('source/main.bs', `
|
|
470
|
+
sub takesObject(obj as Object)
|
|
471
|
+
end sub
|
|
472
|
+
|
|
473
|
+
sub main()
|
|
474
|
+
takesObject(true)
|
|
475
|
+
takesObject(1)
|
|
476
|
+
takesObject(1.2)
|
|
477
|
+
takesObject(1.2#)
|
|
478
|
+
takesObject("text")
|
|
479
|
+
takesObject({})
|
|
480
|
+
takesObject([])
|
|
481
|
+
end sub
|
|
482
|
+
`);
|
|
483
|
+
program.validate();
|
|
484
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
485
|
+
});
|
|
486
|
+
it('allows conversions for arguments', () => {
|
|
487
|
+
program.setFile('source/main.bs', `
|
|
488
|
+
sub takesFloat(fl as float)
|
|
489
|
+
end sub
|
|
490
|
+
|
|
491
|
+
sub someFunc()
|
|
492
|
+
takesFloat(1)
|
|
493
|
+
end sub`);
|
|
494
|
+
program.validate();
|
|
495
|
+
//should have no error
|
|
496
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
497
|
+
});
|
|
498
|
+
it('allows subclasses as arguments', () => {
|
|
499
|
+
program.setFile('source/main.bs', `
|
|
500
|
+
|
|
501
|
+
class Animal
|
|
502
|
+
end class
|
|
503
|
+
|
|
504
|
+
class Dog extends Animal
|
|
505
|
+
end class
|
|
506
|
+
|
|
507
|
+
class Retriever extends Dog
|
|
508
|
+
end class
|
|
509
|
+
|
|
510
|
+
class Lab extends Retriever
|
|
511
|
+
end class
|
|
512
|
+
|
|
513
|
+
sub takesAnimal(thing as Animal)
|
|
514
|
+
end sub
|
|
515
|
+
|
|
516
|
+
sub someFunc()
|
|
517
|
+
fido = new Lab()
|
|
518
|
+
takesAnimal(fido)
|
|
519
|
+
end sub`);
|
|
520
|
+
program.validate();
|
|
521
|
+
//should have no error
|
|
522
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
523
|
+
});
|
|
524
|
+
it('allows subclasses from namespaces as arguments', () => {
|
|
525
|
+
program.setFile('source/main.bs', `
|
|
526
|
+
|
|
527
|
+
class Outside
|
|
528
|
+
end class
|
|
529
|
+
|
|
530
|
+
class ChildOutExtendsInside extends NS.Inside
|
|
531
|
+
end class
|
|
532
|
+
|
|
533
|
+
namespace NS
|
|
534
|
+
class Inside
|
|
535
|
+
end class
|
|
536
|
+
|
|
537
|
+
class ChildInExtendsOutside extends Outside
|
|
538
|
+
end class
|
|
539
|
+
|
|
540
|
+
class ChildInExtendsInside extends Inside
|
|
541
|
+
sub methodTakesInside(i as Inside)
|
|
542
|
+
end sub
|
|
543
|
+
end class
|
|
544
|
+
|
|
545
|
+
sub takesInside(klass as Inside)
|
|
546
|
+
end sub
|
|
547
|
+
|
|
548
|
+
sub testFuncInNamespace()
|
|
549
|
+
takesOutside(new Outside())
|
|
550
|
+
takesOutside(new NS.ChildInExtendsOutside())
|
|
551
|
+
|
|
552
|
+
' These call NS.takesInside
|
|
553
|
+
takesInside(new NS.Inside())
|
|
554
|
+
takesInside(new Inside())
|
|
555
|
+
takesInside(new NS.ChildInExtendsInside())
|
|
556
|
+
takesInside(new ChildInExtendsInside())
|
|
557
|
+
takesInside(new ChildOutExtendsInside())
|
|
558
|
+
|
|
559
|
+
child = new ChildInExtendsInside()
|
|
560
|
+
child.methodTakesInside(new Inside())
|
|
561
|
+
child.methodTakesInside(new ChildInExtendsInside())
|
|
562
|
+
child.methodTakesInside(new ChildOutExtendsInside())
|
|
563
|
+
end sub
|
|
564
|
+
|
|
565
|
+
end namespace
|
|
566
|
+
|
|
567
|
+
sub takesOutside(klass as Outside)
|
|
568
|
+
end sub
|
|
569
|
+
|
|
570
|
+
sub takesInside(klass as NS.Inside)
|
|
571
|
+
end sub
|
|
572
|
+
|
|
573
|
+
sub testFunc()
|
|
574
|
+
takesOutside(new Outside())
|
|
575
|
+
takesOutside(new NS.ChildInExtendsOutside())
|
|
576
|
+
|
|
577
|
+
takesInside(new NS.Inside())
|
|
578
|
+
takesInside(new NS.ChildInExtendsInside())
|
|
579
|
+
takesInside(new ChildOutExtendsInside())
|
|
580
|
+
|
|
581
|
+
NS.takesInside(new NS.Inside())
|
|
582
|
+
NS.takesInside(new NS.ChildInExtendsInside())
|
|
583
|
+
NS.takesInside(new ChildOutExtendsInside())
|
|
584
|
+
|
|
585
|
+
child = new NS.ChildInExtendsInside()
|
|
586
|
+
child.methodTakesInside(new NS.Inside())
|
|
587
|
+
child.methodTakesInside(new NS.ChildInExtendsInside())
|
|
588
|
+
child.methodTakesInside(new ChildOutExtendsInside())
|
|
589
|
+
end sub`);
|
|
590
|
+
program.validate();
|
|
591
|
+
//should have no error
|
|
592
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
593
|
+
});
|
|
594
|
+
it('respects union types', () => {
|
|
595
|
+
program.setFile('source/main.bs', `
|
|
596
|
+
sub takesStringOrKlass(p as string or Klass)
|
|
597
|
+
end sub
|
|
598
|
+
|
|
599
|
+
class Klass
|
|
600
|
+
end class
|
|
601
|
+
|
|
602
|
+
sub someFunc()
|
|
603
|
+
myKlass = new Klass()
|
|
604
|
+
takesStringOrKlass("test")
|
|
605
|
+
takesStringOrKlass(myKlass)
|
|
606
|
+
takesStringOrKlass(1)
|
|
607
|
+
end sub`);
|
|
608
|
+
program.validate();
|
|
609
|
+
//should have error when passed an integer
|
|
610
|
+
(0, chai_1.expect)(program.getDiagnostics().length).to.equal(1);
|
|
611
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
612
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string or Klass').message
|
|
613
|
+
]);
|
|
614
|
+
});
|
|
615
|
+
it('validates functions assigned to variables', () => {
|
|
616
|
+
program.setFile('source/main.bs', `
|
|
617
|
+
sub someFunc()
|
|
618
|
+
myFunc = function(i as integer, s as string)
|
|
619
|
+
print i+1
|
|
620
|
+
print s.len()
|
|
621
|
+
end function
|
|
622
|
+
myFunc("hello", 2)
|
|
623
|
+
end sub`);
|
|
624
|
+
program.validate();
|
|
625
|
+
//should have error when passed incorrect types
|
|
626
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
627
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('string', 'integer').message,
|
|
628
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('integer', 'string').message
|
|
629
|
+
]);
|
|
630
|
+
});
|
|
631
|
+
it('allows any parameter types in a function passed as an argument', () => {
|
|
632
|
+
program.setFile('source/file.brs', `
|
|
633
|
+
function getStrLength(name as string) as integer
|
|
634
|
+
return len(name)
|
|
635
|
+
end function
|
|
636
|
+
|
|
637
|
+
sub tryManyParams(someFunc as function)
|
|
638
|
+
print someFunc(1, 2, "hello", "world")
|
|
639
|
+
end sub
|
|
640
|
+
|
|
641
|
+
sub test()
|
|
642
|
+
tryManyParams(getStrLength)
|
|
643
|
+
end sub
|
|
644
|
+
`);
|
|
645
|
+
program.validate();
|
|
646
|
+
//should have no errors
|
|
647
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
648
|
+
});
|
|
649
|
+
it('allows a inline function as an argument of type function', () => {
|
|
650
|
+
program.setFile('source/file.brs', `
|
|
651
|
+
sub tryManyParams(someFunc as function)
|
|
652
|
+
print someFunc(1, 2, "hello", "world")
|
|
653
|
+
end sub
|
|
654
|
+
|
|
655
|
+
sub test()
|
|
656
|
+
tryManyParams(sub (i as integer)
|
|
657
|
+
print i
|
|
658
|
+
end sub)
|
|
659
|
+
end sub
|
|
660
|
+
`);
|
|
661
|
+
program.validate();
|
|
662
|
+
//should have no errors
|
|
663
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
664
|
+
});
|
|
665
|
+
it('validates when a non-function is used as an argument expecting a function', () => {
|
|
666
|
+
program.setFile('source/file.brs', `
|
|
667
|
+
sub tryManyParams(someFunc as function)
|
|
668
|
+
print someFunc(1, 2, "hello", "world")
|
|
669
|
+
end sub
|
|
670
|
+
|
|
671
|
+
sub test()
|
|
672
|
+
notAFunction = 3.14
|
|
673
|
+
tryManyParams(notAFunction)
|
|
674
|
+
end sub
|
|
675
|
+
`);
|
|
676
|
+
program.validate();
|
|
677
|
+
//should have an error that the argument is not a function
|
|
678
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
679
|
+
DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch('float', 'function').message
|
|
680
|
+
]);
|
|
681
|
+
});
|
|
682
|
+
it('allows any variable to passed as argument to an untyped param with default type invalid', () => {
|
|
683
|
+
program.setFile('source/util.brs', `
|
|
684
|
+
sub doSomething(x = invalid)
|
|
685
|
+
print x
|
|
686
|
+
end sub
|
|
687
|
+
|
|
688
|
+
sub tests()
|
|
689
|
+
doSomething(1)
|
|
690
|
+
doSomething(1.1)
|
|
691
|
+
doSomething("Hello")
|
|
692
|
+
doSomething(true)
|
|
693
|
+
doSomething({test: true})
|
|
694
|
+
end sub
|
|
695
|
+
`);
|
|
696
|
+
program.validate();
|
|
697
|
+
//should have no errors
|
|
698
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
699
|
+
});
|
|
700
|
+
});
|
|
701
|
+
describe('cannotFindName', () => {
|
|
702
|
+
it('finds variables from assignments from member functions of primitive types', () => {
|
|
703
|
+
program.setFile('source/util.brs', `
|
|
704
|
+
function lcaseTrim(str)
|
|
705
|
+
trimmedLowerStr = lcase(str).trim()
|
|
706
|
+
print trimmedLowerStr
|
|
707
|
+
end function
|
|
708
|
+
`);
|
|
709
|
+
program.validate();
|
|
710
|
+
//should have no errors
|
|
711
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
712
|
+
});
|
|
713
|
+
});
|
|
714
|
+
});
|
|
715
|
+
//# sourceMappingURL=ScopeValidator.spec.js.map
|