brighterscript 0.41.2 → 1.0.0-alpha.12

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 (170) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/README.md +2 -2
  3. package/dist/DiagnosticCollection.js +2 -2
  4. package/dist/DiagnosticCollection.js.map +1 -1
  5. package/dist/DiagnosticFilterer.js +2 -2
  6. package/dist/DiagnosticFilterer.js.map +1 -1
  7. package/dist/DiagnosticMessages.d.ts +6 -1
  8. package/dist/DiagnosticMessages.js +5 -0
  9. package/dist/DiagnosticMessages.js.map +1 -1
  10. package/dist/LanguageServer.d.ts +8 -2
  11. package/dist/LanguageServer.js +50 -44
  12. package/dist/LanguageServer.js.map +1 -1
  13. package/dist/Program.d.ts +61 -45
  14. package/dist/Program.js +305 -188
  15. package/dist/Program.js.map +1 -1
  16. package/dist/ProgramBuilder.d.ts +7 -7
  17. package/dist/ProgramBuilder.js +60 -51
  18. package/dist/ProgramBuilder.js.map +1 -1
  19. package/dist/Scope.d.ts +42 -19
  20. package/dist/Scope.js +261 -129
  21. package/dist/Scope.js.map +1 -1
  22. package/dist/SymbolTable.d.ts +73 -0
  23. package/dist/SymbolTable.js +157 -0
  24. package/dist/SymbolTable.js.map +1 -0
  25. package/dist/XmlScope.d.ts +5 -0
  26. package/dist/XmlScope.js +66 -28
  27. package/dist/XmlScope.js.map +1 -1
  28. package/dist/astUtils/creators.d.ts +15 -1
  29. package/dist/astUtils/creators.js +39 -9
  30. package/dist/astUtils/creators.js.map +1 -1
  31. package/dist/astUtils/reflection.d.ts +28 -16
  32. package/dist/astUtils/reflection.js +52 -30
  33. package/dist/astUtils/reflection.js.map +1 -1
  34. package/dist/astUtils/reflection.spec.js +3 -3
  35. package/dist/astUtils/reflection.spec.js.map +1 -1
  36. package/dist/astUtils/visitors.spec.js +12 -13
  37. package/dist/astUtils/visitors.spec.js.map +1 -1
  38. package/dist/astUtils/xml.d.ts +3 -3
  39. package/dist/astUtils/xml.js +2 -2
  40. package/dist/astUtils/xml.js.map +1 -1
  41. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +5 -6
  42. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  43. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +24 -22
  44. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  45. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js +2 -2
  46. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +1 -1
  47. package/dist/examples/plugins/removePrint.js +1 -1
  48. package/dist/examples/plugins/removePrint.js.map +1 -1
  49. package/dist/files/BrsFile.Class.spec.js +356 -41
  50. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  51. package/dist/files/BrsFile.d.ts +55 -37
  52. package/dist/files/BrsFile.js +430 -399
  53. package/dist/files/BrsFile.js.map +1 -1
  54. package/dist/files/BrsFile.spec.js +199 -158
  55. package/dist/files/BrsFile.spec.js.map +1 -1
  56. package/dist/files/XmlFile.d.ts +20 -9
  57. package/dist/files/XmlFile.js +36 -31
  58. package/dist/files/XmlFile.js.map +1 -1
  59. package/dist/files/XmlFile.spec.js +113 -113
  60. package/dist/files/XmlFile.spec.js.map +1 -1
  61. package/dist/files/tests/imports.spec.js +32 -32
  62. package/dist/files/tests/imports.spec.js.map +1 -1
  63. package/dist/globalCallables.js +17 -6
  64. package/dist/globalCallables.js.map +1 -1
  65. package/dist/interfaces.d.ts +155 -39
  66. package/dist/parser/BrsTranspileState.d.ts +7 -0
  67. package/dist/parser/BrsTranspileState.js +10 -1
  68. package/dist/parser/BrsTranspileState.js.map +1 -1
  69. package/dist/parser/Expression.d.ts +23 -12
  70. package/dist/parser/Expression.js +45 -30
  71. package/dist/parser/Expression.js.map +1 -1
  72. package/dist/parser/Parser.Class.spec.js +100 -1
  73. package/dist/parser/Parser.Class.spec.js.map +1 -1
  74. package/dist/parser/Parser.d.ts +118 -5
  75. package/dist/parser/Parser.js +398 -37
  76. package/dist/parser/Parser.js.map +1 -1
  77. package/dist/parser/Parser.spec.js +404 -7
  78. package/dist/parser/Parser.spec.js.map +1 -1
  79. package/dist/parser/SGParser.d.ts +41 -4
  80. package/dist/parser/SGParser.js +185 -174
  81. package/dist/parser/SGParser.js.map +1 -1
  82. package/dist/parser/SGParser.spec.js +17 -4
  83. package/dist/parser/SGParser.spec.js.map +1 -1
  84. package/dist/parser/SGTypes.d.ts +203 -38
  85. package/dist/parser/SGTypes.js +464 -160
  86. package/dist/parser/SGTypes.js.map +1 -1
  87. package/dist/parser/SGTypes.spec.d.ts +1 -0
  88. package/dist/parser/SGTypes.spec.js +351 -0
  89. package/dist/parser/SGTypes.spec.js.map +1 -0
  90. package/dist/parser/Statement.d.ts +37 -26
  91. package/dist/parser/Statement.js +81 -20
  92. package/dist/parser/Statement.js.map +1 -1
  93. package/dist/parser/Statement.spec.js +5 -5
  94. package/dist/parser/Statement.spec.js.map +1 -1
  95. package/dist/parser/TranspileState.d.ts +1 -1
  96. package/dist/parser/TranspileState.js +15 -7
  97. package/dist/parser/TranspileState.js.map +1 -1
  98. package/dist/parser/tests/controlFlow/ForEach.spec.js +5 -4
  99. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  100. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +1 -1
  101. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  102. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +1 -1
  103. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  104. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +1 -1
  105. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  106. package/dist/parser/tests/expression/TernaryExpression.spec.js +1 -1
  107. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  108. package/dist/types/ArrayType.d.ts +1 -0
  109. package/dist/types/ArrayType.js +23 -19
  110. package/dist/types/ArrayType.js.map +1 -1
  111. package/dist/types/BooleanType.d.ts +3 -2
  112. package/dist/types/BooleanType.js +6 -3
  113. package/dist/types/BooleanType.js.map +1 -1
  114. package/dist/types/BscType.d.ts +19 -4
  115. package/dist/types/BscType.js +9 -0
  116. package/dist/types/BscType.js.map +1 -1
  117. package/dist/types/CustomType.d.ts +8 -5
  118. package/dist/types/CustomType.js +12 -12
  119. package/dist/types/CustomType.js.map +1 -1
  120. package/dist/types/DoubleType.d.ts +1 -0
  121. package/dist/types/DoubleType.js +11 -11
  122. package/dist/types/DoubleType.js.map +1 -1
  123. package/dist/types/DynamicType.d.ts +1 -0
  124. package/dist/types/DynamicType.js +4 -0
  125. package/dist/types/DynamicType.js.map +1 -1
  126. package/dist/types/FloatType.d.ts +2 -1
  127. package/dist/types/FloatType.js +11 -11
  128. package/dist/types/FloatType.js.map +1 -1
  129. package/dist/types/FunctionType.d.ts +13 -10
  130. package/dist/types/FunctionType.js +34 -18
  131. package/dist/types/FunctionType.js.map +1 -1
  132. package/dist/types/FunctionType.spec.js +8 -2
  133. package/dist/types/FunctionType.spec.js.map +1 -1
  134. package/dist/types/IntegerType.d.ts +2 -1
  135. package/dist/types/IntegerType.js +11 -11
  136. package/dist/types/IntegerType.js.map +1 -1
  137. package/dist/types/InvalidType.d.ts +3 -2
  138. package/dist/types/InvalidType.js +7 -4
  139. package/dist/types/InvalidType.js.map +1 -1
  140. package/dist/types/LazyType.d.ts +17 -0
  141. package/dist/types/LazyType.js +44 -0
  142. package/dist/types/LazyType.js.map +1 -0
  143. package/dist/types/LongIntegerType.d.ts +2 -1
  144. package/dist/types/LongIntegerType.js +11 -11
  145. package/dist/types/LongIntegerType.js.map +1 -1
  146. package/dist/types/ObjectType.d.ts +6 -2
  147. package/dist/types/ObjectType.js +9 -3
  148. package/dist/types/ObjectType.js.map +1 -1
  149. package/dist/types/StringType.d.ts +3 -2
  150. package/dist/types/StringType.js +6 -3
  151. package/dist/types/StringType.js.map +1 -1
  152. package/dist/types/UninitializedType.d.ts +4 -2
  153. package/dist/types/UninitializedType.js +8 -3
  154. package/dist/types/UninitializedType.js.map +1 -1
  155. package/dist/types/VoidType.d.ts +3 -2
  156. package/dist/types/VoidType.js +6 -3
  157. package/dist/types/VoidType.js.map +1 -1
  158. package/dist/types/helpers.d.ts +42 -0
  159. package/dist/types/helpers.js +113 -0
  160. package/dist/types/helpers.js.map +1 -0
  161. package/dist/util.d.ts +68 -15
  162. package/dist/util.js +193 -45
  163. package/dist/util.js.map +1 -1
  164. package/dist/validators/ClassValidator.d.ts +5 -1
  165. package/dist/validators/ClassValidator.js +31 -17
  166. package/dist/validators/ClassValidator.js.map +1 -1
  167. package/package.json +1 -1
  168. package/dist/FunctionScope.d.ts +0 -27
  169. package/dist/FunctionScope.js +0 -49
  170. package/dist/FunctionScope.js.map +0 -1
@@ -19,6 +19,7 @@ const PluginInterface_1 = require("../PluginInterface");
19
19
  const testHelpers_spec_1 = require("../testHelpers.spec");
20
20
  const Parser_1 = require("../parser/Parser");
21
21
  const Logger_1 = require("../Logger");
22
+ const VoidType_1 = require("../types/VoidType");
22
23
  let sinon = sinonImport.createSandbox();
23
24
  describe('BrsFile', () => {
24
25
  let rootDir = (0, util_1.standardizePath) `${process.cwd()}/.tmp/rootDir`;
@@ -37,7 +38,7 @@ describe('BrsFile', () => {
37
38
  });
38
39
  it('supports the third parameter in CreateObject', () => {
39
40
  var _a;
40
- program.addOrReplaceFile('source/main.brs', `
41
+ program.setFile('source/main.brs', `
41
42
  sub main()
42
43
  regexp = CreateObject("roRegex", "[a-z]+", "i")
43
44
  end sub
@@ -47,7 +48,7 @@ describe('BrsFile', () => {
47
48
  });
48
49
  it('supports the 6 params in CreateObject for roRegion', () => {
49
50
  var _a;
50
- program.addOrReplaceFile('source/main.brs', `
51
+ program.setFile('source/main.brs', `
51
52
  sub createRegion(bitmap as object)
52
53
  region = CreateObject("roRegion", bitmap, 20, 40, 100, 200)
53
54
  end sub
@@ -77,7 +78,7 @@ describe('BrsFile', () => {
77
78
  dest: `source/lib.brs`
78
79
  };
79
80
  it('creates proper tokens', () => {
80
- file = program.addOrReplaceFile(entry, `call(ModuleA.ModuleB.ModuleC.`);
81
+ file = program.setFile(entry, `call(ModuleA.ModuleB.ModuleC.`);
81
82
  (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[7])).to.equal('ModuleA.ModuleB.ModuleC.');
82
83
  (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[6])).to.equal('ModuleA.ModuleB.ModuleC');
83
84
  (0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[5])).to.equal('ModuleA.ModuleB.');
@@ -89,23 +90,23 @@ describe('BrsFile', () => {
89
90
  describe('getScopesForFile', () => {
90
91
  it('finds the scope for the file', () => {
91
92
  var _a;
92
- let file = program.addOrReplaceFile('source/main.brs', ``);
93
+ let file = program.setFile('source/main.brs', ``);
93
94
  (0, chai_1.expect)((_a = program.getScopesForFile(file)[0]) === null || _a === void 0 ? void 0 : _a.name).to.equal('source');
94
95
  });
95
96
  });
96
97
  describe('getCompletions', () => {
97
98
  it('does not crash for callfunc on a function call', () => {
98
- const file = program.addOrReplaceFile('source/main.brs', `
99
+ const file = program.setFile('source/main.brs', `
99
100
  sub main()
100
101
  getManager()@.
101
102
  end sub
102
103
  `);
103
104
  (0, chai_1.expect)(() => {
104
- program.getCompletions(file.pathAbsolute, util_1.default.createPosition(2, 34));
105
+ program.getCompletions(file.srcPath, util_1.default.createPosition(2, 34));
105
106
  }).not.to.throw;
106
107
  });
107
108
  it('suggests pkg paths in strings that match that criteria', () => {
108
- program.addOrReplaceFile('source/main.brs', `
109
+ program.setFile('source/main.brs', `
109
110
  sub main()
110
111
  print "pkg:"
111
112
  end sub
@@ -117,7 +118,7 @@ describe('BrsFile', () => {
117
118
  ]);
118
119
  });
119
120
  it('suggests libpkg paths in strings that match that criteria', () => {
120
- program.addOrReplaceFile('source/main.brs', `
121
+ program.setFile('source/main.brs', `
121
122
  sub main()
122
123
  print "libpkg:"
123
124
  end sub
@@ -129,7 +130,7 @@ describe('BrsFile', () => {
129
130
  ]);
130
131
  });
131
132
  it('suggests pkg paths in template strings', () => {
132
- program.addOrReplaceFile('source/main.brs', `
133
+ program.setFile('source/main.brs', `
133
134
  sub main()
134
135
  print \`pkg:\`
135
136
  end sub
@@ -142,7 +143,7 @@ describe('BrsFile', () => {
142
143
  });
143
144
  it('waits for the file to be processed before collecting completions', () => {
144
145
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
145
- program.addOrReplaceFile('source/main.brs', `
146
+ program.setFile('source/main.brs', `
146
147
  sub Main()
147
148
  print "hello"
148
149
  Say
@@ -158,7 +159,7 @@ describe('BrsFile', () => {
158
159
  });
159
160
  it('always includes `m`', () => {
160
161
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
161
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
162
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
162
163
  sub Main()
163
164
 
164
165
  end sub
@@ -169,14 +170,14 @@ describe('BrsFile', () => {
169
170
  });
170
171
  it('does not fail for missing previousToken', () => {
171
172
  //add a single character to the file, and get completions after it
172
- program.addOrReplaceFile('source/main.brs', `i`);
173
+ program.setFile('source/main.brs', `i`);
173
174
  (0, chai_1.expect)(() => {
174
175
  program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(0, 1)).map(x => x.label);
175
176
  }).not.to.throw;
176
177
  });
177
178
  it('includes all keywords`', () => {
178
179
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
179
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
180
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
180
181
  sub Main()
181
182
 
182
183
  end sub
@@ -197,7 +198,7 @@ describe('BrsFile', () => {
197
198
  });
198
199
  it('does not provide completions within a comment', () => {
199
200
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
200
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
201
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
201
202
  sub Main()
202
203
  'some comment
203
204
  end sub
@@ -208,7 +209,7 @@ describe('BrsFile', () => {
208
209
  });
209
210
  it('does not provide duplicate entries for variables', () => {
210
211
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
211
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
212
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
212
213
  sub Main()
213
214
  name = "bob"
214
215
  age = 12
@@ -223,7 +224,7 @@ describe('BrsFile', () => {
223
224
  });
224
225
  it('does not include `as` and `string` text options when used in function params', () => {
225
226
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
226
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
227
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
227
228
  sub Main(name as string)
228
229
 
229
230
  end sub
@@ -234,7 +235,7 @@ describe('BrsFile', () => {
234
235
  });
235
236
  it('does not provide intellisense results when inside a comment', () => {
236
237
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
237
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
238
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
238
239
  sub Main(name as string)
239
240
  'this is a comment
240
241
  end sub
@@ -245,7 +246,7 @@ describe('BrsFile', () => {
245
246
  it('does provide intellisence for labels only after a goto keyword', () => {
246
247
  var _a;
247
248
  //eslint-disable-next-line @typescript-eslint/no-floating-promises
248
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
249
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
249
250
  sub Main(name as string)
250
251
  something:
251
252
  goto \nend sub
@@ -254,12 +255,38 @@ describe('BrsFile', () => {
254
255
  (0, chai_1.expect)(results.length).to.equal(1);
255
256
  (0, chai_1.expect)((_a = results[0]) === null || _a === void 0 ? void 0 : _a.label).to.equal('something');
256
257
  });
258
+ it('includes properties of objects', () => {
259
+ //eslint-disable-next-line @typescript-eslint/no-floating-promises
260
+ program.setFile('source/main.brs', `
261
+ sub Main()
262
+ myObj = {name:"Bob", age: 34, height:6.0}
263
+ myObj.
264
+ end sub
265
+ `);
266
+ let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 26));
267
+ let names = result.map(x => x.label);
268
+ (0, chai_1.expect)(names).to.contain('name');
269
+ (0, chai_1.expect)(names).to.contain('age');
270
+ (0, chai_1.expect)(names).to.contain('height');
271
+ });
272
+ it('includes properties of m', () => {
273
+ //eslint-disable-next-line @typescript-eslint/no-floating-promises
274
+ program.setFile('source/main.brs', `
275
+ sub Main()
276
+ m.someField= "hello"
277
+ m.
278
+ end sub
279
+ `);
280
+ let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 22));
281
+ let names = result.map(x => x.label);
282
+ (0, chai_1.expect)(names).to.contain('someField');
283
+ });
257
284
  });
258
285
  describe('comment flags', () => {
259
286
  describe('bs:disable-next-line', () => {
260
287
  it('disables critical diagnostic issues', () => {
261
288
  var _a, _b;
262
- program.addOrReplaceFile('source/main.brs', `
289
+ program.setFile('source/main.brs', `
263
290
  sub main()
264
291
  Dim requestData
265
292
  end sub
@@ -267,7 +294,7 @@ describe('BrsFile', () => {
267
294
  //should have an error
268
295
  program.validate();
269
296
  (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
270
- program.addOrReplaceFile('source/main.brs', `
297
+ program.setFile('source/main.brs', `
271
298
  sub main()
272
299
  'bs:disable-next-line
273
300
  Dim requestData
@@ -279,7 +306,7 @@ describe('BrsFile', () => {
279
306
  });
280
307
  it('works with leading whitespace', () => {
281
308
  var _a;
282
- program.addOrReplaceFile('source/main.brs', `
309
+ program.setFile('source/main.brs', `
283
310
  sub main()
284
311
  ' bs:disable-next-line
285
312
  =asdf=sadf=
@@ -291,7 +318,7 @@ describe('BrsFile', () => {
291
318
  });
292
319
  it('works for all', () => {
293
320
  var _a;
294
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
321
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
295
322
  sub Main()
296
323
  'bs:disable-next-line
297
324
  name = "bob
@@ -309,7 +336,7 @@ describe('BrsFile', () => {
309
336
  });
310
337
  it('works for specific codes', () => {
311
338
  var _a;
312
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
339
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
313
340
  sub Main()
314
341
  'bs:disable-next-line: 1083, 1001
315
342
  name = "bob
@@ -326,7 +353,7 @@ describe('BrsFile', () => {
326
353
  });
327
354
  it('ignores non-numeric codes', () => {
328
355
  var _a;
329
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
356
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
330
357
  sub Main()
331
358
  'bs:disable-next-line: LINT9999
332
359
  name = "bob
@@ -336,7 +363,7 @@ describe('BrsFile', () => {
336
363
  (0, chai_1.expect)((_a = program.getDiagnostics()[0]) === null || _a === void 0 ? void 0 : _a.message).to.exist;
337
364
  });
338
365
  it('adds diagnostics for unknown numeric diagnostic codes', () => {
339
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
366
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
340
367
  sub main()
341
368
  print "hi" 'bs:disable-line: 123456 999999 aaaab
342
369
  end sub
@@ -353,7 +380,7 @@ describe('BrsFile', () => {
353
380
  });
354
381
  describe('bs:disable-line', () => {
355
382
  it('works for all', () => {
356
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
383
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
357
384
  sub Main()
358
385
  z::;;%%%%%% 'bs:disable-line
359
386
  end sub
@@ -369,7 +396,7 @@ describe('BrsFile', () => {
369
396
  (0, chai_1.expect)(program.getDiagnostics()).to.be.lengthOf(0);
370
397
  });
371
398
  it('works for specific codes', () => {
372
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
399
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
373
400
  sub main()
374
401
  'should not have any errors
375
402
  DoSomething(1) 'bs:disable-line:1002
@@ -389,7 +416,7 @@ describe('BrsFile', () => {
389
416
  //the current version of BRS causes parse errors after the `parse` keyword, showing error in comments
390
417
  //the program should ignore all diagnostics found in brs:* comment lines EXCEPT
391
418
  //for the diagnostics about using unknown error codes
392
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
419
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
393
420
  sub main()
394
421
  stop 'bs:disable-line
395
422
  print "need a valid line to fix stop error"
@@ -402,7 +429,7 @@ describe('BrsFile', () => {
402
429
  });
403
430
  describe('parse', () => {
404
431
  it('supports iife in assignment', () => {
405
- program.addOrReplaceFile('source/main.brs', `
432
+ program.setFile('source/main.brs', `
406
433
  sub main()
407
434
  result = sub()
408
435
  end sub()
@@ -414,7 +441,7 @@ describe('BrsFile', () => {
414
441
  });
415
442
  it('uses the proper parse mode based on file extension', () => {
416
443
  function testParseMode(destPath, expectedParseMode) {
417
- const file = program.addOrReplaceFile(destPath, '');
444
+ const file = program.setFile(destPath, '');
418
445
  (0, chai_1.expect)(file.parseMode).to.equal(expectedParseMode);
419
446
  }
420
447
  testParseMode('source/main.brs', Parser_1.ParseMode.BrightScript);
@@ -425,7 +452,7 @@ describe('BrsFile', () => {
425
452
  testParseMode('source/main.spec.bs', Parser_1.ParseMode.BrighterScript);
426
453
  });
427
454
  it('supports labels and goto statements', () => {
428
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
455
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
429
456
  sub Main()
430
457
  'multiple goto statements on one line
431
458
  goto myLabel : goto myLabel
@@ -435,7 +462,7 @@ describe('BrsFile', () => {
435
462
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
436
463
  });
437
464
  it('supports empty print statements', () => {
438
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
465
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
439
466
  sub main()
440
467
  print
441
468
  end sub
@@ -444,7 +471,7 @@ describe('BrsFile', () => {
444
471
  });
445
472
  describe('conditional compile', () => {
446
473
  it('works for upper case keywords', () => {
447
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
474
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
448
475
  sub main()
449
476
  #CONST someFlag = true
450
477
  #IF someFlag
@@ -459,7 +486,7 @@ describe('BrsFile', () => {
459
486
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
460
487
  });
461
488
  it('supports single-word #elseif and #endif', () => {
462
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
489
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
463
490
  sub main()
464
491
  #const someFlag = true
465
492
  #if someFlag
@@ -472,7 +499,7 @@ describe('BrsFile', () => {
472
499
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
473
500
  });
474
501
  it('supports multi-word #else if and #end if', () => {
475
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
502
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
476
503
  sub main()
477
504
  #const someFlag = true
478
505
  #if someFlag
@@ -485,7 +512,7 @@ describe('BrsFile', () => {
485
512
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
486
513
  });
487
514
  it('does not choke on invalid code inside a false conditional compile', () => {
488
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
515
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
489
516
  sub main()
490
517
  #if false
491
518
  non-commented code here should not cause parse errors
@@ -495,7 +522,7 @@ describe('BrsFile', () => {
495
522
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
496
523
  });
497
524
  it('detects syntax error in #if', () => {
498
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
525
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
499
526
  sub main()
500
527
  #if true1
501
528
  print "true"
@@ -505,7 +532,7 @@ describe('BrsFile', () => {
505
532
  (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue));
506
533
  });
507
534
  it('detects syntax error in #const', () => {
508
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
535
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
509
536
  sub main()
510
537
  #if %
511
538
  print "true"
@@ -515,7 +542,7 @@ describe('BrsFile', () => {
515
542
  (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%')));
516
543
  });
517
544
  it('detects #const name using reserved word', () => {
518
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
545
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
519
546
  sub main()
520
547
  #const function = true
521
548
  end sub
@@ -523,7 +550,7 @@ describe('BrsFile', () => {
523
550
  (0, chai_1.expect)(file.getDiagnostics()[0]).to.exist.and.deep.include(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord()));
524
551
  });
525
552
  it('detects syntax error in #const', () => {
526
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
553
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
527
554
  sub main()
528
555
  #const someConst = 123
529
556
  end sub
@@ -532,7 +559,7 @@ describe('BrsFile', () => {
532
559
  });
533
560
  });
534
561
  it('supports stop statement', () => {
535
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
562
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
536
563
  sub main()
537
564
  stop
538
565
  end sub
@@ -540,7 +567,7 @@ describe('BrsFile', () => {
540
567
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
541
568
  });
542
569
  it('supports single-line if statements', () => {
543
- 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' }, `
544
571
  sub main()
545
572
  if 1 < 2: return true: end if
546
573
  if 1 < 2: return true
@@ -649,7 +676,7 @@ describe('BrsFile', () => {
649
676
  `);
650
677
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
651
678
  });
652
- it('does not lose function scopes when mismatched end sub', () => {
679
+ it('does not lose function statements when mismatched end sub', () => {
653
680
  file.parse(`
654
681
  sub main()
655
682
  sayHi()
@@ -659,7 +686,7 @@ describe('BrsFile', () => {
659
686
  print "hello world"
660
687
  end sub
661
688
  `);
662
- (0, chai_1.expect)(file.functionScopes).to.be.lengthOf(2);
689
+ (0, chai_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(2);
663
690
  });
664
691
  it('does not lose sub scope when mismatched end function', () => {
665
692
  file.parse(`
@@ -671,7 +698,7 @@ describe('BrsFile', () => {
671
698
  print "hello world"
672
699
  end sub
673
700
  `);
674
- (0, chai_1.expect)(file.functionScopes).to.be.lengthOf(2);
701
+ (0, chai_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(2);
675
702
  });
676
703
  it('does not error with boolean in RHS of set statement', () => {
677
704
  file.parse(`
@@ -892,7 +919,7 @@ describe('BrsFile', () => {
892
919
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
893
920
  });
894
921
  it('adds error for library statements NOT at top of file', () => {
895
- let file = program.addOrReplaceFile('source/main.bs', `
922
+ let file = program.setFile('source/main.bs', `
896
923
  sub main()
897
924
  end sub
898
925
  import "file.brs"
@@ -908,7 +935,7 @@ describe('BrsFile', () => {
908
935
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
909
936
  });
910
937
  it('adds error for library statements NOT at top of file', () => {
911
- let file = program.addOrReplaceFile('source/main.brs', `
938
+ let file = program.setFile('source/main.brs', `
912
939
  sub main()
913
940
  end sub
914
941
  Library "v30/bslCore.brs"
@@ -918,7 +945,7 @@ describe('BrsFile', () => {
918
945
  ]);
919
946
  });
920
947
  it('adds error for library statements inside of function body', () => {
921
- let file = program.addOrReplaceFile('source/main.brs', `
948
+ let file = program.setFile('source/main.brs', `
922
949
  sub main()
923
950
  Library "v30/bslCore.brs"
924
951
  end sub
@@ -936,7 +963,7 @@ describe('BrsFile', () => {
936
963
  (0, chai_1.expect)(file.getDiagnostics()).to.be.lengthOf(0);
937
964
  });
938
965
  it('succeeds when finding variables with "sub" in them', () => {
939
- let file = program.addOrReplaceFile('source/main.brs', `
966
+ let file = program.setFile('source/main.brs', `
940
967
  function DoSomething()
941
968
  return value.subType()
942
969
  end function
@@ -1114,7 +1141,7 @@ describe('BrsFile', () => {
1114
1141
  isOptional: true,
1115
1142
  isRestArgument: false
1116
1143
  });
1117
- (0, chai_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
1144
+ (0, chai_1.expect)(callable.params[0].type).instanceof(IntegerType_1.IntegerType);
1118
1145
  });
1119
1146
  it('finds parameter types', () => {
1120
1147
  let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
@@ -1169,7 +1196,7 @@ describe('BrsFile', () => {
1169
1196
  });
1170
1197
  it('finds function calls nested inside statements', () => {
1171
1198
  var _a;
1172
- program.addOrReplaceFile(`source/main.brs`, `
1199
+ program.setFile(`source/main.brs`, `
1173
1200
  sub main()
1174
1201
  if true then
1175
1202
  DoesNotExist(1, 2)
@@ -1191,15 +1218,15 @@ describe('BrsFile', () => {
1191
1218
  `);
1192
1219
  (0, chai_1.expect)(file.functionCalls.length).to.equal(1);
1193
1220
  (0, chai_1.expect)(file.functionCalls[0].args[0]).deep.include({
1194
- type: new DynamicType_1.DynamicType(),
1221
+ type: new IntegerType_1.IntegerType(),
1195
1222
  text: 'count'
1196
1223
  });
1197
1224
  (0, chai_1.expect)(file.functionCalls[0].args[1]).deep.include({
1198
- type: new DynamicType_1.DynamicType(),
1225
+ type: new StringType_1.StringType(),
1199
1226
  text: 'name'
1200
1227
  });
1201
1228
  (0, chai_1.expect)(file.functionCalls[0].args[2]).deep.include({
1202
- type: new DynamicType_1.DynamicType(),
1229
+ type: new BooleanType_1.BooleanType(),
1203
1230
  text: 'isAlive'
1204
1231
  });
1205
1232
  });
@@ -1212,7 +1239,7 @@ describe('BrsFile', () => {
1212
1239
  (0, chai_1.expect)(file.callables.length).to.equal(0);
1213
1240
  });
1214
1241
  it('finds return type', () => {
1215
- let file = program.addOrReplaceFile('source/main.brs', `
1242
+ let file = program.setFile('source/main.brs', `
1216
1243
  function DoSomething() as string
1217
1244
  end function
1218
1245
  `);
@@ -1225,14 +1252,14 @@ describe('BrsFile', () => {
1225
1252
  (0, chai_1.expect)(file.callables[0].type.returnType).instanceof(StringType_1.StringType);
1226
1253
  });
1227
1254
  });
1228
- describe('createFunctionScopes', () => {
1255
+ describe('function local variable handling', () => {
1229
1256
  it('creates range properly', () => {
1230
1257
  file.parse(`
1231
1258
  sub Main()
1232
1259
  name = 'bob"
1233
1260
  end sub
1234
1261
  `);
1235
- (0, chai_1.expect)(file.functionScopes[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
1262
+ (0, chai_1.expect)(file.parser.references.functionStatements[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
1236
1263
  });
1237
1264
  it('creates scopes for parent and child functions', () => {
1238
1265
  file.parse(`
@@ -1246,23 +1273,9 @@ describe('BrsFile', () => {
1246
1273
  end sub)
1247
1274
  end sub
1248
1275
  `);
1249
- (0, chai_1.expect)(file.functionScopes).to.length(3);
1250
- });
1251
- it('outer function does not capture inner statements', () => {
1252
- file.parse(`
1253
- sub Main()
1254
- name = "john"
1255
- sayHi = sub()
1256
- age = 12
1257
- end sub
1258
- end sub
1259
- `);
1260
- let outerScope = file.getFunctionScopeAtPosition(vscode_languageserver_1.Position.create(2, 25));
1261
- (0, chai_1.expect)(outerScope.variableDeclarations).to.be.lengthOf(2);
1262
- let innerScope = file.getFunctionScopeAtPosition(vscode_languageserver_1.Position.create(4, 10));
1263
- (0, chai_1.expect)(innerScope.variableDeclarations).to.be.lengthOf(1);
1276
+ (0, chai_1.expect)(file.parser.references.functionExpressions).to.be.length(3);
1264
1277
  });
1265
- it('finds variables declared in function scopes', () => {
1278
+ it('finds variables declared in function expressions', () => {
1266
1279
  file.parse(`
1267
1280
  sub Main()
1268
1281
  sayHi = sub()
@@ -1274,24 +1287,15 @@ describe('BrsFile', () => {
1274
1287
  end sub)
1275
1288
  end sub
1276
1289
  `);
1277
- (0, chai_1.expect)(file.functionScopes[0].variableDeclarations).to.be.length(1);
1278
- (0, chai_1.expect)(file.functionScopes[0].variableDeclarations[0]).to.deep.include({
1279
- lineIndex: 2,
1280
- name: 'sayHi'
1281
- });
1282
- (0, chai_1.expect)(file.functionScopes[0].variableDeclarations[0].type).instanceof(FunctionType_1.FunctionType);
1283
- (0, chai_1.expect)(file.functionScopes[1].variableDeclarations).to.be.length(1);
1284
- (0, chai_1.expect)(file.functionScopes[1].variableDeclarations[0]).to.deep.include({
1285
- lineIndex: 3,
1286
- name: 'age'
1287
- });
1288
- (0, chai_1.expect)(file.functionScopes[1].variableDeclarations[0].type).instanceof(IntegerType_1.IntegerType);
1289
- (0, chai_1.expect)(file.functionScopes[2].variableDeclarations).to.be.length(1);
1290
- (0, chai_1.expect)(file.functionScopes[2].variableDeclarations[0]).to.deep.include({
1291
- lineIndex: 7,
1292
- name: 'name'
1293
- });
1294
- (0, chai_1.expect)(file.functionScopes[2].variableDeclarations[0].type).instanceof(StringType_1.StringType);
1290
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
1291
+ ['sayHi', new FunctionType_1.FunctionType(new VoidType_1.VoidType(), true), util_1.default.createRange(2, 20, 2, 25)]
1292
+ ]);
1293
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[1].symbolTable, [
1294
+ ['age', new IntegerType_1.IntegerType(), util_1.default.createRange(3, 24, 3, 27)]
1295
+ ]);
1296
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[2].symbolTable, [
1297
+ ['name', new StringType_1.StringType(), util_1.default.createRange(7, 24, 7, 28)]
1298
+ ]);
1295
1299
  });
1296
1300
  it('finds variable declarations inside of if statements', () => {
1297
1301
  file.parse(`
@@ -1301,12 +1305,12 @@ describe('BrsFile', () => {
1301
1305
  end if
1302
1306
  end sub
1303
1307
  `);
1304
- let scope = file.getFunctionScopeAtPosition(vscode_languageserver_1.Position.create(3, 0));
1305
- (0, chai_1.expect)(scope.variableDeclarations[0]).to.exist;
1306
- (0, chai_1.expect)(scope.variableDeclarations[0].name).to.equal('theLength');
1308
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
1309
+ ['theLength', new IntegerType_1.IntegerType(), util_1.default.createRange(3, 24, 3, 33)]
1310
+ ]);
1307
1311
  });
1308
1312
  it('finds value from global return', () => {
1309
- let file = program.addOrReplaceFile('source/main.brs', `
1313
+ let file = program.setFile('source/main.brs', `
1310
1314
  sub Main()
1311
1315
  myName = GetName()
1312
1316
  end sub
@@ -1315,12 +1319,9 @@ describe('BrsFile', () => {
1315
1319
  return "bob"
1316
1320
  end function
1317
1321
  `);
1318
- (0, chai_1.expect)(file.functionScopes[0].variableDeclarations).to.be.length(1);
1319
- (0, chai_1.expect)(file.functionScopes[0].variableDeclarations[0]).to.deep.include({
1320
- lineIndex: 2,
1321
- name: 'myName'
1322
- });
1323
- (0, chai_1.expect)(file.functionScopes[0].variableDeclarations[0].type).instanceof(StringType_1.StringType);
1322
+ (0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
1323
+ ['myName', new StringType_1.StringType(), util_1.default.createRange(2, 19, 2, 25)]
1324
+ ]);
1324
1325
  });
1325
1326
  it('finds variable type from other variable', () => {
1326
1327
  file.parse(`
@@ -1329,12 +1330,10 @@ describe('BrsFile', () => {
1329
1330
  nameCopy = name
1330
1331
  end sub
1331
1332
  `);
1332
- (0, chai_1.expect)(file.functionScopes[0].variableDeclarations).to.be.length(2);
1333
- (0, chai_1.expect)(file.functionScopes[0].variableDeclarations[1]).to.deep.include({
1334
- lineIndex: 3,
1335
- name: 'nameCopy'
1336
- });
1337
- (0, chai_1.expect)(file.functionScopes[0].variableDeclarations[1].type).instanceof(StringType_1.StringType);
1333
+ (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)]
1336
+ ]);
1338
1337
  });
1339
1338
  it('sets proper range for functions', () => {
1340
1339
  file.parse(`
@@ -1344,14 +1343,16 @@ describe('BrsFile', () => {
1344
1343
  end function
1345
1344
  end sub
1346
1345
  `);
1347
- (0, chai_1.expect)(file.functionScopes).to.be.length(2);
1348
- (0, chai_1.expect)(file.functionScopes[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 5, 23));
1349
- (0, chai_1.expect)(file.functionScopes[1].range).to.eql(vscode_languageserver_1.Range.create(2, 30, 4, 32));
1346
+ (0, chai_1.expect)(file.parser.references.functionExpressions).to.be.length(2);
1347
+ (0, chai_1.expect)(file.parser.references.functionExpressions.map(x => x.range)).to.eql([
1348
+ util_1.default.createRange(1, 16, 5, 23),
1349
+ util_1.default.createRange(2, 30, 4, 32)
1350
+ ]);
1350
1351
  });
1351
1352
  });
1352
1353
  describe('getHover', () => {
1353
1354
  it('works for param types', () => {
1354
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1355
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1355
1356
  sub DoSomething(name as string)
1356
1357
  name = 1
1357
1358
  sayMyName = function(name as string)
@@ -1369,7 +1370,7 @@ describe('BrsFile', () => {
1369
1370
  });
1370
1371
  //ignore this for now...it's not a huge deal
1371
1372
  it('does not match on keywords or data types', () => {
1372
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1373
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1373
1374
  sub Main(name as string)
1374
1375
  end sub
1375
1376
  sub as()
@@ -1381,7 +1382,7 @@ describe('BrsFile', () => {
1381
1382
  (0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 36))).not.to.exist;
1382
1383
  });
1383
1384
  it('finds declared function', () => {
1384
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1385
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1385
1386
  function Main(count = 1)
1386
1387
  firstName = "bob"
1387
1388
  age = 21
@@ -1391,10 +1392,10 @@ describe('BrsFile', () => {
1391
1392
  let hover = file.getHover(vscode_languageserver_1.Position.create(1, 28));
1392
1393
  (0, chai_1.expect)(hover).to.exist;
1393
1394
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
1394
- (0, chai_1.expect)(hover.contents).to.equal('function Main(count? as dynamic) as dynamic');
1395
+ (0, chai_1.expect)(hover.contents).to.equal('function Main(count? as integer) as dynamic');
1395
1396
  });
1396
1397
  it('finds variable function hover in same scope', () => {
1397
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1398
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1398
1399
  sub Main()
1399
1400
  sayMyName = sub(name as string)
1400
1401
  end sub
@@ -1404,10 +1405,10 @@ describe('BrsFile', () => {
1404
1405
  `);
1405
1406
  let hover = file.getHover(vscode_languageserver_1.Position.create(5, 24));
1406
1407
  (0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
1407
- (0, chai_1.expect)(hover.contents).to.equal('sub sayMyName(name as string) as void');
1408
+ (0, chai_1.expect)(hover.contents).to.equal('sub (name as string) as void');
1408
1409
  });
1409
1410
  it('finds function hover in file scope', () => {
1410
- let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1411
+ let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1411
1412
  sub Main()
1412
1413
  sayMyName()
1413
1414
  end sub
@@ -1425,12 +1426,12 @@ describe('BrsFile', () => {
1425
1426
  program = new Program_1.Program({
1426
1427
  rootDir: rootDir
1427
1428
  });
1428
- let mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1429
+ let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1429
1430
  sub Main()
1430
1431
  sayMyName()
1431
1432
  end sub
1432
1433
  `);
1433
- program.addOrReplaceFile({ src: `${rootDir}/source/lib.brs`, dest: 'source/lib.brs' }, `
1434
+ program.setFile({ src: `${rootDir}/source/lib.brs`, dest: 'source/lib.brs' }, `
1434
1435
  sub sayMyName(name as string)
1435
1436
 
1436
1437
  end sub
@@ -1441,7 +1442,7 @@ describe('BrsFile', () => {
1441
1442
  (0, chai_1.expect)(hover.contents).to.equal('sub sayMyName(name as string) as void');
1442
1443
  });
1443
1444
  it('handles mixed case `then` partions of conditionals', () => {
1444
- let mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1445
+ let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1445
1446
  sub Main()
1446
1447
  if true then
1447
1448
  print "works"
@@ -1449,7 +1450,7 @@ describe('BrsFile', () => {
1449
1450
  end sub
1450
1451
  `);
1451
1452
  (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1452
- mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1453
+ mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1453
1454
  sub Main()
1454
1455
  if true Then
1455
1456
  print "works"
@@ -1457,7 +1458,7 @@ describe('BrsFile', () => {
1457
1458
  end sub
1458
1459
  `);
1459
1460
  (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1460
- mainFile = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1461
+ mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1461
1462
  sub Main()
1462
1463
  if true THEN
1463
1464
  print "works"
@@ -1466,9 +1467,50 @@ describe('BrsFile', () => {
1466
1467
  `);
1467
1468
  (0, chai_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
1468
1469
  });
1470
+ it('displays the context from multiple scopes', () => {
1471
+ let commonFile = program.setFile('source/common.brs', `
1472
+ sub displayPi()
1473
+ pi = getPi()
1474
+ print pi
1475
+ end sub
1476
+ `);
1477
+ let scope1File = program.setFile('components/comp1/scope1.brs', `
1478
+ function getPi() as string
1479
+ return "apple"
1480
+ end function
1481
+ `);
1482
+ (0, chai_1.expect)(scope1File.getDiagnostics()).to.be.lengthOf(0);
1483
+ program.setFile('components/comp1/comp1.xml', (0, testHelpers_spec_1.trim) `
1484
+ <?xml version="1.0" encoding="utf-8" ?>
1485
+ <component name="Component1" extends="Group">
1486
+ <script type="text/brightscript" uri="scope1.brs" />
1487
+ <script type="text/brightscript" uri="pkg:/source/common.brs" />
1488
+ </component>
1489
+ `);
1490
+ let scope2File = program.setFile('components/comp2/scope2.brs', `
1491
+ function getPi() as float
1492
+ return 3.14
1493
+ end function
1494
+ `);
1495
+ (0, chai_1.expect)(scope2File.getDiagnostics()).to.be.lengthOf(0);
1496
+ program.setFile('components/comp2/comp2.xml', (0, testHelpers_spec_1.trim) `
1497
+ <?xml version="1.0" encoding="utf-8" ?>
1498
+ <component name="Component2" extends="Group">
1499
+ <script type="text/brightscript" uri="scope2.brs" />
1500
+ <script type="text/brightscript" uri="pkg:/source/common.brs" />
1501
+ </component>
1502
+ `);
1503
+ program.validate();
1504
+ 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');
1507
+ 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');
1510
+ });
1469
1511
  });
1470
1512
  it('does not throw when encountering incomplete import statement', () => {
1471
- program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1513
+ program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
1472
1514
  import
1473
1515
  sub main()
1474
1516
  end sub
@@ -1991,7 +2033,7 @@ describe('BrsFile', () => {
1991
2033
  `);
1992
2034
  });
1993
2035
  it('simple mapped files include a reference to the source map', () => {
1994
- let file = program.addOrReplaceFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
2036
+ let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
1995
2037
  sub logInfo()
1996
2038
  end sub
1997
2039
  `);
@@ -2000,7 +2042,7 @@ describe('BrsFile', () => {
2000
2042
  (0, chai_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
2001
2043
  });
2002
2044
  it('AST generated files include a reference to the source map', () => {
2003
- let file = program.addOrReplaceFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
2045
+ let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
2004
2046
  sub logInfo()
2005
2047
  end sub
2006
2048
  `);
@@ -2009,7 +2051,7 @@ describe('BrsFile', () => {
2009
2051
  (0, chai_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
2010
2052
  });
2011
2053
  it('replaces custom types in parameter types and return types', () => {
2012
- program.addOrReplaceFile('source/SomeKlass.bs', `
2054
+ program.setFile('source/SomeKlass.bs', `
2013
2055
  class SomeKlass
2014
2056
  end class
2015
2057
  `);
@@ -2034,7 +2076,7 @@ describe('BrsFile', () => {
2034
2076
  describe('transpile', () => {
2035
2077
  it('does not produce diagnostics', () => {
2036
2078
  var _a;
2037
- program.addOrReplaceFile('source/main.bs', `
2079
+ program.setFile('source/main.bs', `
2038
2080
  sub main()
2039
2081
  someObject@.someFunction(paramObject.value)
2040
2082
  end sub
@@ -2080,13 +2122,12 @@ describe('BrsFile', () => {
2080
2122
  name: 'transform callback',
2081
2123
  afterFileParse: onParsed
2082
2124
  });
2083
- const file = new BrsFile_1.BrsFile(`absolute_path/file${ext}`, `relative_path/file${ext}`, program);
2084
- (0, chai_1.expect)(file.extension).to.equal(ext);
2085
- file.parse(`
2125
+ file = program.setFile(`source/file.${ext}`, `
2086
2126
  sub Sum()
2087
- print "hello world"
2127
+ print "hello world"
2088
2128
  end sub
2089
2129
  `);
2130
+ (0, chai_1.expect)(file.extension).to.equal(ext);
2090
2131
  return file;
2091
2132
  }
2092
2133
  it('called for BRS file', () => {
@@ -2094,7 +2135,7 @@ describe('BrsFile', () => {
2094
2135
  parseFileWithCallback('.brs', onParsed);
2095
2136
  (0, chai_1.expect)(onParsed.callCount).to.equal(1);
2096
2137
  });
2097
- it('called for BR file', () => {
2138
+ it('called for BS file', () => {
2098
2139
  const onParsed = sinon.spy();
2099
2140
  parseFileWithCallback('.bs', onParsed);
2100
2141
  (0, chai_1.expect)(onParsed.callCount).to.equal(1);
@@ -2102,25 +2143,25 @@ describe('BrsFile', () => {
2102
2143
  });
2103
2144
  describe('typedefKey', () => {
2104
2145
  it('works for .brs files', () => {
2105
- (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`);
2146
+ (0, chai_1.expect)((0, util_1.standardizePath)((program.setFile('source/main.brs', '')).typedefSrcPath)).to.equal((0, util_1.standardizePath) `${rootDir.toLowerCase()}/source/main.d.bs`);
2106
2147
  });
2107
2148
  it('returns undefined for files that should not have a typedef', () => {
2108
- (0, chai_1.expect)((program.addOrReplaceFile('source/main.bs', '')).typedefKey).to.be.undefined;
2109
- (0, chai_1.expect)((program.addOrReplaceFile('source/main.d.bs', '')).typedefKey).to.be.undefined;
2110
- const xmlFile = program.addOrReplaceFile('components/comp.xml', '');
2111
- (0, chai_1.expect)(xmlFile.typedefKey).to.be.undefined;
2149
+ (0, chai_1.expect)((program.setFile('source/main.bs', '')).typedefSrcPath).to.be.undefined;
2150
+ (0, chai_1.expect)((program.setFile('source/main.d.bs', '')).typedefSrcPath).to.be.undefined;
2151
+ const xmlFile = program.setFile('components/comp.xml', '');
2152
+ (0, chai_1.expect)(xmlFile.typedefSrcPath).to.be.undefined;
2112
2153
  });
2113
2154
  });
2114
2155
  describe('type definitions', () => {
2115
2156
  it('only exposes defined functions even if source has more', () => {
2116
2157
  //parse the .brs file first so it doesn't know about the typedef
2117
- program.addOrReplaceFile('source/main.brs', `
2158
+ program.setFile('source/main.brs', `
2118
2159
  sub main()
2119
2160
  end sub
2120
2161
  sub speak()
2121
2162
  end sub
2122
2163
  `);
2123
- program.addOrReplaceFile('source/main.d.bs', `
2164
+ program.setFile('source/main.d.bs', `
2124
2165
  sub main()
2125
2166
  end sub
2126
2167
  `);
@@ -2130,7 +2171,7 @@ describe('BrsFile', () => {
2130
2171
  (0, chai_1.expect)(functionNames).not.to.include('speak');
2131
2172
  });
2132
2173
  it('reacts to typedef file changes', () => {
2133
- let file = program.addOrReplaceFile('source/main.brs', `
2174
+ let file = program.setFile('source/main.brs', `
2134
2175
  sub main()
2135
2176
  end sub
2136
2177
  sub speak()
@@ -2138,14 +2179,14 @@ describe('BrsFile', () => {
2138
2179
  `);
2139
2180
  (0, chai_1.expect)(file.hasTypedef).to.be.false;
2140
2181
  (0, chai_1.expect)(file.typedefFile).not.to.exist;
2141
- program.addOrReplaceFile('source/main.d.bs', `
2182
+ program.setFile('source/main.d.bs', `
2142
2183
  sub main()
2143
2184
  end sub
2144
2185
  `);
2145
2186
  (0, chai_1.expect)(file.hasTypedef).to.be.true;
2146
2187
  (0, chai_1.expect)(file.typedefFile).to.exist;
2147
2188
  //add replace file, does it still find the typedef
2148
- file = program.addOrReplaceFile('source/main.brs', `
2189
+ file = program.setFile('source/main.brs', `
2149
2190
  sub main()
2150
2191
  end sub
2151
2192
  sub speak()
@@ -2160,36 +2201,36 @@ describe('BrsFile', () => {
2160
2201
  });
2161
2202
  describe('typedef', () => {
2162
2203
  it('sets typedef path properly', () => {
2163
- (0, chai_1.expect)((program.addOrReplaceFile('source/main1.brs', '')).typedefKey).to.equal((0, util_1.standardizePath) `${rootDir}/source/main1.d.bs`.toLowerCase());
2164
- (0, chai_1.expect)((program.addOrReplaceFile('source/main2.d.bs', '')).typedefKey).to.equal(undefined);
2165
- (0, chai_1.expect)((program.addOrReplaceFile('source/main3.bs', '')).typedefKey).to.equal(undefined);
2204
+ (0, chai_1.expect)((program.setFile('source/main1.brs', '')).typedefSrcPath).to.equal((0, util_1.standardizePath) `${rootDir}/source/main1.d.bs`.toLowerCase());
2205
+ (0, chai_1.expect)((program.setFile('source/main2.d.bs', '')).typedefSrcPath).to.equal(undefined);
2206
+ (0, chai_1.expect)((program.setFile('source/main3.bs', '')).typedefSrcPath).to.equal(undefined);
2166
2207
  //works for dest with `.brs` extension
2167
- (0, chai_1.expect)((program.addOrReplaceFile({ src: 'source/main4.bs', dest: 'source/main4.brs' }, '')).typedefKey).to.equal(undefined);
2208
+ (0, chai_1.expect)((program.setFile({ src: 'source/main4.bs', dest: 'source/main4.brs' }, '')).typedefSrcPath).to.equal(undefined);
2168
2209
  });
2169
2210
  it('does not link when missing from program', () => {
2170
- const file = program.addOrReplaceFile('source/main.brs', ``);
2211
+ const file = program.setFile('source/main.brs', ``);
2171
2212
  (0, chai_1.expect)(file.typedefFile).not.to.exist;
2172
2213
  });
2173
2214
  it('links typedef when added BEFORE .brs file', () => {
2174
- const typedef = program.addOrReplaceFile('source/main.d.bs', ``);
2175
- const file = program.addOrReplaceFile('source/main.brs', ``);
2215
+ const typedef = program.setFile('source/main.d.bs', ``);
2216
+ const file = program.setFile('source/main.brs', ``);
2176
2217
  (0, chai_1.expect)(file.typedefFile).to.equal(typedef);
2177
2218
  });
2178
2219
  it('links typedef when added AFTER .brs file', () => {
2179
- const file = program.addOrReplaceFile('source/main.brs', ``);
2180
- const typedef = program.addOrReplaceFile('source/main.d.bs', ``);
2220
+ const file = program.setFile('source/main.brs', ``);
2221
+ const typedef = program.setFile('source/main.d.bs', ``);
2181
2222
  (0, chai_1.expect)(file.typedefFile).to.eql(typedef);
2182
2223
  });
2183
2224
  it('removes typedef link when typedef is removed', () => {
2184
- const typedef = program.addOrReplaceFile('source/main.d.bs', ``);
2185
- const file = program.addOrReplaceFile('source/main.brs', ``);
2186
- program.removeFile(typedef.pathAbsolute);
2225
+ const typedef = program.setFile('source/main.d.bs', ``);
2226
+ const file = program.setFile('source/main.brs', ``);
2227
+ program.removeFile(typedef.srcPath);
2187
2228
  (0, chai_1.expect)(file.typedefFile).to.be.undefined;
2188
2229
  });
2189
2230
  });
2190
2231
  describe('getTypedef', () => {
2191
2232
  function testTypedef(original, expected) {
2192
- let file = program.addOrReplaceFile('source/main.brs', original);
2233
+ let file = program.setFile('source/main.brs', original);
2193
2234
  (0, chai_1.expect)(file.getTypedef()).to.eql(expected);
2194
2235
  }
2195
2236
  it('includes namespace on extend class names', () => {
@@ -2440,7 +2481,7 @@ describe('BrsFile', () => {
2440
2481
  });
2441
2482
  describe('parser getter', () => {
2442
2483
  it('recreates the parser when missing', () => {
2443
- const file = program.addOrReplaceFile('source/main.brs', `
2484
+ const file = program.setFile('source/main.brs', `
2444
2485
  sub main()
2445
2486
  end sub
2446
2487
  `);
@@ -2454,11 +2495,11 @@ describe('BrsFile', () => {
2454
2495
  (0, chai_1.expect)(file.parser).to.equal(newParser);
2455
2496
  });
2456
2497
  it('call parse when previously skipped', () => {
2457
- program.addOrReplaceFile('source/main.d.bs', `
2498
+ program.setFile('source/main.d.bs', `
2458
2499
  sub main()
2459
2500
  end sub
2460
2501
  `);
2461
- const file = program.addOrReplaceFile('source/main.brs', `
2502
+ const file = program.setFile('source/main.brs', `
2462
2503
  sub main()
2463
2504
  end sub
2464
2505
  `);