brighterscript 0.66.0-alpha.2 → 0.66.0-alpha.3

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.
Files changed (124) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +0 -6
  3. package/dist/BsConfig.d.ts +0 -5
  4. package/dist/Cache.js +3 -3
  5. package/dist/Cache.js.map +1 -1
  6. package/dist/CodeActionUtil.d.ts +2 -2
  7. package/dist/DiagnosticCollection.js +8 -5
  8. package/dist/DiagnosticCollection.js.map +1 -1
  9. package/dist/DiagnosticMessages.d.ts +6 -1
  10. package/dist/DiagnosticMessages.js +5 -0
  11. package/dist/DiagnosticMessages.js.map +1 -1
  12. package/dist/FunctionScope.d.ts +1 -1
  13. package/dist/LanguageServer.d.ts +5 -1
  14. package/dist/LanguageServer.js +7 -0
  15. package/dist/LanguageServer.js.map +1 -1
  16. package/dist/Logger.d.ts +2 -1
  17. package/dist/Logger.js +10 -2
  18. package/dist/Logger.js.map +1 -1
  19. package/dist/Program.d.ts +1 -3
  20. package/dist/Program.js +4 -12
  21. package/dist/Program.js.map +1 -1
  22. package/dist/ProgramBuilder.js +1 -1
  23. package/dist/ProgramBuilder.js.map +1 -1
  24. package/dist/Scope.d.ts +11 -6
  25. package/dist/Scope.js +77 -93
  26. package/dist/Scope.js.map +1 -1
  27. package/dist/SymbolTable.d.ts +11 -5
  28. package/dist/SymbolTable.js +21 -8
  29. package/dist/SymbolTable.js.map +1 -1
  30. package/dist/astUtils/reflection.d.ts +4 -0
  31. package/dist/astUtils/reflection.js +9 -1
  32. package/dist/astUtils/reflection.js.map +1 -1
  33. package/dist/bscPlugin/hover/HoverProcessor.d.ts +5 -0
  34. package/dist/bscPlugin/hover/HoverProcessor.js +108 -77
  35. package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
  36. package/dist/bscPlugin/hover/HoverProcessor.spec.js +83 -29
  37. package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
  38. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +0 -4
  39. package/dist/bscPlugin/validation/BrsFileValidator.js +10 -16
  40. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  41. package/dist/bscPlugin/validation/ScopeValidator.d.ts +4 -0
  42. package/dist/bscPlugin/validation/ScopeValidator.js +77 -42
  43. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
  44. package/dist/bscPlugin/validation/ScopeValidator.spec.js +684 -0
  45. package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
  46. package/dist/cli.js +95 -13
  47. package/dist/cli.js.map +1 -1
  48. package/dist/files/BrsFile.Class.spec.js +5 -0
  49. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  50. package/dist/files/BrsFile.d.ts +1 -11
  51. package/dist/files/BrsFile.js +9 -101
  52. package/dist/files/BrsFile.js.map +1 -1
  53. package/dist/files/BrsFile.spec.js +3 -267
  54. package/dist/files/BrsFile.spec.js.map +1 -1
  55. package/dist/globalCallables.js +78 -78
  56. package/dist/globalCallables.js.map +1 -1
  57. package/dist/index.d.ts +1 -0
  58. package/dist/index.js +1 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/interfaces.d.ts +7 -5
  61. package/dist/interfaces.js.map +1 -1
  62. package/dist/parser/Expression.d.ts +4 -3
  63. package/dist/parser/Expression.js +32 -9
  64. package/dist/parser/Expression.js.map +1 -1
  65. package/dist/parser/SGParser.d.ts +2 -2
  66. package/dist/parser/Statement.d.ts +11 -6
  67. package/dist/parser/Statement.js +54 -21
  68. package/dist/parser/Statement.js.map +1 -1
  69. package/dist/parser/tests/expression/TernaryExpression.spec.js +2 -2
  70. package/dist/types/BaseFunctionType.d.ts +8 -0
  71. package/dist/types/BaseFunctionType.js +25 -0
  72. package/dist/types/BaseFunctionType.js.map +1 -0
  73. package/dist/types/BooleanType.js +2 -1
  74. package/dist/types/BooleanType.js.map +1 -1
  75. package/dist/types/BscTypeKind.d.ts +1 -0
  76. package/dist/types/BscTypeKind.js +1 -0
  77. package/dist/types/BscTypeKind.js.map +1 -1
  78. package/dist/types/ClassType.js +1 -1
  79. package/dist/types/ClassType.js.map +1 -1
  80. package/dist/types/DoubleType.js +1 -0
  81. package/dist/types/DoubleType.js.map +1 -1
  82. package/dist/types/EnumType.d.ts +20 -4
  83. package/dist/types/EnumType.js +14 -2
  84. package/dist/types/EnumType.js.map +1 -1
  85. package/dist/types/FloatType.js +1 -0
  86. package/dist/types/FloatType.js.map +1 -1
  87. package/dist/types/FunctionType.d.ts +6 -19
  88. package/dist/types/FunctionType.js +12 -44
  89. package/dist/types/FunctionType.js.map +1 -1
  90. package/dist/types/IntegerType.js +1 -0
  91. package/dist/types/IntegerType.js.map +1 -1
  92. package/dist/types/InterfaceType.js +3 -3
  93. package/dist/types/InterfaceType.js.map +1 -1
  94. package/dist/types/InvalidType.d.ts +1 -0
  95. package/dist/types/InvalidType.js +3 -1
  96. package/dist/types/InvalidType.js.map +1 -1
  97. package/dist/types/LongIntegerType.js +1 -0
  98. package/dist/types/LongIntegerType.js.map +1 -1
  99. package/dist/types/ObjectType.js +2 -9
  100. package/dist/types/ObjectType.js.map +1 -1
  101. package/dist/types/ReferenceType.spec.js +6 -6
  102. package/dist/types/ReferenceType.spec.js.map +1 -1
  103. package/dist/types/StringType.js +4 -1
  104. package/dist/types/StringType.js.map +1 -1
  105. package/dist/types/TypedFunctionType.d.ts +27 -0
  106. package/dist/types/TypedFunctionType.js +69 -0
  107. package/dist/types/TypedFunctionType.js.map +1 -0
  108. package/dist/types/TypedFunctionType.spec.d.ts +1 -0
  109. package/dist/types/TypedFunctionType.spec.js +23 -0
  110. package/dist/types/TypedFunctionType.spec.js.map +1 -0
  111. package/dist/types/UnionType.js +1 -1
  112. package/dist/types/UnionType.js.map +1 -1
  113. package/dist/types/VoidType.js +2 -1
  114. package/dist/types/VoidType.js.map +1 -1
  115. package/dist/types/index.d.ts +1 -1
  116. package/dist/types/index.js +1 -1
  117. package/dist/types/index.js.map +1 -1
  118. package/dist/util.d.ts +22 -5
  119. package/dist/util.js +245 -79
  120. package/dist/util.js.map +1 -1
  121. package/package.json +3 -1
  122. package/dist/types/FunctionType.spec.js +0 -23
  123. package/dist/types/FunctionType.spec.js.map +0 -1
  124. /package/dist/{types/FunctionType.spec.d.ts → bscPlugin/validation/ScopeValidator.spec.d.ts} +0 -0
@@ -0,0 +1,684 @@
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
+ });
683
+ });
684
+ //# sourceMappingURL=ScopeValidator.spec.js.map