brighterscript 1.0.0-alpha.13 → 1.0.0-alpha.16

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 (229) hide show
  1. package/CHANGELOG.md +87 -2
  2. package/dist/Cache.d.ts +3 -8
  3. package/dist/Cache.js +9 -14
  4. package/dist/Cache.js.map +1 -1
  5. package/dist/DependencyGraph.js +5 -4
  6. package/dist/DependencyGraph.js.map +1 -1
  7. package/dist/DiagnosticMessages.d.ts +21 -1
  8. package/dist/DiagnosticMessages.js +21 -1
  9. package/dist/DiagnosticMessages.js.map +1 -1
  10. package/dist/LanguageServer.d.ts +1 -6
  11. package/dist/LanguageServer.js +0 -9
  12. package/dist/LanguageServer.js.map +1 -1
  13. package/dist/PluginInterface.d.ts +3 -3
  14. package/dist/PluginInterface.js +3 -0
  15. package/dist/PluginInterface.js.map +1 -1
  16. package/dist/Program.d.ts +30 -16
  17. package/dist/Program.js +108 -43
  18. package/dist/Program.js.map +1 -1
  19. package/dist/ProgramBuilder.js +3 -3
  20. package/dist/ProgramBuilder.js.map +1 -1
  21. package/dist/Scope.d.ts +29 -15
  22. package/dist/Scope.js +68 -28
  23. package/dist/Scope.js.map +1 -1
  24. package/dist/SymbolTable.d.ts +1 -1
  25. package/dist/XmlScope.d.ts +3 -3
  26. package/dist/astUtils/AstEditor.d.ts +6 -0
  27. package/dist/astUtils/AstEditor.js +10 -0
  28. package/dist/astUtils/AstEditor.js.map +1 -1
  29. package/dist/astUtils/AstEditor.spec.js +37 -0
  30. package/dist/astUtils/AstEditor.spec.js.map +1 -1
  31. package/dist/astUtils/creators.d.ts +8 -4
  32. package/dist/astUtils/creators.js +87 -6
  33. package/dist/astUtils/creators.js.map +1 -1
  34. package/dist/astUtils/reflection.d.ts +5 -1
  35. package/dist/astUtils/reflection.js +15 -3
  36. package/dist/astUtils/reflection.js.map +1 -1
  37. package/dist/astUtils/reflection.spec.js +11 -10
  38. package/dist/astUtils/reflection.spec.js.map +1 -1
  39. package/dist/astUtils/visitors.d.ts +3 -1
  40. package/dist/astUtils/visitors.js.map +1 -1
  41. package/dist/astUtils/visitors.spec.js +8 -8
  42. package/dist/astUtils/visitors.spec.js.map +1 -1
  43. package/dist/bscPlugin/BscPlugin.d.ts +4 -1
  44. package/dist/bscPlugin/BscPlugin.js +21 -2
  45. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  46. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
  47. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  48. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  49. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
  50. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
  51. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  52. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.d.ts → BrsFileSemanticTokensProcessor.spec.d.ts} +0 -0
  53. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +30 -2
  54. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  55. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
  56. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +36 -0
  57. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
  58. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
  59. package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
  60. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  61. package/dist/bscPlugin/validation/ScopeValidator.d.ts +11 -0
  62. package/dist/bscPlugin/validation/ScopeValidator.js +94 -0
  63. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  64. package/dist/diagnosticUtils.js +3 -3
  65. package/dist/diagnosticUtils.js.map +1 -1
  66. package/dist/files/BrsFile.Class.spec.js +382 -232
  67. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  68. package/dist/files/BrsFile.d.ts +26 -12
  69. package/dist/files/BrsFile.js +268 -119
  70. package/dist/files/BrsFile.js.map +1 -1
  71. package/dist/files/BrsFile.spec.js +570 -168
  72. package/dist/files/BrsFile.spec.js.map +1 -1
  73. package/dist/files/XmlFile.d.ts +11 -10
  74. package/dist/files/XmlFile.js +16 -11
  75. package/dist/files/XmlFile.js.map +1 -1
  76. package/dist/files/XmlFile.spec.js +60 -58
  77. package/dist/files/XmlFile.spec.js.map +1 -1
  78. package/dist/files/tests/imports.spec.js +8 -6
  79. package/dist/files/tests/imports.spec.js.map +1 -1
  80. package/dist/index.d.ts +12 -3
  81. package/dist/index.js +21 -4
  82. package/dist/index.js.map +1 -1
  83. package/dist/interfaces.d.ts +63 -35
  84. package/dist/lexer/Lexer.js +1 -2
  85. package/dist/lexer/Lexer.js.map +1 -1
  86. package/dist/lexer/Lexer.spec.js +470 -462
  87. package/dist/lexer/Lexer.spec.js.map +1 -1
  88. package/dist/lexer/TokenKind.d.ts +2 -0
  89. package/dist/lexer/TokenKind.js +5 -0
  90. package/dist/lexer/TokenKind.js.map +1 -1
  91. package/dist/parser/Expression.d.ts +18 -16
  92. package/dist/parser/Expression.js +57 -48
  93. package/dist/parser/Expression.js.map +1 -1
  94. package/dist/parser/Parser.Class.spec.js +33 -32
  95. package/dist/parser/Parser.Class.spec.js.map +1 -1
  96. package/dist/parser/Parser.d.ts +28 -7
  97. package/dist/parser/Parser.js +508 -296
  98. package/dist/parser/Parser.js.map +1 -1
  99. package/dist/parser/Parser.spec.js +157 -35
  100. package/dist/parser/Parser.spec.js.map +1 -1
  101. package/dist/parser/SGTypes.spec.js +9 -9
  102. package/dist/parser/SGTypes.spec.js.map +1 -1
  103. package/dist/parser/Statement.d.ts +80 -20
  104. package/dist/parser/Statement.js +257 -92
  105. package/dist/parser/Statement.js.map +1 -1
  106. package/dist/parser/tests/Parser.spec.d.ts +3 -3
  107. package/dist/parser/tests/Parser.spec.js +4 -4
  108. package/dist/parser/tests/Parser.spec.js.map +1 -1
  109. package/dist/parser/tests/controlFlow/For.spec.js +40 -40
  110. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  111. package/dist/parser/tests/controlFlow/ForEach.spec.js +22 -21
  112. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  113. package/dist/parser/tests/controlFlow/If.spec.js +100 -99
  114. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  115. package/dist/parser/tests/controlFlow/While.spec.js +25 -25
  116. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  117. package/dist/parser/tests/expression/Additive.spec.js +21 -21
  118. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  119. package/dist/parser/tests/expression/ArrayLiterals.spec.js +91 -91
  120. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  121. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +102 -102
  122. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  123. package/dist/parser/tests/expression/Boolean.spec.js +15 -15
  124. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  125. package/dist/parser/tests/expression/Call.spec.js +22 -21
  126. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  127. package/dist/parser/tests/expression/Exponential.spec.js +11 -11
  128. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  129. package/dist/parser/tests/expression/Function.spec.js +171 -171
  130. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  131. package/dist/parser/tests/expression/Indexing.spec.js +50 -50
  132. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  133. package/dist/parser/tests/expression/Multiplicative.spec.js +25 -25
  134. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  135. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +16 -16
  136. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  137. package/dist/parser/tests/expression/PrefixUnary.spec.js +26 -26
  138. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  139. package/dist/parser/tests/expression/Primary.spec.js +27 -27
  140. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  141. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +3 -2
  142. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  143. package/dist/parser/tests/expression/Relational.spec.js +25 -25
  144. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  145. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +7 -7
  146. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  147. package/dist/parser/tests/expression/TernaryExpression.spec.js +6 -6
  148. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  149. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  150. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  151. package/dist/parser/tests/statement/Declaration.spec.js +20 -20
  152. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  153. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  154. package/dist/parser/tests/statement/Enum.spec.js +774 -0
  155. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  156. package/dist/parser/tests/statement/For.spec.d.ts +1 -0
  157. package/dist/parser/tests/statement/For.spec.js +46 -0
  158. package/dist/parser/tests/statement/For.spec.js.map +1 -0
  159. package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
  160. package/dist/parser/tests/statement/ForEach.spec.js +37 -0
  161. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
  162. package/dist/parser/tests/statement/Function.spec.js +121 -120
  163. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  164. package/dist/parser/tests/statement/Goto.spec.js +9 -8
  165. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  166. package/dist/parser/tests/statement/Increment.spec.js +22 -22
  167. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  168. package/dist/parser/tests/statement/InterfaceStatement.spec.js +12 -0
  169. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  170. package/dist/parser/tests/statement/LibraryStatement.spec.js +7 -7
  171. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  172. package/dist/parser/tests/statement/Misc.spec.js +71 -70
  173. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  174. package/dist/parser/tests/statement/PrintStatement.spec.js +17 -17
  175. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  176. package/dist/parser/tests/statement/ReturnStatement.spec.js +33 -33
  177. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  178. package/dist/parser/tests/statement/Set.spec.js +53 -53
  179. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  180. package/dist/parser/tests/statement/Stop.spec.js +7 -6
  181. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  182. package/dist/preprocessor/Chunk.d.ts +1 -1
  183. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  184. package/dist/preprocessor/Preprocessor.js +7 -7
  185. package/dist/preprocessor/Preprocessor.js.map +1 -1
  186. package/dist/types/ArrayType.d.ts +8 -5
  187. package/dist/types/ArrayType.js +45 -9
  188. package/dist/types/ArrayType.js.map +1 -1
  189. package/dist/types/ArrayType.spec.js +62 -3
  190. package/dist/types/ArrayType.spec.js.map +1 -1
  191. package/dist/types/BscType.d.ts +1 -1
  192. package/dist/types/CustomType.d.ts +1 -1
  193. package/dist/types/CustomType.js +4 -2
  194. package/dist/types/CustomType.js.map +1 -1
  195. package/dist/types/FunctionType.d.ts +7 -6
  196. package/dist/types/FunctionType.js +21 -18
  197. package/dist/types/FunctionType.js.map +1 -1
  198. package/dist/types/FunctionType.spec.js +6 -0
  199. package/dist/types/FunctionType.spec.js.map +1 -1
  200. package/dist/types/LazyType.d.ts +1 -2
  201. package/dist/types/LazyType.js +1 -5
  202. package/dist/types/LazyType.js.map +1 -1
  203. package/dist/types/UniversalFunctionType.d.ts +9 -0
  204. package/dist/types/UniversalFunctionType.js +25 -0
  205. package/dist/types/UniversalFunctionType.js.map +1 -0
  206. package/dist/types/helpers.js +1 -1
  207. package/dist/types/helpers.js.map +1 -1
  208. package/dist/util.d.ts +26 -10
  209. package/dist/util.js +145 -61
  210. package/dist/util.js.map +1 -1
  211. package/dist/validators/ClassValidator.js +17 -24
  212. package/dist/validators/ClassValidator.js.map +1 -1
  213. package/package.json +3 -3
  214. package/dist/astUtils/index.d.ts +0 -7
  215. package/dist/astUtils/index.js +0 -26
  216. package/dist/astUtils/index.js.map +0 -1
  217. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  218. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
  219. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  220. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  221. package/dist/lexer/index.d.ts +0 -3
  222. package/dist/lexer/index.js +0 -18
  223. package/dist/lexer/index.js.map +0 -1
  224. package/dist/parser/index.d.ts +0 -3
  225. package/dist/parser/index.js +0 -16
  226. package/dist/parser/index.js.map +0 -1
  227. package/dist/preprocessor/index.d.ts +0 -3
  228. package/dist/preprocessor/index.js +0 -16
  229. 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 = {
@@ -157,6 +158,76 @@ describe('BrsFile', () => {
157
158
  (0, chai_1.expect)(names).to.includes('Main');
158
159
  (0, chai_1.expect)(names).to.includes('SayHello');
159
160
  });
161
+ it('includes every type of item at base level', () => {
162
+ program.setFile('source/main.bs', `
163
+ sub main()
164
+ print
165
+ end sub
166
+ sub speak()
167
+ end sub
168
+ namespace stuff
169
+ end namespace
170
+ class Person
171
+ end class
172
+ enum Direction
173
+ end enum
174
+ `);
175
+ (0, testHelpers_spec_1.expectCompletionsIncludes)(program.getCompletions('source/main.bs', util_1.default.createPosition(2, 26)), [{
176
+ label: 'main',
177
+ kind: vscode_languageserver_1.CompletionItemKind.Function
178
+ }, {
179
+ label: 'speak',
180
+ kind: vscode_languageserver_1.CompletionItemKind.Function
181
+ }, {
182
+ label: 'stuff',
183
+ kind: vscode_languageserver_1.CompletionItemKind.Module
184
+ }, {
185
+ label: 'Person',
186
+ kind: vscode_languageserver_1.CompletionItemKind.Class
187
+ }, {
188
+ label: 'Direction',
189
+ kind: vscode_languageserver_1.CompletionItemKind.Enum
190
+ }]);
191
+ });
192
+ describe('namespaces', () => {
193
+ it('gets full namespace completions at any point through the leading identifier', () => {
194
+ program.setFile('source/main.bs', `
195
+ sub main()
196
+ foo.bar
197
+ end sub
198
+
199
+ namespace foo.bar
200
+ end namespace
201
+
202
+ class Person
203
+ end class
204
+ `);
205
+ const result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(2, 24)).map(x => x.label);
206
+ (0, chai_1.expect)(result).includes('main');
207
+ (0, chai_1.expect)(result).includes('foo');
208
+ (0, chai_1.expect)(result).includes('Person');
209
+ });
210
+ it('gets namespace completions', () => {
211
+ program.setFile('source/main.bs', `
212
+ namespace foo.bar
213
+ function sayHello()
214
+ end function
215
+ end namespace
216
+
217
+ sub Main()
218
+ print "hello"
219
+ foo.ba
220
+ foo.bar.
221
+ end sub
222
+ `);
223
+ let result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(8, 30));
224
+ let names = result.map(x => x.label);
225
+ (0, chai_1.expect)(names).to.includes('bar');
226
+ result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(9, 32));
227
+ names = result.map(x => x.label);
228
+ (0, chai_1.expect)(names).to.includes('sayHello');
229
+ });
230
+ });
160
231
  it('always includes `m`', () => {
161
232
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
162
233
  program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -182,7 +253,7 @@ describe('BrsFile', () => {
182
253
 
183
254
  end sub
184
255
  `);
185
- let keywords = Object.keys(lexer_1.Keywords).filter(x => !x.includes(' '));
256
+ let keywords = Object.keys(TokenKind_1.Keywords).filter(x => !x.includes(' '));
186
257
  //inside the function
187
258
  let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
188
259
  let names = result.map(x => x.label);
@@ -285,7 +356,6 @@ describe('BrsFile', () => {
285
356
  describe('comment flags', () => {
286
357
  describe('bs:disable-next-line', () => {
287
358
  it('disables critical diagnostic issues', () => {
288
- var _a, _b;
289
359
  program.setFile('source/main.brs', `
290
360
  sub main()
291
361
  Dim requestData
@@ -293,19 +363,18 @@ describe('BrsFile', () => {
293
363
  `);
294
364
  //should have an error
295
365
  program.validate();
296
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
366
+ (0, testHelpers_spec_1.expectHasDiagnostics)(program);
297
367
  program.setFile('source/main.brs', `
298
368
  sub main()
299
369
  'bs:disable-next-line
300
370
  Dim requestData
301
371
  end sub
302
372
  `);
303
- //should have an error
373
+ //should not have an error
304
374
  program.validate();
305
- (0, chai_1.expect)((_b = program.getDiagnostics()[0]) === null || _b === void 0 ? void 0 : _b.message).not.to.exist;
375
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
306
376
  });
307
377
  it('works with leading whitespace', () => {
308
- var _a;
309
378
  program.setFile('source/main.brs', `
310
379
  sub main()
311
380
  ' bs:disable-next-line
@@ -314,10 +383,9 @@ describe('BrsFile', () => {
314
383
  `);
315
384
  //should have an error
316
385
  program.validate();
317
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
386
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
318
387
  });
319
388
  it('works for all', () => {
320
- var _a;
321
389
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
322
390
  sub Main()
323
391
  'bs:disable-next-line
@@ -332,10 +400,9 @@ describe('BrsFile', () => {
332
400
  });
333
401
  program.validate();
334
402
  //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;
403
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
336
404
  });
337
405
  it('works for specific codes', () => {
338
- var _a;
339
406
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
340
407
  sub Main()
341
408
  'bs:disable-next-line: 1083, 1001
@@ -349,18 +416,17 @@ describe('BrsFile', () => {
349
416
  affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
350
417
  });
351
418
  //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;
419
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
353
420
  });
354
421
  it('recognizes non-numeric codes', () => {
355
- var _a;
356
422
  let file = program.setFile('source/main.brs', `
357
423
  sub Main()
358
424
  'bs:disable-next-line: LINT9999
359
425
  name = "bob
360
426
  end sub
361
- `);
427
+ `);
362
428
  (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;
429
+ (0, testHelpers_spec_1.expectHasDiagnostics)(program);
364
430
  });
365
431
  it('supports disabling non-numeric error codes', () => {
366
432
  const program = new Program_1.Program({});
@@ -368,34 +434,29 @@ describe('BrsFile', () => {
368
434
  sub main()
369
435
  something = true 'bs:disable-line: LINT1005
370
436
  end sub
371
- `);
437
+ `);
372
438
  file.addDiagnostics([{
373
439
  code: 'LINT1005',
374
440
  file: file,
375
441
  message: 'Something is not right',
376
442
  range: util_1.default.createRange(2, 16, 2, 26)
377
443
  }]);
378
- (0, chai_1.expect)(program.getScopesForFile(file)[0].getDiagnostics()).to.be.empty;
444
+ const scope = program.getScopesForFile(file)[0];
445
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(scope);
379
446
  });
380
447
  it('adds diagnostics for unknown numeric diagnostic codes', () => {
381
- program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
448
+ program.setFile({ src: `${rootDir} / source / main.brs`, dest: 'source/main.brs' }, `
382
449
  sub main()
383
450
  print "hi" 'bs:disable-line: 123456 999999 aaaab
384
451
  end sub
385
- `);
452
+ `);
386
453
  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
- });
454
+ (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
455
  });
395
456
  });
396
457
  describe('bs:disable-line', () => {
397
458
  it('works for all', () => {
398
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
459
+ let file = program.setFile({ src: `${rootDir} / source / main.brs`, dest: 'source/main.brs' }, `
399
460
  sub Main()
400
461
  z::;;%%%%%% 'bs:disable-line
401
462
  end sub
@@ -408,10 +469,10 @@ describe('BrsFile', () => {
408
469
  });
409
470
  program.validate();
410
471
  //the "unterminated string" error should be filtered out
411
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(0);
472
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
412
473
  });
413
474
  it('works for specific codes', () => {
414
- program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
475
+ program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
415
476
  sub main()
416
477
  'should not have any errors
417
478
  DoSomething(1) 'bs:disable-line:1002
@@ -422,23 +483,22 @@ describe('BrsFile', () => {
422
483
  end sub
423
484
  `);
424
485
  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
- });
486
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [{
487
+ range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
488
+ }]);
429
489
  });
430
490
  it('handles the erraneous `stop` keyword', () => {
431
491
  //the current version of BRS causes parse errors after the `parse` keyword, showing error in comments
432
492
  //the program should ignore all diagnostics found in brs:* comment lines EXCEPT
433
493
  //for the diagnostics about using unknown error codes
434
- program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
494
+ program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
435
495
  sub main()
436
496
  stop 'bs:disable-line
437
497
  print "need a valid line to fix stop error"
438
498
  end sub
439
- `);
499
+ `);
440
500
  program.validate();
441
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(0);
501
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
442
502
  });
443
503
  });
444
504
  });
@@ -446,9 +506,9 @@ describe('BrsFile', () => {
446
506
  it('supports iife in assignment', () => {
447
507
  program.setFile('source/main.brs', `
448
508
  sub main()
449
- result = sub()
509
+ result = sub()
450
510
  end sub()
451
- result = (sub()
511
+ result = (sub()
452
512
  end sub)()
453
513
  end sub
454
514
  `);
@@ -467,26 +527,26 @@ describe('BrsFile', () => {
467
527
  testParseMode('source/main.spec.bs', Parser_1.ParseMode.BrighterScript);
468
528
  });
469
529
  it('supports labels and goto statements', () => {
470
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
530
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
471
531
  sub Main()
472
532
  'multiple goto statements on one line
473
- goto myLabel : goto myLabel
533
+ goto myLabel: goto myLabel
474
534
  myLabel:
475
535
  end sub
476
536
  `);
477
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
537
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
478
538
  });
479
539
  it('supports empty print statements', () => {
480
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
540
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
481
541
  sub main()
482
- print
542
+ print
483
543
  end sub
484
544
  `);
485
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
545
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
486
546
  });
487
547
  describe('conditional compile', () => {
488
548
  it('works for upper case keywords', () => {
489
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
549
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
490
550
  sub main()
491
551
  #CONST someFlag = true
492
552
  #IF someFlag
@@ -498,10 +558,10 @@ describe('BrsFile', () => {
498
558
  #ENDIF
499
559
  end sub
500
560
  `);
501
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
561
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
502
562
  });
503
563
  it('supports single-word #elseif and #endif', () => {
504
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
564
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
505
565
  sub main()
506
566
  #const someFlag = true
507
567
  #if someFlag
@@ -511,10 +571,10 @@ describe('BrsFile', () => {
511
571
  #endif
512
572
  end sub
513
573
  `);
514
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
574
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
515
575
  });
516
576
  it('supports multi-word #else if and #end if', () => {
517
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
577
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
518
578
  sub main()
519
579
  #const someFlag = true
520
580
  #if someFlag
@@ -524,84 +584,93 @@ describe('BrsFile', () => {
524
584
  #end if
525
585
  end sub
526
586
  `);
527
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
587
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
528
588
  });
529
589
  it('does not choke on invalid code inside a false conditional compile', () => {
530
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
590
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
531
591
  sub main()
532
592
  #if false
533
- non-commented code here should not cause parse errors
593
+ non - commented code here should not cause parse errors
534
594
  #end if
535
595
  end sub
536
596
  `);
537
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
597
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
538
598
  });
539
599
  it('detects syntax error in #if', () => {
540
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
600
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
541
601
  sub main()
542
602
  #if true1
543
603
  print "true"
544
604
  #end if
545
605
  end sub
546
606
  `);
547
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue));
607
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
608
+ DiagnosticMessages_1.DiagnosticMessages.referencedConstDoesNotExist()
609
+ ]);
548
610
  });
549
611
  it('detects syntax error in #const', () => {
550
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
612
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
551
613
  sub main()
552
614
  #if %
553
615
  print "true"
554
616
  #end if
555
617
  end sub
556
618
  `);
557
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%')));
619
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
620
+ DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%'),
621
+ DiagnosticMessages_1.DiagnosticMessages.invalidHashIfValue()
622
+ ]);
558
623
  });
559
624
  it('detects #const name using reserved word', () => {
560
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
625
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
561
626
  sub main()
562
627
  #const function = true
563
628
  end sub
564
629
  `);
565
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord()));
630
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
631
+ DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord(),
632
+ DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('#const')
633
+ ]);
566
634
  });
567
635
  it('detects syntax error in #const', () => {
568
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
636
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
569
637
  sub main()
570
638
  #const someConst = 123
571
639
  end sub
572
640
  `);
573
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()));
641
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
642
+ DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()
643
+ ]);
574
644
  });
575
645
  });
576
646
  it('supports stop statement', () => {
577
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
647
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
578
648
  sub main()
579
- stop
649
+ stop
580
650
  end sub
581
651
  `);
582
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
652
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
583
653
  });
584
654
  it('supports single-line if statements', () => {
585
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
655
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
586
656
  sub main()
587
657
  if 1 < 2: return true: end if
588
658
  if 1 < 2: return true
589
659
  end if
590
660
  if false : print "true" : end if
591
661
  if true: print "8 worked": else if true: print "not run": else: print "not run": end if
592
- if true then : test = sub() : print "yes" : end sub : end if
662
+ if true then: test = sub() : print "yes" : end sub: end if
593
663
  end sub
594
664
  `);
595
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
665
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
596
666
  });
597
667
  it('supports line_num as global variable', () => {
598
- var _a;
599
668
  file.parse(`
600
669
  sub Main()
601
670
  print LINE_NUM
602
671
  end sub
603
672
  `);
604
- (0, chai_1.expect)((_a = file.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
673
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
605
674
  });
606
675
  it('supports many keywords as object property names', () => {
607
676
  file.parse(`
@@ -667,7 +736,7 @@ describe('BrsFile', () => {
667
736
  person.new = true
668
737
  end sub
669
738
  `);
670
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
739
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
671
740
  });
672
741
  it('does not error on numeric literal type designators', () => {
673
742
  file.parse(`
@@ -675,13 +744,13 @@ describe('BrsFile', () => {
675
744
  print &he2
676
745
  print 1.2E+2
677
746
  print 2!
678
- print 12D-12
747
+ print 12D - 12
679
748
  print 2.3#
680
749
  print &hFEDCBA9876543210&
681
750
  print 9876543210&
682
751
  end sub
683
752
  `);
684
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
753
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
685
754
  });
686
755
  it('does not error when encountering sub with return type', () => {
687
756
  file.parse(`
@@ -689,7 +758,7 @@ describe('BrsFile', () => {
689
758
  return
690
759
  end sub
691
760
  `);
692
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
761
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
693
762
  });
694
763
  it('does not lose function statements when mismatched end sub', () => {
695
764
  file.parse(`
@@ -724,7 +793,7 @@ describe('BrsFile', () => {
724
793
  foo.bar = true and false or 3 > 4
725
794
  end sub
726
795
  `);
727
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
796
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
728
797
  });
729
798
  it('does not error with boolean in RHS of set statement', () => {
730
799
  file.parse(`
@@ -737,57 +806,57 @@ describe('BrsFile', () => {
737
806
  m.isTrue = m.isTrue = m.isTrue
738
807
  end sub
739
808
  `);
740
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
809
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
741
810
  });
742
811
  it('supports variable names ending with type designators', () => {
743
812
  file.parse(`
744
813
  sub main()
745
- name$ = "bob"
746
- age% = 1
747
- height! = 5.5
748
- salary# = 9.87654321
749
- someHex& = 13
814
+ name$ = "bob"
815
+ age% = 1
816
+ height! = 5.5
817
+ salary# = 9.87654321
818
+ someHex& = 13
750
819
  end sub
751
820
  `);
752
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
821
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
753
822
  });
754
823
  it('supports multiple spaces between two-word keywords', () => {
755
824
  file.parse(`
756
825
  sub main()
757
826
  if true then
758
827
  print "true"
759
- else if true then
828
+ else if true then
760
829
  print "also true"
761
830
  end if
762
831
  end sub
763
832
  `);
764
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
833
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
765
834
  });
766
835
  it('does not error with `stop` as object key', () => {
767
836
  file.parse(`
768
837
  function GetObject()
769
838
  obj = {
770
- stop: function() as void
839
+ stop: function () as void
771
840
 
772
- end function
841
+ end function
773
842
  }
774
843
  return obj
775
844
  end function
776
845
  `);
777
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
846
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
778
847
  });
779
848
  it('does not error with `run` as object key', () => {
780
849
  file.parse(`
781
850
  function GetObject()
782
851
  obj = {
783
- run: function() as void
852
+ run: function () as void
784
853
 
785
854
  end function
786
- }
855
+ }
787
856
  return obj
788
857
  end function
789
858
  `);
790
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
859
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
791
860
  });
792
861
  it('supports assignment operators', () => {
793
862
  file.parse(`
@@ -804,28 +873,28 @@ describe('BrsFile', () => {
804
873
  print x
805
874
  end function
806
875
  `);
807
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
876
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
808
877
  });
809
878
  it('supports `then` as object property', () => {
810
879
  file.parse(`
811
880
  function Main()
812
881
  promise = {
813
882
  then: sub()
814
- end sub
883
+ end sub
815
884
  }
816
885
  promise.then()
817
886
  end function
818
887
  `);
819
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
888
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
820
889
  });
821
890
  it('supports function as parameter type', () => {
822
891
  file.parse(`
823
892
  sub Main()
824
- doWork = function(callback as function)
893
+ doWork = function (callback as function)
825
894
  end function
826
895
  end sub
827
896
  `);
828
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
897
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
829
898
  });
830
899
  it('supports increment operator', () => {
831
900
  file.parse(`
@@ -834,8 +903,7 @@ describe('BrsFile', () => {
834
903
  x++
835
904
  end function
836
905
  `);
837
- file.getDiagnostics();
838
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
906
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
839
907
  });
840
908
  it('supports decrement operator', () => {
841
909
  file.parse(`
@@ -844,8 +912,7 @@ describe('BrsFile', () => {
844
912
  x--
845
913
  end function
846
914
  `);
847
- file.getDiagnostics();
848
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
915
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
849
916
  });
850
917
  it('supports writing numbers with decimal but no trailing digit', () => {
851
918
  file.parse(`
@@ -854,7 +921,7 @@ describe('BrsFile', () => {
854
921
  print x
855
922
  end function
856
923
  `);
857
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
924
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
858
925
  });
859
926
  it('supports assignment operators against object properties', () => {
860
927
  file.parse(`
@@ -876,7 +943,7 @@ describe('BrsFile', () => {
876
943
  print m.age
877
944
  end function
878
945
  `);
879
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
946
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
880
947
  });
881
948
  //skipped until `brs` supports this
882
949
  it('supports bitshift assignment operators', () => {
@@ -888,7 +955,7 @@ describe('BrsFile', () => {
888
955
  print x
889
956
  end function
890
957
  `);
891
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
958
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
892
959
  });
893
960
  //skipped until `brs` supports this
894
961
  it('supports bitshift assignment operators on objects', () => {
@@ -900,7 +967,7 @@ describe('BrsFile', () => {
900
967
  print m.x
901
968
  end function
902
969
  `);
903
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
970
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
904
971
  });
905
972
  it('supports leading and trailing periods for numeric literals', () => {
906
973
  file.parse(`
@@ -911,7 +978,7 @@ describe('BrsFile', () => {
911
978
  print pointOne
912
979
  end function
913
980
  `);
914
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
981
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
915
982
  });
916
983
  it('supports bitshift assignment operators on object properties accessed by array syntax', () => {
917
984
  file.parse(`
@@ -922,7 +989,7 @@ describe('BrsFile', () => {
922
989
  print m.x
923
990
  end function
924
991
  `);
925
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
992
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
926
993
  });
927
994
  it('supports weird period AA accessor', () => {
928
995
  file.parse(`
@@ -931,51 +998,55 @@ describe('BrsFile', () => {
931
998
  print m.["_uuid"]
932
999
  end function
933
1000
  `);
934
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
1001
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
935
1002
  });
936
1003
  it('adds error for library statements NOT at top of file', () => {
937
- let file = program.setFile('source/main.bs', `
1004
+ program.setFile('source/file.brs', ``);
1005
+ program.setFile('source/main.bs', `
938
1006
  sub main()
939
1007
  end sub
940
1008
  import "file.brs"
941
- `);
942
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
943
- DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile().message
1009
+ `);
1010
+ program.validate();
1011
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1012
+ DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()
944
1013
  ]);
945
1014
  });
946
1015
  it('supports library imports', () => {
947
- file.parse(`
1016
+ program.setFile('source/main.brs', `
948
1017
  Library "v30/bslCore.brs"
949
1018
  `);
950
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
1019
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
951
1020
  });
952
1021
  it('adds error for library statements NOT at top of file', () => {
953
- let file = program.setFile('source/main.brs', `
1022
+ program.setFile('source/main.brs', `
954
1023
  sub main()
955
1024
  end sub
956
1025
  Library "v30/bslCore.brs"
957
1026
  `);
958
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
959
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
1027
+ program.validate();
1028
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1029
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
960
1030
  ]);
961
1031
  });
962
1032
  it('adds error for library statements inside of function body', () => {
963
- let file = program.setFile('source/main.brs', `
1033
+ program.setFile('source/main.brs', `
964
1034
  sub main()
965
1035
  Library "v30/bslCore.brs"
966
1036
  end sub
967
1037
  `);
968
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
969
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
1038
+ program.validate();
1039
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1040
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
970
1041
  ]);
971
1042
  });
972
1043
  it('supports colons as separators in associative array properties', () => {
973
1044
  file.parse(`
974
1045
  sub Main()
975
- obj = {x:0 : y: 1}
1046
+ obj = { x: 0 : y: 1 }
976
1047
  end sub
977
1048
  `);
978
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
1049
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
979
1050
  });
980
1051
  it('succeeds when finding variables with "sub" in them', () => {
981
1052
  let file = program.setFile('source/main.brs', `
@@ -990,8 +1061,8 @@ describe('BrsFile', () => {
990
1061
  });
991
1062
  it('succeeds when finding variables with the word "function" in them', () => {
992
1063
  file.parse(`
993
- function Test()
994
- typeCheckFunction = RBS_CMN_GetFunction(invalid, methodName)
1064
+ function Test()
1065
+ typeCheckFunction = RBS_CMN_GetFunction(invalid, methodName)
995
1066
  end function
996
1067
  `);
997
1068
  });
@@ -1002,14 +1073,14 @@ describe('BrsFile', () => {
1002
1073
  print "A"
1003
1074
  end function
1004
1075
 
1005
- function DoB()
1006
- print "B"
1007
- end function
1076
+ function DoB()
1077
+ print "B"
1078
+ end function
1008
1079
  `);
1009
1080
  (0, chai_1.expect)(file.callables[0].name).to.equal('DoA');
1010
1081
  (0, chai_1.expect)(file.callables[0].nameRange).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 28));
1011
1082
  (0, chai_1.expect)(file.callables[1].name).to.equal('DoB');
1012
- (0, chai_1.expect)(file.callables[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 26, 5, 29));
1083
+ (0, chai_1.expect)(file.callables[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 25, 5, 28));
1013
1084
  });
1014
1085
  it('throws an error if the file has already been parsed', () => {
1015
1086
  let file = new BrsFile_1.BrsFile('abspath', 'relpath', program);
@@ -1061,10 +1132,8 @@ describe('BrsFile', () => {
1061
1132
  function DoSomething
1062
1133
  end function
1063
1134
  `);
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
- });
1135
+ (0, testHelpers_spec_1.expectHasDiagnostics)(file);
1136
+ (0, chai_1.expect)(file.getDiagnostics()[0].file).to.equal(file);
1068
1137
  (0, chai_1.expect)(file.getDiagnostics()[0].range.start.line).to.equal(1);
1069
1138
  });
1070
1139
  it('supports using the `next` keyword in a for loop', () => {
@@ -1076,7 +1145,7 @@ describe('BrsFile', () => {
1076
1145
  next
1077
1146
  end sub
1078
1147
  `);
1079
- (0, chai_1.expect)(file.getDiagnostics()).to.be.empty;
1148
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1080
1149
  });
1081
1150
  //test is not working yet, but will be enabled when brs supports this syntax
1082
1151
  it('supports assigning functions to objects', () => {
@@ -1089,7 +1158,7 @@ describe('BrsFile', () => {
1089
1158
  end sub
1090
1159
  end function
1091
1160
  `);
1092
- (0, chai_1.expect)(file.getDiagnostics().length).to.equal(0);
1161
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1093
1162
  });
1094
1163
  });
1095
1164
  describe('findCallables', () => {
@@ -1210,7 +1279,6 @@ describe('BrsFile', () => {
1210
1279
  }]);
1211
1280
  });
1212
1281
  it('finds function calls nested inside statements', () => {
1213
- var _a;
1214
1282
  program.setFile(`source/main.brs`, `
1215
1283
  sub main()
1216
1284
  if true then
@@ -1219,7 +1287,9 @@ describe('BrsFile', () => {
1219
1287
  end sub
1220
1288
  `);
1221
1289
  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);
1290
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1291
+ DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction('DoesNotExist', 'source')
1292
+ ]);
1223
1293
  });
1224
1294
  it('finds arguments with variable values', () => {
1225
1295
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1341,13 +1411,13 @@ describe('BrsFile', () => {
1341
1411
  it('finds variable type from other variable', () => {
1342
1412
  file.parse(`
1343
1413
  sub Main()
1344
- name = "bob"
1345
- nameCopy = name
1414
+ name = "bob"
1415
+ nameCopy = name
1346
1416
  end sub
1347
1417
  `);
1348
1418
  (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
1349
- ['name', new StringType_1.StringType(), util_1.default.createRange(2, 19, 2, 23)],
1350
- ['nameCopy', new StringType_1.StringType(), util_1.default.createRange(3, 19, 3, 27)]
1419
+ ['name', new StringType_1.StringType(), util_1.default.createRange(2, 20, 2, 24)],
1420
+ ['nameCopy', new StringType_1.StringType(), util_1.default.createRange(3, 20, 3, 28)]
1351
1421
  ]);
1352
1422
  });
1353
1423
  it('sets proper range for functions', () => {
@@ -1358,7 +1428,6 @@ describe('BrsFile', () => {
1358
1428
  end function
1359
1429
  end sub
1360
1430
  `);
1361
- (0, chai_1.expect)(file.parser.references.functionExpressions).to.be.length(2);
1362
1431
  (0, chai_1.expect)(file.parser.references.functionExpressions.map(x => x.range)).to.eql([
1363
1432
  util_1.default.createRange(1, 16, 5, 23),
1364
1433
  util_1.default.createRange(2, 30, 4, 32)
@@ -1367,10 +1436,10 @@ describe('BrsFile', () => {
1367
1436
  });
1368
1437
  describe('getHover', () => {
1369
1438
  it('works for param types', () => {
1370
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1439
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
1371
1440
  sub DoSomething(name as string)
1372
1441
  name = 1
1373
- sayMyName = function(name as string)
1442
+ sayMyName = function (name as string)
1374
1443
  end function
1375
1444
  end sub
1376
1445
  `);
@@ -1385,19 +1454,19 @@ describe('BrsFile', () => {
1385
1454
  });
1386
1455
  //ignore this for now...it's not a huge deal
1387
1456
  it('does not match on keywords or data types', () => {
1388
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1457
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
1389
1458
  sub Main(name as string)
1390
1459
  end sub
1391
- sub as()
1460
+ sub as ()
1392
1461
  end sub
1393
1462
  `);
1394
- //hover over the `as`
1463
+ //hover over the `as `
1395
1464
  (0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 31))).not.to.exist;
1396
1465
  //hover over the `string`
1397
1466
  (0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 36))).not.to.exist;
1398
1467
  });
1399
1468
  it('finds declared function', () => {
1400
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1469
+ let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
1401
1470
  function Main(count = 1)
1402
1471
  firstName = "bob"
1403
1472
  age = 21
@@ -1407,7 +1476,11 @@ describe('BrsFile', () => {
1407
1476
  let hover = file.getHover(vscode_languageserver_1.Position.create(1, 28));
1408
1477
  (0, chai_1.expect)(hover).to.exist;
1409
1478
  (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');
1479
+ (0, chai_1.expect)(hover.contents).to.equal([
1480
+ '```brightscript',
1481
+ 'function Main(count? as integer) as dynamic',
1482
+ '```'
1483
+ ].join('\n'));
1411
1484
  });
1412
1485
  it('finds variable function hover in same scope', () => {
1413
1486
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -1420,7 +1493,35 @@ describe('BrsFile', () => {
1420
1493
  `);
1421
1494
  let hover = file.getHover(vscode_languageserver_1.Position.create(5, 24));
1422
1495
  (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');
1496
+ (0, chai_1.expect)(hover.contents).to.equal([
1497
+ '```brightscript',
1498
+ 'sub (name as string) as void',
1499
+ '```'
1500
+ ].join('\n'));
1501
+ });
1502
+ it('does not crash when hovering on built-in functions', async () => {
1503
+ let file = program.setFile('source/main.brs', `
1504
+ function doUcase(text)
1505
+ return ucase(text)
1506
+ end function
1507
+ `);
1508
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 30))).contents).to.equal([
1509
+ '```brightscript',
1510
+ 'function UCase(s as string) as string',
1511
+ '```'
1512
+ ].join('\n'));
1513
+ });
1514
+ it('does not crash when hovering on object method call', async () => {
1515
+ let file = program.setFile('source/main.brs', `
1516
+ function getInstr(url, text)
1517
+ return url.instr(text)
1518
+ end function
1519
+ `);
1520
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 35))).contents).to.equal([
1521
+ '```brightscript',
1522
+ 'instr as dynamic',
1523
+ '```'
1524
+ ].join('\n'));
1424
1525
  });
1425
1526
  it('finds function hover in file scope', () => {
1426
1527
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -1434,7 +1535,11 @@ describe('BrsFile', () => {
1434
1535
  `);
1435
1536
  let hover = file.getHover(vscode_languageserver_1.Position.create(2, 25));
1436
1537
  (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');
1538
+ (0, chai_1.expect)(hover.contents).to.equal([
1539
+ '```brightscript',
1540
+ 'sub sayMyName() as void',
1541
+ '```'
1542
+ ].join('\n'));
1438
1543
  });
1439
1544
  it('finds function hover in scope', () => {
1440
1545
  let rootDir = process.cwd();
@@ -1454,7 +1559,53 @@ describe('BrsFile', () => {
1454
1559
  let hover = mainFile.getHover(vscode_languageserver_1.Position.create(2, 25));
1455
1560
  (0, chai_1.expect)(hover).to.exist;
1456
1561
  (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');
1562
+ (0, chai_1.expect)(hover.contents).to.equal([
1563
+ '```brightscript',
1564
+ 'sub sayMyName(name as string) as void',
1565
+ '```'
1566
+ ].join('\n'));
1567
+ });
1568
+ it('includes markdown comments in hover.', async () => {
1569
+ let rootDir = process.cwd();
1570
+ program = new Program_1.Program({
1571
+ rootDir: rootDir
1572
+ });
1573
+ const file = program.setFile('source/lib.brs', `
1574
+ '
1575
+ ' The main function
1576
+ '
1577
+ sub main()
1578
+ log("hello")
1579
+ end sub
1580
+
1581
+ '
1582
+ ' Prints a message to the log.
1583
+ ' Works with *markdown* **content**
1584
+ '
1585
+ sub log(message as string)
1586
+ print message
1587
+ end sub
1588
+ `);
1589
+ //hover over log("hello")
1590
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(5, 22))).contents).to.equal([
1591
+ '```brightscript',
1592
+ 'sub log(message as string) as void',
1593
+ '```',
1594
+ '***',
1595
+ '',
1596
+ ' Prints a message to the log.',
1597
+ ' Works with *markdown* **content**',
1598
+ ''
1599
+ ].join('\n'));
1600
+ //hover over sub ma|in()
1601
+ (0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(4, 22))).contents).to.equal((0, testHelpers_spec_1.trim) `
1602
+ \`\`\`brightscript
1603
+ sub main() as void
1604
+ \`\`\`
1605
+ ***
1606
+
1607
+ The main function
1608
+ `);
1458
1609
  });
1459
1610
  it('handles mixed case `then` partions of conditionals', () => {
1460
1611
  let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -1464,7 +1615,7 @@ describe('BrsFile', () => {
1464
1615
  end if
1465
1616
  end sub
1466
1617
  `);
1467
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1618
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1468
1619
  mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1469
1620
  sub Main()
1470
1621
  if true Then
@@ -1472,7 +1623,7 @@ describe('BrsFile', () => {
1472
1623
  end if
1473
1624
  end sub
1474
1625
  `);
1475
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1626
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1476
1627
  mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1477
1628
  sub Main()
1478
1629
  if true THEN
@@ -1480,7 +1631,7 @@ describe('BrsFile', () => {
1480
1631
  end if
1481
1632
  end sub
1482
1633
  `);
1483
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1634
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1484
1635
  });
1485
1636
  it('displays the context from multiple scopes', () => {
1486
1637
  let commonFile = program.setFile('source/common.brs', `
@@ -1517,11 +1668,61 @@ describe('BrsFile', () => {
1517
1668
  `);
1518
1669
  program.validate();
1519
1670
  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');
1671
+ (0, chai_1.expect)(funcCallHover === null || funcCallHover === void 0 ? void 0 : funcCallHover.contents).to.equal([
1672
+ '```brightscript',
1673
+ 'function getPi() as string | function getPi() as float | getPi as uninitialized',
1674
+ '```'
1675
+ ].join('\n'));
1522
1676
  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');
1677
+ (0, chai_1.expect)(variableHover === null || variableHover === void 0 ? void 0 : variableHover.contents).to.equal([
1678
+ '```brightscript',
1679
+ 'pi as string | pi as float | pi as uninitialized',
1680
+ '```'
1681
+ ].join('\n'));
1682
+ });
1683
+ it('finds function with custom types as parameters and return types', () => {
1684
+ let file = program.setFile('source/main.bs', `
1685
+ sub main()
1686
+ k = new MyKlass()
1687
+ processMyKlass(k)
1688
+ end sub
1689
+
1690
+ function processMyKlass(data as MyKlass) as MyKlass
1691
+ return data
1692
+ end function
1693
+
1694
+ class MyKlass
1695
+ end class
1696
+ `);
1697
+ let hover = file.getHover(vscode_languageserver_1.Position.create(3, 29));
1698
+ (0, chai_1.expect)(hover).to.exist;
1699
+ (0, chai_1.expect)(hover.contents).to.equal([
1700
+ '```brightscript',
1701
+ 'function processMyKlass(data as MyKlass) as MyKlass',
1702
+ '```'
1703
+ ].join('\n'));
1704
+ });
1705
+ it('finds function with arrays as parameters and return types', () => {
1706
+ let file = program.setFile('source/main.bs', `
1707
+ sub main()
1708
+ k = new MyKlass()
1709
+ processData([k])
1710
+ end sub
1711
+
1712
+ function processData(data as MyKlass[]) as MyKlass[]
1713
+ return data
1714
+ end function
1715
+
1716
+ class MyKlass
1717
+ end class
1718
+ `);
1719
+ let hover = file.getHover(vscode_languageserver_1.Position.create(3, 29));
1720
+ (0, chai_1.expect)(hover).to.exist;
1721
+ (0, chai_1.expect)(hover.contents).to.equal([
1722
+ '```brightscript',
1723
+ 'function processData(data as MyKlass[]) as MyKlass[]',
1724
+ '```'
1725
+ ].join('\n'));
1525
1726
  });
1526
1727
  });
1527
1728
  it('does not throw when encountering incomplete import statement', () => {
@@ -1830,9 +2031,9 @@ describe('BrsFile', () => {
1830
2031
  });
1831
2032
  it('computes correct locations for sourcemap', async () => {
1832
2033
  let source = `function abc(name)\n firstName = name\nend function`;
1833
- let tokens = lexer_1.Lexer.scan(source).tokens
2034
+ let tokens = Lexer_1.Lexer.scan(source).tokens
1834
2035
  //remove newlines and EOF
1835
- .filter(x => x.kind !== lexer_1.TokenKind.Eof && x.kind !== lexer_1.TokenKind.Newline);
2036
+ .filter(x => x.kind !== TokenKind_1.TokenKind.Eof && x.kind !== TokenKind_1.TokenKind.Newline);
1836
2037
  program.options.sourceMap = true;
1837
2038
  let result = testTranspile(source, source, 'none');
1838
2039
  //load the source map
@@ -2090,14 +2291,13 @@ describe('BrsFile', () => {
2090
2291
  describe('callfunc operator', () => {
2091
2292
  describe('transpile', () => {
2092
2293
  it('does not produce diagnostics', () => {
2093
- var _a;
2094
2294
  program.setFile('source/main.bs', `
2095
2295
  sub main()
2096
2296
  someObject@.someFunction(paramObject.value)
2097
2297
  end sub
2098
2298
  `);
2099
2299
  program.validate();
2100
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
2300
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2101
2301
  });
2102
2302
  it('sets invalid on empty callfunc', () => {
2103
2303
  testTranspile(`
@@ -2137,7 +2337,7 @@ describe('BrsFile', () => {
2137
2337
  name: 'transform callback',
2138
2338
  afterFileParse: onParsed
2139
2339
  });
2140
- file = program.setFile(`source/file.${ext}`, `
2340
+ file = program.setFile({ src: `absolute_path/file${ext}`, dest: `relative_path/file${ext}` }, `
2141
2341
  sub Sum()
2142
2342
  print "hello world"
2143
2343
  end sub
@@ -2510,11 +2710,11 @@ describe('BrsFile', () => {
2510
2710
  (0, chai_1.expect)(file.parser).to.equal(newParser);
2511
2711
  });
2512
2712
  it('call parse when previously skipped', () => {
2513
- program.setFile('source/main.d.bs', `
2713
+ program.setFile('source/main.d.bs', `'typedef
2514
2714
  sub main()
2515
2715
  end sub
2516
2716
  `);
2517
- const file = program.setFile('source/main.brs', `
2717
+ const file = program.setFile('source/main.brs', `'source
2518
2718
  sub main()
2519
2719
  end sub
2520
2720
  `);
@@ -2571,5 +2771,207 @@ describe('BrsFile', () => {
2571
2771
  testPluginTranspile();
2572
2772
  });
2573
2773
  });
2774
+ describe('getSymbolTypeFromToken', () => {
2775
+ function checkSymbolLookups(file, funcExpr, lookups) {
2776
+ const mainScope = program.getScopesForFile(file)[0];
2777
+ mainScope.linkSymbolTable();
2778
+ for (const lookup of lookups) {
2779
+ const position = vscode_languageserver_1.Position.create(lookup.line, lookup.col);
2780
+ const token = file.parser.getTokenAt(position);
2781
+ const symbol = file.getSymbolTypeFromToken(token, funcExpr, mainScope);
2782
+ const context = {
2783
+ file: file,
2784
+ scope: mainScope,
2785
+ position: position
2786
+ };
2787
+ (0, chai_1.expect)(symbol.expandedTokenText).to.equal(lookup.name);
2788
+ (0, chai_1.expect)(symbol.type.equals(lookup.type, context)).be.true;
2789
+ }
2790
+ }
2791
+ it('gets simple types based on the containing function expression', () => {
2792
+ const file = program.setFile('source/main.bs', `
2793
+ sub doSomething(aInt as integer, aFloat as float, aStr as string, aBool as boolean, aObj as object)
2794
+ print aInt
2795
+ print aFloat
2796
+ print aStr
2797
+ print aBool
2798
+ print aObj
2799
+ end sub
2800
+ `);
2801
+ const funcExpr = file.parser.references.functionExpressions[0];
2802
+ const lookups = [
2803
+ { line: 2, col: 28, name: 'aInt', type: new IntegerType_1.IntegerType() },
2804
+ { line: 3, col: 28, name: 'aFloat', type: new FloatType_1.FloatType() },
2805
+ { line: 4, col: 28, name: 'aStr', type: new StringType_1.StringType() },
2806
+ { line: 5, col: 28, name: 'aBool', type: new BooleanType_1.BooleanType() },
2807
+ { line: 6, col: 28, name: 'aObj', type: new ObjectType_1.ObjectType() }
2808
+ ];
2809
+ checkSymbolLookups(file, funcExpr, lookups);
2810
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2811
+ });
2812
+ it('gets custom types based on the containing function expression', () => {
2813
+ const file = program.setFile('source/main.bs', `
2814
+ sub doSomething(klass as MyKlass)
2815
+ print klass
2816
+ end sub
2817
+
2818
+ class MyKlass
2819
+ end class
2820
+ `);
2821
+ const mainScope = program.getScopesForFile(file)[0];
2822
+ mainScope.linkSymbolTable();
2823
+ const funcExpr = file.parser.references.functionExpressions[0];
2824
+ const token = file.parser.getTokenAt(vscode_languageserver_1.Position.create(2, 28));
2825
+ const symbol = file.getSymbolTypeFromToken(token, funcExpr, mainScope);
2826
+ (0, chai_1.expect)(symbol.expandedTokenText).to.equal('klass');
2827
+ const classStmt = file.parser.references.classStatements[0];
2828
+ (0, chai_1.expect)(classStmt.name.text).to.equal('MyKlass');
2829
+ (0, chai_1.expect)(symbol.type.isAssignableTo(classStmt.getCustomType())).be.true;
2830
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2831
+ });
2832
+ it('gets types of properties of a klass', () => {
2833
+ const file = program.setFile('source/main.bs', `
2834
+ sub doSomething()
2835
+ klass = new MyKlass()
2836
+ print klass.name
2837
+ print klass.age
2838
+ ' verify case insensitivity
2839
+ print KLASS.NAME
2840
+ print klass.AGE
2841
+ end sub
2842
+
2843
+ class MyKlass
2844
+ name as string
2845
+ age as integer
2846
+ end class
2847
+ `);
2848
+ const funcExpr = file.parser.references.functionExpressions[0];
2849
+ const lookups = [
2850
+ { line: 3, col: 35, name: 'MyKlass.name', type: new StringType_1.StringType() },
2851
+ { line: 4, col: 35, name: 'MyKlass.age', type: new IntegerType_1.IntegerType() }
2852
+ ];
2853
+ checkSymbolLookups(file, funcExpr, lookups);
2854
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2855
+ });
2856
+ it('gets types of properties of an object', () => {
2857
+ const file = program.setFile('source/main.bs', `
2858
+ sub doSomething()
2859
+ obj = { name: "Joe", age: 37}
2860
+ print obj.name
2861
+ print obj.age
2862
+ end sub
2863
+ `);
2864
+ const funcExpr = file.parser.references.functionExpressions[0];
2865
+ const lookups = [
2866
+ { line: 3, col: 32, name: 'obj.name', type: new StringType_1.StringType() },
2867
+ { line: 4, col: 32, name: 'obj.age', type: new IntegerType_1.IntegerType() }
2868
+ ];
2869
+ checkSymbolLookups(file, funcExpr, lookups);
2870
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2871
+ });
2872
+ it('gets return types of functions', () => {
2873
+ const file = program.setFile('source/main.bs', `
2874
+ sub doSomething()
2875
+ pi = makeKlass().getSelf().getPi()
2876
+ print pi
2877
+ end sub
2878
+
2879
+ function makeKlass() as MyKlass
2880
+ return new MyKlass()
2881
+ end function
2882
+
2883
+ class MyKlass
2884
+ function getPi() as float
2885
+ return 3.14
2886
+ end function
2887
+
2888
+ function getSelf() as MyKlass
2889
+ return m
2890
+ end function
2891
+ end class
2892
+ `);
2893
+ const mainScope = program.getScopesForFile(file)[0];
2894
+ mainScope.linkSymbolTable();
2895
+ const funcExpr = file.parser.references.functionExpressions[0];
2896
+ const klassMemberTable = file.parser.references.classStatements[0].memberTable;
2897
+ const lookups = [
2898
+ { line: 2, col: 31, name: 'makeKlass', type: file.parser.references.functionExpressions[1].getFunctionType() },
2899
+ // The expanded text for this should probably be MyKlass.getSelf()
2900
+ { line: 2, col: 41, name: 'MyKlass.MyKlass', type: klassMemberTable.getSymbol('getSelf')[0].type },
2901
+ { line: 2, col: 51, name: 'MyKlass.getPi', type: klassMemberTable.getSymbol('getPi')[0].type },
2902
+ { line: 3, col: 28, name: 'pi', type: new FloatType_1.FloatType() }
2903
+ ];
2904
+ checkSymbolLookups(file, funcExpr, lookups);
2905
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2906
+ });
2907
+ it('gets types of elements of arrays', () => {
2908
+ const file = program.setFile('source/main.bs', `
2909
+ sub doSomething(words as string[], klasses as MyKlass[])
2910
+ myWord = words[0]
2911
+ pi = klasses[0].getPi()
2912
+ print myWord
2913
+ print pi
2914
+ end sub
2915
+
2916
+ class MyKlass
2917
+ function getPi() as float
2918
+ return 3.14
2919
+ end function
2920
+ end class
2921
+ `);
2922
+ const mainScope = program.getScopesForFile(file)[0];
2923
+ mainScope.linkSymbolTable();
2924
+ const funcExpr = file.parser.references.functionExpressions[0];
2925
+ const klassMemberTable = file.parser.references.classStatements[0].memberTable;
2926
+ const lookups = [
2927
+ { line: 2, col: 34, name: 'words', type: new ArrayType_1.ArrayType(new StringType_1.StringType()) },
2928
+ { line: 3, col: 41, name: 'MyKlass.getPi', type: klassMemberTable.getSymbol('getPi')[0].type },
2929
+ { line: 4, col: 28, name: 'myWord', type: new StringType_1.StringType() },
2930
+ { line: 5, col: 28, name: 'pi', type: new FloatType_1.FloatType() }
2931
+ ];
2932
+ checkSymbolLookups(file, funcExpr, lookups);
2933
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2934
+ });
2935
+ it('gets types of elements of arrays via square bracket reference', () => {
2936
+ const file = program.setFile('source/main.bs', `
2937
+ function printFirst(numbers as float[]) as float
2938
+ firstFloat = numbers[0]
2939
+ print firstFloat
2940
+ return firstFloat
2941
+ end function
2942
+ `);
2943
+ const mainScope = program.getScopesForFile(file)[0];
2944
+ mainScope.linkSymbolTable();
2945
+ const funcExpr = file.parser.references.functionExpressions[0];
2946
+ const lookups = [
2947
+ { line: 2, col: 26, name: 'firstFloat', type: new FloatType_1.FloatType() },
2948
+ { line: 3, col: 32, name: 'firstFloat', type: new FloatType_1.FloatType() }
2949
+ ];
2950
+ checkSymbolLookups(file, funcExpr, lookups);
2951
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2952
+ });
2953
+ it('gets types of elements of arrays after for each', () => {
2954
+ const file = program.setFile('source/main.bs', `
2955
+ function printAllReturnFirst(numbers as float[]) as float
2956
+ for each num in numbers
2957
+ print num
2958
+ end for
2959
+
2960
+ firstFloat = numbers[0]
2961
+ print firstFloat
2962
+ return firstFloat
2963
+ end function
2964
+ `);
2965
+ const mainScope = program.getScopesForFile(file)[0];
2966
+ mainScope.linkSymbolTable();
2967
+ const funcExpr = file.parser.references.functionExpressions[0];
2968
+ const lookups = [
2969
+ { line: 6, col: 26, name: 'firstFloat', type: new FloatType_1.FloatType() },
2970
+ { line: 7, col: 32, name: 'firstFloat', type: new FloatType_1.FloatType() }
2971
+ ];
2972
+ checkSymbolLookups(file, funcExpr, lookups);
2973
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2974
+ });
2975
+ });
2574
2976
  });
2575
2977
  //# sourceMappingURL=BrsFile.spec.js.map