brighterscript 1.0.0-alpha.13 → 1.0.0-alpha.14

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 (180) hide show
  1. package/CHANGELOG.md +46 -2
  2. package/dist/Cache.d.ts +3 -3
  3. package/dist/Cache.js +10 -6
  4. package/dist/Cache.js.map +1 -1
  5. package/dist/LanguageServer.d.ts +1 -6
  6. package/dist/LanguageServer.js +0 -9
  7. package/dist/LanguageServer.js.map +1 -1
  8. package/dist/PluginInterface.d.ts +3 -3
  9. package/dist/PluginInterface.js +3 -0
  10. package/dist/PluginInterface.js.map +1 -1
  11. package/dist/Program.d.ts +30 -16
  12. package/dist/Program.js +106 -43
  13. package/dist/Program.js.map +1 -1
  14. package/dist/ProgramBuilder.js +3 -3
  15. package/dist/ProgramBuilder.js.map +1 -1
  16. package/dist/Scope.d.ts +15 -6
  17. package/dist/Scope.js +39 -25
  18. package/dist/Scope.js.map +1 -1
  19. package/dist/SymbolTable.d.ts +1 -1
  20. package/dist/astUtils/reflection.spec.js +6 -6
  21. package/dist/astUtils/reflection.spec.js.map +1 -1
  22. package/dist/astUtils/visitors.spec.js +8 -8
  23. package/dist/astUtils/visitors.spec.js.map +1 -1
  24. package/dist/bscPlugin/BscPlugin.js +5 -2
  25. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  26. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
  27. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  28. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  29. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +8 -0
  30. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.js → BrsFileSemanticTokensProcessor.js} +12 -14
  31. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  32. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.d.ts → BrsFileSemanticTokensProcessor.spec.d.ts} +0 -0
  33. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +2 -2
  34. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  35. package/dist/files/BrsFile.Class.spec.js +389 -238
  36. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  37. package/dist/files/BrsFile.d.ts +17 -11
  38. package/dist/files/BrsFile.js +160 -91
  39. package/dist/files/BrsFile.js.map +1 -1
  40. package/dist/files/BrsFile.spec.js +442 -109
  41. package/dist/files/BrsFile.spec.js.map +1 -1
  42. package/dist/files/XmlFile.d.ts +6 -5
  43. package/dist/files/XmlFile.js +13 -8
  44. package/dist/files/XmlFile.js.map +1 -1
  45. package/dist/files/XmlFile.spec.js +57 -55
  46. package/dist/files/XmlFile.spec.js.map +1 -1
  47. package/dist/files/tests/imports.spec.js +8 -6
  48. package/dist/files/tests/imports.spec.js.map +1 -1
  49. package/dist/index.d.ts +12 -3
  50. package/dist/index.js +21 -4
  51. package/dist/index.js.map +1 -1
  52. package/dist/interfaces.d.ts +46 -10
  53. package/dist/lexer/Lexer.js +1 -2
  54. package/dist/lexer/Lexer.js.map +1 -1
  55. package/dist/lexer/Lexer.spec.js +462 -462
  56. package/dist/lexer/Lexer.spec.js.map +1 -1
  57. package/dist/parser/Expression.d.ts +1 -1
  58. package/dist/parser/Expression.js +10 -10
  59. package/dist/parser/Expression.js.map +1 -1
  60. package/dist/parser/Parser.Class.spec.js +33 -32
  61. package/dist/parser/Parser.Class.spec.js.map +1 -1
  62. package/dist/parser/Parser.d.ts +17 -5
  63. package/dist/parser/Parser.js +403 -288
  64. package/dist/parser/Parser.js.map +1 -1
  65. package/dist/parser/Parser.spec.js +157 -35
  66. package/dist/parser/Parser.spec.js.map +1 -1
  67. package/dist/parser/SGTypes.spec.js +9 -9
  68. package/dist/parser/SGTypes.spec.js.map +1 -1
  69. package/dist/parser/Statement.d.ts +3 -3
  70. package/dist/parser/Statement.js +8 -8
  71. package/dist/parser/Statement.js.map +1 -1
  72. package/dist/parser/tests/Parser.spec.d.ts +3 -3
  73. package/dist/parser/tests/Parser.spec.js +4 -4
  74. package/dist/parser/tests/Parser.spec.js.map +1 -1
  75. package/dist/parser/tests/controlFlow/For.spec.js +40 -40
  76. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  77. package/dist/parser/tests/controlFlow/ForEach.spec.js +22 -21
  78. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  79. package/dist/parser/tests/controlFlow/If.spec.js +100 -99
  80. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  81. package/dist/parser/tests/controlFlow/While.spec.js +25 -25
  82. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  83. package/dist/parser/tests/expression/Additive.spec.js +21 -21
  84. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  85. package/dist/parser/tests/expression/ArrayLiterals.spec.js +91 -91
  86. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  87. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +102 -102
  88. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  89. package/dist/parser/tests/expression/Boolean.spec.js +15 -15
  90. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  91. package/dist/parser/tests/expression/Call.spec.js +22 -21
  92. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  93. package/dist/parser/tests/expression/Exponential.spec.js +11 -11
  94. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  95. package/dist/parser/tests/expression/Function.spec.js +171 -171
  96. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  97. package/dist/parser/tests/expression/Indexing.spec.js +50 -50
  98. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  99. package/dist/parser/tests/expression/Multiplicative.spec.js +25 -25
  100. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  101. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +16 -16
  102. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  103. package/dist/parser/tests/expression/PrefixUnary.spec.js +26 -26
  104. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  105. package/dist/parser/tests/expression/Primary.spec.js +27 -27
  106. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  107. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +3 -2
  108. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  109. package/dist/parser/tests/expression/Relational.spec.js +25 -25
  110. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  111. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +7 -7
  112. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  113. package/dist/parser/tests/expression/TernaryExpression.spec.js +6 -6
  114. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  115. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  116. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  117. package/dist/parser/tests/statement/Declaration.spec.js +20 -20
  118. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  119. package/dist/parser/tests/statement/Function.spec.js +121 -120
  120. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  121. package/dist/parser/tests/statement/Goto.spec.js +9 -8
  122. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  123. package/dist/parser/tests/statement/Increment.spec.js +22 -22
  124. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  125. package/dist/parser/tests/statement/InterfaceStatement.spec.js +12 -0
  126. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  127. package/dist/parser/tests/statement/LibraryStatement.spec.js +7 -7
  128. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  129. package/dist/parser/tests/statement/Misc.spec.js +71 -70
  130. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  131. package/dist/parser/tests/statement/PrintStatement.spec.js +17 -17
  132. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  133. package/dist/parser/tests/statement/ReturnStatement.spec.js +33 -33
  134. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  135. package/dist/parser/tests/statement/Set.spec.js +53 -53
  136. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  137. package/dist/parser/tests/statement/Stop.spec.js +7 -6
  138. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  139. package/dist/preprocessor/Chunk.d.ts +1 -1
  140. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  141. package/dist/preprocessor/Preprocessor.js +7 -7
  142. package/dist/preprocessor/Preprocessor.js.map +1 -1
  143. package/dist/types/ArrayType.d.ts +8 -5
  144. package/dist/types/ArrayType.js +45 -9
  145. package/dist/types/ArrayType.js.map +1 -1
  146. package/dist/types/ArrayType.spec.js +62 -3
  147. package/dist/types/ArrayType.spec.js.map +1 -1
  148. package/dist/types/BscType.d.ts +1 -1
  149. package/dist/types/CustomType.d.ts +1 -1
  150. package/dist/types/CustomType.js +4 -2
  151. package/dist/types/CustomType.js.map +1 -1
  152. package/dist/types/FunctionType.d.ts +5 -5
  153. package/dist/types/FunctionType.js +11 -11
  154. package/dist/types/FunctionType.js.map +1 -1
  155. package/dist/types/LazyType.d.ts +1 -2
  156. package/dist/types/LazyType.js +1 -5
  157. package/dist/types/LazyType.js.map +1 -1
  158. package/dist/types/helpers.js +1 -1
  159. package/dist/types/helpers.js.map +1 -1
  160. package/dist/util.d.ts +15 -9
  161. package/dist/util.js +93 -50
  162. package/dist/util.js.map +1 -1
  163. package/dist/validators/ClassValidator.js +17 -24
  164. package/dist/validators/ClassValidator.js.map +1 -1
  165. package/package.json +2 -1
  166. package/dist/astUtils/index.d.ts +0 -7
  167. package/dist/astUtils/index.js +0 -26
  168. package/dist/astUtils/index.js.map +0 -1
  169. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  170. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  171. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  172. package/dist/lexer/index.d.ts +0 -3
  173. package/dist/lexer/index.js +0 -18
  174. package/dist/lexer/index.js.map +0 -1
  175. package/dist/parser/index.d.ts +0 -3
  176. package/dist/parser/index.js +0 -16
  177. package/dist/parser/index.js.map +0 -1
  178. package/dist/preprocessor/index.d.ts +0 -3
  179. package/dist/preprocessor/index.js +0 -16
  180. package/dist/preprocessor/index.js.map +0 -1
@@ -12,7 +12,8 @@ const IntegerType_1 = require("../types/IntegerType");
12
12
  const StringType_1 = require("../types/StringType");
13
13
  const BrsFile_1 = require("./BrsFile");
14
14
  const source_map_1 = require("source-map");
15
- const lexer_1 = require("../lexer");
15
+ const Lexer_1 = require("../lexer/Lexer");
16
+ const TokenKind_1 = require("../lexer/TokenKind");
16
17
  const DiagnosticMessages_1 = require("../DiagnosticMessages");
17
18
  const util_1 = require("../util");
18
19
  const PluginInterface_1 = require("../PluginInterface");
@@ -20,6 +21,9 @@ const testHelpers_spec_1 = require("../testHelpers.spec");
20
21
  const Parser_1 = require("../parser/Parser");
21
22
  const Logger_1 = require("../Logger");
22
23
  const VoidType_1 = require("../types/VoidType");
24
+ const FloatType_1 = require("../types/FloatType");
25
+ const ObjectType_1 = require("../types/ObjectType");
26
+ const ArrayType_1 = require("../types/ArrayType");
23
27
  let sinon = sinonImport.createSandbox();
24
28
  describe('BrsFile', () => {
25
29
  let rootDir = (0, util_1.standardizePath) `${process.cwd()}/.tmp/rootDir`;
@@ -37,24 +41,22 @@ describe('BrsFile', () => {
37
41
  program.dispose();
38
42
  });
39
43
  it('supports the third parameter in CreateObject', () => {
40
- var _a;
41
44
  program.setFile('source/main.brs', `
42
45
  sub main()
43
46
  regexp = CreateObject("roRegex", "[a-z]+", "i")
44
47
  end sub
45
48
  `);
46
49
  program.validate();
47
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
50
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
48
51
  });
49
52
  it('supports the 6 params in CreateObject for roRegion', () => {
50
- var _a;
51
53
  program.setFile('source/main.brs', `
52
54
  sub createRegion(bitmap as object)
53
55
  region = CreateObject("roRegion", bitmap, 20, 40, 100, 200)
54
56
  end sub
55
57
  `);
56
58
  program.validate();
57
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
59
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
58
60
  });
59
61
  it('sets needsTranspiled to true for .bs files', () => {
60
62
  //BrightScript
@@ -69,8 +71,7 @@ describe('BrsFile', () => {
69
71
  range: undefined
70
72
  }];
71
73
  file.addDiagnostics(expected);
72
- const actual = file.getDiagnostics();
73
- (0, chai_1.expect)(actual).deep.equal(expected);
74
+ (0, testHelpers_spec_1.expectDiagnostics)(file, expected);
74
75
  });
75
76
  describe('getPartialVariableName', () => {
76
77
  let entry = {
@@ -182,7 +183,7 @@ describe('BrsFile', () => {
182
183
 
183
184
  end sub
184
185
  `);
185
- let keywords = Object.keys(lexer_1.Keywords).filter(x => !x.includes(' '));
186
+ let keywords = Object.keys(TokenKind_1.Keywords).filter(x => !x.includes(' '));
186
187
  //inside the function
187
188
  let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
188
189
  let names = result.map(x => x.label);
@@ -285,7 +286,6 @@ describe('BrsFile', () => {
285
286
  describe('comment flags', () => {
286
287
  describe('bs:disable-next-line', () => {
287
288
  it('disables critical diagnostic issues', () => {
288
- var _a, _b;
289
289
  program.setFile('source/main.brs', `
290
290
  sub main()
291
291
  Dim requestData
@@ -293,19 +293,18 @@ describe('BrsFile', () => {
293
293
  `);
294
294
  //should have an error
295
295
  program.validate();
296
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
296
+ (0, testHelpers_spec_1.expectHasDiagnostics)(program);
297
297
  program.setFile('source/main.brs', `
298
298
  sub main()
299
299
  'bs:disable-next-line
300
300
  Dim requestData
301
301
  end sub
302
302
  `);
303
- //should have an error
303
+ //should not have an error
304
304
  program.validate();
305
- (0, chai_1.expect)((_b = program.getDiagnostics()[0]) === null || _b === void 0 ? void 0 : _b.message).not.to.exist;
305
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
306
306
  });
307
307
  it('works with leading whitespace', () => {
308
- var _a;
309
308
  program.setFile('source/main.brs', `
310
309
  sub main()
311
310
  ' bs:disable-next-line
@@ -314,10 +313,9 @@ describe('BrsFile', () => {
314
313
  `);
315
314
  //should have an error
316
315
  program.validate();
317
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
316
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
318
317
  });
319
318
  it('works for all', () => {
320
- var _a;
321
319
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
322
320
  sub Main()
323
321
  'bs:disable-next-line
@@ -332,10 +330,9 @@ describe('BrsFile', () => {
332
330
  });
333
331
  program.validate();
334
332
  //the "unterminated string" error should be filtered out
335
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
333
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
336
334
  });
337
335
  it('works for specific codes', () => {
338
- var _a;
339
336
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
340
337
  sub Main()
341
338
  'bs:disable-next-line: 1083, 1001
@@ -349,10 +346,9 @@ describe('BrsFile', () => {
349
346
  affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
350
347
  });
351
348
  //the "unterminated string" error should be filtered out
352
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
349
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
353
350
  });
354
351
  it('recognizes non-numeric codes', () => {
355
- var _a;
356
352
  let file = program.setFile('source/main.brs', `
357
353
  sub Main()
358
354
  'bs:disable-next-line: LINT9999
@@ -360,7 +356,7 @@ describe('BrsFile', () => {
360
356
  end sub
361
357
  `);
362
358
  (0, chai_1.expect)(file.commentFlags[0]).to.exist;
363
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
359
+ (0, testHelpers_spec_1.expectHasDiagnostics)(program);
364
360
  });
365
361
  it('supports disabling non-numeric error codes', () => {
366
362
  const program = new Program_1.Program({});
@@ -375,7 +371,8 @@ describe('BrsFile', () => {
375
371
  message: 'Something is not right',
376
372
  range: util_1.default.createRange(2, 16, 2, 26)
377
373
  }]);
378
- (0, chai_1.expect)(program.getScopesForFile(file)[0].getDiagnostics()).to.be.empty;
374
+ const scope = program.getScopesForFile(file)[0];
375
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(scope);
379
376
  });
380
377
  it('adds diagnostics for unknown numeric diagnostic codes', () => {
381
378
  program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -384,13 +381,7 @@ describe('BrsFile', () => {
384
381
  end sub
385
382
  `);
386
383
  program.validate();
387
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(2);
388
- (0, chai_1.expect)(program.getDiagnostics()[0]).to.deep.include({
389
- range: vscode_languageserver_1.Range.create(2, 53, 2, 59)
390
- });
391
- (0, chai_1.expect)(program.getDiagnostics()[1]).to.deep.include({
392
- range: vscode_languageserver_1.Range.create(2, 60, 2, 66)
393
- });
384
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownDiagnosticCode(123456)), { range: vscode_languageserver_1.Range.create(2, 53, 2, 59) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownDiagnosticCode(999999)), { range: vscode_languageserver_1.Range.create(2, 60, 2, 66) })]);
394
385
  });
395
386
  });
396
387
  describe('bs:disable-line', () => {
@@ -408,7 +399,7 @@ describe('BrsFile', () => {
408
399
  });
409
400
  program.validate();
410
401
  //the "unterminated string" error should be filtered out
411
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(0);
402
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
412
403
  });
413
404
  it('works for specific codes', () => {
414
405
  program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -422,10 +413,9 @@ describe('BrsFile', () => {
422
413
  end sub
423
414
  `);
424
415
  program.validate();
425
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(1);
426
- (0, chai_1.expect)(program.getDiagnostics()[0]).to.deep.include({
427
- range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
428
- });
416
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [{
417
+ range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
418
+ }]);
429
419
  });
430
420
  it('handles the erraneous `stop` keyword', () => {
431
421
  //the current version of BRS causes parse errors after the `parse` keyword, showing error in comments
@@ -438,7 +428,7 @@ describe('BrsFile', () => {
438
428
  end sub
439
429
  `);
440
430
  program.validate();
441
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(0);
431
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
442
432
  });
443
433
  });
444
434
  });
@@ -474,7 +464,7 @@ describe('BrsFile', () => {
474
464
  myLabel:
475
465
  end sub
476
466
  `);
477
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
467
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
478
468
  });
479
469
  it('supports empty print statements', () => {
480
470
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -482,7 +472,7 @@ describe('BrsFile', () => {
482
472
  print
483
473
  end sub
484
474
  `);
485
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
475
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
486
476
  });
487
477
  describe('conditional compile', () => {
488
478
  it('works for upper case keywords', () => {
@@ -498,7 +488,7 @@ describe('BrsFile', () => {
498
488
  #ENDIF
499
489
  end sub
500
490
  `);
501
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
491
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
502
492
  });
503
493
  it('supports single-word #elseif and #endif', () => {
504
494
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -511,7 +501,7 @@ describe('BrsFile', () => {
511
501
  #endif
512
502
  end sub
513
503
  `);
514
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
504
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
515
505
  });
516
506
  it('supports multi-word #else if and #end if', () => {
517
507
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -524,7 +514,7 @@ describe('BrsFile', () => {
524
514
  #end if
525
515
  end sub
526
516
  `);
527
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
517
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
528
518
  });
529
519
  it('does not choke on invalid code inside a false conditional compile', () => {
530
520
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -534,7 +524,7 @@ describe('BrsFile', () => {
534
524
  #end if
535
525
  end sub
536
526
  `);
537
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
527
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
538
528
  });
539
529
  it('detects syntax error in #if', () => {
540
530
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -544,7 +534,9 @@ describe('BrsFile', () => {
544
534
  #end if
545
535
  end sub
546
536
  `);
547
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue));
537
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
538
+ DiagnosticMessages_1.DiagnosticMessages.referencedConstDoesNotExist()
539
+ ]);
548
540
  });
549
541
  it('detects syntax error in #const', () => {
550
542
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -554,7 +546,10 @@ describe('BrsFile', () => {
554
546
  #end if
555
547
  end sub
556
548
  `);
557
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%')));
549
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
550
+ DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%'),
551
+ DiagnosticMessages_1.DiagnosticMessages.invalidHashIfValue()
552
+ ]);
558
553
  });
559
554
  it('detects #const name using reserved word', () => {
560
555
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -562,7 +557,10 @@ describe('BrsFile', () => {
562
557
  #const function = true
563
558
  end sub
564
559
  `);
565
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord()));
560
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
561
+ DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord(),
562
+ DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('#const')
563
+ ]);
566
564
  });
567
565
  it('detects syntax error in #const', () => {
568
566
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -570,7 +568,9 @@ describe('BrsFile', () => {
570
568
  #const someConst = 123
571
569
  end sub
572
570
  `);
573
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()));
571
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
572
+ DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()
573
+ ]);
574
574
  });
575
575
  });
576
576
  it('supports stop statement', () => {
@@ -579,7 +579,7 @@ describe('BrsFile', () => {
579
579
  stop
580
580
  end sub
581
581
  `);
582
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
582
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
583
583
  });
584
584
  it('supports single-line if statements', () => {
585
585
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -592,16 +592,15 @@ describe('BrsFile', () => {
592
592
  if true then : test = sub() : print "yes" : end sub : end if
593
593
  end sub
594
594
  `);
595
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
595
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
596
596
  });
597
597
  it('supports line_num as global variable', () => {
598
- var _a;
599
598
  file.parse(`
600
599
  sub Main()
601
600
  print LINE_NUM
602
601
  end sub
603
602
  `);
604
- (0, chai_1.expect)((_a = file.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
603
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
605
604
  });
606
605
  it('supports many keywords as object property names', () => {
607
606
  file.parse(`
@@ -667,7 +666,7 @@ describe('BrsFile', () => {
667
666
  person.new = true
668
667
  end sub
669
668
  `);
670
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
669
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
671
670
  });
672
671
  it('does not error on numeric literal type designators', () => {
673
672
  file.parse(`
@@ -681,7 +680,7 @@ describe('BrsFile', () => {
681
680
  print 9876543210&
682
681
  end sub
683
682
  `);
684
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
683
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
685
684
  });
686
685
  it('does not error when encountering sub with return type', () => {
687
686
  file.parse(`
@@ -689,7 +688,7 @@ describe('BrsFile', () => {
689
688
  return
690
689
  end sub
691
690
  `);
692
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
691
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
693
692
  });
694
693
  it('does not lose function statements when mismatched end sub', () => {
695
694
  file.parse(`
@@ -724,7 +723,7 @@ describe('BrsFile', () => {
724
723
  foo.bar = true and false or 3 > 4
725
724
  end sub
726
725
  `);
727
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
726
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
728
727
  });
729
728
  it('does not error with boolean in RHS of set statement', () => {
730
729
  file.parse(`
@@ -737,7 +736,7 @@ describe('BrsFile', () => {
737
736
  m.isTrue = m.isTrue = m.isTrue
738
737
  end sub
739
738
  `);
740
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
739
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
741
740
  });
742
741
  it('supports variable names ending with type designators', () => {
743
742
  file.parse(`
@@ -749,7 +748,7 @@ describe('BrsFile', () => {
749
748
  someHex& = 13
750
749
  end sub
751
750
  `);
752
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
751
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
753
752
  });
754
753
  it('supports multiple spaces between two-word keywords', () => {
755
754
  file.parse(`
@@ -761,7 +760,7 @@ describe('BrsFile', () => {
761
760
  end if
762
761
  end sub
763
762
  `);
764
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
763
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
765
764
  });
766
765
  it('does not error with `stop` as object key', () => {
767
766
  file.parse(`
@@ -774,7 +773,7 @@ describe('BrsFile', () => {
774
773
  return obj
775
774
  end function
776
775
  `);
777
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
776
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
778
777
  });
779
778
  it('does not error with `run` as object key', () => {
780
779
  file.parse(`
@@ -787,7 +786,7 @@ describe('BrsFile', () => {
787
786
  return obj
788
787
  end function
789
788
  `);
790
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
789
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
791
790
  });
792
791
  it('supports assignment operators', () => {
793
792
  file.parse(`
@@ -804,7 +803,7 @@ describe('BrsFile', () => {
804
803
  print x
805
804
  end function
806
805
  `);
807
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
806
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
808
807
  });
809
808
  it('supports `then` as object property', () => {
810
809
  file.parse(`
@@ -816,7 +815,7 @@ describe('BrsFile', () => {
816
815
  promise.then()
817
816
  end function
818
817
  `);
819
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
818
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
820
819
  });
821
820
  it('supports function as parameter type', () => {
822
821
  file.parse(`
@@ -825,7 +824,7 @@ describe('BrsFile', () => {
825
824
  end function
826
825
  end sub
827
826
  `);
828
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
827
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
829
828
  });
830
829
  it('supports increment operator', () => {
831
830
  file.parse(`
@@ -834,8 +833,7 @@ describe('BrsFile', () => {
834
833
  x++
835
834
  end function
836
835
  `);
837
- file.getDiagnostics();
838
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
836
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
839
837
  });
840
838
  it('supports decrement operator', () => {
841
839
  file.parse(`
@@ -844,8 +842,7 @@ describe('BrsFile', () => {
844
842
  x--
845
843
  end function
846
844
  `);
847
- file.getDiagnostics();
848
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
845
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
849
846
  });
850
847
  it('supports writing numbers with decimal but no trailing digit', () => {
851
848
  file.parse(`
@@ -854,7 +851,7 @@ describe('BrsFile', () => {
854
851
  print x
855
852
  end function
856
853
  `);
857
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
854
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
858
855
  });
859
856
  it('supports assignment operators against object properties', () => {
860
857
  file.parse(`
@@ -876,7 +873,7 @@ describe('BrsFile', () => {
876
873
  print m.age
877
874
  end function
878
875
  `);
879
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
876
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
880
877
  });
881
878
  //skipped until `brs` supports this
882
879
  it('supports bitshift assignment operators', () => {
@@ -888,7 +885,7 @@ describe('BrsFile', () => {
888
885
  print x
889
886
  end function
890
887
  `);
891
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
888
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
892
889
  });
893
890
  //skipped until `brs` supports this
894
891
  it('supports bitshift assignment operators on objects', () => {
@@ -900,7 +897,7 @@ describe('BrsFile', () => {
900
897
  print m.x
901
898
  end function
902
899
  `);
903
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
900
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
904
901
  });
905
902
  it('supports leading and trailing periods for numeric literals', () => {
906
903
  file.parse(`
@@ -911,7 +908,7 @@ describe('BrsFile', () => {
911
908
  print pointOne
912
909
  end function
913
910
  `);
914
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
911
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
915
912
  });
916
913
  it('supports bitshift assignment operators on object properties accessed by array syntax', () => {
917
914
  file.parse(`
@@ -922,7 +919,7 @@ describe('BrsFile', () => {
922
919
  print m.x
923
920
  end function
924
921
  `);
925
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
922
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
926
923
  });
927
924
  it('supports weird period AA accessor', () => {
928
925
  file.parse(`
@@ -931,42 +928,46 @@ describe('BrsFile', () => {
931
928
  print m.["_uuid"]
932
929
  end function
933
930
  `);
934
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
931
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
935
932
  });
936
933
  it('adds error for library statements NOT at top of file', () => {
937
- let file = program.setFile('source/main.bs', `
934
+ program.setFile('source/file.brs', ``);
935
+ program.setFile('source/main.bs', `
938
936
  sub main()
939
937
  end sub
940
938
  import "file.brs"
941
939
  `);
942
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
943
- DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile().message
940
+ program.validate();
941
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
942
+ DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()
944
943
  ]);
945
944
  });
946
945
  it('supports library imports', () => {
947
- file.parse(`
946
+ program.setFile('source/main.brs', `
948
947
  Library "v30/bslCore.brs"
949
948
  `);
950
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
949
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
951
950
  });
952
951
  it('adds error for library statements NOT at top of file', () => {
953
- let file = program.setFile('source/main.brs', `
952
+ program.setFile('source/main.brs', `
954
953
  sub main()
955
954
  end sub
956
955
  Library "v30/bslCore.brs"
957
956
  `);
958
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
959
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
957
+ program.validate();
958
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
959
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
960
960
  ]);
961
961
  });
962
962
  it('adds error for library statements inside of function body', () => {
963
- let file = program.setFile('source/main.brs', `
963
+ program.setFile('source/main.brs', `
964
964
  sub main()
965
965
  Library "v30/bslCore.brs"
966
966
  end sub
967
967
  `);
968
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
969
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
968
+ program.validate();
969
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
970
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
970
971
  ]);
971
972
  });
972
973
  it('supports colons as separators in associative array properties', () => {
@@ -975,7 +976,7 @@ describe('BrsFile', () => {
975
976
  obj = {x:0 : y: 1}
976
977
  end sub
977
978
  `);
978
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
979
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
979
980
  });
980
981
  it('succeeds when finding variables with "sub" in them', () => {
981
982
  let file = program.setFile('source/main.brs', `
@@ -1061,10 +1062,8 @@ describe('BrsFile', () => {
1061
1062
  function DoSomething
1062
1063
  end function
1063
1064
  `);
1064
- (0, chai_1.expect)(file.getDiagnostics().length).to.be.greaterThan(0);
1065
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.deep.include({
1066
- file: file
1067
- });
1065
+ (0, testHelpers_spec_1.expectHasDiagnostics)(file);
1066
+ (0, chai_1.expect)(file.getDiagnostics()[0].file).to.equal(file);
1068
1067
  (0, chai_1.expect)(file.getDiagnostics()[0].range.start.line).to.equal(1);
1069
1068
  });
1070
1069
  it('supports using the `next` keyword in a for loop', () => {
@@ -1076,7 +1075,7 @@ describe('BrsFile', () => {
1076
1075
  next
1077
1076
  end sub
1078
1077
  `);
1079
- (0, chai_1.expect)(file.getDiagnostics()).to.be.empty;
1078
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1080
1079
  });
1081
1080
  //test is not working yet, but will be enabled when brs supports this syntax
1082
1081
  it('supports assigning functions to objects', () => {
@@ -1089,7 +1088,7 @@ describe('BrsFile', () => {
1089
1088
  end sub
1090
1089
  end function
1091
1090
  `);
1092
- (0, chai_1.expect)(file.getDiagnostics().length).to.equal(0);
1091
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1093
1092
  });
1094
1093
  });
1095
1094
  describe('findCallables', () => {
@@ -1210,7 +1209,6 @@ describe('BrsFile', () => {
1210
1209
  }]);
1211
1210
  });
1212
1211
  it('finds function calls nested inside statements', () => {
1213
- var _a;
1214
1212
  program.setFile(`source/main.brs`, `
1215
1213
  sub main()
1216
1214
  if true then
@@ -1219,7 +1217,9 @@ describe('BrsFile', () => {
1219
1217
  end sub
1220
1218
  `);
1221
1219
  program.validate();
1222
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction('DoesNotExist', 'source').message);
1220
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1221
+ DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction('DoesNotExist', 'source')
1222
+ ]);
1223
1223
  });
1224
1224
  it('finds arguments with variable values', () => {
1225
1225
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1407,7 +1407,11 @@ describe('BrsFile', () => {
1407
1407
  let hover = file.getHover(vscode_languageserver_1.Position.create(1, 28));
1408
1408
  (0, chai_1.expect)(hover).to.exist;
1409
1409
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
1410
- (0, chai_1.expect)(hover.contents).to.equal('function Main(count? as integer) as dynamic');
1410
+ (0, chai_1.expect)(hover.contents).to.equal([
1411
+ '```brightscript',
1412
+ 'function Main(count? as integer) as dynamic',
1413
+ '```'
1414
+ ].join('\n'));
1411
1415
  });
1412
1416
  it('finds variable function hover in same scope', () => {
1413
1417
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -1420,7 +1424,35 @@ describe('BrsFile', () => {
1420
1424
  `);
1421
1425
  let hover = file.getHover(vscode_languageserver_1.Position.create(5, 24));
1422
1426
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
1423
- (0, chai_1.expect)(hover.contents).to.equal('sub (name as string) as void');
1427
+ (0, chai_1.expect)(hover.contents).to.equal([
1428
+ '```brightscript',
1429
+ 'sub (name as string) as void',
1430
+ '```'
1431
+ ].join('\n'));
1432
+ });
1433
+ it('does not crash when hovering on built-in functions', async () => {
1434
+ let file = program.setFile('source/main.brs', `
1435
+ function doUcase(text)
1436
+ return ucase(text)
1437
+ end function
1438
+ `);
1439
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 30))).contents).to.equal([
1440
+ '```brightscript',
1441
+ 'function UCase(s as string) as string',
1442
+ '```'
1443
+ ].join('\n'));
1444
+ });
1445
+ it('does not crash when hovering on object method call', async () => {
1446
+ let file = program.setFile('source/main.brs', `
1447
+ function getInstr(url, text)
1448
+ return url.instr(text)
1449
+ end function
1450
+ `);
1451
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 35))).contents).to.equal([
1452
+ '```brightscript',
1453
+ 'instr as dynamic',
1454
+ '```'
1455
+ ].join('\n'));
1424
1456
  });
1425
1457
  it('finds function hover in file scope', () => {
1426
1458
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -1434,7 +1466,11 @@ describe('BrsFile', () => {
1434
1466
  `);
1435
1467
  let hover = file.getHover(vscode_languageserver_1.Position.create(2, 25));
1436
1468
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1437
- (0, chai_1.expect)(hover.contents).to.equal('sub sayMyName() as void');
1469
+ (0, chai_1.expect)(hover.contents).to.equal([
1470
+ '```brightscript',
1471
+ 'sub sayMyName() as void',
1472
+ '```'
1473
+ ].join('\n'));
1438
1474
  });
1439
1475
  it('finds function hover in scope', () => {
1440
1476
  let rootDir = process.cwd();
@@ -1454,7 +1490,53 @@ describe('BrsFile', () => {
1454
1490
  let hover = mainFile.getHover(vscode_languageserver_1.Position.create(2, 25));
1455
1491
  (0, chai_1.expect)(hover).to.exist;
1456
1492
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1457
- (0, chai_1.expect)(hover.contents).to.equal('sub sayMyName(name as string) as void');
1493
+ (0, chai_1.expect)(hover.contents).to.equal([
1494
+ '```brightscript',
1495
+ 'sub sayMyName(name as string) as void',
1496
+ '```'
1497
+ ].join('\n'));
1498
+ });
1499
+ it('includes markdown comments in hover.', async () => {
1500
+ let rootDir = process.cwd();
1501
+ program = new Program_1.Program({
1502
+ rootDir: rootDir
1503
+ });
1504
+ const file = program.setFile('source/lib.brs', `
1505
+ '
1506
+ ' The main function
1507
+ '
1508
+ sub main()
1509
+ log("hello")
1510
+ end sub
1511
+
1512
+ '
1513
+ ' Prints a message to the log.
1514
+ ' Works with *markdown* **content**
1515
+ '
1516
+ sub log(message as string)
1517
+ print message
1518
+ end sub
1519
+ `);
1520
+ //hover over log("hello")
1521
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(5, 22))).contents).to.equal([
1522
+ '```brightscript',
1523
+ 'sub log(message as string) as void',
1524
+ '```',
1525
+ '***',
1526
+ '',
1527
+ ' Prints a message to the log.',
1528
+ ' Works with *markdown* **content**',
1529
+ ''
1530
+ ].join('\n'));
1531
+ //hover over sub ma|in()
1532
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(4, 22))).contents).to.equal((0, testHelpers_spec_1.trim) `
1533
+ \`\`\`brightscript
1534
+ sub main() as void
1535
+ \`\`\`
1536
+ ***
1537
+
1538
+ The main function
1539
+ `);
1458
1540
  });
1459
1541
  it('handles mixed case `then` partions of conditionals', () => {
1460
1542
  let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -1464,7 +1546,7 @@ describe('BrsFile', () => {
1464
1546
  end if
1465
1547
  end sub
1466
1548
  `);
1467
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1549
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1468
1550
  mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1469
1551
  sub Main()
1470
1552
  if true Then
@@ -1472,7 +1554,7 @@ describe('BrsFile', () => {
1472
1554
  end if
1473
1555
  end sub
1474
1556
  `);
1475
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1557
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1476
1558
  mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1477
1559
  sub Main()
1478
1560
  if true THEN
@@ -1480,7 +1562,7 @@ describe('BrsFile', () => {
1480
1562
  end if
1481
1563
  end sub
1482
1564
  `);
1483
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1565
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1484
1566
  });
1485
1567
  it('displays the context from multiple scopes', () => {
1486
1568
  let commonFile = program.setFile('source/common.brs', `
@@ -1517,11 +1599,61 @@ describe('BrsFile', () => {
1517
1599
  `);
1518
1600
  program.validate();
1519
1601
  let funcCallHover = commonFile.getHover(vscode_languageserver_1.Position.create(2, 27));
1520
- (0, chai_1.expect)(funcCallHover).to.exist;
1521
- (0, chai_1.expect)(funcCallHover.contents).to.equal('getPi as uninitialized | function getPi() as string | function getPi() as float');
1602
+ (0, chai_1.expect)(funcCallHover === null || funcCallHover === void 0 ? void 0 : funcCallHover.contents).to.equal([
1603
+ '```brightscript',
1604
+ 'function getPi() as string | function getPi() as float | getPi as uninitialized',
1605
+ '```'
1606
+ ].join('\n'));
1522
1607
  let variableHover = commonFile.getHover(vscode_languageserver_1.Position.create(3, 27));
1523
- (0, chai_1.expect)(variableHover).to.exist;
1524
- (0, chai_1.expect)(variableHover.contents).to.equal('pi as uninitialized | pi as string | pi as float');
1608
+ (0, chai_1.expect)(variableHover === null || variableHover === void 0 ? void 0 : variableHover.contents).to.equal([
1609
+ '```brightscript',
1610
+ 'pi as string | pi as float | pi as uninitialized',
1611
+ '```'
1612
+ ].join('\n'));
1613
+ });
1614
+ it('finds function with custom types as parameters and return types', () => {
1615
+ let file = program.setFile('source/main.bs', `
1616
+ sub main()
1617
+ k = new MyKlass()
1618
+ processMyKlass(k)
1619
+ end sub
1620
+
1621
+ function processMyKlass(data as MyKlass) as MyKlass
1622
+ return data
1623
+ end function
1624
+
1625
+ class MyKlass
1626
+ end class
1627
+ `);
1628
+ let hover = file.getHover(vscode_languageserver_1.Position.create(3, 29));
1629
+ (0, chai_1.expect)(hover).to.exist;
1630
+ (0, chai_1.expect)(hover.contents).to.equal([
1631
+ '```brightscript',
1632
+ 'function processMyKlass(data as MyKlass) as MyKlass',
1633
+ '```'
1634
+ ].join('\n'));
1635
+ });
1636
+ it('finds function with arrays as parameters and return types', () => {
1637
+ let file = program.setFile('source/main.bs', `
1638
+ sub main()
1639
+ k = new MyKlass()
1640
+ processData([k])
1641
+ end sub
1642
+
1643
+ function processData(data as MyKlass[]) as MyKlass[]
1644
+ return data
1645
+ end function
1646
+
1647
+ class MyKlass
1648
+ end class
1649
+ `);
1650
+ let hover = file.getHover(vscode_languageserver_1.Position.create(3, 29));
1651
+ (0, chai_1.expect)(hover).to.exist;
1652
+ (0, chai_1.expect)(hover.contents).to.equal([
1653
+ '```brightscript',
1654
+ 'function processData(data as MyKlass[]) as MyKlass[]',
1655
+ '```'
1656
+ ].join('\n'));
1525
1657
  });
1526
1658
  });
1527
1659
  it('does not throw when encountering incomplete import statement', () => {
@@ -1830,9 +1962,9 @@ describe('BrsFile', () => {
1830
1962
  });
1831
1963
  it('computes correct locations for sourcemap', async () => {
1832
1964
  let source = `function abc(name)\n firstName = name\nend function`;
1833
- let tokens = lexer_1.Lexer.scan(source).tokens
1965
+ let tokens = Lexer_1.Lexer.scan(source).tokens
1834
1966
  //remove newlines and EOF
1835
- .filter(x => x.kind !== lexer_1.TokenKind.Eof && x.kind !== lexer_1.TokenKind.Newline);
1967
+ .filter(x => x.kind !== TokenKind_1.TokenKind.Eof && x.kind !== TokenKind_1.TokenKind.Newline);
1836
1968
  program.options.sourceMap = true;
1837
1969
  let result = testTranspile(source, source, 'none');
1838
1970
  //load the source map
@@ -2090,14 +2222,13 @@ describe('BrsFile', () => {
2090
2222
  describe('callfunc operator', () => {
2091
2223
  describe('transpile', () => {
2092
2224
  it('does not produce diagnostics', () => {
2093
- var _a;
2094
2225
  program.setFile('source/main.bs', `
2095
2226
  sub main()
2096
2227
  someObject@.someFunction(paramObject.value)
2097
2228
  end sub
2098
2229
  `);
2099
2230
  program.validate();
2100
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
2231
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2101
2232
  });
2102
2233
  it('sets invalid on empty callfunc', () => {
2103
2234
  testTranspile(`
@@ -2137,7 +2268,7 @@ describe('BrsFile', () => {
2137
2268
  name: 'transform callback',
2138
2269
  afterFileParse: onParsed
2139
2270
  });
2140
- file = program.setFile(`source/file.${ext}`, `
2271
+ file = program.setFile({ src: `absolute_path/file${ext}`, dest: `relative_path/file${ext}` }, `
2141
2272
  sub Sum()
2142
2273
  print "hello world"
2143
2274
  end sub
@@ -2510,11 +2641,11 @@ describe('BrsFile', () => {
2510
2641
  (0, chai_1.expect)(file.parser).to.equal(newParser);
2511
2642
  });
2512
2643
  it('call parse when previously skipped', () => {
2513
- program.setFile('source/main.d.bs', `
2644
+ program.setFile('source/main.d.bs', `'typedef
2514
2645
  sub main()
2515
2646
  end sub
2516
2647
  `);
2517
- const file = program.setFile('source/main.brs', `
2648
+ const file = program.setFile('source/main.brs', `'source
2518
2649
  sub main()
2519
2650
  end sub
2520
2651
  `);
@@ -2571,5 +2702,207 @@ describe('BrsFile', () => {
2571
2702
  testPluginTranspile();
2572
2703
  });
2573
2704
  });
2705
+ describe('getSymbolTypeFromToken', () => {
2706
+ function checkSymbolLookups(file, funcExpr, lookups) {
2707
+ const mainScope = program.getScopesForFile(file)[0];
2708
+ mainScope.linkSymbolTable();
2709
+ for (const lookup of lookups) {
2710
+ const position = vscode_languageserver_1.Position.create(lookup.line, lookup.col);
2711
+ const token = file.parser.getTokenAt(position);
2712
+ const symbol = file.getSymbolTypeFromToken(token, funcExpr, mainScope);
2713
+ const context = {
2714
+ file: file,
2715
+ scope: mainScope,
2716
+ position: position
2717
+ };
2718
+ (0, chai_1.expect)(symbol.expandedTokenText).to.equal(lookup.name);
2719
+ (0, chai_1.expect)(symbol.type.equals(lookup.type, context)).be.true;
2720
+ }
2721
+ }
2722
+ it('gets simple types based on the containing function expression', () => {
2723
+ const file = program.setFile('source/main.bs', `
2724
+ sub doSomething(aInt as integer, aFloat as float, aStr as string, aBool as boolean, aObj as object)
2725
+ print aInt
2726
+ print aFloat
2727
+ print aStr
2728
+ print aBool
2729
+ print aObj
2730
+ end sub
2731
+ `);
2732
+ const funcExpr = file.parser.references.functionExpressions[0];
2733
+ const lookups = [
2734
+ { line: 2, col: 28, name: 'aInt', type: new IntegerType_1.IntegerType() },
2735
+ { line: 3, col: 28, name: 'aFloat', type: new FloatType_1.FloatType() },
2736
+ { line: 4, col: 28, name: 'aStr', type: new StringType_1.StringType() },
2737
+ { line: 5, col: 28, name: 'aBool', type: new BooleanType_1.BooleanType() },
2738
+ { line: 6, col: 28, name: 'aObj', type: new ObjectType_1.ObjectType() }
2739
+ ];
2740
+ checkSymbolLookups(file, funcExpr, lookups);
2741
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2742
+ });
2743
+ it('gets custom types based on the containing function expression', () => {
2744
+ const file = program.setFile('source/main.bs', `
2745
+ sub doSomething(klass as MyKlass)
2746
+ print klass
2747
+ end sub
2748
+
2749
+ class MyKlass
2750
+ end class
2751
+ `);
2752
+ const mainScope = program.getScopesForFile(file)[0];
2753
+ mainScope.linkSymbolTable();
2754
+ const funcExpr = file.parser.references.functionExpressions[0];
2755
+ const token = file.parser.getTokenAt(vscode_languageserver_1.Position.create(2, 28));
2756
+ const symbol = file.getSymbolTypeFromToken(token, funcExpr, mainScope);
2757
+ (0, chai_1.expect)(symbol.expandedTokenText).to.equal('klass');
2758
+ const classStmt = file.parser.references.classStatements[0];
2759
+ (0, chai_1.expect)(classStmt.name.text).to.equal('MyKlass');
2760
+ (0, chai_1.expect)(symbol.type.isAssignableTo(classStmt.getCustomType())).be.true;
2761
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2762
+ });
2763
+ it('gets types of properties of a klass', () => {
2764
+ const file = program.setFile('source/main.bs', `
2765
+ sub doSomething()
2766
+ klass = new MyKlass()
2767
+ print klass.name
2768
+ print klass.age
2769
+ ' verify case insensitivity
2770
+ print KLASS.NAME
2771
+ print klass.AGE
2772
+ end sub
2773
+
2774
+ class MyKlass
2775
+ name as string
2776
+ age as integer
2777
+ end class
2778
+ `);
2779
+ const funcExpr = file.parser.references.functionExpressions[0];
2780
+ const lookups = [
2781
+ { line: 3, col: 35, name: 'MyKlass.name', type: new StringType_1.StringType() },
2782
+ { line: 4, col: 35, name: 'MyKlass.age', type: new IntegerType_1.IntegerType() }
2783
+ ];
2784
+ checkSymbolLookups(file, funcExpr, lookups);
2785
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2786
+ });
2787
+ it('gets types of properties of an object', () => {
2788
+ const file = program.setFile('source/main.bs', `
2789
+ sub doSomething()
2790
+ obj = { name: "Joe", age: 37}
2791
+ print obj.name
2792
+ print obj.age
2793
+ end sub
2794
+ `);
2795
+ const funcExpr = file.parser.references.functionExpressions[0];
2796
+ const lookups = [
2797
+ { line: 3, col: 32, name: 'obj.name', type: new StringType_1.StringType() },
2798
+ { line: 4, col: 32, name: 'obj.age', type: new IntegerType_1.IntegerType() }
2799
+ ];
2800
+ checkSymbolLookups(file, funcExpr, lookups);
2801
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2802
+ });
2803
+ it('gets return types of functions', () => {
2804
+ const file = program.setFile('source/main.bs', `
2805
+ sub doSomething()
2806
+ pi = makeKlass().getSelf().getPi()
2807
+ print pi
2808
+ end sub
2809
+
2810
+ function makeKlass() as MyKlass
2811
+ return new MyKlass()
2812
+ end function
2813
+
2814
+ class MyKlass
2815
+ function getPi() as float
2816
+ return 3.14
2817
+ end function
2818
+
2819
+ function getSelf() as MyKlass
2820
+ return m
2821
+ end function
2822
+ end class
2823
+ `);
2824
+ const mainScope = program.getScopesForFile(file)[0];
2825
+ mainScope.linkSymbolTable();
2826
+ const funcExpr = file.parser.references.functionExpressions[0];
2827
+ const klassMemberTable = file.parser.references.classStatements[0].memberTable;
2828
+ const lookups = [
2829
+ { line: 2, col: 31, name: 'makeKlass', type: file.parser.references.functionExpressions[1].getFunctionType() },
2830
+ // The expanded text for this should probably be MyKlass.getSelf()
2831
+ { line: 2, col: 41, name: 'MyKlass.MyKlass', type: klassMemberTable.getSymbol('getSelf')[0].type },
2832
+ { line: 2, col: 51, name: 'MyKlass.getPi', type: klassMemberTable.getSymbol('getPi')[0].type },
2833
+ { line: 3, col: 28, name: 'pi', type: new FloatType_1.FloatType() }
2834
+ ];
2835
+ checkSymbolLookups(file, funcExpr, lookups);
2836
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2837
+ });
2838
+ it('gets types of elements of arrays', () => {
2839
+ const file = program.setFile('source/main.bs', `
2840
+ sub doSomething(words as string[], klasses as MyKlass[])
2841
+ myWord = words[0]
2842
+ pi = klasses[0].getPi()
2843
+ print myWord
2844
+ print pi
2845
+ end sub
2846
+
2847
+ class MyKlass
2848
+ function getPi() as float
2849
+ return 3.14
2850
+ end function
2851
+ end class
2852
+ `);
2853
+ const mainScope = program.getScopesForFile(file)[0];
2854
+ mainScope.linkSymbolTable();
2855
+ const funcExpr = file.parser.references.functionExpressions[0];
2856
+ const klassMemberTable = file.parser.references.classStatements[0].memberTable;
2857
+ const lookups = [
2858
+ { line: 2, col: 34, name: 'words', type: new ArrayType_1.ArrayType(new StringType_1.StringType()) },
2859
+ { line: 3, col: 41, name: 'MyKlass.getPi', type: klassMemberTable.getSymbol('getPi')[0].type },
2860
+ { line: 4, col: 28, name: 'myWord', type: new StringType_1.StringType() },
2861
+ { line: 5, col: 28, name: 'pi', type: new FloatType_1.FloatType() }
2862
+ ];
2863
+ checkSymbolLookups(file, funcExpr, lookups);
2864
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2865
+ });
2866
+ it('gets types of elements of arrays via square bracket reference', () => {
2867
+ const file = program.setFile('source/main.bs', `
2868
+ function printFirst(numbers as float[]) as float
2869
+ firstFloat = numbers[0]
2870
+ print firstFloat
2871
+ return firstFloat
2872
+ end function
2873
+ `);
2874
+ const mainScope = program.getScopesForFile(file)[0];
2875
+ mainScope.linkSymbolTable();
2876
+ const funcExpr = file.parser.references.functionExpressions[0];
2877
+ const lookups = [
2878
+ { line: 2, col: 26, name: 'firstFloat', type: new FloatType_1.FloatType() },
2879
+ { line: 3, col: 32, name: 'firstFloat', type: new FloatType_1.FloatType() }
2880
+ ];
2881
+ checkSymbolLookups(file, funcExpr, lookups);
2882
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2883
+ });
2884
+ it('gets types of elements of arrays after for each', () => {
2885
+ const file = program.setFile('source/main.bs', `
2886
+ function printAllReturnFirst(numbers as float[]) as float
2887
+ for each num in numbers
2888
+ print num
2889
+ end for
2890
+
2891
+ firstFloat = numbers[0]
2892
+ print firstFloat
2893
+ return firstFloat
2894
+ end function
2895
+ `);
2896
+ const mainScope = program.getScopesForFile(file)[0];
2897
+ mainScope.linkSymbolTable();
2898
+ const funcExpr = file.parser.references.functionExpressions[0];
2899
+ const lookups = [
2900
+ { line: 6, col: 26, name: 'firstFloat', type: new FloatType_1.FloatType() },
2901
+ { line: 7, col: 32, name: 'firstFloat', type: new FloatType_1.FloatType() }
2902
+ ];
2903
+ checkSymbolLookups(file, funcExpr, lookups);
2904
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2905
+ });
2906
+ });
2574
2907
  });
2575
2908
  //# sourceMappingURL=BrsFile.spec.js.map