brighterscript 0.42.0 → 0.45.0

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 (201) hide show
  1. package/CHANGELOG.md +49 -0
  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/DiagnosticMessages.d.ts +21 -1
  6. package/dist/DiagnosticMessages.js +20 -0
  7. package/dist/DiagnosticMessages.js.map +1 -1
  8. package/dist/LanguageServer.d.ts +1 -6
  9. package/dist/LanguageServer.js +3 -12
  10. package/dist/LanguageServer.js.map +1 -1
  11. package/dist/PluginInterface.d.ts +3 -3
  12. package/dist/PluginInterface.js +3 -0
  13. package/dist/PluginInterface.js.map +1 -1
  14. package/dist/Program.d.ts +68 -25
  15. package/dist/Program.js +169 -76
  16. package/dist/Program.js.map +1 -1
  17. package/dist/ProgramBuilder.js +6 -6
  18. package/dist/ProgramBuilder.js.map +1 -1
  19. package/dist/Scope.d.ts +18 -11
  20. package/dist/Scope.js +41 -14
  21. package/dist/Scope.js.map +1 -1
  22. package/dist/XmlScope.d.ts +3 -3
  23. package/dist/astUtils/AstEditor.d.ts +6 -0
  24. package/dist/astUtils/AstEditor.js +10 -0
  25. package/dist/astUtils/AstEditor.js.map +1 -1
  26. package/dist/astUtils/AstEditor.spec.js +37 -0
  27. package/dist/astUtils/AstEditor.spec.js.map +1 -1
  28. package/dist/astUtils/reflection.d.ts +5 -2
  29. package/dist/astUtils/reflection.js +14 -2
  30. package/dist/astUtils/reflection.js.map +1 -1
  31. package/dist/astUtils/reflection.spec.js +6 -6
  32. package/dist/astUtils/reflection.spec.js.map +1 -1
  33. package/dist/astUtils/visitors.d.ts +3 -1
  34. package/dist/astUtils/visitors.js.map +1 -1
  35. package/dist/astUtils/visitors.spec.js +15 -18
  36. package/dist/astUtils/visitors.spec.js.map +1 -1
  37. package/dist/bscPlugin/BscPlugin.d.ts +4 -1
  38. package/dist/bscPlugin/BscPlugin.js +21 -2
  39. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  40. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
  41. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  42. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +18 -16
  43. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  44. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
  45. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
  46. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  47. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.d.ts → BrsFileSemanticTokensProcessor.spec.d.ts} +0 -0
  48. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +32 -4
  49. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  50. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
  51. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +36 -0
  52. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
  53. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
  54. package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
  55. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  56. package/dist/bscPlugin/validation/ScopeValidator.d.ts +11 -0
  57. package/dist/bscPlugin/validation/ScopeValidator.js +94 -0
  58. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  59. package/dist/files/BrsFile.Class.spec.js +218 -114
  60. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  61. package/dist/files/BrsFile.d.ts +27 -8
  62. package/dist/files/BrsFile.js +216 -95
  63. package/dist/files/BrsFile.js.map +1 -1
  64. package/dist/files/BrsFile.spec.js +338 -190
  65. package/dist/files/BrsFile.spec.js.map +1 -1
  66. package/dist/files/XmlFile.d.ts +11 -5
  67. package/dist/files/XmlFile.js +15 -9
  68. package/dist/files/XmlFile.js.map +1 -1
  69. package/dist/files/XmlFile.spec.js +118 -114
  70. package/dist/files/XmlFile.spec.js.map +1 -1
  71. package/dist/files/tests/imports.spec.js +29 -27
  72. package/dist/files/tests/imports.spec.js.map +1 -1
  73. package/dist/index.d.ts +12 -3
  74. package/dist/index.js +21 -4
  75. package/dist/index.js.map +1 -1
  76. package/dist/interfaces.d.ts +50 -9
  77. package/dist/lexer/Lexer.js +1 -2
  78. package/dist/lexer/Lexer.js.map +1 -1
  79. package/dist/lexer/Lexer.spec.js +470 -462
  80. package/dist/lexer/Lexer.spec.js.map +1 -1
  81. package/dist/lexer/TokenKind.d.ts +2 -0
  82. package/dist/lexer/TokenKind.js +5 -0
  83. package/dist/lexer/TokenKind.js.map +1 -1
  84. package/dist/parser/Expression.d.ts +1 -1
  85. package/dist/parser/Expression.js +10 -10
  86. package/dist/parser/Expression.js.map +1 -1
  87. package/dist/parser/Parser.Class.spec.js +32 -31
  88. package/dist/parser/Parser.Class.spec.js.map +1 -1
  89. package/dist/parser/Parser.d.ts +23 -2
  90. package/dist/parser/Parser.js +445 -254
  91. package/dist/parser/Parser.js.map +1 -1
  92. package/dist/parser/Parser.spec.js +86 -24
  93. package/dist/parser/Parser.spec.js.map +1 -1
  94. package/dist/parser/SGParser.spec.js +1 -1
  95. package/dist/parser/SGParser.spec.js.map +1 -1
  96. package/dist/parser/Statement.d.ts +54 -2
  97. package/dist/parser/Statement.js +162 -9
  98. package/dist/parser/Statement.js.map +1 -1
  99. package/dist/parser/Statement.spec.js +5 -5
  100. package/dist/parser/Statement.spec.js.map +1 -1
  101. package/dist/parser/tests/Parser.spec.d.ts +3 -3
  102. package/dist/parser/tests/Parser.spec.js +4 -4
  103. package/dist/parser/tests/Parser.spec.js.map +1 -1
  104. package/dist/parser/tests/controlFlow/For.spec.js +40 -40
  105. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  106. package/dist/parser/tests/controlFlow/ForEach.spec.js +22 -21
  107. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  108. package/dist/parser/tests/controlFlow/If.spec.js +100 -99
  109. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  110. package/dist/parser/tests/controlFlow/While.spec.js +25 -25
  111. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  112. package/dist/parser/tests/expression/Additive.spec.js +21 -21
  113. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  114. package/dist/parser/tests/expression/ArrayLiterals.spec.js +91 -91
  115. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  116. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +102 -102
  117. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  118. package/dist/parser/tests/expression/Boolean.spec.js +15 -15
  119. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  120. package/dist/parser/tests/expression/Call.spec.js +22 -21
  121. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  122. package/dist/parser/tests/expression/Exponential.spec.js +11 -11
  123. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  124. package/dist/parser/tests/expression/Function.spec.js +171 -171
  125. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  126. package/dist/parser/tests/expression/Indexing.spec.js +50 -50
  127. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  128. package/dist/parser/tests/expression/Multiplicative.spec.js +25 -25
  129. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  130. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +17 -17
  131. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  132. package/dist/parser/tests/expression/PrefixUnary.spec.js +26 -26
  133. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  134. package/dist/parser/tests/expression/Primary.spec.js +27 -27
  135. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  136. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +4 -3
  137. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  138. package/dist/parser/tests/expression/Relational.spec.js +25 -25
  139. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  140. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +8 -8
  141. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  142. package/dist/parser/tests/expression/TernaryExpression.spec.js +7 -7
  143. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  144. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  145. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  146. package/dist/parser/tests/statement/Declaration.spec.js +20 -20
  147. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  148. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  149. package/dist/parser/tests/statement/Enum.spec.js +774 -0
  150. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  151. package/dist/parser/tests/statement/Function.spec.js +121 -120
  152. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  153. package/dist/parser/tests/statement/Goto.spec.js +9 -8
  154. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  155. package/dist/parser/tests/statement/Increment.spec.js +22 -22
  156. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  157. package/dist/parser/tests/statement/InterfaceStatement.spec.js +12 -0
  158. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  159. package/dist/parser/tests/statement/LibraryStatement.spec.js +7 -7
  160. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  161. package/dist/parser/tests/statement/Misc.spec.js +71 -70
  162. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  163. package/dist/parser/tests/statement/PrintStatement.spec.js +17 -17
  164. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  165. package/dist/parser/tests/statement/ReturnStatement.spec.js +33 -33
  166. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  167. package/dist/parser/tests/statement/Set.spec.js +53 -53
  168. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  169. package/dist/parser/tests/statement/Stop.spec.js +7 -6
  170. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  171. package/dist/preprocessor/Chunk.d.ts +1 -1
  172. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  173. package/dist/preprocessor/Preprocessor.js +7 -7
  174. package/dist/preprocessor/Preprocessor.js.map +1 -1
  175. package/dist/types/FunctionType.d.ts +2 -2
  176. package/dist/types/FunctionType.js +3 -3
  177. package/dist/types/FunctionType.js.map +1 -1
  178. package/dist/types/FunctionType.spec.js +2 -2
  179. package/dist/types/FunctionType.spec.js.map +1 -1
  180. package/dist/util.d.ts +27 -1
  181. package/dist/util.js +96 -29
  182. package/dist/util.js.map +1 -1
  183. package/dist/validators/ClassValidator.js +20 -27
  184. package/dist/validators/ClassValidator.js.map +1 -1
  185. package/package.json +2 -1
  186. package/dist/astUtils/index.d.ts +0 -7
  187. package/dist/astUtils/index.js +0 -26
  188. package/dist/astUtils/index.js.map +0 -1
  189. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  190. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
  191. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  192. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  193. package/dist/lexer/index.d.ts +0 -3
  194. package/dist/lexer/index.js +0 -18
  195. package/dist/lexer/index.js.map +0 -1
  196. package/dist/parser/index.d.ts +0 -3
  197. package/dist/parser/index.js +0 -16
  198. package/dist/parser/index.js.map +0 -1
  199. package/dist/preprocessor/index.d.ts +0 -3
  200. package/dist/preprocessor/index.js +0 -16
  201. 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");
@@ -36,24 +37,22 @@ describe('BrsFile', () => {
36
37
  program.dispose();
37
38
  });
38
39
  it('supports the third parameter in CreateObject', () => {
39
- var _a;
40
- program.addOrReplaceFile('source/main.brs', `
40
+ program.setFile('source/main.brs', `
41
41
  sub main()
42
42
  regexp = CreateObject("roRegex", "[a-z]+", "i")
43
43
  end sub
44
44
  `);
45
45
  program.validate();
46
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
46
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
47
47
  });
48
48
  it('supports the 6 params in CreateObject for roRegion', () => {
49
- var _a;
50
- program.addOrReplaceFile('source/main.brs', `
49
+ program.setFile('source/main.brs', `
51
50
  sub createRegion(bitmap as object)
52
51
  region = CreateObject("roRegion", bitmap, 20, 40, 100, 200)
53
52
  end sub
54
53
  `);
55
54
  program.validate();
56
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
55
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
57
56
  });
58
57
  it('sets needsTranspiled to true for .bs files', () => {
59
58
  //BrightScript
@@ -68,8 +67,7 @@ describe('BrsFile', () => {
68
67
  range: undefined
69
68
  }];
70
69
  file.addDiagnostics(expected);
71
- const actual = file.getDiagnostics();
72
- (0, chai_1.expect)(actual).deep.equal(expected);
70
+ (0, testHelpers_spec_1.expectDiagnostics)(file, expected);
73
71
  });
74
72
  describe('getPartialVariableName', () => {
75
73
  let entry = {
@@ -77,7 +75,7 @@ describe('BrsFile', () => {
77
75
  dest: `source/lib.brs`
78
76
  };
79
77
  it('creates proper tokens', () => {
80
- file = program.addOrReplaceFile(entry, `call(ModuleA.ModuleB.ModuleC.`);
78
+ file = program.setFile(entry, `call(ModuleA.ModuleB.ModuleC.`);
81
79
  (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[7])).to.equal('ModuleA.ModuleB.ModuleC.');
82
80
  (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[6])).to.equal('ModuleA.ModuleB.ModuleC');
83
81
  (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[5])).to.equal('ModuleA.ModuleB.');
@@ -89,13 +87,13 @@ describe('BrsFile', () => {
89
87
  describe('getScopesForFile', () => {
90
88
  it('finds the scope for the file', () => {
91
89
  var _a;
92
- let file = program.addOrReplaceFile('source/main.brs', ``);
90
+ let file = program.setFile('source/main.brs', ``);
93
91
  (0, chai_1.expect)((_a = program.getScopesForFile(file)[0]) === null || _a === void 0 ? void 0 : _a.name).to.equal('source');
94
92
  });
95
93
  });
96
94
  describe('getCompletions', () => {
97
95
  it('does not crash for callfunc on a function call', () => {
98
- const file = program.addOrReplaceFile('source/main.brs', `
96
+ const file = program.setFile('source/main.brs', `
99
97
  sub main()
100
98
  getManager()@.
101
99
  end sub
@@ -105,7 +103,7 @@ describe('BrsFile', () => {
105
103
  }).not.to.throw;
106
104
  });
107
105
  it('suggests pkg paths in strings that match that criteria', () => {
108
- program.addOrReplaceFile('source/main.brs', `
106
+ program.setFile('source/main.brs', `
109
107
  sub main()
110
108
  print "pkg:"
111
109
  end sub
@@ -117,7 +115,7 @@ describe('BrsFile', () => {
117
115
  ]);
118
116
  });
119
117
  it('suggests libpkg paths in strings that match that criteria', () => {
120
- program.addOrReplaceFile('source/main.brs', `
118
+ program.setFile('source/main.brs', `
121
119
  sub main()
122
120
  print "libpkg:"
123
121
  end sub
@@ -129,7 +127,7 @@ describe('BrsFile', () => {
129
127
  ]);
130
128
  });
131
129
  it('suggests pkg paths in template strings', () => {
132
- program.addOrReplaceFile('source/main.brs', `
130
+ program.setFile('source/main.brs', `
133
131
  sub main()
134
132
  print \`pkg:\`
135
133
  end sub
@@ -142,7 +140,7 @@ describe('BrsFile', () => {
142
140
  });
143
141
  it('waits for the file to be processed before collecting completions', () => {
144
142
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
145
- program.addOrReplaceFile('source/main.brs', `
143
+ program.setFile('source/main.brs', `
146
144
  sub Main()
147
145
  print "hello"
148
146
  Say
@@ -156,9 +154,79 @@ describe('BrsFile', () => {
156
154
  (0, chai_1.expect)(names).to.includes('Main');
157
155
  (0, chai_1.expect)(names).to.includes('SayHello');
158
156
  });
157
+ it('includes every type of item at base level', () => {
158
+ program.setFile('source/main.bs', `
159
+ sub main()
160
+ print
161
+ end sub
162
+ sub speak()
163
+ end sub
164
+ namespace stuff
165
+ end namespace
166
+ class Person
167
+ end class
168
+ enum Direction
169
+ end enum
170
+ `);
171
+ (0, testHelpers_spec_1.expectCompletionsIncludes)(program.getCompletions('source/main.bs', util_1.default.createPosition(2, 26)), [{
172
+ label: 'main',
173
+ kind: vscode_languageserver_1.CompletionItemKind.Function
174
+ }, {
175
+ label: 'speak',
176
+ kind: vscode_languageserver_1.CompletionItemKind.Function
177
+ }, {
178
+ label: 'stuff',
179
+ kind: vscode_languageserver_1.CompletionItemKind.Module
180
+ }, {
181
+ label: 'Person',
182
+ kind: vscode_languageserver_1.CompletionItemKind.Class
183
+ }, {
184
+ label: 'Direction',
185
+ kind: vscode_languageserver_1.CompletionItemKind.Enum
186
+ }]);
187
+ });
188
+ describe('namespaces', () => {
189
+ it('gets full namespace completions at any point through the leading identifier', () => {
190
+ program.setFile('source/main.bs', `
191
+ sub main()
192
+ foo.bar
193
+ end sub
194
+
195
+ namespace foo.bar
196
+ end namespace
197
+
198
+ class Person
199
+ end class
200
+ `);
201
+ const result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(2, 24)).map(x => x.label);
202
+ (0, chai_1.expect)(result).includes('main');
203
+ (0, chai_1.expect)(result).includes('foo');
204
+ (0, chai_1.expect)(result).includes('Person');
205
+ });
206
+ it('gets namespace completions', () => {
207
+ program.setFile('source/main.bs', `
208
+ namespace foo.bar
209
+ function sayHello()
210
+ end function
211
+ end namespace
212
+
213
+ sub Main()
214
+ print "hello"
215
+ foo.ba
216
+ foo.bar.
217
+ end sub
218
+ `);
219
+ let result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(8, 30));
220
+ let names = result.map(x => x.label);
221
+ (0, chai_1.expect)(names).to.includes('bar');
222
+ result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(9, 32));
223
+ names = result.map(x => x.label);
224
+ (0, chai_1.expect)(names).to.includes('sayHello');
225
+ });
226
+ });
159
227
  it('always includes `m`', () => {
160
228
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
161
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
229
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
162
230
  sub Main()
163
231
 
164
232
  end sub
@@ -169,19 +237,19 @@ describe('BrsFile', () => {
169
237
  });
170
238
  it('does not fail for missing previousToken', () => {
171
239
  //add a single character to the file, and get completions after it
172
- program.addOrReplaceFile('source/main.brs', `i`);
240
+ program.setFile('source/main.brs', `i`);
173
241
  (0, chai_1.expect)(() => {
174
242
  program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(0, 1)).map(x => x.label);
175
243
  }).not.to.throw;
176
244
  });
177
245
  it('includes all keywords`', () => {
178
246
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
179
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
247
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
180
248
  sub Main()
181
249
 
182
250
  end sub
183
251
  `);
184
- let keywords = Object.keys(lexer_1.Keywords).filter(x => !x.includes(' '));
252
+ let keywords = Object.keys(TokenKind_1.Keywords).filter(x => !x.includes(' '));
185
253
  //inside the function
186
254
  let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
187
255
  let names = result.map(x => x.label);
@@ -197,7 +265,7 @@ describe('BrsFile', () => {
197
265
  });
198
266
  it('does not provide completions within a comment', () => {
199
267
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
200
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
268
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
201
269
  sub Main()
202
270
  'some comment
203
271
  end sub
@@ -208,7 +276,7 @@ describe('BrsFile', () => {
208
276
  });
209
277
  it('does not provide duplicate entries for variables', () => {
210
278
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
211
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
279
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
212
280
  sub Main()
213
281
  name = "bob"
214
282
  age = 12
@@ -223,7 +291,7 @@ describe('BrsFile', () => {
223
291
  });
224
292
  it('does not include `as` and `string` text options when used in function params', () => {
225
293
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
226
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
294
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
227
295
  sub Main(name as string)
228
296
 
229
297
  end sub
@@ -234,7 +302,7 @@ describe('BrsFile', () => {
234
302
  });
235
303
  it('does not provide intellisense results when inside a comment', () => {
236
304
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
237
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
305
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
238
306
  sub Main(name as string)
239
307
  'this is a comment
240
308
  end sub
@@ -245,7 +313,7 @@ describe('BrsFile', () => {
245
313
  it('does provide intellisence for labels only after a goto keyword', () => {
246
314
  var _a;
247
315
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
248
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
316
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
249
317
  sub Main(name as string)
250
318
  something:
251
319
  goto \nend sub
@@ -258,28 +326,26 @@ describe('BrsFile', () => {
258
326
  describe('comment flags', () => {
259
327
  describe('bs:disable-next-line', () => {
260
328
  it('disables critical diagnostic issues', () => {
261
- var _a, _b;
262
- program.addOrReplaceFile('source/main.brs', `
329
+ program.setFile('source/main.brs', `
263
330
  sub main()
264
331
  Dim requestData
265
332
  end sub
266
333
  `);
267
334
  //should have an error
268
335
  program.validate();
269
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
270
- program.addOrReplaceFile('source/main.brs', `
336
+ (0, testHelpers_spec_1.expectHasDiagnostics)(program);
337
+ program.setFile('source/main.brs', `
271
338
  sub main()
272
339
  'bs:disable-next-line
273
340
  Dim requestData
274
341
  end sub
275
342
  `);
276
- //should have an error
343
+ //should not have an error
277
344
  program.validate();
278
- (0, chai_1.expect)((_b = program.getDiagnostics()[0]) === null || _b === void 0 ? void 0 : _b.message).not.to.exist;
345
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
279
346
  });
280
347
  it('works with leading whitespace', () => {
281
- var _a;
282
- program.addOrReplaceFile('source/main.brs', `
348
+ program.setFile('source/main.brs', `
283
349
  sub main()
284
350
  ' bs:disable-next-line
285
351
  =asdf=sadf=
@@ -287,11 +353,10 @@ describe('BrsFile', () => {
287
353
  `);
288
354
  //should have an error
289
355
  program.validate();
290
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
356
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
291
357
  });
292
358
  it('works for all', () => {
293
- var _a;
294
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
359
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
295
360
  sub Main()
296
361
  'bs:disable-next-line
297
362
  name = "bob
@@ -305,11 +370,10 @@ describe('BrsFile', () => {
305
370
  });
306
371
  program.validate();
307
372
  //the "unterminated string" error should be filtered out
308
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
373
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
309
374
  });
310
375
  it('works for specific codes', () => {
311
- var _a;
312
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
376
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
313
377
  sub Main()
314
378
  'bs:disable-next-line: 1083, 1001
315
379
  name = "bob
@@ -322,22 +386,21 @@ describe('BrsFile', () => {
322
386
  affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
323
387
  });
324
388
  //the "unterminated string" error should be filtered out
325
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.not.exist;
389
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
326
390
  });
327
391
  it('recognizes non-numeric codes', () => {
328
- var _a;
329
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
392
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
330
393
  sub Main()
331
394
  'bs:disable-next-line: LINT9999
332
395
  name = "bob
333
396
  end sub
334
397
  `);
335
398
  (0, chai_1.expect)(file.commentFlags[0]).to.exist;
336
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
399
+ (0, testHelpers_spec_1.expectHasDiagnostics)(program);
337
400
  });
338
401
  it('supports disabling non-numeric error codes', () => {
339
402
  const program = new Program_1.Program({});
340
- const file = program.addOrReplaceFile('source/main.brs', `
403
+ const file = program.setFile('source/main.brs', `
341
404
  sub main()
342
405
  something = true 'bs:disable-line: LINT1005
343
406
  end sub
@@ -348,27 +411,22 @@ describe('BrsFile', () => {
348
411
  message: 'Something is not right',
349
412
  range: util_1.default.createRange(2, 16, 2, 26)
350
413
  }]);
351
- (0, chai_1.expect)(program.getScopesForFile(file)[0].getDiagnostics()).to.be.empty;
414
+ const scope = program.getScopesForFile(file)[0];
415
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(scope);
352
416
  });
353
417
  it('adds diagnostics for unknown numeric diagnostic codes', () => {
354
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
418
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
355
419
  sub main()
356
420
  print "hi" 'bs:disable-line: 123456 999999 aaaab
357
421
  end sub
358
422
  `);
359
423
  program.validate();
360
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(2);
361
- (0, chai_1.expect)(program.getDiagnostics()[0]).to.deep.include({
362
- range: vscode_languageserver_1.Range.create(2, 53, 2, 59)
363
- });
364
- (0, chai_1.expect)(program.getDiagnostics()[1]).to.deep.include({
365
- range: vscode_languageserver_1.Range.create(2, 60, 2, 66)
366
- });
424
+ (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) })]);
367
425
  });
368
426
  });
369
427
  describe('bs:disable-line', () => {
370
428
  it('works for all', () => {
371
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
429
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
372
430
  sub Main()
373
431
  z::;;%%%%%% 'bs:disable-line
374
432
  end sub
@@ -381,10 +439,10 @@ describe('BrsFile', () => {
381
439
  });
382
440
  program.validate();
383
441
  //the "unterminated string" error should be filtered out
384
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(0);
442
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
385
443
  });
386
444
  it('works for specific codes', () => {
387
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
445
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
388
446
  sub main()
389
447
  'should not have any errors
390
448
  DoSomething(1) 'bs:disable-line:1002
@@ -395,29 +453,28 @@ describe('BrsFile', () => {
395
453
  end sub
396
454
  `);
397
455
  program.validate();
398
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(1);
399
- (0, chai_1.expect)(program.getDiagnostics()[0]).to.deep.include({
400
- range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
401
- });
456
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [{
457
+ range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
458
+ }]);
402
459
  });
403
460
  it('handles the erraneous `stop` keyword', () => {
404
461
  //the current version of BRS causes parse errors after the `parse` keyword, showing error in comments
405
462
  //the program should ignore all diagnostics found in brs:* comment lines EXCEPT
406
463
  //for the diagnostics about using unknown error codes
407
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
464
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
408
465
  sub main()
409
466
  stop 'bs:disable-line
410
467
  print "need a valid line to fix stop error"
411
468
  end sub
412
469
  `);
413
470
  program.validate();
414
- (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(0);
471
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
415
472
  });
416
473
  });
417
474
  });
418
475
  describe('parse', () => {
419
476
  it('supports iife in assignment', () => {
420
- program.addOrReplaceFile('source/main.brs', `
477
+ program.setFile('source/main.brs', `
421
478
  sub main()
422
479
  result = sub()
423
480
  end sub()
@@ -429,7 +486,7 @@ describe('BrsFile', () => {
429
486
  });
430
487
  it('uses the proper parse mode based on file extension', () => {
431
488
  function testParseMode(destPath, expectedParseMode) {
432
- const file = program.addOrReplaceFile(destPath, '');
489
+ const file = program.setFile(destPath, '');
433
490
  (0, chai_1.expect)(file.parseMode).to.equal(expectedParseMode);
434
491
  }
435
492
  testParseMode('source/main.brs', Parser_1.ParseMode.BrightScript);
@@ -440,26 +497,26 @@ describe('BrsFile', () => {
440
497
  testParseMode('source/main.spec.bs', Parser_1.ParseMode.BrighterScript);
441
498
  });
442
499
  it('supports labels and goto statements', () => {
443
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
500
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
444
501
  sub Main()
445
502
  'multiple goto statements on one line
446
503
  goto myLabel : goto myLabel
447
504
  myLabel:
448
505
  end sub
449
506
  `);
450
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
507
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
451
508
  });
452
509
  it('supports empty print statements', () => {
453
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
510
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
454
511
  sub main()
455
512
  print
456
513
  end sub
457
514
  `);
458
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
515
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
459
516
  });
460
517
  describe('conditional compile', () => {
461
518
  it('works for upper case keywords', () => {
462
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
519
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
463
520
  sub main()
464
521
  #CONST someFlag = true
465
522
  #IF someFlag
@@ -471,10 +528,10 @@ describe('BrsFile', () => {
471
528
  #ENDIF
472
529
  end sub
473
530
  `);
474
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
531
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
475
532
  });
476
533
  it('supports single-word #elseif and #endif', () => {
477
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
534
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
478
535
  sub main()
479
536
  #const someFlag = true
480
537
  #if someFlag
@@ -484,10 +541,10 @@ describe('BrsFile', () => {
484
541
  #endif
485
542
  end sub
486
543
  `);
487
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
544
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
488
545
  });
489
546
  it('supports multi-word #else if and #end if', () => {
490
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
547
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
491
548
  sub main()
492
549
  #const someFlag = true
493
550
  #if someFlag
@@ -497,65 +554,75 @@ describe('BrsFile', () => {
497
554
  #end if
498
555
  end sub
499
556
  `);
500
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
557
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
501
558
  });
502
559
  it('does not choke on invalid code inside a false conditional compile', () => {
503
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
560
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
504
561
  sub main()
505
562
  #if false
506
563
  non-commented code here should not cause parse errors
507
564
  #end if
508
565
  end sub
509
566
  `);
510
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
567
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
511
568
  });
512
569
  it('detects syntax error in #if', () => {
513
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
570
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
514
571
  sub main()
515
572
  #if true1
516
573
  print "true"
517
574
  #end if
518
575
  end sub
519
576
  `);
520
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue));
577
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
578
+ DiagnosticMessages_1.DiagnosticMessages.referencedConstDoesNotExist()
579
+ ]);
521
580
  });
522
581
  it('detects syntax error in #const', () => {
523
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
582
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
524
583
  sub main()
525
584
  #if %
526
585
  print "true"
527
586
  #end if
528
587
  end sub
529
588
  `);
530
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%')));
589
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
590
+ DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%'),
591
+ DiagnosticMessages_1.DiagnosticMessages.invalidHashIfValue()
592
+ ]);
531
593
  });
532
594
  it('detects #const name using reserved word', () => {
533
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
595
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
534
596
  sub main()
535
597
  #const function = true
536
598
  end sub
537
599
  `);
538
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord()));
600
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
601
+ DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord(),
602
+ DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('#const')
603
+ ]);
539
604
  });
540
605
  it('detects syntax error in #const', () => {
541
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
606
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
542
607
  sub main()
543
608
  #const someConst = 123
544
609
  end sub
545
610
  `);
546
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()));
611
+ (0, testHelpers_spec_1.expectDiagnostics)(file, [
612
+ DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()
613
+ ]);
547
614
  });
548
615
  });
549
616
  it('supports stop statement', () => {
550
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
617
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
551
618
  sub main()
552
619
  stop
553
620
  end sub
554
621
  `);
555
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
622
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
556
623
  });
557
624
  it('supports single-line if statements', () => {
558
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
625
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
559
626
  sub main()
560
627
  if 1 < 2: return true: end if
561
628
  if 1 < 2: return true
@@ -565,16 +632,15 @@ describe('BrsFile', () => {
565
632
  if true then : test = sub() : print "yes" : end sub : end if
566
633
  end sub
567
634
  `);
568
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
635
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
569
636
  });
570
637
  it('supports line_num as global variable', () => {
571
- var _a;
572
638
  file.parse(`
573
639
  sub Main()
574
640
  print LINE_NUM
575
641
  end sub
576
642
  `);
577
- (0, chai_1.expect)((_a = file.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
643
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
578
644
  });
579
645
  it('supports many keywords as object property names', () => {
580
646
  file.parse(`
@@ -640,7 +706,7 @@ describe('BrsFile', () => {
640
706
  person.new = true
641
707
  end sub
642
708
  `);
643
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
709
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
644
710
  });
645
711
  it('does not error on numeric literal type designators', () => {
646
712
  file.parse(`
@@ -654,7 +720,7 @@ describe('BrsFile', () => {
654
720
  print 9876543210&
655
721
  end sub
656
722
  `);
657
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
723
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
658
724
  });
659
725
  it('does not error when encountering sub with return type', () => {
660
726
  file.parse(`
@@ -662,7 +728,7 @@ describe('BrsFile', () => {
662
728
  return
663
729
  end sub
664
730
  `);
665
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
731
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
666
732
  });
667
733
  it('does not lose function scopes when mismatched end sub', () => {
668
734
  file.parse(`
@@ -697,7 +763,7 @@ describe('BrsFile', () => {
697
763
  foo.bar = true and false or 3 > 4
698
764
  end sub
699
765
  `);
700
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
766
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
701
767
  });
702
768
  it('does not error with boolean in RHS of set statement', () => {
703
769
  file.parse(`
@@ -710,7 +776,7 @@ describe('BrsFile', () => {
710
776
  m.isTrue = m.isTrue = m.isTrue
711
777
  end sub
712
778
  `);
713
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
779
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
714
780
  });
715
781
  it('supports variable names ending with type designators', () => {
716
782
  file.parse(`
@@ -722,7 +788,7 @@ describe('BrsFile', () => {
722
788
  someHex& = 13
723
789
  end sub
724
790
  `);
725
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
791
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
726
792
  });
727
793
  it('supports multiple spaces between two-word keywords', () => {
728
794
  file.parse(`
@@ -734,7 +800,7 @@ describe('BrsFile', () => {
734
800
  end if
735
801
  end sub
736
802
  `);
737
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
803
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
738
804
  });
739
805
  it('does not error with `stop` as object key', () => {
740
806
  file.parse(`
@@ -747,7 +813,7 @@ describe('BrsFile', () => {
747
813
  return obj
748
814
  end function
749
815
  `);
750
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
816
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
751
817
  });
752
818
  it('does not error with `run` as object key', () => {
753
819
  file.parse(`
@@ -760,7 +826,7 @@ describe('BrsFile', () => {
760
826
  return obj
761
827
  end function
762
828
  `);
763
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
829
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
764
830
  });
765
831
  it('supports assignment operators', () => {
766
832
  file.parse(`
@@ -777,7 +843,7 @@ describe('BrsFile', () => {
777
843
  print x
778
844
  end function
779
845
  `);
780
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
846
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
781
847
  });
782
848
  it('supports `then` as object property', () => {
783
849
  file.parse(`
@@ -789,7 +855,7 @@ describe('BrsFile', () => {
789
855
  promise.then()
790
856
  end function
791
857
  `);
792
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
858
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
793
859
  });
794
860
  it('supports function as parameter type', () => {
795
861
  file.parse(`
@@ -798,7 +864,7 @@ describe('BrsFile', () => {
798
864
  end function
799
865
  end sub
800
866
  `);
801
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
867
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
802
868
  });
803
869
  it('supports increment operator', () => {
804
870
  file.parse(`
@@ -807,8 +873,7 @@ describe('BrsFile', () => {
807
873
  x++
808
874
  end function
809
875
  `);
810
- file.getDiagnostics();
811
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
876
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
812
877
  });
813
878
  it('supports decrement operator', () => {
814
879
  file.parse(`
@@ -817,8 +882,7 @@ describe('BrsFile', () => {
817
882
  x--
818
883
  end function
819
884
  `);
820
- file.getDiagnostics();
821
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
885
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
822
886
  });
823
887
  it('supports writing numbers with decimal but no trailing digit', () => {
824
888
  file.parse(`
@@ -827,7 +891,7 @@ describe('BrsFile', () => {
827
891
  print x
828
892
  end function
829
893
  `);
830
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
894
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
831
895
  });
832
896
  it('supports assignment operators against object properties', () => {
833
897
  file.parse(`
@@ -849,7 +913,7 @@ describe('BrsFile', () => {
849
913
  print m.age
850
914
  end function
851
915
  `);
852
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
916
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
853
917
  });
854
918
  //skipped until `brs` supports this
855
919
  it('supports bitshift assignment operators', () => {
@@ -861,7 +925,7 @@ describe('BrsFile', () => {
861
925
  print x
862
926
  end function
863
927
  `);
864
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
928
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
865
929
  });
866
930
  //skipped until `brs` supports this
867
931
  it('supports bitshift assignment operators on objects', () => {
@@ -873,7 +937,7 @@ describe('BrsFile', () => {
873
937
  print m.x
874
938
  end function
875
939
  `);
876
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
940
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
877
941
  });
878
942
  it('supports leading and trailing periods for numeric literals', () => {
879
943
  file.parse(`
@@ -884,7 +948,7 @@ describe('BrsFile', () => {
884
948
  print pointOne
885
949
  end function
886
950
  `);
887
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
951
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
888
952
  });
889
953
  it('supports bitshift assignment operators on object properties accessed by array syntax', () => {
890
954
  file.parse(`
@@ -895,7 +959,7 @@ describe('BrsFile', () => {
895
959
  print m.x
896
960
  end function
897
961
  `);
898
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
962
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
899
963
  });
900
964
  it('supports weird period AA accessor', () => {
901
965
  file.parse(`
@@ -904,42 +968,46 @@ describe('BrsFile', () => {
904
968
  print m.["_uuid"]
905
969
  end function
906
970
  `);
907
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
971
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
908
972
  });
909
973
  it('adds error for library statements NOT at top of file', () => {
910
- let file = program.addOrReplaceFile('source/main.bs', `
974
+ program.setFile('source/file.brs', ``);
975
+ program.setFile('source/main.bs', `
911
976
  sub main()
912
977
  end sub
913
978
  import "file.brs"
914
979
  `);
915
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
916
- DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile().message
980
+ program.validate();
981
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
982
+ DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()
917
983
  ]);
918
984
  });
919
985
  it('supports library imports', () => {
920
- file.parse(`
986
+ program.setFile('source/main.brs', `
921
987
  Library "v30/bslCore.brs"
922
988
  `);
923
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
989
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
924
990
  });
925
991
  it('adds error for library statements NOT at top of file', () => {
926
- let file = program.addOrReplaceFile('source/main.brs', `
992
+ program.setFile('source/main.brs', `
927
993
  sub main()
928
994
  end sub
929
995
  Library "v30/bslCore.brs"
930
996
  `);
931
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
932
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
997
+ program.validate();
998
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
999
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
933
1000
  ]);
934
1001
  });
935
1002
  it('adds error for library statements inside of function body', () => {
936
- let file = program.addOrReplaceFile('source/main.brs', `
1003
+ program.setFile('source/main.brs', `
937
1004
  sub main()
938
1005
  Library "v30/bslCore.brs"
939
1006
  end sub
940
1007
  `);
941
- (0, chai_1.expect)(file.getDiagnostics().map(x => x.message)).to.eql([
942
- DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile().message
1008
+ program.validate();
1009
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1010
+ DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
943
1011
  ]);
944
1012
  });
945
1013
  it('supports colons as separators in associative array properties', () => {
@@ -948,10 +1016,10 @@ describe('BrsFile', () => {
948
1016
  obj = {x:0 : y: 1}
949
1017
  end sub
950
1018
  `);
951
- (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
1019
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
952
1020
  });
953
1021
  it('succeeds when finding variables with "sub" in them', () => {
954
- let file = program.addOrReplaceFile('source/main.brs', `
1022
+ let file = program.setFile('source/main.brs', `
955
1023
  function DoSomething()
956
1024
  return value.subType()
957
1025
  end function
@@ -1034,10 +1102,8 @@ describe('BrsFile', () => {
1034
1102
  function DoSomething
1035
1103
  end function
1036
1104
  `);
1037
- (0, chai_1.expect)(file.getDiagnostics().length).to.be.greaterThan(0);
1038
- (0, chai_1.expect)(file.getDiagnostics()[0]).to.deep.include({
1039
- file: file
1040
- });
1105
+ (0, testHelpers_spec_1.expectHasDiagnostics)(file);
1106
+ (0, chai_1.expect)(file.getDiagnostics()[0].file).to.equal(file);
1041
1107
  (0, chai_1.expect)(file.getDiagnostics()[0].range.start.line).to.equal(1);
1042
1108
  });
1043
1109
  it('supports using the `next` keyword in a for loop', () => {
@@ -1049,7 +1115,7 @@ describe('BrsFile', () => {
1049
1115
  next
1050
1116
  end sub
1051
1117
  `);
1052
- (0, chai_1.expect)(file.getDiagnostics()).to.be.empty;
1118
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1053
1119
  });
1054
1120
  //test is not working yet, but will be enabled when brs supports this syntax
1055
1121
  it('supports assigning functions to objects', () => {
@@ -1062,7 +1128,7 @@ describe('BrsFile', () => {
1062
1128
  end sub
1063
1129
  end function
1064
1130
  `);
1065
- (0, chai_1.expect)(file.getDiagnostics().length).to.equal(0);
1131
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(file);
1066
1132
  });
1067
1133
  });
1068
1134
  describe('findCallables', () => {
@@ -1183,8 +1249,7 @@ describe('BrsFile', () => {
1183
1249
  }]);
1184
1250
  });
1185
1251
  it('finds function calls nested inside statements', () => {
1186
- var _a;
1187
- program.addOrReplaceFile(`source/main.brs`, `
1252
+ program.setFile(`source/main.brs`, `
1188
1253
  sub main()
1189
1254
  if true then
1190
1255
  DoesNotExist(1, 2)
@@ -1192,7 +1257,9 @@ describe('BrsFile', () => {
1192
1257
  end sub
1193
1258
  `);
1194
1259
  program.validate();
1195
- (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);
1260
+ (0, testHelpers_spec_1.expectDiagnostics)(program, [
1261
+ DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction('DoesNotExist', 'source')
1262
+ ]);
1196
1263
  });
1197
1264
  it('finds arguments with variable values', () => {
1198
1265
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1227,7 +1294,7 @@ describe('BrsFile', () => {
1227
1294
  (0, chai_1.expect)(file.callables.length).to.equal(0);
1228
1295
  });
1229
1296
  it('finds return type', () => {
1230
- let file = program.addOrReplaceFile('source/main.brs', `
1297
+ let file = program.setFile('source/main.brs', `
1231
1298
  function DoSomething() as string
1232
1299
  end function
1233
1300
  `);
@@ -1321,7 +1388,7 @@ describe('BrsFile', () => {
1321
1388
  (0, chai_1.expect)(scope.variableDeclarations[0].name).to.equal('theLength');
1322
1389
  });
1323
1390
  it('finds value from global return', () => {
1324
- let file = program.addOrReplaceFile('source/main.brs', `
1391
+ let file = program.setFile('source/main.brs', `
1325
1392
  sub Main()
1326
1393
  myName = GetName()
1327
1394
  end sub
@@ -1366,7 +1433,7 @@ describe('BrsFile', () => {
1366
1433
  });
1367
1434
  describe('getHover', () => {
1368
1435
  it('works for param types', () => {
1369
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1436
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1370
1437
  sub DoSomething(name as string)
1371
1438
  name = 1
1372
1439
  sayMyName = function(name as string)
@@ -1384,7 +1451,7 @@ describe('BrsFile', () => {
1384
1451
  });
1385
1452
  //ignore this for now...it's not a huge deal
1386
1453
  it('does not match on keywords or data types', () => {
1387
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1454
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1388
1455
  sub Main(name as string)
1389
1456
  end sub
1390
1457
  sub as()
@@ -1396,7 +1463,7 @@ describe('BrsFile', () => {
1396
1463
  (0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 36))).not.to.exist;
1397
1464
  });
1398
1465
  it('finds declared function', () => {
1399
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1466
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1400
1467
  function Main(count = 1)
1401
1468
  firstName = "bob"
1402
1469
  age = 21
@@ -1406,10 +1473,14 @@ describe('BrsFile', () => {
1406
1473
  let hover = file.getHover(vscode_languageserver_1.Position.create(1, 28));
1407
1474
  (0, chai_1.expect)(hover).to.exist;
1408
1475
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
1409
- (0, chai_1.expect)(hover.contents).to.equal('function Main(count? as dynamic) as dynamic');
1476
+ (0, chai_1.expect)(hover.contents).to.equal([
1477
+ '```brightscript',
1478
+ 'function Main(count? as dynamic) as dynamic',
1479
+ '```'
1480
+ ].join('\n'));
1410
1481
  });
1411
1482
  it('finds variable function hover in same scope', () => {
1412
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1483
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1413
1484
  sub Main()
1414
1485
  sayMyName = sub(name as string)
1415
1486
  end sub
@@ -1419,10 +1490,39 @@ describe('BrsFile', () => {
1419
1490
  `);
1420
1491
  let hover = file.getHover(vscode_languageserver_1.Position.create(5, 24));
1421
1492
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
1422
- (0, chai_1.expect)(hover.contents).to.equal('sub sayMyName(name as string) as void');
1493
+ (0, chai_1.expect)(hover.contents).to.equal([
1494
+ '```brightscript',
1495
+ 'sub sayMyName(name as string) as void',
1496
+ '```'
1497
+ ].join('\n'));
1498
+ });
1499
+ it('does not crash when hovering on built-in functions', async () => {
1500
+ let file = program.setFile('source/main.brs', `
1501
+ function doUcase(text)
1502
+ return ucase(text)
1503
+ end function
1504
+ `);
1505
+ (0, chai_1.expect)((await program.getHover(file.pathAbsolute, vscode_languageserver_1.Position.create(2, 30))).contents).to.equal([
1506
+ '```brightscript',
1507
+ 'function UCase(s as string) as string',
1508
+ '```'
1509
+ ].join('\n'));
1510
+ });
1511
+ it('does not crash when hovering on object method call', async () => {
1512
+ let file = program.setFile('source/main.brs', `
1513
+ function getInstr(url, text)
1514
+ return url.instr(text)
1515
+ end function
1516
+ `);
1517
+ (0, chai_1.expect)((await program.getHover(file.pathAbsolute, vscode_languageserver_1.Position.create(2, 35))).contents).to.equal([
1518
+ '```brightscript',
1519
+ //TODO this really shouldn't be returning the global function, but it does...so make sure it doesn't crash right now.
1520
+ 'function Instr(start as integer, text as string, substring as string) as integer',
1521
+ '```'
1522
+ ].join('\n'));
1423
1523
  });
1424
1524
  it('finds function hover in file scope', () => {
1425
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1525
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1426
1526
  sub Main()
1427
1527
  sayMyName()
1428
1528
  end sub
@@ -1433,19 +1533,23 @@ describe('BrsFile', () => {
1433
1533
  `);
1434
1534
  let hover = file.getHover(vscode_languageserver_1.Position.create(2, 25));
1435
1535
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1436
- (0, chai_1.expect)(hover.contents).to.equal('sub sayMyName() as void');
1536
+ (0, chai_1.expect)(hover.contents).to.equal([
1537
+ '```brightscript',
1538
+ 'sub sayMyName() as void',
1539
+ '```'
1540
+ ].join('\n'));
1437
1541
  });
1438
1542
  it('finds function hover in scope', () => {
1439
1543
  let rootDir = process.cwd();
1440
1544
  program = new Program_1.Program({
1441
1545
  rootDir: rootDir
1442
1546
  });
1443
- let mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1547
+ let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1444
1548
  sub Main()
1445
1549
  sayMyName()
1446
1550
  end sub
1447
1551
  `);
1448
- program.addOrReplaceFile({ src: `${rootDir}/source/lib.brs`, dest: 'source/lib.brs' }, `
1552
+ program.setFile({ src: `${rootDir}/source/lib.brs`, dest: 'source/lib.brs' }, `
1449
1553
  sub sayMyName(name as string)
1450
1554
 
1451
1555
  end sub
@@ -1453,37 +1557,83 @@ describe('BrsFile', () => {
1453
1557
  let hover = mainFile.getHover(vscode_languageserver_1.Position.create(2, 25));
1454
1558
  (0, chai_1.expect)(hover).to.exist;
1455
1559
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
1456
- (0, chai_1.expect)(hover.contents).to.equal('sub sayMyName(name as string) as void');
1560
+ (0, chai_1.expect)(hover.contents).to.equal([
1561
+ '```brightscript',
1562
+ 'sub sayMyName(name as string) as void',
1563
+ '```'
1564
+ ].join('\n'));
1565
+ });
1566
+ it('includes markdown comments in hover.', async () => {
1567
+ let rootDir = process.cwd();
1568
+ program = new Program_1.Program({
1569
+ rootDir: rootDir
1570
+ });
1571
+ const file = program.setFile('source/lib.brs', `
1572
+ '
1573
+ ' The main function
1574
+ '
1575
+ sub main()
1576
+ log("hello")
1577
+ end sub
1578
+
1579
+ '
1580
+ ' Prints a message to the log.
1581
+ ' Works with *markdown* **content**
1582
+ '
1583
+ sub log(message as string)
1584
+ print message
1585
+ end sub
1586
+ `);
1587
+ //hover over log("hello")
1588
+ (0, chai_1.expect)((await program.getHover(file.pathAbsolute, vscode_languageserver_1.Position.create(5, 22))).contents).to.equal([
1589
+ '```brightscript',
1590
+ 'sub log(message as string) as void',
1591
+ '```',
1592
+ '***',
1593
+ '',
1594
+ ' Prints a message to the log.',
1595
+ ' Works with *markdown* **content**',
1596
+ ''
1597
+ ].join('\n'));
1598
+ //hover over sub ma|in()
1599
+ (0, chai_1.expect)((await program.getHover(file.pathAbsolute, vscode_languageserver_1.Position.create(4, 22))).contents).to.equal((0, testHelpers_spec_1.trim) `
1600
+ \`\`\`brightscript
1601
+ sub main() as void
1602
+ \`\`\`
1603
+ ***
1604
+
1605
+ The main function
1606
+ `);
1457
1607
  });
1458
1608
  it('handles mixed case `then` partions of conditionals', () => {
1459
- let mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1609
+ let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1460
1610
  sub Main()
1461
1611
  if true then
1462
1612
  print "works"
1463
1613
  end if
1464
1614
  end sub
1465
1615
  `);
1466
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1467
- mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1616
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1617
+ mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1468
1618
  sub Main()
1469
1619
  if true Then
1470
1620
  print "works"
1471
1621
  end if
1472
1622
  end sub
1473
1623
  `);
1474
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1475
- mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1624
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1625
+ mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1476
1626
  sub Main()
1477
1627
  if true THEN
1478
1628
  print "works"
1479
1629
  end if
1480
1630
  end sub
1481
1631
  `);
1482
- (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1632
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
1483
1633
  });
1484
1634
  });
1485
1635
  it('does not throw when encountering incomplete import statement', () => {
1486
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1636
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1487
1637
  import
1488
1638
  sub main()
1489
1639
  end sub
@@ -1788,9 +1938,9 @@ describe('BrsFile', () => {
1788
1938
  });
1789
1939
  it('computes correct locations for sourcemap', async () => {
1790
1940
  let source = `function abc(name)\n firstName = name\nend function`;
1791
- let tokens = lexer_1.Lexer.scan(source).tokens
1941
+ let tokens = Lexer_1.Lexer.scan(source).tokens
1792
1942
  //remove newlines and EOF
1793
- .filter(x => x.kind !== lexer_1.TokenKind.Eof && x.kind !== lexer_1.TokenKind.Newline);
1943
+ .filter(x => x.kind !== TokenKind_1.TokenKind.Eof && x.kind !== TokenKind_1.TokenKind.Newline);
1794
1944
  program.options.sourceMap = true;
1795
1945
  let result = testTranspile(source, source, 'none');
1796
1946
  //load the source map
@@ -2006,7 +2156,7 @@ describe('BrsFile', () => {
2006
2156
  `);
2007
2157
  });
2008
2158
  it('simple mapped files include a reference to the source map', () => {
2009
- let file = program.addOrReplaceFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
2159
+ let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
2010
2160
  sub logInfo()
2011
2161
  end sub
2012
2162
  `);
@@ -2015,7 +2165,7 @@ describe('BrsFile', () => {
2015
2165
  (0, chai_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
2016
2166
  });
2017
2167
  it('AST generated files include a reference to the source map', () => {
2018
- let file = program.addOrReplaceFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
2168
+ let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
2019
2169
  sub logInfo()
2020
2170
  end sub
2021
2171
  `);
@@ -2024,7 +2174,7 @@ describe('BrsFile', () => {
2024
2174
  (0, chai_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
2025
2175
  });
2026
2176
  it('replaces custom types in parameter types and return types', () => {
2027
- program.addOrReplaceFile('source/SomeKlass.bs', `
2177
+ program.setFile('source/SomeKlass.bs', `
2028
2178
  class SomeKlass
2029
2179
  end class
2030
2180
  `);
@@ -2048,14 +2198,13 @@ describe('BrsFile', () => {
2048
2198
  describe('callfunc operator', () => {
2049
2199
  describe('transpile', () => {
2050
2200
  it('does not produce diagnostics', () => {
2051
- var _a;
2052
- program.addOrReplaceFile('source/main.bs', `
2201
+ program.setFile('source/main.bs', `
2053
2202
  sub main()
2054
2203
  someObject@.someFunction(paramObject.value)
2055
2204
  end sub
2056
2205
  `);
2057
2206
  program.validate();
2058
- (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).not.to.exist;
2207
+ (0, testHelpers_spec_1.expectZeroDiagnostics)(program);
2059
2208
  });
2060
2209
  it('sets invalid on empty callfunc', () => {
2061
2210
  testTranspile(`
@@ -2095,13 +2244,12 @@ describe('BrsFile', () => {
2095
2244
  name: 'transform callback',
2096
2245
  afterFileParse: onParsed
2097
2246
  });
2098
- const file = new BrsFile_1.BrsFile(`absolute_path/file${ext}`, `relative_path/file${ext}`, program);
2099
- (0, chai_1.expect)(file.extension).to.equal(ext);
2100
- file.parse(`
2247
+ file = program.setFile({ src: `absolute_path/file${ext}`, dest: `relative_path/file${ext}` }, `
2101
2248
  sub Sum()
2102
2249
  print "hello world"
2103
2250
  end sub
2104
2251
  `);
2252
+ (0, chai_1.expect)(file.extension).to.equal(ext);
2105
2253
  return file;
2106
2254
  }
2107
2255
  it('called for BRS file', () => {
@@ -2117,25 +2265,25 @@ describe('BrsFile', () => {
2117
2265
  });
2118
2266
  describe('typedefKey', () => {
2119
2267
  it('works for .brs files', () => {
2120
- (0, chai_1.expect)((0, util_1.standardizePath)((program.addOrReplaceFile('source/main.brs', '')).typedefKey)).to.equal((0, util_1.standardizePath) `${rootDir.toLowerCase()}/source/main.d.bs`);
2268
+ (0, chai_1.expect)((0, util_1.standardizePath)((program.setFile('source/main.brs', '')).typedefKey)).to.equal((0, util_1.standardizePath) `${rootDir.toLowerCase()}/source/main.d.bs`);
2121
2269
  });
2122
2270
  it('returns undefined for files that should not have a typedef', () => {
2123
- (0, chai_1.expect)((program.addOrReplaceFile('source/main.bs', '')).typedefKey).to.be.undefined;
2124
- (0, chai_1.expect)((program.addOrReplaceFile('source/main.d.bs', '')).typedefKey).to.be.undefined;
2125
- const xmlFile = program.addOrReplaceFile('components/comp.xml', '');
2271
+ (0, chai_1.expect)((program.setFile('source/main.bs', '')).typedefKey).to.be.undefined;
2272
+ (0, chai_1.expect)((program.setFile('source/main.d.bs', '')).typedefKey).to.be.undefined;
2273
+ const xmlFile = program.setFile('components/comp.xml', '');
2126
2274
  (0, chai_1.expect)(xmlFile.typedefKey).to.be.undefined;
2127
2275
  });
2128
2276
  });
2129
2277
  describe('type definitions', () => {
2130
2278
  it('only exposes defined functions even if source has more', () => {
2131
2279
  //parse the .brs file first so it doesn't know about the typedef
2132
- program.addOrReplaceFile('source/main.brs', `
2280
+ program.setFile('source/main.brs', `
2133
2281
  sub main()
2134
2282
  end sub
2135
2283
  sub speak()
2136
2284
  end sub
2137
2285
  `);
2138
- program.addOrReplaceFile('source/main.d.bs', `
2286
+ program.setFile('source/main.d.bs', `
2139
2287
  sub main()
2140
2288
  end sub
2141
2289
  `);
@@ -2145,7 +2293,7 @@ describe('BrsFile', () => {
2145
2293
  (0, chai_1.expect)(functionNames).not.to.include('speak');
2146
2294
  });
2147
2295
  it('reacts to typedef file changes', () => {
2148
- let file = program.addOrReplaceFile('source/main.brs', `
2296
+ let file = program.setFile('source/main.brs', `
2149
2297
  sub main()
2150
2298
  end sub
2151
2299
  sub speak()
@@ -2153,14 +2301,14 @@ describe('BrsFile', () => {
2153
2301
  `);
2154
2302
  (0, chai_1.expect)(file.hasTypedef).to.be.false;
2155
2303
  (0, chai_1.expect)(file.typedefFile).not.to.exist;
2156
- program.addOrReplaceFile('source/main.d.bs', `
2304
+ program.setFile('source/main.d.bs', `
2157
2305
  sub main()
2158
2306
  end sub
2159
2307
  `);
2160
2308
  (0, chai_1.expect)(file.hasTypedef).to.be.true;
2161
2309
  (0, chai_1.expect)(file.typedefFile).to.exist;
2162
2310
  //add replace file, does it still find the typedef
2163
- file = program.addOrReplaceFile('source/main.brs', `
2311
+ file = program.setFile('source/main.brs', `
2164
2312
  sub main()
2165
2313
  end sub
2166
2314
  sub speak()
@@ -2175,36 +2323,36 @@ describe('BrsFile', () => {
2175
2323
  });
2176
2324
  describe('typedef', () => {
2177
2325
  it('sets typedef path properly', () => {
2178
- (0, chai_1.expect)((program.addOrReplaceFile('source/main1.brs', '')).typedefKey).to.equal((0, util_1.standardizePath) `${rootDir}/source/main1.d.bs`.toLowerCase());
2179
- (0, chai_1.expect)((program.addOrReplaceFile('source/main2.d.bs', '')).typedefKey).to.equal(undefined);
2180
- (0, chai_1.expect)((program.addOrReplaceFile('source/main3.bs', '')).typedefKey).to.equal(undefined);
2326
+ (0, chai_1.expect)((program.setFile('source/main1.brs', '')).typedefKey).to.equal((0, util_1.standardizePath) `${rootDir}/source/main1.d.bs`.toLowerCase());
2327
+ (0, chai_1.expect)((program.setFile('source/main2.d.bs', '')).typedefKey).to.equal(undefined);
2328
+ (0, chai_1.expect)((program.setFile('source/main3.bs', '')).typedefKey).to.equal(undefined);
2181
2329
  //works for dest with `.brs` extension
2182
- (0, chai_1.expect)((program.addOrReplaceFile({ src: 'source/main4.bs', dest: 'source/main4.brs' }, '')).typedefKey).to.equal(undefined);
2330
+ (0, chai_1.expect)((program.setFile({ src: 'source/main4.bs', dest: 'source/main4.brs' }, '')).typedefKey).to.equal(undefined);
2183
2331
  });
2184
2332
  it('does not link when missing from program', () => {
2185
- const file = program.addOrReplaceFile('source/main.brs', ``);
2333
+ const file = program.setFile('source/main.brs', ``);
2186
2334
  (0, chai_1.expect)(file.typedefFile).not.to.exist;
2187
2335
  });
2188
2336
  it('links typedef when added BEFORE .brs file', () => {
2189
- const typedef = program.addOrReplaceFile('source/main.d.bs', ``);
2190
- const file = program.addOrReplaceFile('source/main.brs', ``);
2337
+ const typedef = program.setFile('source/main.d.bs', ``);
2338
+ const file = program.setFile('source/main.brs', ``);
2191
2339
  (0, chai_1.expect)(file.typedefFile).to.equal(typedef);
2192
2340
  });
2193
2341
  it('links typedef when added AFTER .brs file', () => {
2194
- const file = program.addOrReplaceFile('source/main.brs', ``);
2195
- const typedef = program.addOrReplaceFile('source/main.d.bs', ``);
2342
+ const file = program.setFile('source/main.brs', ``);
2343
+ const typedef = program.setFile('source/main.d.bs', ``);
2196
2344
  (0, chai_1.expect)(file.typedefFile).to.eql(typedef);
2197
2345
  });
2198
2346
  it('removes typedef link when typedef is removed', () => {
2199
- const typedef = program.addOrReplaceFile('source/main.d.bs', ``);
2200
- const file = program.addOrReplaceFile('source/main.brs', ``);
2347
+ const typedef = program.setFile('source/main.d.bs', ``);
2348
+ const file = program.setFile('source/main.brs', ``);
2201
2349
  program.removeFile(typedef.pathAbsolute);
2202
2350
  (0, chai_1.expect)(file.typedefFile).to.be.undefined;
2203
2351
  });
2204
2352
  });
2205
2353
  describe('getTypedef', () => {
2206
2354
  function testTypedef(original, expected) {
2207
- let file = program.addOrReplaceFile('source/main.brs', original);
2355
+ let file = program.setFile('source/main.brs', original);
2208
2356
  (0, chai_1.expect)(file.getTypedef()).to.eql(expected);
2209
2357
  }
2210
2358
  it('includes namespace on extend class names', () => {
@@ -2455,7 +2603,7 @@ describe('BrsFile', () => {
2455
2603
  });
2456
2604
  describe('parser getter', () => {
2457
2605
  it('recreates the parser when missing', () => {
2458
- const file = program.addOrReplaceFile('source/main.brs', `
2606
+ const file = program.setFile('source/main.brs', `
2459
2607
  sub main()
2460
2608
  end sub
2461
2609
  `);
@@ -2469,11 +2617,11 @@ describe('BrsFile', () => {
2469
2617
  (0, chai_1.expect)(file.parser).to.equal(newParser);
2470
2618
  });
2471
2619
  it('call parse when previously skipped', () => {
2472
- program.addOrReplaceFile('source/main.d.bs', `
2620
+ program.setFile('source/main.d.bs', `'typedef
2473
2621
  sub main()
2474
2622
  end sub
2475
2623
  `);
2476
- const file = program.addOrReplaceFile('source/main.brs', `
2624
+ const file = program.setFile('source/main.brs', `'source
2477
2625
  sub main()
2478
2626
  end sub
2479
2627
  `);