brighterscript 1.0.0-alpha.11 → 1.0.0-alpha.15

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 (228) hide show
  1. package/CHANGELOG.md +253 -268
  2. package/README.md +2 -2
  3. package/dist/Cache.d.ts +3 -8
  4. package/dist/Cache.js +9 -14
  5. package/dist/Cache.js.map +1 -1
  6. package/dist/CommentFlagProcessor.js +5 -3
  7. package/dist/CommentFlagProcessor.js.map +1 -1
  8. package/dist/DiagnosticMessages.d.ts +21 -1
  9. package/dist/DiagnosticMessages.js +21 -1
  10. package/dist/DiagnosticMessages.js.map +1 -1
  11. package/dist/LanguageServer.d.ts +1 -6
  12. package/dist/LanguageServer.js +0 -9
  13. package/dist/LanguageServer.js.map +1 -1
  14. package/dist/PluginInterface.d.ts +3 -3
  15. package/dist/PluginInterface.js +3 -0
  16. package/dist/PluginInterface.js.map +1 -1
  17. package/dist/Program.d.ts +30 -16
  18. package/dist/Program.js +110 -45
  19. package/dist/Program.js.map +1 -1
  20. package/dist/ProgramBuilder.js +3 -3
  21. package/dist/ProgramBuilder.js.map +1 -1
  22. package/dist/Scope.d.ts +31 -17
  23. package/dist/Scope.js +86 -48
  24. package/dist/Scope.js.map +1 -1
  25. package/dist/SymbolTable.d.ts +1 -1
  26. package/dist/XmlScope.d.ts +3 -3
  27. package/dist/astUtils/AstEditor.d.ts +33 -0
  28. package/dist/astUtils/AstEditor.js +107 -0
  29. package/dist/astUtils/AstEditor.js.map +1 -0
  30. package/dist/{bscPlugin/semanticTokens/SemanticTokensProcessor.spec.d.ts → astUtils/AstEditor.spec.d.ts} +0 -0
  31. package/dist/astUtils/AstEditor.spec.js +170 -0
  32. package/dist/astUtils/AstEditor.spec.js.map +1 -0
  33. package/dist/astUtils/reflection.d.ts +3 -1
  34. package/dist/astUtils/reflection.js +10 -2
  35. package/dist/astUtils/reflection.js.map +1 -1
  36. package/dist/astUtils/reflection.spec.js +6 -6
  37. package/dist/astUtils/reflection.spec.js.map +1 -1
  38. package/dist/astUtils/visitors.d.ts +3 -1
  39. package/dist/astUtils/visitors.js.map +1 -1
  40. package/dist/astUtils/visitors.spec.js +8 -8
  41. package/dist/astUtils/visitors.spec.js.map +1 -1
  42. package/dist/astUtils/xml.d.ts +1 -0
  43. package/dist/astUtils/xml.js +6 -1
  44. package/dist/astUtils/xml.js.map +1 -1
  45. package/dist/bscPlugin/BscPlugin.d.ts +4 -1
  46. package/dist/bscPlugin/BscPlugin.js +21 -2
  47. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  48. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
  49. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  50. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  51. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
  52. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
  53. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  54. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
  55. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +30 -2
  56. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  57. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
  58. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +36 -0
  59. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
  60. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
  61. package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
  62. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  63. package/dist/bscPlugin/validation/ScopeValidator.d.ts +11 -0
  64. package/dist/bscPlugin/validation/ScopeValidator.js +94 -0
  65. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  66. package/dist/files/BrsFile.Class.spec.js +404 -230
  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 +265 -127
  70. package/dist/files/BrsFile.js.map +1 -1
  71. package/dist/files/BrsFile.spec.js +586 -169
  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 +13 -8
  75. package/dist/files/XmlFile.js.map +1 -1
  76. package/dist/files/XmlFile.spec.js +106 -59
  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/globalCallables.d.ts +3 -1
  81. package/dist/globalCallables.js +198 -99
  82. package/dist/globalCallables.js.map +1 -1
  83. package/dist/index.d.ts +12 -3
  84. package/dist/index.js +21 -4
  85. package/dist/index.js.map +1 -1
  86. package/dist/interfaces.d.ts +68 -15
  87. package/dist/lexer/Lexer.js +1 -2
  88. package/dist/lexer/Lexer.js.map +1 -1
  89. package/dist/lexer/Lexer.spec.js +470 -462
  90. package/dist/lexer/Lexer.spec.js.map +1 -1
  91. package/dist/lexer/TokenKind.d.ts +2 -0
  92. package/dist/lexer/TokenKind.js +5 -0
  93. package/dist/lexer/TokenKind.js.map +1 -1
  94. package/dist/parser/Expression.d.ts +1 -1
  95. package/dist/parser/Expression.js +10 -10
  96. package/dist/parser/Expression.js.map +1 -1
  97. package/dist/parser/Parser.Class.spec.js +33 -32
  98. package/dist/parser/Parser.Class.spec.js.map +1 -1
  99. package/dist/parser/Parser.d.ts +28 -7
  100. package/dist/parser/Parser.js +494 -290
  101. package/dist/parser/Parser.js.map +1 -1
  102. package/dist/parser/Parser.spec.js +157 -35
  103. package/dist/parser/Parser.spec.js.map +1 -1
  104. package/dist/parser/SGParser.js +1 -1
  105. package/dist/parser/SGParser.js.map +1 -1
  106. package/dist/parser/SGTypes.d.ts +3 -0
  107. package/dist/parser/SGTypes.js +8 -3
  108. package/dist/parser/SGTypes.js.map +1 -1
  109. package/dist/parser/SGTypes.spec.js +9 -9
  110. package/dist/parser/SGTypes.spec.js.map +1 -1
  111. package/dist/parser/Statement.d.ts +55 -3
  112. package/dist/parser/Statement.js +162 -9
  113. package/dist/parser/Statement.js.map +1 -1
  114. package/dist/parser/tests/Parser.spec.d.ts +3 -3
  115. package/dist/parser/tests/Parser.spec.js +4 -4
  116. package/dist/parser/tests/Parser.spec.js.map +1 -1
  117. package/dist/parser/tests/controlFlow/For.spec.js +40 -40
  118. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  119. package/dist/parser/tests/controlFlow/ForEach.spec.js +22 -21
  120. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  121. package/dist/parser/tests/controlFlow/If.spec.js +100 -99
  122. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  123. package/dist/parser/tests/controlFlow/While.spec.js +25 -25
  124. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  125. package/dist/parser/tests/expression/Additive.spec.js +21 -21
  126. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  127. package/dist/parser/tests/expression/ArrayLiterals.spec.js +91 -91
  128. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  129. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +102 -102
  130. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  131. package/dist/parser/tests/expression/Boolean.spec.js +15 -15
  132. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  133. package/dist/parser/tests/expression/Call.spec.js +22 -21
  134. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  135. package/dist/parser/tests/expression/Exponential.spec.js +11 -11
  136. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  137. package/dist/parser/tests/expression/Function.spec.js +171 -171
  138. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  139. package/dist/parser/tests/expression/Indexing.spec.js +50 -50
  140. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  141. package/dist/parser/tests/expression/Multiplicative.spec.js +25 -25
  142. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  143. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +30 -18
  144. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  145. package/dist/parser/tests/expression/PrefixUnary.spec.js +26 -26
  146. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  147. package/dist/parser/tests/expression/Primary.spec.js +27 -27
  148. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  149. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +3 -2
  150. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  151. package/dist/parser/tests/expression/Relational.spec.js +25 -25
  152. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  153. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +7 -7
  154. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  155. package/dist/parser/tests/expression/TernaryExpression.spec.js +6 -6
  156. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  157. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  158. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  159. package/dist/parser/tests/statement/Declaration.spec.js +20 -20
  160. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  161. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  162. package/dist/parser/tests/statement/Enum.spec.js +774 -0
  163. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  164. package/dist/parser/tests/statement/Function.spec.js +121 -120
  165. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  166. package/dist/parser/tests/statement/Goto.spec.js +9 -8
  167. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  168. package/dist/parser/tests/statement/Increment.spec.js +22 -22
  169. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  170. package/dist/parser/tests/statement/InterfaceStatement.spec.js +12 -0
  171. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  172. package/dist/parser/tests/statement/LibraryStatement.spec.js +7 -7
  173. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  174. package/dist/parser/tests/statement/Misc.spec.js +71 -70
  175. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  176. package/dist/parser/tests/statement/PrintStatement.spec.js +17 -17
  177. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  178. package/dist/parser/tests/statement/ReturnStatement.spec.js +33 -33
  179. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  180. package/dist/parser/tests/statement/Set.spec.js +53 -53
  181. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  182. package/dist/parser/tests/statement/Stop.spec.js +7 -6
  183. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  184. package/dist/preprocessor/Chunk.d.ts +1 -1
  185. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  186. package/dist/preprocessor/Preprocessor.js +7 -7
  187. package/dist/preprocessor/Preprocessor.js.map +1 -1
  188. package/dist/types/ArrayType.d.ts +8 -5
  189. package/dist/types/ArrayType.js +45 -9
  190. package/dist/types/ArrayType.js.map +1 -1
  191. package/dist/types/ArrayType.spec.js +62 -3
  192. package/dist/types/ArrayType.spec.js.map +1 -1
  193. package/dist/types/BscType.d.ts +1 -1
  194. package/dist/types/CustomType.d.ts +1 -1
  195. package/dist/types/CustomType.js +4 -2
  196. package/dist/types/CustomType.js.map +1 -1
  197. package/dist/types/FunctionType.d.ts +5 -5
  198. package/dist/types/FunctionType.js +11 -11
  199. package/dist/types/FunctionType.js.map +1 -1
  200. package/dist/types/FunctionType.spec.js +1 -1
  201. package/dist/types/FunctionType.spec.js.map +1 -1
  202. package/dist/types/LazyType.d.ts +1 -2
  203. package/dist/types/LazyType.js +1 -5
  204. package/dist/types/LazyType.js.map +1 -1
  205. package/dist/types/helpers.js +1 -1
  206. package/dist/types/helpers.js.map +1 -1
  207. package/dist/util.d.ts +25 -9
  208. package/dist/util.js +139 -55
  209. package/dist/util.js.map +1 -1
  210. package/dist/validators/ClassValidator.js +27 -27
  211. package/dist/validators/ClassValidator.js.map +1 -1
  212. package/package.json +4 -3
  213. package/dist/astUtils/index.d.ts +0 -7
  214. package/dist/astUtils/index.js +0 -26
  215. package/dist/astUtils/index.js.map +0 -1
  216. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  217. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
  218. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  219. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  220. package/dist/lexer/index.d.ts +0 -3
  221. package/dist/lexer/index.js +0 -18
  222. package/dist/lexer/index.js.map +0 -1
  223. package/dist/parser/index.d.ts +0 -3
  224. package/dist/parser/index.js +0 -16
  225. package/dist/parser/index.js.map +0 -1
  226. package/dist/preprocessor/index.d.ts +0 -3
  227. package/dist/preprocessor/index.js +0 -16
  228. 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,38 +416,47 @@ 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
- it('ignores non-numeric codes', () => {
355
- var _a;
356
- let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
421
+ it('recognizes non-numeric codes', () => {
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
- `);
362
- (0, chai_1.expect)(file.commentFlags[0]).to.not.exist;
363
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
427
+ `);
428
+ (0, chai_1.expect)(file.commentFlags[0]).to.exist;
429
+ (0, testHelpers_spec_1.expectHasDiagnostics)(program);
430
+ });
431
+ it('supports disabling non-numeric error codes', () => {
432
+ const program = new Program_1.Program({});
433
+ const file = program.setFile('source/main.brs', `
434
+ sub main()
435
+ something = true 'bs:disable-line: LINT1005
436
+ end sub
437
+ `);
438
+ file.addDiagnostics([{
439
+ code: 'LINT1005',
440
+ file: file,
441
+ message: 'Something is not right',
442
+ range: util_1.default.createRange(2, 16, 2, 26)
443
+ }]);
444
+ const scope = program.getScopesForFile(file)[0];
445
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(scope);
364
446
  });
365
447
  it('adds diagnostics for unknown numeric diagnostic codes', () => {
366
- program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
448
+ program.setFile({ src: `${rootDir} / source / main.brs`, dest: 'source/main.brs' }, `
367
449
  sub main()
368
450
  print "hi" 'bs:disable-line: 123456 999999 aaaab
369
451
  end sub
370
- `);
452
+ `);
371
453
  program.validate();
372
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(2);
373
- (0, chai_1.expect)(program.getDiagnostics()[0]).to.deep.include({
374
- range: vscode_languageserver_1.Range.create(2, 53, 2, 59)
375
- });
376
- (0, chai_1.expect)(program.getDiagnostics()[1]).to.deep.include({
377
- range: vscode_languageserver_1.Range.create(2, 60, 2, 66)
378
- });
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) })]);
379
455
  });
380
456
  });
381
457
  describe('bs:disable-line', () => {
382
458
  it('works for all', () => {
383
- 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' }, `
384
460
  sub Main()
385
461
  z::;;%%%%%% 'bs:disable-line
386
462
  end sub
@@ -393,10 +469,10 @@ describe('BrsFile', () => {
393
469
  });
394
470
  program.validate();
395
471
  //the "unterminated string" error should be filtered out
396
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(0);
472
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
397
473
  });
398
474
  it('works for specific codes', () => {
399
- program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
475
+ program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
400
476
  sub main()
401
477
  'should not have any errors
402
478
  DoSomething(1) 'bs:disable-line:1002
@@ -407,23 +483,22 @@ describe('BrsFile', () => {
407
483
  end sub
408
484
  `);
409
485
  program.validate();
410
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(1);
411
- (0, chai_1.expect)(program.getDiagnostics()[0]).to.deep.include({
412
- range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
413
- });
486
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [{
487
+ range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
488
+ }]);
414
489
  });
415
490
  it('handles the erraneous `stop` keyword', () => {
416
491
  //the current version of BRS causes parse errors after the `parse` keyword, showing error in comments
417
492
  //the program should ignore all diagnostics found in brs:* comment lines EXCEPT
418
493
  //for the diagnostics about using unknown error codes
419
- program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
494
+ program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
420
495
  sub main()
421
496
  stop 'bs:disable-line
422
497
  print "need a valid line to fix stop error"
423
498
  end sub
424
- `);
499
+ `);
425
500
  program.validate();
426
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(0);
501
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
427
502
  });
428
503
  });
429
504
  });
@@ -431,9 +506,9 @@ describe('BrsFile', () => {
431
506
  it('supports iife in assignment', () => {
432
507
  program.setFile('source/main.brs', `
433
508
  sub main()
434
- result = sub()
509
+ result = sub()
435
510
  end sub()
436
- result = (sub()
511
+ result = (sub()
437
512
  end sub)()
438
513
  end sub
439
514
  `);
@@ -452,26 +527,26 @@ describe('BrsFile', () => {
452
527
  testParseMode('source/main.spec.bs', Parser_1.ParseMode.BrighterScript);
453
528
  });
454
529
  it('supports labels and goto statements', () => {
455
- 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' }, `
456
531
  sub Main()
457
532
  'multiple goto statements on one line
458
- goto myLabel : goto myLabel
533
+ goto myLabel: goto myLabel
459
534
  myLabel:
460
535
  end sub
461
536
  `);
462
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
537
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
463
538
  });
464
539
  it('supports empty print statements', () => {
465
- 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' }, `
466
541
  sub main()
467
- print
542
+ print
468
543
  end sub
469
544
  `);
470
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
545
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
471
546
  });
472
547
  describe('conditional compile', () => {
473
548
  it('works for upper case keywords', () => {
474
- 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' }, `
475
550
  sub main()
476
551
  #CONST someFlag = true
477
552
  #IF someFlag
@@ -483,10 +558,10 @@ describe('BrsFile', () => {
483
558
  #ENDIF
484
559
  end sub
485
560
  `);
486
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
561
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
487
562
  });
488
563
  it('supports single-word #elseif and #endif', () => {
489
- 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' }, `
490
565
  sub main()
491
566
  #const someFlag = true
492
567
  #if someFlag
@@ -496,10 +571,10 @@ describe('BrsFile', () => {
496
571
  #endif
497
572
  end sub
498
573
  `);
499
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
574
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
500
575
  });
501
576
  it('supports multi-word #else if and #end if', () => {
502
- 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' }, `
503
578
  sub main()
504
579
  #const someFlag = true
505
580
  #if someFlag
@@ -509,84 +584,93 @@ describe('BrsFile', () => {
509
584
  #end if
510
585
  end sub
511
586
  `);
512
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
587
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
513
588
  });
514
589
  it('does not choke on invalid code inside a false conditional compile', () => {
515
- 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' }, `
516
591
  sub main()
517
592
  #if false
518
- non-commented code here should not cause parse errors
593
+ non - commented code here should not cause parse errors
519
594
  #end if
520
595
  end sub
521
596
  `);
522
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
597
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
523
598
  });
524
599
  it('detects syntax error in #if', () => {
525
- 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' }, `
526
601
  sub main()
527
602
  #if true1
528
603
  print "true"
529
604
  #end if
530
605
  end sub
531
606
  `);
532
- (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
+ ]);
533
610
  });
534
611
  it('detects syntax error in #const', () => {
535
- 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' }, `
536
613
  sub main()
537
614
  #if %
538
615
  print "true"
539
616
  #end if
540
617
  end sub
541
618
  `);
542
- (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
+ ]);
543
623
  });
544
624
  it('detects #const name using reserved word', () => {
545
- 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' }, `
546
626
  sub main()
547
627
  #const function = true
548
628
  end sub
549
629
  `);
550
- (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
+ ]);
551
634
  });
552
635
  it('detects syntax error in #const', () => {
553
- 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' }, `
554
637
  sub main()
555
638
  #const someConst = 123
556
639
  end sub
557
640
  `);
558
- (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
+ ]);
559
644
  });
560
645
  });
561
646
  it('supports stop statement', () => {
562
- 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' }, `
563
648
  sub main()
564
- stop
649
+ stop
565
650
  end sub
566
651
  `);
567
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
652
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
568
653
  });
569
654
  it('supports single-line if statements', () => {
570
- 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' }, `
571
656
  sub main()
572
657
  if 1 < 2: return true: end if
573
658
  if 1 < 2: return true
574
659
  end if
575
660
  if false : print "true" : end if
576
661
  if true: print "8 worked": else if true: print "not run": else: print "not run": end if
577
- if true then : test = sub() : print "yes" : end sub : end if
662
+ if true then: test = sub() : print "yes" : end sub: end if
578
663
  end sub
579
664
  `);
580
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
665
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
581
666
  });
582
667
  it('supports line_num as global variable', () => {
583
- var _a;
584
668
  file.parse(`
585
669
  sub Main()
586
670
  print LINE_NUM
587
671
  end sub
588
672
  `);
589
- (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);
590
674
  });
591
675
  it('supports many keywords as object property names', () => {
592
676
  file.parse(`
@@ -652,7 +736,7 @@ describe('BrsFile', () => {
652
736
  person.new = true
653
737
  end sub
654
738
  `);
655
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
739
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
656
740
  });
657
741
  it('does not error on numeric literal type designators', () => {
658
742
  file.parse(`
@@ -660,13 +744,13 @@ describe('BrsFile', () => {
660
744
  print &he2
661
745
  print 1.2E+2
662
746
  print 2!
663
- print 12D-12
747
+ print 12D - 12
664
748
  print 2.3#
665
749
  print &hFEDCBA9876543210&
666
750
  print 9876543210&
667
751
  end sub
668
752
  `);
669
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
753
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
670
754
  });
671
755
  it('does not error when encountering sub with return type', () => {
672
756
  file.parse(`
@@ -674,7 +758,7 @@ describe('BrsFile', () => {
674
758
  return
675
759
  end sub
676
760
  `);
677
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
761
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
678
762
  });
679
763
  it('does not lose function statements when mismatched end sub', () => {
680
764
  file.parse(`
@@ -709,7 +793,7 @@ describe('BrsFile', () => {
709
793
  foo.bar = true and false or 3 > 4
710
794
  end sub
711
795
  `);
712
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
796
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
713
797
  });
714
798
  it('does not error with boolean in RHS of set statement', () => {
715
799
  file.parse(`
@@ -722,57 +806,57 @@ describe('BrsFile', () => {
722
806
  m.isTrue = m.isTrue = m.isTrue
723
807
  end sub
724
808
  `);
725
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
809
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
726
810
  });
727
811
  it('supports variable names ending with type designators', () => {
728
812
  file.parse(`
729
813
  sub main()
730
- name$ = "bob"
731
- age% = 1
732
- height! = 5.5
733
- salary# = 9.87654321
734
- someHex& = 13
814
+ name$ = "bob"
815
+ age% = 1
816
+ height! = 5.5
817
+ salary# = 9.87654321
818
+ someHex& = 13
735
819
  end sub
736
820
  `);
737
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
821
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
738
822
  });
739
823
  it('supports multiple spaces between two-word keywords', () => {
740
824
  file.parse(`
741
825
  sub main()
742
826
  if true then
743
827
  print "true"
744
- else if true then
828
+ else if true then
745
829
  print "also true"
746
830
  end if
747
831
  end sub
748
832
  `);
749
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
833
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
750
834
  });
751
835
  it('does not error with `stop` as object key', () => {
752
836
  file.parse(`
753
837
  function GetObject()
754
838
  obj = {
755
- stop: function() as void
839
+ stop: function () as void
756
840
 
757
- end function
841
+ end function
758
842
  }
759
843
  return obj
760
844
  end function
761
845
  `);
762
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
846
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
763
847
  });
764
848
  it('does not error with `run` as object key', () => {
765
849
  file.parse(`
766
850
  function GetObject()
767
851
  obj = {
768
- run: function() as void
852
+ run: function () as void
769
853
 
770
854
  end function
771
- }
855
+ }
772
856
  return obj
773
857
  end function
774
858
  `);
775
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
859
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
776
860
  });
777
861
  it('supports assignment operators', () => {
778
862
  file.parse(`
@@ -789,28 +873,28 @@ describe('BrsFile', () => {
789
873
  print x
790
874
  end function
791
875
  `);
792
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
876
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
793
877
  });
794
878
  it('supports `then` as object property', () => {
795
879
  file.parse(`
796
880
  function Main()
797
881
  promise = {
798
882
  then: sub()
799
- end sub
883
+ end sub
800
884
  }
801
885
  promise.then()
802
886
  end function
803
887
  `);
804
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
888
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
805
889
  });
806
890
  it('supports function as parameter type', () => {
807
891
  file.parse(`
808
892
  sub Main()
809
- doWork = function(callback as function)
893
+ doWork = function (callback as function)
810
894
  end function
811
895
  end sub
812
896
  `);
813
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
897
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
814
898
  });
815
899
  it('supports increment operator', () => {
816
900
  file.parse(`
@@ -819,8 +903,7 @@ describe('BrsFile', () => {
819
903
  x++
820
904
  end function
821
905
  `);
822
- file.getDiagnostics();
823
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
906
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
824
907
  });
825
908
  it('supports decrement operator', () => {
826
909
  file.parse(`
@@ -829,8 +912,7 @@ describe('BrsFile', () => {
829
912
  x--
830
913
  end function
831
914
  `);
832
- file.getDiagnostics();
833
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
915
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
834
916
  });
835
917
  it('supports writing numbers with decimal but no trailing digit', () => {
836
918
  file.parse(`
@@ -839,7 +921,7 @@ describe('BrsFile', () => {
839
921
  print x
840
922
  end function
841
923
  `);
842
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
924
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
843
925
  });
844
926
  it('supports assignment operators against object properties', () => {
845
927
  file.parse(`
@@ -861,7 +943,7 @@ describe('BrsFile', () => {
861
943
  print m.age
862
944
  end function
863
945
  `);
864
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
946
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
865
947
  });
866
948
  //skipped until `brs` supports this
867
949
  it('supports bitshift assignment operators', () => {
@@ -873,7 +955,7 @@ describe('BrsFile', () => {
873
955
  print x
874
956
  end function
875
957
  `);
876
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
958
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
877
959
  });
878
960
  //skipped until `brs` supports this
879
961
  it('supports bitshift assignment operators on objects', () => {
@@ -885,7 +967,7 @@ describe('BrsFile', () => {
885
967
  print m.x
886
968
  end function
887
969
  `);
888
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
970
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
889
971
  });
890
972
  it('supports leading and trailing periods for numeric literals', () => {
891
973
  file.parse(`
@@ -896,7 +978,7 @@ describe('BrsFile', () => {
896
978
  print pointOne
897
979
  end function
898
980
  `);
899
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
981
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
900
982
  });
901
983
  it('supports bitshift assignment operators on object properties accessed by array syntax', () => {
902
984
  file.parse(`
@@ -907,7 +989,7 @@ describe('BrsFile', () => {
907
989
  print m.x
908
990
  end function
909
991
  `);
910
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
992
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
911
993
  });
912
994
  it('supports weird period AA accessor', () => {
913
995
  file.parse(`
@@ -916,51 +998,55 @@ describe('BrsFile', () => {
916
998
  print m.["_uuid"]
917
999
  end function
918
1000
  `);
919
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
1001
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
920
1002
  });
921
1003
  it('adds error for library statements NOT at top of file', () => {
922
- let file = program.setFile('source/main.bs', `
1004
+ program.setFile('source/file.brs', ``);
1005
+ program.setFile('source/main.bs', `
923
1006
  sub main()
924
1007
  end sub
925
1008
  import "file.brs"
926
- `);
927
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
928
- DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile().message
1009
+ `);
1010
+ program.validate();
1011
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1012
+ DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()
929
1013
  ]);
930
1014
  });
931
1015
  it('supports library imports', () => {
932
- file.parse(`
1016
+ program.setFile('source/main.brs', `
933
1017
  Library "v30/bslCore.brs"
934
1018
  `);
935
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
1019
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
936
1020
  });
937
1021
  it('adds error for library statements NOT at top of file', () => {
938
- let file = program.setFile('source/main.brs', `
1022
+ program.setFile('source/main.brs', `
939
1023
  sub main()
940
1024
  end sub
941
1025
  Library "v30/bslCore.brs"
942
1026
  `);
943
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
944
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
1027
+ program.validate();
1028
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1029
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
945
1030
  ]);
946
1031
  });
947
1032
  it('adds error for library statements inside of function body', () => {
948
- let file = program.setFile('source/main.brs', `
1033
+ program.setFile('source/main.brs', `
949
1034
  sub main()
950
1035
  Library "v30/bslCore.brs"
951
1036
  end sub
952
1037
  `);
953
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
954
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
1038
+ program.validate();
1039
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1040
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
955
1041
  ]);
956
1042
  });
957
1043
  it('supports colons as separators in associative array properties', () => {
958
1044
  file.parse(`
959
1045
  sub Main()
960
- obj = {x:0 : y: 1}
1046
+ obj = { x: 0 : y: 1 }
961
1047
  end sub
962
1048
  `);
963
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
1049
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
964
1050
  });
965
1051
  it('succeeds when finding variables with "sub" in them', () => {
966
1052
  let file = program.setFile('source/main.brs', `
@@ -975,8 +1061,8 @@ describe('BrsFile', () => {
975
1061
  });
976
1062
  it('succeeds when finding variables with the word "function" in them', () => {
977
1063
  file.parse(`
978
- function Test()
979
- typeCheckFunction = RBS_CMN_GetFunction(invalid, methodName)
1064
+ function Test()
1065
+ typeCheckFunction = RBS_CMN_GetFunction(invalid, methodName)
980
1066
  end function
981
1067
  `);
982
1068
  });
@@ -987,14 +1073,14 @@ describe('BrsFile', () => {
987
1073
  print "A"
988
1074
  end function
989
1075
 
990
- function DoB()
991
- print "B"
992
- end function
1076
+ function DoB()
1077
+ print "B"
1078
+ end function
993
1079
  `);
994
1080
  (0, chai_1.expect)(file.callables[0].name).to.equal('DoA');
995
1081
  (0, chai_1.expect)(file.callables[0].nameRange).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 28));
996
1082
  (0, chai_1.expect)(file.callables[1].name).to.equal('DoB');
997
- (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));
998
1084
  });
999
1085
  it('throws an error if the file has already been parsed', () => {
1000
1086
  let file = new BrsFile_1.BrsFile('abspath', 'relpath', program);
@@ -1046,10 +1132,8 @@ describe('BrsFile', () => {
1046
1132
  function DoSomething
1047
1133
  end function
1048
1134
  `);
1049
- (0, chai_1.expect)(file.getDiagnostics().length).to.be.greaterThan(0);
1050
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.deep.include({
1051
- file: file
1052
- });
1135
+ (0, testHelpers_spec_1.expectHasDiagnostics)(file);
1136
+ (0, chai_1.expect)(file.getDiagnostics()[0].file).to.equal(file);
1053
1137
  (0, chai_1.expect)(file.getDiagnostics()[0].range.start.line).to.equal(1);
1054
1138
  });
1055
1139
  it('supports using the `next` keyword in a for loop', () => {
@@ -1061,7 +1145,7 @@ describe('BrsFile', () => {
1061
1145
  next
1062
1146
  end sub
1063
1147
  `);
1064
- (0, chai_1.expect)(file.getDiagnostics()).to.be.empty;
1148
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1065
1149
  });
1066
1150
  //test is not working yet, but will be enabled when brs supports this syntax
1067
1151
  it('supports assigning functions to objects', () => {
@@ -1074,7 +1158,7 @@ describe('BrsFile', () => {
1074
1158
  end sub
1075
1159
  end function
1076
1160
  `);
1077
- (0, chai_1.expect)(file.getDiagnostics().length).to.equal(0);
1161
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1078
1162
  });
1079
1163
  });
1080
1164
  describe('findCallables', () => {
@@ -1195,7 +1279,6 @@ describe('BrsFile', () => {
1195
1279
  }]);
1196
1280
  });
1197
1281
  it('finds function calls nested inside statements', () => {
1198
- var _a;
1199
1282
  program.setFile(`source/main.brs`, `
1200
1283
  sub main()
1201
1284
  if true then
@@ -1204,7 +1287,9 @@ describe('BrsFile', () => {
1204
1287
  end sub
1205
1288
  `);
1206
1289
  program.validate();
1207
- (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
+ ]);
1208
1293
  });
1209
1294
  it('finds arguments with variable values', () => {
1210
1295
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1326,13 +1411,13 @@ describe('BrsFile', () => {
1326
1411
  it('finds variable type from other variable', () => {
1327
1412
  file.parse(`
1328
1413
  sub Main()
1329
- name = "bob"
1330
- nameCopy = name
1414
+ name = "bob"
1415
+ nameCopy = name
1331
1416
  end sub
1332
1417
  `);
1333
1418
  (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
1334
- ['name', new StringType_1.StringType(), util_1.default.createRange(2, 19, 2, 23)],
1335
- ['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)]
1336
1421
  ]);
1337
1422
  });
1338
1423
  it('sets proper range for functions', () => {
@@ -1343,7 +1428,6 @@ describe('BrsFile', () => {
1343
1428
  end function
1344
1429
  end sub
1345
1430
  `);
1346
- (0, chai_1.expect)(file.parser.references.functionExpressions).to.be.length(2);
1347
1431
  (0, chai_1.expect)(file.parser.references.functionExpressions.map(x => x.range)).to.eql([
1348
1432
  util_1.default.createRange(1, 16, 5, 23),
1349
1433
  util_1.default.createRange(2, 30, 4, 32)
@@ -1352,10 +1436,10 @@ describe('BrsFile', () => {
1352
1436
  });
1353
1437
  describe('getHover', () => {
1354
1438
  it('works for param types', () => {
1355
- 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' }, `
1356
1440
  sub DoSomething(name as string)
1357
1441
  name = 1
1358
- sayMyName = function(name as string)
1442
+ sayMyName = function (name as string)
1359
1443
  end function
1360
1444
  end sub
1361
1445
  `);
@@ -1370,19 +1454,19 @@ describe('BrsFile', () => {
1370
1454
  });
1371
1455
  //ignore this for now...it's not a huge deal
1372
1456
  it('does not match on keywords or data types', () => {
1373
- 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' }, `
1374
1458
  sub Main(name as string)
1375
1459
  end sub
1376
- sub as()
1460
+ sub as ()
1377
1461
  end sub
1378
1462
  `);
1379
- //hover over the `as`
1463
+ //hover over the `as `
1380
1464
  (0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 31))).not.to.exist;
1381
1465
  //hover over the `string`
1382
1466
  (0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 36))).not.to.exist;
1383
1467
  });
1384
1468
  it('finds declared function', () => {
1385
- 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' }, `
1386
1470
  function Main(count = 1)
1387
1471
  firstName = "bob"
1388
1472
  age = 21
@@ -1392,7 +1476,11 @@ describe('BrsFile', () => {
1392
1476
  let hover = file.getHover(vscode_languageserver_1.Position.create(1, 28));
1393
1477
  (0, chai_1.expect)(hover).to.exist;
1394
1478
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
1395
- (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'));
1396
1484
  });
1397
1485
  it('finds variable function hover in same scope', () => {
1398
1486
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -1405,7 +1493,35 @@ describe('BrsFile', () => {
1405
1493
  `);
1406
1494
  let hover = file.getHover(vscode_languageserver_1.Position.create(5, 24));
1407
1495
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
1408
- (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'));
1409
1525
  });
1410
1526
  it('finds function hover in file scope', () => {
1411
1527
  let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -1419,7 +1535,11 @@ describe('BrsFile', () => {
1419
1535
  `);
1420
1536
  let hover = file.getHover(vscode_languageserver_1.Position.create(2, 25));
1421
1537
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1422
- (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'));
1423
1543
  });
1424
1544
  it('finds function hover in scope', () => {
1425
1545
  let rootDir = process.cwd();
@@ -1439,7 +1559,53 @@ describe('BrsFile', () => {
1439
1559
  let hover = mainFile.getHover(vscode_languageserver_1.Position.create(2, 25));
1440
1560
  (0, chai_1.expect)(hover).to.exist;
1441
1561
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1442
- (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
+ `);
1443
1609
  });
1444
1610
  it('handles mixed case `then` partions of conditionals', () => {
1445
1611
  let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
@@ -1449,7 +1615,7 @@ describe('BrsFile', () => {
1449
1615
  end if
1450
1616
  end sub
1451
1617
  `);
1452
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1618
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1453
1619
  mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1454
1620
  sub Main()
1455
1621
  if true Then
@@ -1457,7 +1623,7 @@ describe('BrsFile', () => {
1457
1623
  end if
1458
1624
  end sub
1459
1625
  `);
1460
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1626
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1461
1627
  mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1462
1628
  sub Main()
1463
1629
  if true THEN
@@ -1465,7 +1631,7 @@ describe('BrsFile', () => {
1465
1631
  end if
1466
1632
  end sub
1467
1633
  `);
1468
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1634
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1469
1635
  });
1470
1636
  it('displays the context from multiple scopes', () => {
1471
1637
  let commonFile = program.setFile('source/common.brs', `
@@ -1502,11 +1668,61 @@ describe('BrsFile', () => {
1502
1668
  `);
1503
1669
  program.validate();
1504
1670
  let funcCallHover = commonFile.getHover(vscode_languageserver_1.Position.create(2, 27));
1505
- (0, chai_1.expect)(funcCallHover).to.exist;
1506
- (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'));
1507
1676
  let variableHover = commonFile.getHover(vscode_languageserver_1.Position.create(3, 27));
1508
- (0, chai_1.expect)(variableHover).to.exist;
1509
- (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'));
1510
1726
  });
1511
1727
  });
1512
1728
  it('does not throw when encountering incomplete import statement', () => {
@@ -1815,9 +2031,9 @@ describe('BrsFile', () => {
1815
2031
  });
1816
2032
  it('computes correct locations for sourcemap', async () => {
1817
2033
  let source = `function abc(name)\n firstName = name\nend function`;
1818
- let tokens = lexer_1.Lexer.scan(source).tokens
2034
+ let tokens = Lexer_1.Lexer.scan(source).tokens
1819
2035
  //remove newlines and EOF
1820
- .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);
1821
2037
  program.options.sourceMap = true;
1822
2038
  let result = testTranspile(source, source, 'none');
1823
2039
  //load the source map
@@ -2075,14 +2291,13 @@ describe('BrsFile', () => {
2075
2291
  describe('callfunc operator', () => {
2076
2292
  describe('transpile', () => {
2077
2293
  it('does not produce diagnostics', () => {
2078
- var _a;
2079
2294
  program.setFile('source/main.bs', `
2080
2295
  sub main()
2081
2296
  someObject@.someFunction(paramObject.value)
2082
2297
  end sub
2083
2298
  `);
2084
2299
  program.validate();
2085
- (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);
2086
2301
  });
2087
2302
  it('sets invalid on empty callfunc', () => {
2088
2303
  testTranspile(`
@@ -2122,7 +2337,7 @@ describe('BrsFile', () => {
2122
2337
  name: 'transform callback',
2123
2338
  afterFileParse: onParsed
2124
2339
  });
2125
- file = program.setFile(`source/file.${ext}`, `
2340
+ file = program.setFile({ src: `absolute_path/file${ext}`, dest: `relative_path/file${ext}` }, `
2126
2341
  sub Sum()
2127
2342
  print "hello world"
2128
2343
  end sub
@@ -2495,11 +2710,11 @@ describe('BrsFile', () => {
2495
2710
  (0, chai_1.expect)(file.parser).to.equal(newParser);
2496
2711
  });
2497
2712
  it('call parse when previously skipped', () => {
2498
- program.setFile('source/main.d.bs', `
2713
+ program.setFile('source/main.d.bs', `'typedef
2499
2714
  sub main()
2500
2715
  end sub
2501
2716
  `);
2502
- const file = program.setFile('source/main.brs', `
2717
+ const file = program.setFile('source/main.brs', `'source
2503
2718
  sub main()
2504
2719
  end sub
2505
2720
  `);
@@ -2556,5 +2771,207 @@ describe('BrsFile', () => {
2556
2771
  testPluginTranspile();
2557
2772
  });
2558
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
+ });
2559
2976
  });
2560
2977
  //# sourceMappingURL=BrsFile.spec.js.map