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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/CHANGELOG.md +46 -2
  2. package/dist/Cache.d.ts +3 -3
  3. package/dist/Cache.js +10 -6
  4. package/dist/Cache.js.map +1 -1
  5. package/dist/LanguageServer.d.ts +1 -6
  6. package/dist/LanguageServer.js +0 -9
  7. package/dist/LanguageServer.js.map +1 -1
  8. package/dist/PluginInterface.d.ts +3 -3
  9. package/dist/PluginInterface.js +3 -0
  10. package/dist/PluginInterface.js.map +1 -1
  11. package/dist/Program.d.ts +30 -16
  12. package/dist/Program.js +106 -43
  13. package/dist/Program.js.map +1 -1
  14. package/dist/ProgramBuilder.js +3 -3
  15. package/dist/ProgramBuilder.js.map +1 -1
  16. package/dist/Scope.d.ts +15 -6
  17. package/dist/Scope.js +39 -25
  18. package/dist/Scope.js.map +1 -1
  19. package/dist/SymbolTable.d.ts +1 -1
  20. package/dist/astUtils/reflection.spec.js +6 -6
  21. package/dist/astUtils/reflection.spec.js.map +1 -1
  22. package/dist/astUtils/visitors.spec.js +8 -8
  23. package/dist/astUtils/visitors.spec.js.map +1 -1
  24. package/dist/bscPlugin/BscPlugin.js +5 -2
  25. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  26. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
  27. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  28. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  29. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +8 -0
  30. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.js → BrsFileSemanticTokensProcessor.js} +12 -14
  31. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  32. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.d.ts → BrsFileSemanticTokensProcessor.spec.d.ts} +0 -0
  33. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +2 -2
  34. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  35. package/dist/files/BrsFile.Class.spec.js +389 -238
  36. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  37. package/dist/files/BrsFile.d.ts +17 -11
  38. package/dist/files/BrsFile.js +160 -91
  39. package/dist/files/BrsFile.js.map +1 -1
  40. package/dist/files/BrsFile.spec.js +442 -109
  41. package/dist/files/BrsFile.spec.js.map +1 -1
  42. package/dist/files/XmlFile.d.ts +6 -5
  43. package/dist/files/XmlFile.js +13 -8
  44. package/dist/files/XmlFile.js.map +1 -1
  45. package/dist/files/XmlFile.spec.js +57 -55
  46. package/dist/files/XmlFile.spec.js.map +1 -1
  47. package/dist/files/tests/imports.spec.js +8 -6
  48. package/dist/files/tests/imports.spec.js.map +1 -1
  49. package/dist/index.d.ts +12 -3
  50. package/dist/index.js +21 -4
  51. package/dist/index.js.map +1 -1
  52. package/dist/interfaces.d.ts +46 -10
  53. package/dist/lexer/Lexer.js +1 -2
  54. package/dist/lexer/Lexer.js.map +1 -1
  55. package/dist/lexer/Lexer.spec.js +462 -462
  56. package/dist/lexer/Lexer.spec.js.map +1 -1
  57. package/dist/parser/Expression.d.ts +1 -1
  58. package/dist/parser/Expression.js +10 -10
  59. package/dist/parser/Expression.js.map +1 -1
  60. package/dist/parser/Parser.Class.spec.js +33 -32
  61. package/dist/parser/Parser.Class.spec.js.map +1 -1
  62. package/dist/parser/Parser.d.ts +17 -5
  63. package/dist/parser/Parser.js +403 -288
  64. package/dist/parser/Parser.js.map +1 -1
  65. package/dist/parser/Parser.spec.js +157 -35
  66. package/dist/parser/Parser.spec.js.map +1 -1
  67. package/dist/parser/SGTypes.spec.js +9 -9
  68. package/dist/parser/SGTypes.spec.js.map +1 -1
  69. package/dist/parser/Statement.d.ts +3 -3
  70. package/dist/parser/Statement.js +8 -8
  71. package/dist/parser/Statement.js.map +1 -1
  72. package/dist/parser/tests/Parser.spec.d.ts +3 -3
  73. package/dist/parser/tests/Parser.spec.js +4 -4
  74. package/dist/parser/tests/Parser.spec.js.map +1 -1
  75. package/dist/parser/tests/controlFlow/For.spec.js +40 -40
  76. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  77. package/dist/parser/tests/controlFlow/ForEach.spec.js +22 -21
  78. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  79. package/dist/parser/tests/controlFlow/If.spec.js +100 -99
  80. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  81. package/dist/parser/tests/controlFlow/While.spec.js +25 -25
  82. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  83. package/dist/parser/tests/expression/Additive.spec.js +21 -21
  84. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  85. package/dist/parser/tests/expression/ArrayLiterals.spec.js +91 -91
  86. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  87. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +102 -102
  88. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  89. package/dist/parser/tests/expression/Boolean.spec.js +15 -15
  90. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  91. package/dist/parser/tests/expression/Call.spec.js +22 -21
  92. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  93. package/dist/parser/tests/expression/Exponential.spec.js +11 -11
  94. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  95. package/dist/parser/tests/expression/Function.spec.js +171 -171
  96. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  97. package/dist/parser/tests/expression/Indexing.spec.js +50 -50
  98. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  99. package/dist/parser/tests/expression/Multiplicative.spec.js +25 -25
  100. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  101. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +16 -16
  102. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  103. package/dist/parser/tests/expression/PrefixUnary.spec.js +26 -26
  104. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  105. package/dist/parser/tests/expression/Primary.spec.js +27 -27
  106. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  107. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +3 -2
  108. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  109. package/dist/parser/tests/expression/Relational.spec.js +25 -25
  110. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  111. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +7 -7
  112. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  113. package/dist/parser/tests/expression/TernaryExpression.spec.js +6 -6
  114. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  115. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  116. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  117. package/dist/parser/tests/statement/Declaration.spec.js +20 -20
  118. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  119. package/dist/parser/tests/statement/Function.spec.js +121 -120
  120. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  121. package/dist/parser/tests/statement/Goto.spec.js +9 -8
  122. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  123. package/dist/parser/tests/statement/Increment.spec.js +22 -22
  124. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  125. package/dist/parser/tests/statement/InterfaceStatement.spec.js +12 -0
  126. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  127. package/dist/parser/tests/statement/LibraryStatement.spec.js +7 -7
  128. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  129. package/dist/parser/tests/statement/Misc.spec.js +71 -70
  130. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  131. package/dist/parser/tests/statement/PrintStatement.spec.js +17 -17
  132. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  133. package/dist/parser/tests/statement/ReturnStatement.spec.js +33 -33
  134. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  135. package/dist/parser/tests/statement/Set.spec.js +53 -53
  136. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  137. package/dist/parser/tests/statement/Stop.spec.js +7 -6
  138. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  139. package/dist/preprocessor/Chunk.d.ts +1 -1
  140. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  141. package/dist/preprocessor/Preprocessor.js +7 -7
  142. package/dist/preprocessor/Preprocessor.js.map +1 -1
  143. package/dist/types/ArrayType.d.ts +8 -5
  144. package/dist/types/ArrayType.js +45 -9
  145. package/dist/types/ArrayType.js.map +1 -1
  146. package/dist/types/ArrayType.spec.js +62 -3
  147. package/dist/types/ArrayType.spec.js.map +1 -1
  148. package/dist/types/BscType.d.ts +1 -1
  149. package/dist/types/CustomType.d.ts +1 -1
  150. package/dist/types/CustomType.js +4 -2
  151. package/dist/types/CustomType.js.map +1 -1
  152. package/dist/types/FunctionType.d.ts +5 -5
  153. package/dist/types/FunctionType.js +11 -11
  154. package/dist/types/FunctionType.js.map +1 -1
  155. package/dist/types/LazyType.d.ts +1 -2
  156. package/dist/types/LazyType.js +1 -5
  157. package/dist/types/LazyType.js.map +1 -1
  158. package/dist/types/helpers.js +1 -1
  159. package/dist/types/helpers.js.map +1 -1
  160. package/dist/util.d.ts +15 -9
  161. package/dist/util.js +93 -50
  162. package/dist/util.js.map +1 -1
  163. package/dist/validators/ClassValidator.js +17 -24
  164. package/dist/validators/ClassValidator.js.map +1 -1
  165. package/package.json +2 -1
  166. package/dist/astUtils/index.d.ts +0 -7
  167. package/dist/astUtils/index.js +0 -26
  168. package/dist/astUtils/index.js.map +0 -1
  169. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  170. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  171. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  172. package/dist/lexer/index.d.ts +0 -3
  173. package/dist/lexer/index.js +0 -18
  174. package/dist/lexer/index.js.map +0 -1
  175. package/dist/parser/index.d.ts +0 -3
  176. package/dist/parser/index.js +0 -16
  177. package/dist/parser/index.js.map +0 -1
  178. package/dist/preprocessor/index.d.ts +0 -3
  179. package/dist/preprocessor/index.js +0 -16
  180. package/dist/preprocessor/index.js.map +0 -1
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getBscTypeFromExpression = exports.TokenUsage = exports.References = exports.ParseMode = exports.Parser = void 0;
4
- const lexer_1 = require("../lexer");
4
+ const Token_1 = require("../lexer/Token");
5
+ const Lexer_1 = require("../lexer/Lexer");
6
+ const TokenKind_1 = require("../lexer/TokenKind");
5
7
  const Statement_1 = require("./Statement");
6
8
  const DiagnosticMessages_1 = require("../DiagnosticMessages");
7
9
  const util_1 = require("../util");
@@ -10,12 +12,11 @@ const Logger_1 = require("../Logger");
10
12
  const reflection_1 = require("../astUtils/reflection");
11
13
  const visitors_1 = require("../astUtils/visitors");
12
14
  const creators_1 = require("../astUtils/creators");
13
- const DynamicType_1 = require("../types/DynamicType");
14
15
  const SymbolTable_1 = require("../SymbolTable");
16
+ const DynamicType_1 = require("../types/DynamicType");
15
17
  const ObjectType_1 = require("../types/ObjectType");
16
18
  const ArrayType_1 = require("../types/ArrayType");
17
19
  const helpers_1 = require("../types/helpers");
18
- const _1 = require(".");
19
20
  class Parser {
20
21
  constructor() {
21
22
  /**
@@ -61,7 +62,7 @@ class Parser {
61
62
  this._references = undefined;
62
63
  }
63
64
  addPropertyHints(item) {
64
- if ((0, lexer_1.isToken)(item)) {
65
+ if ((0, Token_1.isToken)(item)) {
65
66
  const name = item.text;
66
67
  this._references.propertyHints[name.toLowerCase()] = name;
67
68
  }
@@ -93,7 +94,7 @@ class Parser {
93
94
  static parse(toParse, options) {
94
95
  let tokens;
95
96
  if (typeof toParse === 'string') {
96
- tokens = lexer_1.Lexer.scan(toParse).tokens;
97
+ tokens = Lexer_1.Lexer.scan(toParse).tokens;
97
98
  }
98
99
  else {
99
100
  tokens = toParse;
@@ -111,9 +112,9 @@ class Parser {
111
112
  this.tokens = tokens;
112
113
  this.options = this.sanitizeParseOptions(options);
113
114
  this.allowedLocalIdentifiers = [
114
- ...lexer_1.AllowedLocalIdentifiers,
115
+ ...TokenKind_1.AllowedLocalIdentifiers,
115
116
  //when in plain brightscript mode, the BrighterScript source literals can be used as regular variables
116
- ...(this.options.mode === ParseMode.BrightScript ? lexer_1.BrighterScriptSourceLiterals : [])
117
+ ...(this.options.mode === ParseMode.BrightScript ? TokenKind_1.BrighterScriptSourceLiterals : [])
117
118
  ];
118
119
  this.current = 0;
119
120
  this.diagnostics = [];
@@ -184,16 +185,16 @@ class Parser {
184
185
  }
185
186
  declaration() {
186
187
  try {
187
- if (this.checkAny(lexer_1.TokenKind.Sub, lexer_1.TokenKind.Function)) {
188
+ if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
188
189
  return this.functionDeclaration(false);
189
190
  }
190
191
  if (this.checkLibrary()) {
191
192
  return this.libraryStatement();
192
193
  }
193
- if (this.check(lexer_1.TokenKind.At) && this.checkNext(lexer_1.TokenKind.Identifier)) {
194
+ if (this.check(TokenKind_1.TokenKind.At) && this.checkNext(TokenKind_1.TokenKind.Identifier)) {
194
195
  return this.annotationExpression();
195
196
  }
196
- if (this.check(lexer_1.TokenKind.Comment)) {
197
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
197
198
  return this.commentStatement();
198
199
  }
199
200
  //catch certain global terminators to prevent unnecessary lookahead (i.e. like `end namespace`, no need to continue)
@@ -211,17 +212,17 @@ class Parser {
211
212
  }
212
213
  }
213
214
  identifier(...additionalTokenKinds) {
214
- const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...additionalTokenKinds);
215
+ const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
215
216
  // force the name into an identifier so the AST makes some sense
216
- identifier.kind = lexer_1.TokenKind.Identifier;
217
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
217
218
  return identifier;
218
219
  }
219
220
  /**
220
221
  * Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration`
221
222
  */
222
223
  interfaceFieldStatement() {
223
- const name = this.identifier(...lexer_1.AllowedProperties);
224
- let asToken = this.consumeToken(lexer_1.TokenKind.As);
224
+ const name = this.identifier(...TokenKind_1.AllowedProperties);
225
+ let asToken = this.consumeToken(TokenKind_1.TokenKind.As);
225
226
  let typeToken = this.typeToken();
226
227
  const type = util_1.util.tokenToBscType(typeToken);
227
228
  if (!type) {
@@ -235,13 +236,13 @@ class Parser {
235
236
  */
236
237
  interfaceMethodStatement() {
237
238
  const functionType = this.advance();
238
- const name = this.identifier(...lexer_1.AllowedProperties);
239
- const leftParen = this.consumeToken(lexer_1.TokenKind.LeftParen);
239
+ const name = this.identifier(...TokenKind_1.AllowedProperties);
240
+ const leftParen = this.consumeToken(TokenKind_1.TokenKind.LeftParen);
240
241
  const params = [];
241
- const rightParen = this.consumeToken(lexer_1.TokenKind.RightParen);
242
+ const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
242
243
  let asToken = null;
243
244
  let returnTypeToken = null;
244
- if (this.check(lexer_1.TokenKind.As)) {
245
+ if (this.check(TokenKind_1.TokenKind.As)) {
245
246
  asToken = this.advance();
246
247
  returnTypeToken = this.typeToken();
247
248
  const returnType = util_1.util.tokenToBscType(returnTypeToken);
@@ -255,7 +256,7 @@ class Parser {
255
256
  interfaceDeclaration() {
256
257
  this.warnIfNotBrighterScriptMode('interface declarations');
257
258
  const parentAnnotations = this.enterAnnotationBlock();
258
- const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(lexer_1.TokenKind.Interface), lexer_1.TokenKind.Interface);
259
+ const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
259
260
  const nameToken = this.identifier(...this.allowedLocalIdentifiers);
260
261
  let extendsToken;
261
262
  let parentInterfaceName;
@@ -266,23 +267,23 @@ class Parser {
266
267
  this.consumeStatementSeparators();
267
268
  //gather up all interface members (Fields, Methods)
268
269
  let body = [];
269
- while (this.checkAny(lexer_1.TokenKind.Comment, lexer_1.TokenKind.Identifier, lexer_1.TokenKind.At, ...lexer_1.AllowedProperties)) {
270
+ while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
270
271
  try {
271
272
  let decl;
272
273
  //collect leading annotations
273
- if (this.check(lexer_1.TokenKind.At)) {
274
+ if (this.check(TokenKind_1.TokenKind.At)) {
274
275
  this.annotationExpression();
275
276
  }
276
277
  //fields
277
- if (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties) && this.checkNext(lexer_1.TokenKind.As)) {
278
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.As)) {
278
279
  decl = this.interfaceFieldStatement();
279
280
  //methods (function/sub keyword followed by opening paren)
280
281
  }
281
- else if (this.checkAny(lexer_1.TokenKind.Function, lexer_1.TokenKind.Sub) && this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties)) {
282
+ else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
282
283
  decl = this.interfaceMethodStatement();
283
284
  //comments
284
285
  }
285
- else if (this.check(lexer_1.TokenKind.Comment)) {
286
+ else if (this.check(TokenKind_1.TokenKind.Comment)) {
286
287
  decl = this.commentStatement();
287
288
  }
288
289
  if (decl) {
@@ -291,23 +292,22 @@ class Parser {
291
292
  }
292
293
  else {
293
294
  //we didn't find a declaration...flag tokens until next line
294
- this.flagUntil(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Eof);
295
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
295
296
  }
296
297
  }
297
298
  catch (e) {
298
299
  //throw out any failed members and move on to the next line
299
- this.flagUntil(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Eof);
300
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
300
301
  }
301
302
  //ensure statement separator
302
303
  this.consumeStatementSeparators();
303
304
  //break out of this loop if we encountered the `EndInterface` token not followed by `as`
304
- if (this.check(lexer_1.TokenKind.EndInterface) && !this.checkNext(lexer_1.TokenKind.As)) {
305
+ if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
305
306
  break;
306
307
  }
307
308
  }
308
309
  //consume the final `end interface` token
309
- const endInterfaceToken = this.consumeToken(lexer_1.TokenKind.EndInterface);
310
- this.consumeStatementSeparators();
310
+ const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
311
311
  const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endInterfaceToken, this.currentNamespaceName);
312
312
  this._references.interfaceStatements.push(statement);
313
313
  this.exitAnnotationBlock(parentAnnotations);
@@ -319,11 +319,11 @@ class Parser {
319
319
  classDeclaration() {
320
320
  this.warnIfNotBrighterScriptMode('class declarations');
321
321
  const parentAnnotations = this.enterAnnotationBlock();
322
- let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(lexer_1.TokenKind.Class), lexer_1.TokenKind.Class);
322
+ let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Class), TokenKind_1.TokenKind.Class);
323
323
  let extendsKeyword;
324
324
  let parentClassName;
325
325
  //get the class name
326
- let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
326
+ let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
327
327
  //see if the class inherits from parent
328
328
  if (this.peek().text.toLowerCase() === 'extends') {
329
329
  extendsKeyword = this.advance();
@@ -333,14 +333,14 @@ class Parser {
333
333
  this.consumeStatementSeparators();
334
334
  //gather up all class members (Fields, Methods)
335
335
  let body = [];
336
- while (this.checkAny(lexer_1.TokenKind.Public, lexer_1.TokenKind.Protected, lexer_1.TokenKind.Private, lexer_1.TokenKind.Function, lexer_1.TokenKind.Sub, lexer_1.TokenKind.Comment, lexer_1.TokenKind.Identifier, lexer_1.TokenKind.At, ...lexer_1.AllowedProperties)) {
336
+ while (this.checkAny(TokenKind_1.TokenKind.Public, TokenKind_1.TokenKind.Protected, TokenKind_1.TokenKind.Private, TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
337
337
  try {
338
338
  let decl;
339
339
  let accessModifier;
340
- if (this.check(lexer_1.TokenKind.At)) {
340
+ if (this.check(TokenKind_1.TokenKind.At)) {
341
341
  this.annotationExpression();
342
342
  }
343
- if (this.checkAny(lexer_1.TokenKind.Public, lexer_1.TokenKind.Protected, lexer_1.TokenKind.Private)) {
343
+ if (this.checkAny(TokenKind_1.TokenKind.Public, TokenKind_1.TokenKind.Protected, TokenKind_1.TokenKind.Private)) {
344
344
  //use actual access modifier
345
345
  accessModifier = this.advance();
346
346
  }
@@ -349,7 +349,7 @@ class Parser {
349
349
  overrideKeyword = this.advance();
350
350
  }
351
351
  //methods (function/sub keyword OR identifier followed by opening paren)
352
- if (this.checkAny(lexer_1.TokenKind.Function, lexer_1.TokenKind.Sub) || (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties) && this.checkNext(lexer_1.TokenKind.LeftParen))) {
352
+ if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) || (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.LeftParen))) {
353
353
  const funcDeclaration = this.functionDeclaration(false, false, true);
354
354
  //remove this function from the lists because it's not a callable
355
355
  const functionStatement = this._references.functionStatements.pop();
@@ -362,7 +362,7 @@ class Parser {
362
362
  functionStatement.func.functionStatement = decl;
363
363
  //fields
364
364
  }
365
- else if (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties)) {
365
+ else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
366
366
  decl = this.classFieldDeclaration(accessModifier);
367
367
  //class fields cannot be overridden
368
368
  if (overrideKeyword) {
@@ -370,7 +370,7 @@ class Parser {
370
370
  }
371
371
  //comments
372
372
  }
373
- else if (this.check(lexer_1.TokenKind.Comment)) {
373
+ else if (this.check(TokenKind_1.TokenKind.Comment)) {
374
374
  decl = this.commentStatement();
375
375
  }
376
376
  if (decl) {
@@ -380,13 +380,13 @@ class Parser {
380
380
  }
381
381
  catch (e) {
382
382
  //throw out any failed members and move on to the next line
383
- this.flagUntil(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Eof);
383
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
384
384
  }
385
385
  //ensure statement separator
386
386
  this.consumeStatementSeparators();
387
387
  }
388
388
  let endingKeyword = this.advance();
389
- if (endingKeyword.kind !== lexer_1.TokenKind.EndClass) {
389
+ if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
390
390
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
391
391
  }
392
392
  const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName, this.currentSymbolTable);
@@ -398,11 +398,11 @@ class Parser {
398
398
  return result;
399
399
  }
400
400
  classFieldDeclaration(accessModifier) {
401
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
401
+ let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
402
402
  let asToken;
403
403
  let fieldType;
404
404
  //look for `as SOME_TYPE`
405
- if (this.check(lexer_1.TokenKind.As)) {
405
+ if (this.check(TokenKind_1.TokenKind.As)) {
406
406
  asToken = this.advance();
407
407
  fieldType = this.typeToken();
408
408
  //no field type specified
@@ -413,7 +413,7 @@ class Parser {
413
413
  let initialValue;
414
414
  let equal;
415
415
  //if there is a field initializer
416
- if (this.check(lexer_1.TokenKind.Equal)) {
416
+ if (this.check(TokenKind_1.TokenKind.Equal)) {
417
417
  equal = this.advance();
418
418
  initialValue = this.expression();
419
419
  }
@@ -427,14 +427,14 @@ class Parser {
427
427
  //track depth to help certain statements need to know if they are contained within a function body
428
428
  this.namespaceAndFunctionDepth++;
429
429
  let functionType;
430
- if (this.checkAny(lexer_1.TokenKind.Sub, lexer_1.TokenKind.Function)) {
430
+ if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
431
431
  functionType = this.advance();
432
432
  }
433
433
  else {
434
434
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
435
435
  functionType = {
436
436
  isReserved: true,
437
- kind: lexer_1.TokenKind.Function,
437
+ kind: TokenKind_1.TokenKind.Function,
438
438
  text: 'function',
439
439
  //zero-length location means derived
440
440
  range: {
@@ -444,16 +444,16 @@ class Parser {
444
444
  leadingWhitespace: ''
445
445
  };
446
446
  }
447
- let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === lexer_1.TokenKind.Sub;
447
+ let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === TokenKind_1.TokenKind.Sub;
448
448
  let functionTypeText = isSub ? 'sub' : 'function';
449
449
  let name;
450
450
  let leftParen;
451
451
  if (isAnonymous) {
452
- leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), lexer_1.TokenKind.LeftParen);
452
+ leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), TokenKind_1.TokenKind.LeftParen);
453
453
  }
454
454
  else {
455
- name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
456
- leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), lexer_1.TokenKind.LeftParen);
455
+ name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
456
+ leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), TokenKind_1.TokenKind.LeftParen);
457
457
  //prevent functions from ending with type designators
458
458
  let lastChar = name.text[name.text.length - 1];
459
459
  if (['$', '%', '!', '#', '&'].includes(lastChar)) {
@@ -461,23 +461,23 @@ class Parser {
461
461
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionTypeText, name.text, lastChar)), { range: name.range }));
462
462
  }
463
463
  //flag functions with keywords for names (only for standard functions)
464
- if (checkIdentifier && lexer_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
464
+ if (checkIdentifier && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
465
465
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
466
466
  }
467
467
  }
468
468
  let params = [];
469
469
  let asToken;
470
470
  let typeToken;
471
- if (!this.check(lexer_1.TokenKind.RightParen)) {
471
+ if (!this.check(TokenKind_1.TokenKind.RightParen)) {
472
472
  do {
473
473
  if (params.length >= Expression_1.CallExpression.MaximumArguments) {
474
474
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(params.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
475
475
  }
476
476
  params.push(this.functionParameter());
477
- } while (this.match(lexer_1.TokenKind.Comma));
477
+ } while (this.match(TokenKind_1.TokenKind.Comma));
478
478
  }
479
479
  let rightParen = this.advance();
480
- if (this.check(lexer_1.TokenKind.As)) {
480
+ if (this.check(TokenKind_1.TokenKind.As)) {
481
481
  asToken = this.advance();
482
482
  typeToken = this.typeToken();
483
483
  if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
@@ -529,7 +529,7 @@ class Parser {
529
529
  }
530
530
  // consume 'end sub' or 'end function'
531
531
  func.end = this.advance();
532
- let expectedEndKind = isSub ? lexer_1.TokenKind.EndSub : lexer_1.TokenKind.EndFunction;
532
+ let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
533
533
  //if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
534
534
  //add an error but don't hard-fail so the AST can continue more gracefully
535
535
  if (func.end.kind !== expectedEndKind) {
@@ -553,22 +553,22 @@ class Parser {
553
553
  }
554
554
  }
555
555
  functionParameter() {
556
- if (!this.checkAny(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
556
+ if (!this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
557
557
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
558
558
  throw this.lastDiagnosticAsError();
559
559
  }
560
- const name = this.identifier(...lexer_1.AllowedLocalIdentifiers);
560
+ const name = this.identifier(...TokenKind_1.AllowedLocalIdentifiers);
561
561
  let typeToken;
562
562
  let defaultValue;
563
563
  let equalsToken;
564
564
  // parse argument default value
565
- if (this.match(lexer_1.TokenKind.Equal)) {
565
+ if (this.match(TokenKind_1.TokenKind.Equal)) {
566
566
  equalsToken = this.previous();
567
567
  // it seems any expression is allowed here -- including ones that operate on other arguments!
568
568
  defaultValue = this.expression();
569
569
  }
570
570
  let asToken = null;
571
- if (this.check(lexer_1.TokenKind.As)) {
571
+ if (this.check(TokenKind_1.TokenKind.As)) {
572
572
  asToken = this.advance();
573
573
  typeToken = this.typeToken();
574
574
  if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
@@ -594,17 +594,20 @@ class Parser {
594
594
  assignment() {
595
595
  let name = this.identifier(...this.allowedLocalIdentifiers);
596
596
  //add diagnostic if name is a reserved word that cannot be used as an identifier
597
- if (lexer_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
597
+ if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
598
598
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
599
599
  }
600
- let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(lexer_1.AssignmentOperators, name.text), ...lexer_1.AssignmentOperators);
600
+ let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(TokenKind_1.AssignmentOperators, name.text), ...TokenKind_1.AssignmentOperators);
601
601
  let value = this.expression();
602
602
  let result;
603
- if (operator.kind === lexer_1.TokenKind.Equal) {
603
+ if (operator.kind === TokenKind_1.TokenKind.Equal) {
604
604
  result = new Statement_1.AssignmentStatement(name, operator, value, this.currentFunctionExpression);
605
605
  }
606
606
  else {
607
607
  result = new Statement_1.AssignmentStatement(name, operator, new Expression_1.BinaryExpression(new Expression_1.VariableExpression(name, this.currentNamespaceName), operator, value), this.currentFunctionExpression);
608
+ //remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
609
+ this._references.expressions.delete(value);
610
+ this._references.expressions.add(result);
608
611
  }
609
612
  this._references.assignmentStatements.push(result);
610
613
  const assignmentType = getBscTypeFromExpression(result.value, this.currentFunctionExpression);
@@ -612,14 +615,14 @@ class Parser {
612
615
  return result;
613
616
  }
614
617
  checkLibrary() {
615
- let isLibraryToken = this.check(lexer_1.TokenKind.Library);
618
+ let isLibraryToken = this.check(TokenKind_1.TokenKind.Library);
616
619
  //if we are at the top level, any line that starts with "library" should be considered a library statement
617
620
  if (this.isAtRootLevel() && isLibraryToken) {
618
621
  return true;
619
622
  //not at root level, library statements are all invalid here, but try to detect if the tokens look
620
623
  //like a library statement (and let the libraryStatement function handle emitting the diagnostics)
621
624
  }
622
- else if (isLibraryToken && this.checkNext(lexer_1.TokenKind.StringLiteral)) {
625
+ else if (isLibraryToken && this.checkNext(TokenKind_1.TokenKind.StringLiteral)) {
623
626
  return true;
624
627
  //definitely not a library statement
625
628
  }
@@ -631,54 +634,54 @@ class Parser {
631
634
  if (this.checkLibrary()) {
632
635
  return this.libraryStatement();
633
636
  }
634
- if (this.check(lexer_1.TokenKind.Import)) {
637
+ if (this.check(TokenKind_1.TokenKind.Import)) {
635
638
  return this.importStatement();
636
639
  }
637
- if (this.check(lexer_1.TokenKind.Stop)) {
640
+ if (this.check(TokenKind_1.TokenKind.Stop)) {
638
641
  return this.stopStatement();
639
642
  }
640
- if (this.check(lexer_1.TokenKind.If)) {
643
+ if (this.check(TokenKind_1.TokenKind.If)) {
641
644
  return this.ifStatement();
642
645
  }
643
646
  //`try` must be followed by a block, otherwise it could be a local variable
644
- if (this.check(lexer_1.TokenKind.Try) && this.checkAnyNext(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Comment)) {
647
+ if (this.check(TokenKind_1.TokenKind.Try) && this.checkAnyNext(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
645
648
  return this.tryCatchStatement();
646
649
  }
647
- if (this.check(lexer_1.TokenKind.Throw)) {
650
+ if (this.check(TokenKind_1.TokenKind.Throw)) {
648
651
  return this.throwStatement();
649
652
  }
650
- if (this.checkAny(lexer_1.TokenKind.Print, lexer_1.TokenKind.Question)) {
653
+ if (this.checkAny(TokenKind_1.TokenKind.Print, TokenKind_1.TokenKind.Question)) {
651
654
  return this.printStatement();
652
655
  }
653
- if (this.check(lexer_1.TokenKind.Dim)) {
656
+ if (this.check(TokenKind_1.TokenKind.Dim)) {
654
657
  return this.dimStatement();
655
658
  }
656
- if (this.check(lexer_1.TokenKind.While)) {
659
+ if (this.check(TokenKind_1.TokenKind.While)) {
657
660
  return this.whileStatement();
658
661
  }
659
- if (this.check(lexer_1.TokenKind.ExitWhile)) {
662
+ if (this.check(TokenKind_1.TokenKind.ExitWhile)) {
660
663
  return this.exitWhile();
661
664
  }
662
- if (this.check(lexer_1.TokenKind.For)) {
665
+ if (this.check(TokenKind_1.TokenKind.For)) {
663
666
  return this.forStatement();
664
667
  }
665
- if (this.check(lexer_1.TokenKind.ForEach)) {
668
+ if (this.check(TokenKind_1.TokenKind.ForEach)) {
666
669
  return this.forEachStatement();
667
670
  }
668
- if (this.check(lexer_1.TokenKind.ExitFor)) {
671
+ if (this.check(TokenKind_1.TokenKind.ExitFor)) {
669
672
  return this.exitFor();
670
673
  }
671
- if (this.check(lexer_1.TokenKind.End)) {
674
+ if (this.check(TokenKind_1.TokenKind.End)) {
672
675
  return this.endStatement();
673
676
  }
674
- if (this.match(lexer_1.TokenKind.Return)) {
677
+ if (this.match(TokenKind_1.TokenKind.Return)) {
675
678
  return this.returnStatement();
676
679
  }
677
- if (this.check(lexer_1.TokenKind.Goto)) {
680
+ if (this.check(TokenKind_1.TokenKind.Goto)) {
678
681
  return this.gotoStatement();
679
682
  }
680
683
  //does this line look like a label? (i.e. `someIdentifier:` )
681
- if (this.check(lexer_1.TokenKind.Identifier) && this.checkNext(lexer_1.TokenKind.Colon) && this.checkPrevious(lexer_1.TokenKind.Newline)) {
684
+ if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
682
685
  try {
683
686
  return this.labelStatement();
684
687
  }
@@ -692,18 +695,18 @@ class Parser {
692
695
  // BrightScript is like python, in that variables can be declared without a `var`,
693
696
  // `let`, (...) keyword. As such, we must check the token *after* an identifier to figure
694
697
  // out what to do with it.
695
- if (this.checkAny(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers) &&
696
- this.checkAnyNext(...lexer_1.AssignmentOperators)) {
698
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers) &&
699
+ this.checkAnyNext(...TokenKind_1.AssignmentOperators)) {
697
700
  return this.assignment();
698
701
  }
699
702
  //some BrighterScript keywords are allowed as a local identifiers, so we need to check for them AFTER the assignment check
700
- if (this.check(lexer_1.TokenKind.Interface)) {
703
+ if (this.check(TokenKind_1.TokenKind.Interface)) {
701
704
  return this.interfaceDeclaration();
702
705
  }
703
- if (this.check(lexer_1.TokenKind.Class)) {
706
+ if (this.check(TokenKind_1.TokenKind.Class)) {
704
707
  return this.classDeclaration();
705
708
  }
706
- if (this.check(lexer_1.TokenKind.Namespace)) {
709
+ if (this.check(TokenKind_1.TokenKind.Namespace)) {
707
710
  return this.namespaceStatement();
708
711
  }
709
712
  // TODO: support multi-statements
@@ -713,9 +716,9 @@ class Parser {
713
716
  const whileKeyword = this.advance();
714
717
  const condition = this.expression();
715
718
  this.consumeStatementSeparators();
716
- const whileBlock = this.block(lexer_1.TokenKind.EndWhile);
719
+ const whileBlock = this.block(TokenKind_1.TokenKind.EndWhile);
717
720
  let endWhile;
718
- if (!whileBlock || this.peek().kind !== lexer_1.TokenKind.EndWhile) {
721
+ if (!whileBlock || this.peek().kind !== TokenKind_1.TokenKind.EndWhile) {
719
722
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('while')), { range: this.peek().range }));
720
723
  if (!whileBlock) {
721
724
  throw this.lastDiagnosticAsError();
@@ -738,7 +741,7 @@ class Parser {
738
741
  const finalValue = this.expression();
739
742
  let incrementExpression;
740
743
  let stepToken;
741
- if (this.check(lexer_1.TokenKind.Step)) {
744
+ if (this.check(TokenKind_1.TokenKind.Step)) {
742
745
  stepToken = this.advance();
743
746
  incrementExpression = this.expression();
744
747
  }
@@ -746,9 +749,9 @@ class Parser {
746
749
  // BrightScript for/to/step loops default to a step of 1 if no `step` is provided
747
750
  }
748
751
  this.consumeStatementSeparators();
749
- let body = this.block(lexer_1.TokenKind.EndFor, lexer_1.TokenKind.Next);
752
+ let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
750
753
  let endForToken;
751
- if (!body || !this.checkAny(lexer_1.TokenKind.EndFor, lexer_1.TokenKind.Next)) {
754
+ if (!body || !this.checkAny(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next)) {
752
755
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
753
756
  if (!body) {
754
757
  throw this.lastDiagnosticAsError();
@@ -765,7 +768,7 @@ class Parser {
765
768
  let forEach = this.advance();
766
769
  let name = this.identifier(...this.allowedLocalIdentifiers);
767
770
  let maybeIn = this.peek();
768
- if (this.check(lexer_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
771
+ if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
769
772
  this.advance();
770
773
  }
771
774
  else {
@@ -778,14 +781,17 @@ class Parser {
778
781
  throw this.lastDiagnosticAsError();
779
782
  }
780
783
  this.consumeStatementSeparators();
781
- let body = this.block(lexer_1.TokenKind.EndFor, lexer_1.TokenKind.Next);
784
+ let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
782
785
  if (!body) {
783
786
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
784
787
  throw this.lastDiagnosticAsError();
785
788
  }
786
789
  let endFor = this.advance();
787
- //TODO TYPES infer type from `target`
788
- const itemType = new DynamicType_1.DynamicType();
790
+ let itemType = new DynamicType_1.DynamicType();
791
+ const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
792
+ if ((0, reflection_1.isArrayType)(targetType)) {
793
+ itemType = targetType.getDefaultType();
794
+ }
789
795
  this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
790
796
  return new Statement_1.ForEachStatement(forEach, name, maybeIn, target, body, endFor);
791
797
  }
@@ -802,7 +808,7 @@ class Parser {
802
808
  }
803
809
  else {
804
810
  let comments = [this.advance()];
805
- while (this.check(lexer_1.TokenKind.Newline) && this.checkNext(lexer_1.TokenKind.Comment)) {
811
+ while (this.check(TokenKind_1.TokenKind.Newline) && this.checkNext(TokenKind_1.TokenKind.Comment)) {
806
812
  this.advance();
807
813
  comments.push(this.advance());
808
814
  }
@@ -820,13 +826,13 @@ class Parser {
820
826
  //set the current namespace name
821
827
  let result = new Statement_1.NamespaceStatement(keyword, name, null, null, this.currentSymbolTable);
822
828
  this.currentNamespace = result;
823
- this.globalTerminators.push([lexer_1.TokenKind.EndNamespace]);
829
+ this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
824
830
  let body = this.body();
825
831
  this.globalTerminators.pop();
826
832
  //unset the current namespace name
827
833
  this.currentNamespace = undefined;
828
834
  let endKeyword;
829
- if (this.check(lexer_1.TokenKind.EndNamespace)) {
835
+ if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
830
836
  endKeyword = this.advance();
831
837
  }
832
838
  else {
@@ -843,24 +849,24 @@ class Parser {
843
849
  * Get an expression with identifiers separated by periods. Useful for namespaces and class extends
844
850
  */
845
851
  getNamespacedVariableNameExpression() {
846
- let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
852
+ let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
847
853
  let expr;
848
854
  if (firstIdentifier) {
849
855
  // force it into an identifier so the AST makes some sense
850
- firstIdentifier.kind = lexer_1.TokenKind.Identifier;
856
+ firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
851
857
  expr = new Expression_1.VariableExpression(firstIdentifier, null);
852
858
  //consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
853
- while (this.check(lexer_1.TokenKind.Dot)) {
854
- let dot = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), lexer_1.TokenKind.Dot);
859
+ while (this.check(TokenKind_1.TokenKind.Dot)) {
860
+ let dot = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.Dot);
855
861
  if (!dot) {
856
862
  break;
857
863
  }
858
- let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, ...lexer_1.AllowedProperties);
864
+ let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, ...TokenKind_1.AllowedProperties);
859
865
  if (!identifier) {
860
866
  break;
861
867
  }
862
868
  // force it into an identifier so the AST makes some sense
863
- identifier.kind = lexer_1.TokenKind.Identifier;
869
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
864
870
  expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
865
871
  }
866
872
  }
@@ -892,7 +898,7 @@ class Parser {
892
898
  let libStatement = new Statement_1.LibraryStatement({
893
899
  library: this.advance(),
894
900
  //grab the next token only if it's a string
895
- filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), lexer_1.TokenKind.StringLiteral)
901
+ filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
896
902
  });
897
903
  this._references.libraryStatements.push(libStatement);
898
904
  return libStatement;
@@ -901,20 +907,20 @@ class Parser {
901
907
  this.warnIfNotBrighterScriptMode('import statements');
902
908
  let importStatement = new Statement_1.ImportStatement(this.advance(),
903
909
  //grab the next token only if it's a string
904
- this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), lexer_1.TokenKind.StringLiteral));
910
+ this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
905
911
  this._references.importStatements.push(importStatement);
906
912
  return importStatement;
907
913
  }
908
914
  annotationExpression() {
909
915
  const atToken = this.advance();
910
- const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
916
+ const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
911
917
  if (identifier) {
912
- identifier.kind = lexer_1.TokenKind.Identifier;
918
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
913
919
  }
914
920
  let annotation = new Expression_1.AnnotationExpression(atToken, identifier);
915
921
  this.pendingAnnotations.push(annotation);
916
922
  //optional arguments
917
- if (this.check(lexer_1.TokenKind.LeftParen)) {
923
+ if (this.check(TokenKind_1.TokenKind.LeftParen)) {
918
924
  let leftParen = this.advance();
919
925
  annotation.call = this.finishCall(leftParen, annotation, false);
920
926
  }
@@ -927,7 +933,7 @@ class Parser {
927
933
  }
928
934
  const questionMarkToken = this.advance();
929
935
  //consume newlines or comments
930
- while (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
936
+ while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
931
937
  this.advance();
932
938
  }
933
939
  let consequent;
@@ -936,12 +942,12 @@ class Parser {
936
942
  }
937
943
  catch (_a) { }
938
944
  //consume newlines or comments
939
- while (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
945
+ while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
940
946
  this.advance();
941
947
  }
942
- const colonToken = this.tryConsumeToken(lexer_1.TokenKind.Colon);
948
+ const colonToken = this.tryConsumeToken(TokenKind_1.TokenKind.Colon);
943
949
  //consume newlines
944
- while (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
950
+ while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
945
951
  this.advance();
946
952
  }
947
953
  let alternate;
@@ -959,7 +965,7 @@ class Parser {
959
965
  }
960
966
  regexLiteralExpression() {
961
967
  this.warnIfNotBrighterScriptMode('regular expression literal');
962
- return new _1.RegexLiteralExpression({
968
+ return new Expression_1.RegexLiteralExpression({
963
969
  regexLiteral: this.advance()
964
970
  });
965
971
  }
@@ -968,23 +974,23 @@ class Parser {
968
974
  //get the tag name
969
975
  let tagName;
970
976
  if (isTagged) {
971
- tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
977
+ tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
972
978
  // force it into an identifier so the AST makes some sense
973
- tagName.kind = lexer_1.TokenKind.Identifier;
979
+ tagName.kind = TokenKind_1.TokenKind.Identifier;
974
980
  }
975
981
  let quasis = [];
976
982
  let expressions = [];
977
983
  let openingBacktick = this.peek();
978
984
  this.advance();
979
985
  let currentQuasiExpressionParts = [];
980
- while (!this.isAtEnd() && !this.check(lexer_1.TokenKind.BackTick)) {
986
+ while (!this.isAtEnd() && !this.check(TokenKind_1.TokenKind.BackTick)) {
981
987
  let next = this.peek();
982
- if (next.kind === lexer_1.TokenKind.TemplateStringQuasi) {
988
+ if (next.kind === TokenKind_1.TokenKind.TemplateStringQuasi) {
983
989
  //a quasi can actually be made up of multiple quasis when it includes char literals
984
990
  currentQuasiExpressionParts.push(new Expression_1.LiteralExpression(next));
985
991
  this.advance();
986
992
  }
987
- else if (next.kind === lexer_1.TokenKind.EscapedCharCodeLiteral) {
993
+ else if (next.kind === TokenKind_1.TokenKind.EscapedCharCodeLiteral) {
988
994
  currentQuasiExpressionParts.push(new Expression_1.EscapedCharCodeLiteralExpression(next));
989
995
  this.advance();
990
996
  }
@@ -992,12 +998,12 @@ class Parser {
992
998
  //finish up the current quasi
993
999
  quasis.push(new Expression_1.TemplateStringQuasiExpression(currentQuasiExpressionParts));
994
1000
  currentQuasiExpressionParts = [];
995
- if (next.kind === lexer_1.TokenKind.TemplateStringExpressionBegin) {
1001
+ if (next.kind === TokenKind_1.TokenKind.TemplateStringExpressionBegin) {
996
1002
  this.advance();
997
1003
  }
998
1004
  //now keep this expression
999
1005
  expressions.push(this.expression());
1000
- if (!this.isAtEnd() && this.check(lexer_1.TokenKind.TemplateStringExpressionEnd)) {
1006
+ if (!this.isAtEnd() && this.check(TokenKind_1.TokenKind.TemplateStringExpressionEnd)) {
1001
1007
  //TODO is it an error if this is not present?
1002
1008
  this.advance();
1003
1009
  }
@@ -1029,12 +1035,12 @@ class Parser {
1029
1035
  const statement = new Statement_1.TryCatchStatement(tryToken);
1030
1036
  //ensure statement separator
1031
1037
  this.consumeStatementSeparators();
1032
- statement.tryBranch = this.block(lexer_1.TokenKind.Catch, lexer_1.TokenKind.EndTry);
1038
+ statement.tryBranch = this.block(TokenKind_1.TokenKind.Catch, TokenKind_1.TokenKind.EndTry);
1033
1039
  const peek = this.peek();
1034
- if (peek.kind !== lexer_1.TokenKind.Catch) {
1040
+ if (peek.kind !== TokenKind_1.TokenKind.Catch) {
1035
1041
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedCatchBlockInTryCatch()), { range: this.peek().range }));
1036
1042
  //gracefully handle end-try
1037
- if (peek.kind === lexer_1.TokenKind.EndTry) {
1043
+ if (peek.kind === TokenKind_1.TokenKind.EndTry) {
1038
1044
  statement.endTryToken = this.advance();
1039
1045
  }
1040
1046
  return statement;
@@ -1042,16 +1048,16 @@ class Parser {
1042
1048
  else {
1043
1049
  statement.catchToken = this.advance();
1044
1050
  }
1045
- const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1051
+ const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1046
1052
  if (exceptionVarToken) {
1047
1053
  // force it into an identifier so the AST makes some sense
1048
- exceptionVarToken.kind = lexer_1.TokenKind.Identifier;
1054
+ exceptionVarToken.kind = TokenKind_1.TokenKind.Identifier;
1049
1055
  statement.exceptionVariable = exceptionVarToken;
1050
1056
  }
1051
1057
  //ensure statement sepatator
1052
1058
  this.consumeStatementSeparators();
1053
- statement.catchBranch = this.block(lexer_1.TokenKind.EndTry);
1054
- if (this.peek().kind !== lexer_1.TokenKind.EndTry) {
1059
+ statement.catchBranch = this.block(TokenKind_1.TokenKind.EndTry);
1060
+ if (this.peek().kind !== TokenKind_1.TokenKind.EndTry) {
1055
1061
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndTryToTerminateTryCatch()), { range: this.peek().range }));
1056
1062
  }
1057
1063
  else {
@@ -1062,7 +1068,7 @@ class Parser {
1062
1068
  throwStatement() {
1063
1069
  const throwToken = this.advance();
1064
1070
  let expression;
1065
- if (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon)) {
1071
+ if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
1066
1072
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExceptionExpressionAfterThrowKeyword()), { range: throwToken.range }));
1067
1073
  }
1068
1074
  else {
@@ -1072,19 +1078,19 @@ class Parser {
1072
1078
  }
1073
1079
  dimStatement() {
1074
1080
  const dim = this.advance();
1075
- let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1081
+ let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1076
1082
  // force to an identifier so the AST makes some sense
1077
1083
  if (identifier) {
1078
- identifier.kind = lexer_1.TokenKind.Identifier;
1084
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
1079
1085
  }
1080
- let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(), lexer_1.TokenKind.LeftSquareBracket);
1086
+ let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.LeftSquareBracket);
1081
1087
  let expressions = [];
1082
1088
  let expression;
1083
1089
  do {
1084
1090
  try {
1085
1091
  expression = this.expression();
1086
1092
  expressions.push(expression);
1087
- if (this.check(lexer_1.TokenKind.Comma)) {
1093
+ if (this.check(TokenKind_1.TokenKind.Comma)) {
1088
1094
  this.advance();
1089
1095
  }
1090
1096
  else {
@@ -1098,15 +1104,15 @@ class Parser {
1098
1104
  if (expressions.length === 0) {
1099
1105
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
1100
1106
  }
1101
- let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), lexer_1.TokenKind.RightSquareBracket);
1107
+ let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
1102
1108
  return new Statement_1.DimStatement(dim, identifier, leftSquareBracket, expressions, rightSquareBracket);
1103
1109
  }
1104
1110
  ifStatement() {
1105
1111
  // colon before `if` is usually not allowed, unless it's after `then`
1106
1112
  if (this.current > 0) {
1107
1113
  const prev = this.previous();
1108
- if (prev.kind === lexer_1.TokenKind.Colon) {
1109
- if (this.current > 1 && this.tokens[this.current - 2].kind !== lexer_1.TokenKind.Then) {
1114
+ if (prev.kind === TokenKind_1.TokenKind.Colon) {
1115
+ if (this.current > 1 && this.tokens[this.current - 2].kind !== TokenKind_1.TokenKind.Then) {
1110
1116
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedColonBeforeIfStatement()), { range: prev.range }));
1111
1117
  }
1112
1118
  }
@@ -1120,14 +1126,14 @@ class Parser {
1120
1126
  let endIfToken;
1121
1127
  let elseToken;
1122
1128
  //optional `then`
1123
- if (this.check(lexer_1.TokenKind.Then)) {
1129
+ if (this.check(TokenKind_1.TokenKind.Then)) {
1124
1130
  thenToken = this.advance();
1125
1131
  }
1126
1132
  //is it inline or multi-line if?
1127
- const isInlineIfThen = !this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Comment);
1133
+ const isInlineIfThen = !this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment);
1128
1134
  if (isInlineIfThen) {
1129
1135
  /*** PARSE INLINE IF STATEMENT ***/
1130
- thenBranch = this.inlineConditionalBranch(lexer_1.TokenKind.Else, lexer_1.TokenKind.EndIf);
1136
+ thenBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
1131
1137
  if (!thenBranch) {
1132
1138
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementToFollowConditionalCondition(ifToken.text)), { range: this.peek().range }));
1133
1139
  throw this.lastDiagnosticAsError();
@@ -1136,9 +1142,9 @@ class Parser {
1136
1142
  this.ensureInline(thenBranch.statements);
1137
1143
  }
1138
1144
  //else branch
1139
- if (this.check(lexer_1.TokenKind.Else)) {
1145
+ if (this.check(TokenKind_1.TokenKind.Else)) {
1140
1146
  elseToken = this.advance();
1141
- if (this.check(lexer_1.TokenKind.If)) {
1147
+ if (this.check(TokenKind_1.TokenKind.If)) {
1142
1148
  // recurse-read `else if`
1143
1149
  elseBranch = this.ifStatement();
1144
1150
  //no multi-line if chained with an inline if
@@ -1146,13 +1152,13 @@ class Parser {
1146
1152
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: elseBranch.range }));
1147
1153
  }
1148
1154
  }
1149
- else if (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon)) {
1155
+ else if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
1150
1156
  //expecting inline else branch
1151
1157
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: this.peek().range }));
1152
1158
  throw this.lastDiagnosticAsError();
1153
1159
  }
1154
1160
  else {
1155
- elseBranch = this.inlineConditionalBranch(lexer_1.TokenKind.Else, lexer_1.TokenKind.EndIf);
1161
+ elseBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
1156
1162
  if (elseBranch) {
1157
1163
  this.ensureInline(elseBranch.statements);
1158
1164
  }
@@ -1166,9 +1172,9 @@ class Parser {
1166
1172
  if (!elseBranch || !(0, reflection_1.isIfStatement)(elseBranch)) {
1167
1173
  //enforce newline at the end of the inline if statement
1168
1174
  const peek = this.peek();
1169
- if (peek.kind !== lexer_1.TokenKind.Newline && peek.kind !== lexer_1.TokenKind.Comment && !this.isAtEnd()) {
1175
+ if (peek.kind !== TokenKind_1.TokenKind.Newline && peek.kind !== TokenKind_1.TokenKind.Comment && !this.isAtEnd()) {
1170
1176
  //ignore last error if it was about a colon
1171
- if (this.previous().kind === lexer_1.TokenKind.Colon) {
1177
+ if (this.previous().kind === TokenKind_1.TokenKind.Colon) {
1172
1178
  this.diagnostics.pop();
1173
1179
  this.current--;
1174
1180
  }
@@ -1183,9 +1189,9 @@ class Parser {
1183
1189
  //ensure newline/colon before next keyword
1184
1190
  this.ensureNewLineOrColon();
1185
1191
  //else branch
1186
- if (this.check(lexer_1.TokenKind.Else)) {
1192
+ if (this.check(TokenKind_1.TokenKind.Else)) {
1187
1193
  elseToken = this.advance();
1188
- if (this.check(lexer_1.TokenKind.If)) {
1194
+ if (this.check(TokenKind_1.TokenKind.If)) {
1189
1195
  // recurse-read `else if`
1190
1196
  elseBranch = this.ifStatement();
1191
1197
  }
@@ -1196,7 +1202,7 @@ class Parser {
1196
1202
  }
1197
1203
  }
1198
1204
  if (!(0, reflection_1.isIfStatement)(elseBranch)) {
1199
- if (this.check(lexer_1.TokenKind.EndIf)) {
1205
+ if (this.check(TokenKind_1.TokenKind.EndIf)) {
1200
1206
  endIfToken = this.advance();
1201
1207
  }
1202
1208
  else {
@@ -1219,7 +1225,7 @@ class Parser {
1219
1225
  let diagnosticsLengthBeforeBlock = this.diagnostics.length;
1220
1226
  // we're parsing a multi-line ("block") form of the BrightScript if/then and must find
1221
1227
  // a trailing "end if" or "else if"
1222
- let branch = this.block(lexer_1.TokenKind.EndIf, lexer_1.TokenKind.Else);
1228
+ let branch = this.block(TokenKind_1.TokenKind.EndIf, TokenKind_1.TokenKind.Else);
1223
1229
  if (!branch) {
1224
1230
  //throw out any new diagnostics created as a result of a `then` block parse failure.
1225
1231
  //the block() function will discard the current line, so any discarded diagnostics will
@@ -1233,7 +1239,7 @@ class Parser {
1233
1239
  }
1234
1240
  ensureNewLineOrColon(silent = false) {
1235
1241
  const prev = this.previous().kind;
1236
- if (prev !== lexer_1.TokenKind.Newline && prev !== lexer_1.TokenKind.Colon) {
1242
+ if (prev !== TokenKind_1.TokenKind.Newline && prev !== TokenKind_1.TokenKind.Colon) {
1237
1243
  if (!silent) {
1238
1244
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedNewlineOrColon()), { range: this.peek().range }));
1239
1245
  }
@@ -1262,12 +1268,12 @@ class Parser {
1262
1268
  const startingRange = statement.range;
1263
1269
  //look for colon statement separator
1264
1270
  let foundColon = false;
1265
- while (this.match(lexer_1.TokenKind.Colon)) {
1271
+ while (this.match(TokenKind_1.TokenKind.Colon)) {
1266
1272
  foundColon = true;
1267
1273
  }
1268
1274
  //if a colon was found, add the next statement or err if unexpected
1269
1275
  if (foundColon) {
1270
- if (!this.checkAny(lexer_1.TokenKind.Newline, ...additionalTerminators)) {
1276
+ if (!this.checkAny(TokenKind_1.TokenKind.Newline, ...additionalTerminators)) {
1271
1277
  //if not an ending keyword, add next statement
1272
1278
  let extra = this.inlineConditionalBranch(...additionalTerminators);
1273
1279
  if (!extra) {
@@ -1285,9 +1291,9 @@ class Parser {
1285
1291
  }
1286
1292
  expressionStatement(expr) {
1287
1293
  let expressionStart = this.peek();
1288
- if (this.checkAny(lexer_1.TokenKind.PlusPlus, lexer_1.TokenKind.MinusMinus)) {
1294
+ if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
1289
1295
  let operator = this.advance();
1290
- if (this.checkAny(lexer_1.TokenKind.PlusPlus, lexer_1.TokenKind.MinusMinus)) {
1296
+ if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
1291
1297
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.consecutiveIncrementDecrementOperatorsAreNotAllowed()), { range: this.peek().range }));
1292
1298
  throw this.lastDiagnosticAsError();
1293
1299
  }
@@ -1295,7 +1301,9 @@ class Parser {
1295
1301
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incrementDecrementOperatorsAreNotAllowedAsResultOfFunctionCall()), { range: expressionStart.range }));
1296
1302
  throw this.lastDiagnosticAsError();
1297
1303
  }
1298
- return new Statement_1.IncrementStatement(expr, operator);
1304
+ const result = new Statement_1.IncrementStatement(expr, operator);
1305
+ this._references.expressions.add(result);
1306
+ return result;
1299
1307
  }
1300
1308
  if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
1301
1309
  return new Statement_1.ExpressionStatement(expr);
@@ -1312,18 +1320,18 @@ class Parser {
1312
1320
  * priority as standalone function calls though, so we can parse them in the same way.
1313
1321
  */
1314
1322
  let expr = this.call();
1315
- if (this.checkAny(...lexer_1.AssignmentOperators) && !((0, reflection_1.isCallExpression)(expr))) {
1323
+ if (this.checkAny(...TokenKind_1.AssignmentOperators) && !((0, reflection_1.isCallExpression)(expr))) {
1316
1324
  let left = expr;
1317
1325
  let operator = this.advance();
1318
1326
  let right = this.expression();
1319
1327
  // Create a dotted or indexed "set" based on the left-hand side's type
1320
1328
  if ((0, reflection_1.isIndexedGetExpression)(left)) {
1321
- return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === lexer_1.TokenKind.Equal
1329
+ return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
1322
1330
  ? right
1323
1331
  : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
1324
1332
  }
1325
1333
  else if ((0, reflection_1.isDottedGetExpression)(left)) {
1326
- const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === lexer_1.TokenKind.Equal
1334
+ const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
1327
1335
  ? right
1328
1336
  : new Expression_1.BinaryExpression(left, operator, right));
1329
1337
  this._references.dottedSetStatements.push(dottedSetStmt);
@@ -1336,13 +1344,13 @@ class Parser {
1336
1344
  let printKeyword = this.advance();
1337
1345
  let values = [];
1338
1346
  while (!this.checkEndOfStatement()) {
1339
- if (this.check(lexer_1.TokenKind.Semicolon)) {
1347
+ if (this.check(TokenKind_1.TokenKind.Semicolon)) {
1340
1348
  values.push(this.advance());
1341
1349
  }
1342
- else if (this.check(lexer_1.TokenKind.Comma)) {
1350
+ else if (this.check(TokenKind_1.TokenKind.Comma)) {
1343
1351
  values.push(this.advance());
1344
1352
  }
1345
- else if (this.check(lexer_1.TokenKind.Else)) {
1353
+ else if (this.check(TokenKind_1.TokenKind.Else)) {
1346
1354
  break; // inline branch
1347
1355
  }
1348
1356
  else {
@@ -1355,7 +1363,7 @@ class Parser {
1355
1363
  values.push(emptyStringLiteral);
1356
1364
  }
1357
1365
  let last = values[values.length - 1];
1358
- if ((0, lexer_1.isToken)(last)) {
1366
+ if ((0, Token_1.isToken)(last)) {
1359
1367
  // TODO: error, expected value
1360
1368
  }
1361
1369
  return new Statement_1.PrintStatement({ print: printKeyword }, values);
@@ -1369,7 +1377,7 @@ class Parser {
1369
1377
  if (this.checkEndOfStatement()) {
1370
1378
  return new Statement_1.ReturnStatement(tokens);
1371
1379
  }
1372
- let toReturn = this.check(lexer_1.TokenKind.Else) ? undefined : this.expression();
1380
+ let toReturn = this.check(TokenKind_1.TokenKind.Else) ? undefined : this.expression();
1373
1381
  return new Statement_1.ReturnStatement(tokens, toReturn);
1374
1382
  }
1375
1383
  /**
@@ -1382,7 +1390,7 @@ class Parser {
1382
1390
  colon: this.advance()
1383
1391
  };
1384
1392
  //label must be alone on its line, this is probably not a label
1385
- if (!this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
1393
+ if (!this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1386
1394
  //rewind and cancel
1387
1395
  this.current -= 2;
1388
1396
  throw new CancelStatementError();
@@ -1398,7 +1406,7 @@ class Parser {
1398
1406
  gotoStatement() {
1399
1407
  let tokens = {
1400
1408
  goto: this.advance(),
1401
- label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(), lexer_1.TokenKind.Identifier)
1409
+ label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(), TokenKind_1.TokenKind.Identifier)
1402
1410
  };
1403
1411
  return new Statement_1.GotoStatement(tokens);
1404
1412
  }
@@ -1429,7 +1437,7 @@ class Parser {
1429
1437
  this.consumeStatementSeparators(true);
1430
1438
  let startingToken = this.peek();
1431
1439
  const statements = [];
1432
- while (!this.isAtEnd() && !this.checkAny(lexer_1.TokenKind.EndSub, lexer_1.TokenKind.EndFunction, ...terminators)) {
1440
+ while (!this.isAtEnd() && !this.checkAny(TokenKind_1.TokenKind.EndSub, TokenKind_1.TokenKind.EndFunction, ...terminators)) {
1433
1441
  //grab the location of the current token
1434
1442
  let loopCurrent = this.current;
1435
1443
  let dec = this.declaration();
@@ -1445,7 +1453,7 @@ class Parser {
1445
1453
  //something went wrong. reset to the top of the loop
1446
1454
  this.current = loopCurrent;
1447
1455
  //scrap the entire line (hopefully whatever failed has added a diagnostic)
1448
- this.consumeUntil(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Eof);
1456
+ this.consumeUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
1449
1457
  //trash the next token. this prevents an infinite loop. not exactly sure why we need this,
1450
1458
  //but there's already an error in the file being parsed, so just leave this line here
1451
1459
  this.advance();
@@ -1462,8 +1470,8 @@ class Parser {
1462
1470
  //if so, we need to restore the statement separator
1463
1471
  let prev = this.previous().kind;
1464
1472
  let peek = this.peek().kind;
1465
- if ((peek === lexer_1.TokenKind.EndSub || peek === lexer_1.TokenKind.EndFunction) &&
1466
- (prev === lexer_1.TokenKind.Newline || prev === lexer_1.TokenKind.Colon)) {
1473
+ if ((peek === TokenKind_1.TokenKind.EndSub || peek === TokenKind_1.TokenKind.EndFunction) &&
1474
+ (prev === TokenKind_1.TokenKind.Newline || prev === TokenKind_1.TokenKind.Colon)) {
1467
1475
  this.current--;
1468
1476
  }
1469
1477
  }
@@ -1495,13 +1503,15 @@ class Parser {
1495
1503
  this.pendingAnnotations = parentAnnotations;
1496
1504
  }
1497
1505
  expression() {
1498
- return this.anonymousFunction();
1506
+ const expression = this.anonymousFunction();
1507
+ this._references.expressions.add(expression);
1508
+ return expression;
1499
1509
  }
1500
1510
  anonymousFunction() {
1501
- if (this.checkAny(lexer_1.TokenKind.Sub, lexer_1.TokenKind.Function)) {
1511
+ if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
1502
1512
  const func = this.functionDeclaration(true);
1503
1513
  //if there's an open paren after this, this is an IIFE
1504
- if (this.check(lexer_1.TokenKind.LeftParen)) {
1514
+ if (this.check(TokenKind_1.TokenKind.LeftParen)) {
1505
1515
  return this.finishCall(this.advance(), func);
1506
1516
  }
1507
1517
  else {
@@ -1509,10 +1519,10 @@ class Parser {
1509
1519
  }
1510
1520
  }
1511
1521
  let expr = this.boolean();
1512
- if (this.check(lexer_1.TokenKind.Question)) {
1522
+ if (this.check(TokenKind_1.TokenKind.Question)) {
1513
1523
  return this.ternaryExpression(expr);
1514
1524
  }
1515
- else if (this.check(lexer_1.TokenKind.QuestionQuestion)) {
1525
+ else if (this.check(TokenKind_1.TokenKind.QuestionQuestion)) {
1516
1526
  return this.nullCoalescingExpression(expr);
1517
1527
  }
1518
1528
  else {
@@ -1521,7 +1531,7 @@ class Parser {
1521
1531
  }
1522
1532
  boolean() {
1523
1533
  let expr = this.relational();
1524
- while (this.matchAny(lexer_1.TokenKind.And, lexer_1.TokenKind.Or)) {
1534
+ while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
1525
1535
  let operator = this.previous();
1526
1536
  let right = this.relational();
1527
1537
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1530,7 +1540,7 @@ class Parser {
1530
1540
  }
1531
1541
  relational() {
1532
1542
  let expr = this.additive();
1533
- while (this.matchAny(lexer_1.TokenKind.Equal, lexer_1.TokenKind.LessGreater, lexer_1.TokenKind.Greater, lexer_1.TokenKind.GreaterEqual, lexer_1.TokenKind.Less, lexer_1.TokenKind.LessEqual)) {
1543
+ while (this.matchAny(TokenKind_1.TokenKind.Equal, TokenKind_1.TokenKind.LessGreater, TokenKind_1.TokenKind.Greater, TokenKind_1.TokenKind.GreaterEqual, TokenKind_1.TokenKind.Less, TokenKind_1.TokenKind.LessEqual)) {
1534
1544
  let operator = this.previous();
1535
1545
  let right = this.additive();
1536
1546
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1540,7 +1550,7 @@ class Parser {
1540
1550
  // TODO: bitshift
1541
1551
  additive() {
1542
1552
  let expr = this.multiplicative();
1543
- while (this.matchAny(lexer_1.TokenKind.Plus, lexer_1.TokenKind.Minus)) {
1553
+ while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
1544
1554
  let operator = this.previous();
1545
1555
  let right = this.multiplicative();
1546
1556
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1549,7 +1559,7 @@ class Parser {
1549
1559
  }
1550
1560
  multiplicative() {
1551
1561
  let expr = this.exponential();
1552
- while (this.matchAny(lexer_1.TokenKind.Forwardslash, lexer_1.TokenKind.Backslash, lexer_1.TokenKind.Star, lexer_1.TokenKind.Mod, lexer_1.TokenKind.LeftShift, lexer_1.TokenKind.RightShift)) {
1562
+ while (this.matchAny(TokenKind_1.TokenKind.Forwardslash, TokenKind_1.TokenKind.Backslash, TokenKind_1.TokenKind.Star, TokenKind_1.TokenKind.Mod, TokenKind_1.TokenKind.LeftShift, TokenKind_1.TokenKind.RightShift)) {
1553
1563
  let operator = this.previous();
1554
1564
  let right = this.exponential();
1555
1565
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1558,7 +1568,7 @@ class Parser {
1558
1568
  }
1559
1569
  exponential() {
1560
1570
  let expr = this.prefixUnary();
1561
- while (this.match(lexer_1.TokenKind.Caret)) {
1571
+ while (this.match(TokenKind_1.TokenKind.Caret)) {
1562
1572
  let operator = this.previous();
1563
1573
  let right = this.prefixUnary();
1564
1574
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1567,7 +1577,7 @@ class Parser {
1567
1577
  }
1568
1578
  prefixUnary() {
1569
1579
  const nextKind = this.peek().kind;
1570
- if (nextKind === lexer_1.TokenKind.Not || nextKind === lexer_1.TokenKind.Minus) {
1580
+ if (nextKind === TokenKind_1.TokenKind.Not || nextKind === TokenKind_1.TokenKind.Minus) {
1571
1581
  this.current++; //advance
1572
1582
  let operator = this.previous();
1573
1583
  let right = this.prefixUnary();
@@ -1577,17 +1587,17 @@ class Parser {
1577
1587
  }
1578
1588
  indexedGet(expr) {
1579
1589
  let openingSquare = this.previous();
1580
- while (this.match(lexer_1.TokenKind.Newline)) { }
1590
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1581
1591
  let index = this.expression();
1582
- while (this.match(lexer_1.TokenKind.Newline)) { }
1583
- let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), lexer_1.TokenKind.RightSquareBracket);
1592
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1593
+ let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
1584
1594
  return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare);
1585
1595
  }
1586
1596
  newExpression() {
1587
1597
  this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
1588
1598
  let newToken = this.advance();
1589
1599
  let nameExpr = this.getNamespacedVariableNameExpression();
1590
- let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), lexer_1.TokenKind.LeftParen);
1600
+ let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.LeftParen);
1591
1601
  let call = this.finishCall(leftParen, nameExpr);
1592
1602
  //pop the call from the callExpressions list because this is technically something else
1593
1603
  this.callExpressions.pop();
@@ -1601,46 +1611,52 @@ class Parser {
1601
1611
  callfunc(callee) {
1602
1612
  this.warnIfNotBrighterScriptMode('callfunc operator');
1603
1613
  let operator = this.previous();
1604
- let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1614
+ let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1605
1615
  // force it into an identifier so the AST makes some sense
1606
- methodName.kind = lexer_1.TokenKind.Identifier;
1607
- let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(), lexer_1.TokenKind.LeftParen);
1616
+ methodName.kind = TokenKind_1.TokenKind.Identifier;
1617
+ let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(), TokenKind_1.TokenKind.LeftParen);
1608
1618
  let call = this.finishCall(openParen, callee, false);
1609
1619
  return new Expression_1.CallfuncExpression(callee, operator, methodName, openParen, call.args, call.closingParen);
1610
1620
  }
1611
1621
  call() {
1612
- if (this.check(lexer_1.TokenKind.New) && this.checkAnyNext(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
1622
+ if (this.check(TokenKind_1.TokenKind.New) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
1613
1623
  return this.newExpression();
1614
1624
  }
1615
1625
  let expr = this.primary();
1626
+ //an expression to keep for _references
1627
+ let referenceCallExpression;
1616
1628
  while (true) {
1617
- if (this.match(lexer_1.TokenKind.LeftParen)) {
1629
+ if (this.match(TokenKind_1.TokenKind.LeftParen)) {
1618
1630
  expr = this.finishCall(this.previous(), expr);
1631
+ //store this call expression in references
1632
+ referenceCallExpression = expr;
1619
1633
  }
1620
- else if (this.match(lexer_1.TokenKind.LeftSquareBracket)) {
1634
+ else if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
1621
1635
  expr = this.indexedGet(expr);
1622
1636
  }
1623
- else if (this.match(lexer_1.TokenKind.Callfunc)) {
1637
+ else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
1624
1638
  expr = this.callfunc(expr);
1639
+ //store this callfunc expression in references
1640
+ referenceCallExpression = expr;
1625
1641
  }
1626
- else if (this.match(lexer_1.TokenKind.Dot)) {
1627
- if (this.match(lexer_1.TokenKind.LeftSquareBracket)) {
1642
+ else if (this.match(TokenKind_1.TokenKind.Dot)) {
1643
+ if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
1628
1644
  expr = this.indexedGet(expr);
1629
1645
  }
1630
1646
  else {
1631
1647
  let dot = this.previous();
1632
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1648
+ let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1633
1649
  // force it into an identifier so the AST makes some sense
1634
- name.kind = lexer_1.TokenKind.Identifier;
1650
+ name.kind = TokenKind_1.TokenKind.Identifier;
1635
1651
  expr = new Expression_1.DottedGetExpression(expr, name, dot);
1636
1652
  this.addPropertyHints(name);
1637
1653
  }
1638
1654
  }
1639
- else if (this.check(lexer_1.TokenKind.At)) {
1655
+ else if (this.check(TokenKind_1.TokenKind.At)) {
1640
1656
  let dot = this.advance();
1641
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1657
+ let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1642
1658
  // force it into an identifier so the AST makes some sense
1643
- name.kind = lexer_1.TokenKind.Identifier;
1659
+ name.kind = TokenKind_1.TokenKind.Identifier;
1644
1660
  expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
1645
1661
  //only allow a single `@` expression
1646
1662
  break;
@@ -1649,24 +1665,28 @@ class Parser {
1649
1665
  break;
1650
1666
  }
1651
1667
  }
1668
+ //if we found a callExpression, add it to `expressions` in references
1669
+ if (referenceCallExpression) {
1670
+ this._references.expressions.add(referenceCallExpression);
1671
+ }
1652
1672
  return expr;
1653
1673
  }
1654
1674
  finishCall(openingParen, callee, addToCallExpressionList = true) {
1655
1675
  let args = [];
1656
- while (this.match(lexer_1.TokenKind.Newline)) {
1676
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1657
1677
  }
1658
- if (!this.check(lexer_1.TokenKind.RightParen)) {
1678
+ if (!this.check(TokenKind_1.TokenKind.RightParen)) {
1659
1679
  do {
1660
- while (this.match(lexer_1.TokenKind.Newline)) { }
1680
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1661
1681
  if (args.length >= Expression_1.CallExpression.MaximumArguments) {
1662
1682
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
1663
1683
  throw this.lastDiagnosticAsError();
1664
1684
  }
1665
1685
  args.push(this.expression());
1666
- } while (this.match(lexer_1.TokenKind.Comma));
1686
+ } while (this.match(TokenKind_1.TokenKind.Comma));
1667
1687
  }
1668
- while (this.match(lexer_1.TokenKind.Newline)) { }
1669
- const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), lexer_1.TokenKind.RightParen);
1688
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1689
+ const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
1670
1690
  if ((0, reflection_1.isVariableExpression)(callee)) {
1671
1691
  callee.isCalled = true;
1672
1692
  }
@@ -1683,15 +1703,15 @@ class Parser {
1683
1703
  */
1684
1704
  typeToken() {
1685
1705
  let typeToken;
1686
- if (this.checkAny(...lexer_1.DeclarableTypes)) {
1706
+ if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
1687
1707
  // Token is a built in type
1688
1708
  typeToken = this.advance();
1689
1709
  }
1690
1710
  else if (this.options.mode === ParseMode.BrighterScript) {
1691
1711
  try {
1692
- // see if we can get a namespaced identifer
1712
+ // see if we can get a namespaced identifier
1693
1713
  const qualifiedType = this.getNamespacedVariableNameExpression();
1694
- typeToken = (0, creators_1.createToken)(lexer_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
1714
+ typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
1695
1715
  }
1696
1716
  catch (_a) {
1697
1717
  //could not get an identifier - just get whatever's next
@@ -1702,57 +1722,68 @@ class Parser {
1702
1722
  // just get whatever's next
1703
1723
  typeToken = this.advance();
1704
1724
  }
1725
+ if (typeToken && this.options.mode === ParseMode.BrighterScript) {
1726
+ // Check if it is an array - that is, if it has `[]` after the type
1727
+ // eg. `string[]` or `SomeKlass[]`
1728
+ if (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
1729
+ this.advance();
1730
+ if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1731
+ const rightBracket = this.advance();
1732
+ typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, typeToken.text + '[]', util_1.util.getRange(typeToken, rightBracket));
1733
+ }
1734
+ }
1735
+ }
1705
1736
  return typeToken;
1706
1737
  }
1707
1738
  primary() {
1708
1739
  switch (true) {
1709
- case this.matchAny(lexer_1.TokenKind.False, lexer_1.TokenKind.True, lexer_1.TokenKind.Invalid, lexer_1.TokenKind.IntegerLiteral, lexer_1.TokenKind.LongIntegerLiteral, lexer_1.TokenKind.FloatLiteral, lexer_1.TokenKind.DoubleLiteral, lexer_1.TokenKind.StringLiteral):
1740
+ case this.matchAny(TokenKind_1.TokenKind.False, TokenKind_1.TokenKind.True, TokenKind_1.TokenKind.Invalid, TokenKind_1.TokenKind.IntegerLiteral, TokenKind_1.TokenKind.LongIntegerLiteral, TokenKind_1.TokenKind.FloatLiteral, TokenKind_1.TokenKind.DoubleLiteral, TokenKind_1.TokenKind.StringLiteral):
1710
1741
  return new Expression_1.LiteralExpression(this.previous());
1711
1742
  //capture source literals (LINE_NUM if brightscript, or a bunch of them if brighterscript)
1712
- case this.matchAny(lexer_1.TokenKind.LineNumLiteral, ...(this.options.mode === ParseMode.BrightScript ? [] : lexer_1.BrighterScriptSourceLiterals)):
1743
+ case this.matchAny(TokenKind_1.TokenKind.LineNumLiteral, ...(this.options.mode === ParseMode.BrightScript ? [] : TokenKind_1.BrighterScriptSourceLiterals)):
1713
1744
  return new Expression_1.SourceLiteralExpression(this.previous());
1714
1745
  //template string
1715
- case this.check(lexer_1.TokenKind.BackTick):
1746
+ case this.check(TokenKind_1.TokenKind.BackTick):
1716
1747
  return this.templateString(false);
1717
1748
  //tagged template string (currently we do not support spaces between the identifier and the backtick)
1718
- case this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedLocalIdentifiers) && this.checkNext(lexer_1.TokenKind.BackTick):
1749
+ case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
1719
1750
  return this.templateString(true);
1720
- case this.matchAny(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
1751
+ case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
1721
1752
  return new Expression_1.VariableExpression(this.previous(), this.currentNamespaceName);
1722
- case this.match(lexer_1.TokenKind.LeftParen):
1753
+ case this.match(TokenKind_1.TokenKind.LeftParen):
1723
1754
  let left = this.previous();
1724
1755
  let expr = this.expression();
1725
- let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), lexer_1.TokenKind.RightParen);
1756
+ let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), TokenKind_1.TokenKind.RightParen);
1726
1757
  return new Expression_1.GroupingExpression({ left: left, right: right }, expr);
1727
- case this.match(lexer_1.TokenKind.LeftSquareBracket):
1758
+ case this.match(TokenKind_1.TokenKind.LeftSquareBracket):
1728
1759
  let elements = [];
1729
1760
  let openingSquare = this.previous();
1730
1761
  //add any comment found right after the opening square
1731
- if (this.check(lexer_1.TokenKind.Comment)) {
1762
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
1732
1763
  elements.push(new Statement_1.CommentStatement([this.advance()]));
1733
1764
  }
1734
- while (this.match(lexer_1.TokenKind.Newline)) {
1765
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1735
1766
  }
1736
- if (!this.match(lexer_1.TokenKind.RightSquareBracket)) {
1767
+ if (!this.match(TokenKind_1.TokenKind.RightSquareBracket)) {
1737
1768
  elements.push(this.expression());
1738
- while (this.matchAny(lexer_1.TokenKind.Comma, lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
1739
- if (this.checkPrevious(lexer_1.TokenKind.Comment) || this.check(lexer_1.TokenKind.Comment)) {
1740
- let comment = this.check(lexer_1.TokenKind.Comment) ? this.advance() : this.previous();
1769
+ while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1770
+ if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
1771
+ let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
1741
1772
  elements.push(new Statement_1.CommentStatement([comment]));
1742
1773
  }
1743
- while (this.match(lexer_1.TokenKind.Newline)) {
1774
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1744
1775
  }
1745
- if (this.check(lexer_1.TokenKind.RightSquareBracket)) {
1776
+ if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1746
1777
  break;
1747
1778
  }
1748
1779
  elements.push(this.expression());
1749
1780
  }
1750
- this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), lexer_1.TokenKind.RightSquareBracket);
1781
+ this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
1751
1782
  }
1752
1783
  let closingSquare = this.previous();
1753
1784
  //this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
1754
1785
  return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
1755
- case this.match(lexer_1.TokenKind.LeftCurlyBrace):
1786
+ case this.match(TokenKind_1.TokenKind.LeftCurlyBrace):
1756
1787
  let openingBrace = this.previous();
1757
1788
  let members = [];
1758
1789
  let key = () => {
@@ -1761,25 +1792,25 @@ class Parser {
1761
1792
  keyToken: null,
1762
1793
  range: null
1763
1794
  };
1764
- if (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties)) {
1795
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
1765
1796
  result.keyToken = this.advance();
1766
1797
  }
1767
- else if (this.check(lexer_1.TokenKind.StringLiteral)) {
1798
+ else if (this.check(TokenKind_1.TokenKind.StringLiteral)) {
1768
1799
  result.keyToken = this.advance();
1769
1800
  }
1770
1801
  else {
1771
1802
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedAAKey()), { range: this.peek().range }));
1772
1803
  throw this.lastDiagnosticAsError();
1773
1804
  }
1774
- result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(), lexer_1.TokenKind.Colon);
1805
+ result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(), TokenKind_1.TokenKind.Colon);
1775
1806
  result.range = util_1.util.getRange(result.keyToken, result.colonToken);
1776
1807
  return result;
1777
1808
  };
1778
- while (this.match(lexer_1.TokenKind.Newline)) {
1809
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1779
1810
  }
1780
- if (!this.match(lexer_1.TokenKind.RightCurlyBrace)) {
1811
+ if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
1781
1812
  let lastAAMember;
1782
- if (this.check(lexer_1.TokenKind.Comment)) {
1813
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
1783
1814
  lastAAMember = null;
1784
1815
  members.push(new Statement_1.CommentStatement([this.advance()]));
1785
1816
  }
@@ -1789,26 +1820,26 @@ class Parser {
1789
1820
  lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
1790
1821
  members.push(lastAAMember);
1791
1822
  }
1792
- while (this.matchAny(lexer_1.TokenKind.Comma, lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Comment)) {
1823
+ while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
1793
1824
  // collect comma at end of expression
1794
- if (lastAAMember && this.checkPrevious(lexer_1.TokenKind.Comma)) {
1825
+ if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
1795
1826
  lastAAMember.commaToken = this.previous();
1796
1827
  }
1797
1828
  //check for comment at the end of the current line
1798
- if (this.check(lexer_1.TokenKind.Comment) || this.checkPrevious(lexer_1.TokenKind.Comment)) {
1799
- let token = this.checkPrevious(lexer_1.TokenKind.Comment) ? this.previous() : this.advance();
1829
+ if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1830
+ let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1800
1831
  members.push(new Statement_1.CommentStatement([token]));
1801
1832
  }
1802
1833
  else {
1803
1834
  this.consumeStatementSeparators(true);
1804
1835
  //check for a comment on its own line
1805
- if (this.check(lexer_1.TokenKind.Comment) || this.checkPrevious(lexer_1.TokenKind.Comment)) {
1806
- let token = this.checkPrevious(lexer_1.TokenKind.Comment) ? this.previous() : this.advance();
1836
+ if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1837
+ let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1807
1838
  lastAAMember = null;
1808
1839
  members.push(new Statement_1.CommentStatement([token]));
1809
1840
  continue;
1810
1841
  }
1811
- if (this.check(lexer_1.TokenKind.RightCurlyBrace)) {
1842
+ if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
1812
1843
  break;
1813
1844
  }
1814
1845
  let k = key();
@@ -1817,23 +1848,23 @@ class Parser {
1817
1848
  members.push(lastAAMember);
1818
1849
  }
1819
1850
  }
1820
- this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), lexer_1.TokenKind.RightCurlyBrace);
1851
+ this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), TokenKind_1.TokenKind.RightCurlyBrace);
1821
1852
  }
1822
1853
  let closingBrace = this.previous();
1823
1854
  const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace, this.currentFunctionExpression);
1824
1855
  this._references.aaLiterals.push(aaExpr);
1825
1856
  this.addPropertyHints(aaExpr);
1826
1857
  return aaExpr;
1827
- case this.matchAny(lexer_1.TokenKind.Pos, lexer_1.TokenKind.Tab):
1858
+ case this.matchAny(TokenKind_1.TokenKind.Pos, TokenKind_1.TokenKind.Tab):
1828
1859
  let token = Object.assign(this.previous(), {
1829
- kind: lexer_1.TokenKind.Identifier
1860
+ kind: TokenKind_1.TokenKind.Identifier
1830
1861
  });
1831
1862
  return new Expression_1.VariableExpression(token, this.currentNamespaceName);
1832
- case this.checkAny(lexer_1.TokenKind.Function, lexer_1.TokenKind.Sub):
1863
+ case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
1833
1864
  return this.anonymousFunction();
1834
- case this.check(lexer_1.TokenKind.RegexLiteral):
1865
+ case this.check(TokenKind_1.TokenKind.RegexLiteral):
1835
1866
  return this.regexLiteralExpression();
1836
- case this.check(lexer_1.TokenKind.Comment):
1867
+ case this.check(TokenKind_1.TokenKind.Comment):
1837
1868
  return new Statement_1.CommentStatement([this.advance()]);
1838
1869
  default:
1839
1870
  //if we found an expected terminator, don't throw a diagnostic...just return undefined
@@ -1903,12 +1934,12 @@ class Parser {
1903
1934
  }
1904
1935
  consumeStatementSeparators(optional = false) {
1905
1936
  //a comment or EOF mark the end of the statement
1906
- if (this.isAtEnd() || this.check(lexer_1.TokenKind.Comment)) {
1937
+ if (this.isAtEnd() || this.check(TokenKind_1.TokenKind.Comment)) {
1907
1938
  return true;
1908
1939
  }
1909
1940
  let consumed = false;
1910
1941
  //consume any newlines and colons
1911
- while (this.matchAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon)) {
1942
+ while (this.matchAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
1912
1943
  consumed = true;
1913
1944
  }
1914
1945
  if (!optional && !consumed) {
@@ -1924,7 +1955,7 @@ class Parser {
1924
1955
  }
1925
1956
  checkEndOfStatement() {
1926
1957
  const nextKind = this.peek().kind;
1927
- return [lexer_1.TokenKind.Colon, lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment, lexer_1.TokenKind.Eof].includes(nextKind);
1958
+ return [TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Eof].includes(nextKind);
1928
1959
  }
1929
1960
  checkPrevious(tokenKind) {
1930
1961
  var _a;
@@ -1932,14 +1963,14 @@ class Parser {
1932
1963
  }
1933
1964
  check(tokenKind) {
1934
1965
  const nextKind = this.peek().kind;
1935
- if (nextKind === lexer_1.TokenKind.Eof) {
1966
+ if (nextKind === TokenKind_1.TokenKind.Eof) {
1936
1967
  return false;
1937
1968
  }
1938
1969
  return nextKind === tokenKind;
1939
1970
  }
1940
1971
  checkAny(...tokenKinds) {
1941
1972
  const nextKind = this.peek().kind;
1942
- if (nextKind === lexer_1.TokenKind.Eof) {
1973
+ if (nextKind === TokenKind_1.TokenKind.Eof) {
1943
1974
  return false;
1944
1975
  }
1945
1976
  return tokenKinds.includes(nextKind);
@@ -1958,7 +1989,7 @@ class Parser {
1958
1989
  return tokenKinds.includes(nextKind);
1959
1990
  }
1960
1991
  isAtEnd() {
1961
- return this.peek().kind === lexer_1.TokenKind.Eof;
1992
+ return this.peek().kind === TokenKind_1.TokenKind.Eof;
1962
1993
  }
1963
1994
  peekNext() {
1964
1995
  if (this.isAtEnd()) {
@@ -1980,16 +2011,16 @@ class Parser {
1980
2011
  return;
1981
2012
  }
1982
2013
  switch (this.peek().kind) { //eslint-disable-line @typescript-eslint/switch-exhaustiveness-check
1983
- case lexer_1.TokenKind.Namespace:
1984
- case lexer_1.TokenKind.Class:
1985
- case lexer_1.TokenKind.Function:
1986
- case lexer_1.TokenKind.Sub:
1987
- case lexer_1.TokenKind.If:
1988
- case lexer_1.TokenKind.For:
1989
- case lexer_1.TokenKind.ForEach:
1990
- case lexer_1.TokenKind.While:
1991
- case lexer_1.TokenKind.Print:
1992
- case lexer_1.TokenKind.Return:
2014
+ case TokenKind_1.TokenKind.Namespace:
2015
+ case TokenKind_1.TokenKind.Class:
2016
+ case TokenKind_1.TokenKind.Function:
2017
+ case TokenKind_1.TokenKind.Sub:
2018
+ case TokenKind_1.TokenKind.If:
2019
+ case TokenKind_1.TokenKind.For:
2020
+ case TokenKind_1.TokenKind.ForEach:
2021
+ case TokenKind_1.TokenKind.While:
2022
+ case TokenKind_1.TokenKind.Print:
2023
+ case TokenKind_1.TokenKind.Return:
1993
2024
  // start parsing again from the next block starter or obvious
1994
2025
  // expression start
1995
2026
  return;
@@ -2035,17 +2066,17 @@ class Parser {
2035
2066
  const previousToken = this.getPreviousToken(closestToken);
2036
2067
  const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
2037
2068
  //next to matched token
2038
- if (!closestToken || closestToken.kind === lexer_1.TokenKind.Eof) {
2069
+ if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
2039
2070
  return false;
2040
2071
  }
2041
2072
  else if (closestToken.kind === tokenKind) {
2042
2073
  return true;
2043
2074
  }
2044
- else if (closestToken.kind === lexer_1.TokenKind.Newline || previousTokenKind === lexer_1.TokenKind.Newline) {
2075
+ else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
2045
2076
  return false;
2046
2077
  //next to an identifier, which is next to token kind
2047
2078
  }
2048
- else if (closestToken.kind === lexer_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
2079
+ else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
2049
2080
  return true;
2050
2081
  }
2051
2082
  else {
@@ -2056,7 +2087,7 @@ class Parser {
2056
2087
  const index = this.tokens.indexOf(currentToken);
2057
2088
  for (let i = index - 1; i >= 0; i--) {
2058
2089
  currentToken = this.tokens[i];
2059
- if (currentToken.kind === lexer_1.TokenKind.Newline) {
2090
+ if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
2060
2091
  break;
2061
2092
  }
2062
2093
  else if (currentToken.kind === tokenKind) {
@@ -2076,7 +2107,7 @@ class Parser {
2076
2107
  let tokens = [];
2077
2108
  for (let i = this.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.tokens.length; i += direction) {
2078
2109
  currentToken = this.tokens[i];
2079
- if (currentToken.kind === lexer_1.TokenKind.Newline || currentToken.kind === tokenKind) {
2110
+ if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
2080
2111
  break;
2081
2112
  }
2082
2113
  tokens.push(currentToken);
@@ -2147,12 +2178,12 @@ class Parser {
2147
2178
  currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2148
2179
  currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2149
2180
  }
2150
- if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === lexer_1.TokenKind.Dot) {
2181
+ if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.Dot) {
2151
2182
  previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2152
2183
  currentToken = previousTokenResult.token;
2153
2184
  currentTokenIndex = previousTokenResult.index;
2154
2185
  }
2155
- previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, lexer_1.TokenKind.LeftParen, lexer_1.TokenKind.RightParen);
2186
+ previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.RightParen);
2156
2187
  currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2157
2188
  currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2158
2189
  if (previousTokenResult.hasBrackets) {
@@ -2160,7 +2191,7 @@ class Parser {
2160
2191
  }
2161
2192
  let tokenTypeIsNotKnowable = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable;
2162
2193
  if (currentTokenIndex) {
2163
- previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, lexer_1.TokenKind.LeftSquareBracket, lexer_1.TokenKind.RightSquareBracket);
2194
+ previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.RightSquareBracket);
2164
2195
  currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2165
2196
  currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2166
2197
  if (previousTokenResult.hasBrackets) {
@@ -2178,15 +2209,15 @@ class Parser {
2178
2209
  if (!currentToken || lastTokenHasWhitespace) {
2179
2210
  return false;
2180
2211
  }
2181
- if (currentToken.kind === lexer_1.TokenKind.Identifier) {
2212
+ if (currentToken.kind === TokenKind_1.TokenKind.Identifier) {
2182
2213
  return true;
2183
2214
  }
2184
2215
  if (currentToken.leadingWhitespace.length === 0) {
2185
2216
  // start of the chain
2186
- return lexer_1.AllowedLocalIdentifiers.includes(currentToken.kind);
2217
+ return TokenKind_1.AllowedLocalIdentifiers.includes(currentToken.kind);
2187
2218
  }
2188
2219
  // not the start of the chain
2189
- return lexer_1.AllowedProperties.includes(currentToken.kind);
2220
+ return TokenKind_1.AllowedProperties.includes(currentToken.kind);
2190
2221
  }
2191
2222
  /**
2192
2223
  * Builds up a chain of tokens, starting with the first in the chain, and ending with currentToken
@@ -2233,32 +2264,67 @@ class Parser {
2233
2264
  */
2234
2265
  findReferences() {
2235
2266
  this._references = new References();
2267
+ const excludedExpressions = new Set();
2268
+ const visitCallExpression = (e) => {
2269
+ for (const p of e.args) {
2270
+ this._references.expressions.add(p);
2271
+ }
2272
+ //add calls that were not excluded (from loop below)
2273
+ if (!excludedExpressions.has(e)) {
2274
+ this._references.expressions.add(e);
2275
+ }
2276
+ //if this call is part of a longer expression that includes a call higher up, find that higher one and remove it
2277
+ if (e.callee) {
2278
+ let node = e.callee;
2279
+ while (node) {
2280
+ //the primary goal for this loop. If we found a parent call expression, remove it from `references`
2281
+ if ((0, reflection_1.isCallExpression)(node)) {
2282
+ this.references.expressions.delete(node);
2283
+ excludedExpressions.add(node);
2284
+ //stop here. even if there are multiple calls in the chain, each child will find and remove its closest parent, so that reduces excess walking.
2285
+ break;
2286
+ //when we hit a variable expression, we're definitely at the leftmost expression so stop
2287
+ }
2288
+ else if ((0, reflection_1.isVariableExpression)(node)) {
2289
+ break;
2290
+ //if
2291
+ }
2292
+ else if ((0, reflection_1.isDottedGetExpression)(node) || (0, reflection_1.isIndexedGetExpression)(node)) {
2293
+ node = node.obj;
2294
+ }
2295
+ else {
2296
+ //some expression we don't understand. log it and quit the loop
2297
+ this.logger.info('Encountered unknown expression while calculating function expression chain', node);
2298
+ break;
2299
+ }
2300
+ }
2301
+ }
2302
+ };
2236
2303
  //gather up all the top-level statements
2237
2304
  this.ast.walk((0, visitors_1.createVisitor)({
2305
+ AssignmentStatement: s => {
2306
+ this._references.assignmentStatements.push(s);
2307
+ this.references.expressions.add(s.value);
2308
+ },
2238
2309
  ClassStatement: s => {
2239
2310
  this._references.classStatements.push(s);
2240
2311
  },
2312
+ ClassFieldStatement: s => {
2313
+ if (s.initialValue) {
2314
+ this._references.expressions.add(s.initialValue);
2315
+ }
2316
+ },
2241
2317
  NamespaceStatement: s => {
2242
2318
  this._references.namespaceStatements.push(s);
2243
2319
  },
2244
2320
  FunctionStatement: s => {
2245
2321
  this._references.functionStatements.push(s);
2246
- //add the initial set of function expressions for function statements
2247
- this._references.functionExpressions.push(s.func);
2248
2322
  },
2249
2323
  ImportStatement: s => {
2250
2324
  this._references.importStatements.push(s);
2251
2325
  },
2252
2326
  LibraryStatement: s => {
2253
2327
  this._references.libraryStatements.push(s);
2254
- }
2255
- }), {
2256
- walkMode: visitors_1.WalkMode.visitStatements
2257
- });
2258
- let func;
2259
- let visitor = (0, visitors_1.createVisitor)({
2260
- AssignmentStatement: s => {
2261
- this._references.assignmentStatements.push(s);
2262
2328
  },
2263
2329
  FunctionExpression: (expression, parent) => {
2264
2330
  if (!(0, reflection_1.isClassMethodStatement)(parent)) {
@@ -2267,25 +2333,51 @@ class Parser {
2267
2333
  },
2268
2334
  NewExpression: e => {
2269
2335
  this._references.newExpressions.push(e);
2336
+ for (const p of e.call.args) {
2337
+ this._references.expressions.add(p);
2338
+ }
2339
+ },
2340
+ ExpressionStatement: s => {
2341
+ this._references.expressions.add(s.expression);
2342
+ },
2343
+ CallfuncExpression: e => {
2344
+ visitCallExpression(e);
2345
+ },
2346
+ CallExpression: e => {
2347
+ visitCallExpression(e);
2270
2348
  },
2271
2349
  AALiteralExpression: e => {
2272
2350
  this.addPropertyHints(e);
2351
+ this._references.expressions.add(e);
2352
+ for (const member of e.elements) {
2353
+ if ((0, reflection_1.isAAMemberExpression)(member)) {
2354
+ this._references.expressions.add(member.value);
2355
+ }
2356
+ }
2357
+ },
2358
+ ArrayLiteralExpression: e => {
2359
+ for (const element of e.elements) {
2360
+ //keep everything except comments
2361
+ if (!(0, reflection_1.isCommentStatement)(element)) {
2362
+ this._references.expressions.add(element);
2363
+ }
2364
+ }
2273
2365
  },
2274
2366
  DottedGetExpression: e => {
2275
2367
  this.addPropertyHints(e.name);
2276
2368
  },
2277
2369
  DottedSetStatement: e => {
2278
2370
  this.addPropertyHints(e.name);
2371
+ },
2372
+ UnaryExpression: e => {
2373
+ this._references.expressions.add(e);
2374
+ },
2375
+ IncrementStatement: e => {
2376
+ this._references.expressions.add(e);
2279
2377
  }
2378
+ }), {
2379
+ walkMode: visitors_1.WalkMode.visitAllRecursive
2280
2380
  });
2281
- //walk all function expressions (we'll add new ones as we move along too)
2282
- for (let i = 0; i < this._references.functionExpressions.length; i++) {
2283
- func = this._references.functionExpressions[i];
2284
- //walk this function expression
2285
- func.body.walk(visitor, {
2286
- walkMode: visitors_1.WalkMode.visitAll
2287
- });
2288
- }
2289
2381
  }
2290
2382
  getContainingClass(currentToken) {
2291
2383
  return this.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
@@ -2297,7 +2389,10 @@ class Parser {
2297
2389
  return this.references.namespaceStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
2298
2390
  }
2299
2391
  getContainingFunctionExpression(currentToken) {
2300
- return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, currentToken.range.start));
2392
+ return this.getContainingFunctionExpressionByPosition(currentToken.range.start);
2393
+ }
2394
+ getContainingFunctionExpressionByPosition(position) {
2395
+ return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, position));
2301
2396
  }
2302
2397
  dispose() {
2303
2398
  }
@@ -2317,6 +2412,17 @@ class References {
2317
2412
  this.functionExpressions = [];
2318
2413
  this.functionStatements = [];
2319
2414
  this.interfaceStatements = [];
2415
+ /**
2416
+ * A collection of full expressions. This excludes intermediary expressions.
2417
+ *
2418
+ * Example 1:
2419
+ * `a.b.c` is composed of `a` (variableExpression) `.b` (DottedGetExpression) `.c` (DottedGetExpression)
2420
+ * This will only contain the final `.c` DottedGetExpression because `.b` and `a` can both be derived by walking back from the `.c` DottedGetExpression.
2421
+ *
2422
+ * Example 2:
2423
+ * `name.space.doSomething(a.b.c)` will result in 2 entries in this list. the `CallExpression` for `doSomething`, and the `.c` DottedGetExpression.
2424
+ */
2425
+ this.expressions = new Set();
2320
2426
  this.importStatements = [];
2321
2427
  this.libraryStatements = [];
2322
2428
  this.namespaceStatements = [];
@@ -2388,7 +2494,10 @@ function getBscTypeFromExpression(expression, functionExpression) {
2388
2494
  //Array literal
2389
2495
  }
2390
2496
  else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {
2391
- return new ArrayType_1.ArrayType();
2497
+ const innerTypes = expression.elements.filter((element) => !(0, reflection_1.isCommentStatement)(element)).map((element) => {
2498
+ return getBscTypeFromExpression(element, functionExpression);
2499
+ });
2500
+ return new ArrayType_1.ArrayType(...innerTypes);
2392
2501
  //function call
2393
2502
  }
2394
2503
  else if ((0, reflection_1.isNewExpression)(expression)) {
@@ -2404,6 +2513,12 @@ function getBscTypeFromExpression(expression, functionExpression) {
2404
2513
  else if ((0, reflection_1.isDottedGetExpression)(expression)) {
2405
2514
  return (0, helpers_1.getTypeFromDottedGetExpression)(expression, functionExpression);
2406
2515
  }
2516
+ else if ((0, reflection_1.isIndexedGetExpression)(expression)) {
2517
+ const source = getBscTypeFromExpression(expression.obj, functionExpression);
2518
+ if ((0, reflection_1.isArrayType)(source)) {
2519
+ return source.getDefaultType();
2520
+ }
2521
+ }
2407
2522
  }
2408
2523
  catch (e) {
2409
2524
  //do nothing. Just return dynamic