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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/CHANGELOG.md +253 -268
  2. package/README.md +2 -2
  3. package/dist/Cache.d.ts +3 -8
  4. package/dist/Cache.js +9 -14
  5. package/dist/Cache.js.map +1 -1
  6. package/dist/CommentFlagProcessor.js +5 -3
  7. package/dist/CommentFlagProcessor.js.map +1 -1
  8. package/dist/DiagnosticMessages.d.ts +21 -1
  9. package/dist/DiagnosticMessages.js +21 -1
  10. package/dist/DiagnosticMessages.js.map +1 -1
  11. package/dist/LanguageServer.d.ts +1 -6
  12. package/dist/LanguageServer.js +0 -9
  13. package/dist/LanguageServer.js.map +1 -1
  14. package/dist/PluginInterface.d.ts +3 -3
  15. package/dist/PluginInterface.js +3 -0
  16. package/dist/PluginInterface.js.map +1 -1
  17. package/dist/Program.d.ts +30 -16
  18. package/dist/Program.js +110 -45
  19. package/dist/Program.js.map +1 -1
  20. package/dist/ProgramBuilder.js +3 -3
  21. package/dist/ProgramBuilder.js.map +1 -1
  22. package/dist/Scope.d.ts +31 -17
  23. package/dist/Scope.js +86 -48
  24. package/dist/Scope.js.map +1 -1
  25. package/dist/SymbolTable.d.ts +1 -1
  26. package/dist/XmlScope.d.ts +3 -3
  27. package/dist/astUtils/AstEditor.d.ts +33 -0
  28. package/dist/astUtils/AstEditor.js +107 -0
  29. package/dist/astUtils/AstEditor.js.map +1 -0
  30. package/dist/{bscPlugin/semanticTokens/SemanticTokensProcessor.spec.d.ts → astUtils/AstEditor.spec.d.ts} +0 -0
  31. package/dist/astUtils/AstEditor.spec.js +170 -0
  32. package/dist/astUtils/AstEditor.spec.js.map +1 -0
  33. package/dist/astUtils/reflection.d.ts +3 -1
  34. package/dist/astUtils/reflection.js +10 -2
  35. package/dist/astUtils/reflection.js.map +1 -1
  36. package/dist/astUtils/reflection.spec.js +6 -6
  37. package/dist/astUtils/reflection.spec.js.map +1 -1
  38. package/dist/astUtils/visitors.d.ts +3 -1
  39. package/dist/astUtils/visitors.js.map +1 -1
  40. package/dist/astUtils/visitors.spec.js +8 -8
  41. package/dist/astUtils/visitors.spec.js.map +1 -1
  42. package/dist/astUtils/xml.d.ts +1 -0
  43. package/dist/astUtils/xml.js +6 -1
  44. package/dist/astUtils/xml.js.map +1 -1
  45. package/dist/bscPlugin/BscPlugin.d.ts +4 -1
  46. package/dist/bscPlugin/BscPlugin.js +21 -2
  47. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  48. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
  49. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  50. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  51. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
  52. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
  53. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  54. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
  55. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +30 -2
  56. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  57. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
  58. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +36 -0
  59. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
  60. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
  61. package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
  62. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  63. package/dist/bscPlugin/validation/ScopeValidator.d.ts +11 -0
  64. package/dist/bscPlugin/validation/ScopeValidator.js +94 -0
  65. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  66. package/dist/files/BrsFile.Class.spec.js +404 -230
  67. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  68. package/dist/files/BrsFile.d.ts +26 -12
  69. package/dist/files/BrsFile.js +265 -127
  70. package/dist/files/BrsFile.js.map +1 -1
  71. package/dist/files/BrsFile.spec.js +586 -169
  72. package/dist/files/BrsFile.spec.js.map +1 -1
  73. package/dist/files/XmlFile.d.ts +11 -10
  74. package/dist/files/XmlFile.js +13 -8
  75. package/dist/files/XmlFile.js.map +1 -1
  76. package/dist/files/XmlFile.spec.js +106 -59
  77. package/dist/files/XmlFile.spec.js.map +1 -1
  78. package/dist/files/tests/imports.spec.js +8 -6
  79. package/dist/files/tests/imports.spec.js.map +1 -1
  80. package/dist/globalCallables.d.ts +3 -1
  81. package/dist/globalCallables.js +198 -99
  82. package/dist/globalCallables.js.map +1 -1
  83. package/dist/index.d.ts +12 -3
  84. package/dist/index.js +21 -4
  85. package/dist/index.js.map +1 -1
  86. package/dist/interfaces.d.ts +68 -15
  87. package/dist/lexer/Lexer.js +1 -2
  88. package/dist/lexer/Lexer.js.map +1 -1
  89. package/dist/lexer/Lexer.spec.js +470 -462
  90. package/dist/lexer/Lexer.spec.js.map +1 -1
  91. package/dist/lexer/TokenKind.d.ts +2 -0
  92. package/dist/lexer/TokenKind.js +5 -0
  93. package/dist/lexer/TokenKind.js.map +1 -1
  94. package/dist/parser/Expression.d.ts +1 -1
  95. package/dist/parser/Expression.js +10 -10
  96. package/dist/parser/Expression.js.map +1 -1
  97. package/dist/parser/Parser.Class.spec.js +33 -32
  98. package/dist/parser/Parser.Class.spec.js.map +1 -1
  99. package/dist/parser/Parser.d.ts +28 -7
  100. package/dist/parser/Parser.js +494 -290
  101. package/dist/parser/Parser.js.map +1 -1
  102. package/dist/parser/Parser.spec.js +157 -35
  103. package/dist/parser/Parser.spec.js.map +1 -1
  104. package/dist/parser/SGParser.js +1 -1
  105. package/dist/parser/SGParser.js.map +1 -1
  106. package/dist/parser/SGTypes.d.ts +3 -0
  107. package/dist/parser/SGTypes.js +8 -3
  108. package/dist/parser/SGTypes.js.map +1 -1
  109. package/dist/parser/SGTypes.spec.js +9 -9
  110. package/dist/parser/SGTypes.spec.js.map +1 -1
  111. package/dist/parser/Statement.d.ts +55 -3
  112. package/dist/parser/Statement.js +162 -9
  113. package/dist/parser/Statement.js.map +1 -1
  114. package/dist/parser/tests/Parser.spec.d.ts +3 -3
  115. package/dist/parser/tests/Parser.spec.js +4 -4
  116. package/dist/parser/tests/Parser.spec.js.map +1 -1
  117. package/dist/parser/tests/controlFlow/For.spec.js +40 -40
  118. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  119. package/dist/parser/tests/controlFlow/ForEach.spec.js +22 -21
  120. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  121. package/dist/parser/tests/controlFlow/If.spec.js +100 -99
  122. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  123. package/dist/parser/tests/controlFlow/While.spec.js +25 -25
  124. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  125. package/dist/parser/tests/expression/Additive.spec.js +21 -21
  126. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  127. package/dist/parser/tests/expression/ArrayLiterals.spec.js +91 -91
  128. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  129. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +102 -102
  130. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  131. package/dist/parser/tests/expression/Boolean.spec.js +15 -15
  132. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  133. package/dist/parser/tests/expression/Call.spec.js +22 -21
  134. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  135. package/dist/parser/tests/expression/Exponential.spec.js +11 -11
  136. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  137. package/dist/parser/tests/expression/Function.spec.js +171 -171
  138. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  139. package/dist/parser/tests/expression/Indexing.spec.js +50 -50
  140. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  141. package/dist/parser/tests/expression/Multiplicative.spec.js +25 -25
  142. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  143. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +30 -18
  144. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  145. package/dist/parser/tests/expression/PrefixUnary.spec.js +26 -26
  146. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  147. package/dist/parser/tests/expression/Primary.spec.js +27 -27
  148. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  149. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +3 -2
  150. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  151. package/dist/parser/tests/expression/Relational.spec.js +25 -25
  152. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  153. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +7 -7
  154. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  155. package/dist/parser/tests/expression/TernaryExpression.spec.js +6 -6
  156. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  157. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  158. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  159. package/dist/parser/tests/statement/Declaration.spec.js +20 -20
  160. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  161. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  162. package/dist/parser/tests/statement/Enum.spec.js +774 -0
  163. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  164. package/dist/parser/tests/statement/Function.spec.js +121 -120
  165. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  166. package/dist/parser/tests/statement/Goto.spec.js +9 -8
  167. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  168. package/dist/parser/tests/statement/Increment.spec.js +22 -22
  169. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  170. package/dist/parser/tests/statement/InterfaceStatement.spec.js +12 -0
  171. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  172. package/dist/parser/tests/statement/LibraryStatement.spec.js +7 -7
  173. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  174. package/dist/parser/tests/statement/Misc.spec.js +71 -70
  175. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  176. package/dist/parser/tests/statement/PrintStatement.spec.js +17 -17
  177. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  178. package/dist/parser/tests/statement/ReturnStatement.spec.js +33 -33
  179. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  180. package/dist/parser/tests/statement/Set.spec.js +53 -53
  181. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  182. package/dist/parser/tests/statement/Stop.spec.js +7 -6
  183. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  184. package/dist/preprocessor/Chunk.d.ts +1 -1
  185. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  186. package/dist/preprocessor/Preprocessor.js +7 -7
  187. package/dist/preprocessor/Preprocessor.js.map +1 -1
  188. package/dist/types/ArrayType.d.ts +8 -5
  189. package/dist/types/ArrayType.js +45 -9
  190. package/dist/types/ArrayType.js.map +1 -1
  191. package/dist/types/ArrayType.spec.js +62 -3
  192. package/dist/types/ArrayType.spec.js.map +1 -1
  193. package/dist/types/BscType.d.ts +1 -1
  194. package/dist/types/CustomType.d.ts +1 -1
  195. package/dist/types/CustomType.js +4 -2
  196. package/dist/types/CustomType.js.map +1 -1
  197. package/dist/types/FunctionType.d.ts +5 -5
  198. package/dist/types/FunctionType.js +11 -11
  199. package/dist/types/FunctionType.js.map +1 -1
  200. package/dist/types/FunctionType.spec.js +1 -1
  201. package/dist/types/FunctionType.spec.js.map +1 -1
  202. package/dist/types/LazyType.d.ts +1 -2
  203. package/dist/types/LazyType.js +1 -5
  204. package/dist/types/LazyType.js.map +1 -1
  205. package/dist/types/helpers.js +1 -1
  206. package/dist/types/helpers.js.map +1 -1
  207. package/dist/util.d.ts +25 -9
  208. package/dist/util.js +139 -55
  209. package/dist/util.js.map +1 -1
  210. package/dist/validators/ClassValidator.js +27 -27
  211. package/dist/validators/ClassValidator.js.map +1 -1
  212. package/package.json +4 -3
  213. package/dist/astUtils/index.d.ts +0 -7
  214. package/dist/astUtils/index.js +0 -26
  215. package/dist/astUtils/index.js.map +0 -1
  216. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  217. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
  218. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  219. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  220. package/dist/lexer/index.d.ts +0 -3
  221. package/dist/lexer/index.js +0 -18
  222. package/dist/lexer/index.js.map +0 -1
  223. package/dist/parser/index.d.ts +0 -3
  224. package/dist/parser/index.js +0 -16
  225. package/dist/parser/index.js.map +0 -1
  226. package/dist/preprocessor/index.d.ts +0 -3
  227. package/dist/preprocessor/index.js +0 -16
  228. package/dist/preprocessor/index.js.map +0 -1
@@ -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,12 @@ 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");
15
+ const Cache_1 = require("../Cache");
13
16
  const DynamicType_1 = require("../types/DynamicType");
14
- const SymbolTable_1 = require("../SymbolTable");
15
- const ObjectType_1 = require("../types/ObjectType");
16
17
  const ArrayType_1 = require("../types/ArrayType");
17
18
  const helpers_1 = require("../types/helpers");
18
- const _1 = require(".");
19
+ const SymbolTable_1 = require("../SymbolTable");
20
+ const ObjectType_1 = require("../types/ObjectType");
19
21
  class Parser {
20
22
  constructor() {
21
23
  /**
@@ -61,7 +63,7 @@ class Parser {
61
63
  this._references = undefined;
62
64
  }
63
65
  addPropertyHints(item) {
64
- if ((0, lexer_1.isToken)(item)) {
66
+ if ((0, Token_1.isToken)(item)) {
65
67
  const name = item.text;
66
68
  this._references.propertyHints[name.toLowerCase()] = name;
67
69
  }
@@ -93,7 +95,7 @@ class Parser {
93
95
  static parse(toParse, options) {
94
96
  let tokens;
95
97
  if (typeof toParse === 'string') {
96
- tokens = lexer_1.Lexer.scan(toParse).tokens;
98
+ tokens = Lexer_1.Lexer.scan(toParse).tokens;
97
99
  }
98
100
  else {
99
101
  tokens = toParse;
@@ -111,9 +113,9 @@ class Parser {
111
113
  this.tokens = tokens;
112
114
  this.options = this.sanitizeParseOptions(options);
113
115
  this.allowedLocalIdentifiers = [
114
- ...lexer_1.AllowedLocalIdentifiers,
116
+ ...TokenKind_1.AllowedLocalIdentifiers,
115
117
  //when in plain brightscript mode, the BrighterScript source literals can be used as regular variables
116
- ...(this.options.mode === ParseMode.BrightScript ? lexer_1.BrighterScriptSourceLiterals : [])
118
+ ...(this.options.mode === ParseMode.BrightScript ? TokenKind_1.BrighterScriptSourceLiterals : [])
117
119
  ];
118
120
  this.current = 0;
119
121
  this.diagnostics = [];
@@ -184,16 +186,16 @@ class Parser {
184
186
  }
185
187
  declaration() {
186
188
  try {
187
- if (this.checkAny(lexer_1.TokenKind.Sub, lexer_1.TokenKind.Function)) {
189
+ if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
188
190
  return this.functionDeclaration(false);
189
191
  }
190
192
  if (this.checkLibrary()) {
191
193
  return this.libraryStatement();
192
194
  }
193
- if (this.check(lexer_1.TokenKind.At) && this.checkNext(lexer_1.TokenKind.Identifier)) {
195
+ if (this.check(TokenKind_1.TokenKind.At) && this.checkNext(TokenKind_1.TokenKind.Identifier)) {
194
196
  return this.annotationExpression();
195
197
  }
196
- if (this.check(lexer_1.TokenKind.Comment)) {
198
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
197
199
  return this.commentStatement();
198
200
  }
199
201
  //catch certain global terminators to prevent unnecessary lookahead (i.e. like `end namespace`, no need to continue)
@@ -210,18 +212,39 @@ class Parser {
210
212
  this.synchronize();
211
213
  }
212
214
  }
215
+ /**
216
+ * Try to get an identifier. If not found, add diagnostic and return undefined
217
+ */
218
+ tryIdentifier(...additionalTokenKinds) {
219
+ const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
220
+ if (identifier) {
221
+ // force the name into an identifier so the AST makes some sense
222
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
223
+ return identifier;
224
+ }
225
+ }
213
226
  identifier(...additionalTokenKinds) {
214
- const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...additionalTokenKinds);
227
+ const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
215
228
  // force the name into an identifier so the AST makes some sense
216
- identifier.kind = lexer_1.TokenKind.Identifier;
229
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
217
230
  return identifier;
218
231
  }
232
+ enumMemberStatement() {
233
+ const statement = new Statement_1.EnumMemberStatement({});
234
+ statement.tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
235
+ //look for `= SOME_EXPRESSION`
236
+ if (this.check(TokenKind_1.TokenKind.Equal)) {
237
+ statement.tokens.equal = this.advance();
238
+ statement.value = this.expression();
239
+ }
240
+ return statement;
241
+ }
219
242
  /**
220
243
  * Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration`
221
244
  */
222
245
  interfaceFieldStatement() {
223
- const name = this.identifier(...lexer_1.AllowedProperties);
224
- let asToken = this.consumeToken(lexer_1.TokenKind.As);
246
+ const name = this.identifier(...TokenKind_1.AllowedProperties);
247
+ let asToken = this.consumeToken(TokenKind_1.TokenKind.As);
225
248
  let typeToken = this.typeToken();
226
249
  const type = util_1.util.tokenToBscType(typeToken);
227
250
  if (!type) {
@@ -235,13 +258,13 @@ class Parser {
235
258
  */
236
259
  interfaceMethodStatement() {
237
260
  const functionType = this.advance();
238
- const name = this.identifier(...lexer_1.AllowedProperties);
239
- const leftParen = this.consumeToken(lexer_1.TokenKind.LeftParen);
261
+ const name = this.identifier(...TokenKind_1.AllowedProperties);
262
+ const leftParen = this.consumeToken(TokenKind_1.TokenKind.LeftParen);
240
263
  const params = [];
241
- const rightParen = this.consumeToken(lexer_1.TokenKind.RightParen);
264
+ const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
242
265
  let asToken = null;
243
266
  let returnTypeToken = null;
244
- if (this.check(lexer_1.TokenKind.As)) {
267
+ if (this.check(TokenKind_1.TokenKind.As)) {
245
268
  asToken = this.advance();
246
269
  returnTypeToken = this.typeToken();
247
270
  const returnType = util_1.util.tokenToBscType(returnTypeToken);
@@ -255,7 +278,7 @@ class Parser {
255
278
  interfaceDeclaration() {
256
279
  this.warnIfNotBrighterScriptMode('interface declarations');
257
280
  const parentAnnotations = this.enterAnnotationBlock();
258
- const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(lexer_1.TokenKind.Interface), lexer_1.TokenKind.Interface);
281
+ const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
259
282
  const nameToken = this.identifier(...this.allowedLocalIdentifiers);
260
283
  let extendsToken;
261
284
  let parentInterfaceName;
@@ -266,23 +289,23 @@ class Parser {
266
289
  this.consumeStatementSeparators();
267
290
  //gather up all interface members (Fields, Methods)
268
291
  let body = [];
269
- while (this.checkAny(lexer_1.TokenKind.Comment, lexer_1.TokenKind.Identifier, lexer_1.TokenKind.At, ...lexer_1.AllowedProperties)) {
292
+ while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
270
293
  try {
271
294
  let decl;
272
295
  //collect leading annotations
273
- if (this.check(lexer_1.TokenKind.At)) {
296
+ if (this.check(TokenKind_1.TokenKind.At)) {
274
297
  this.annotationExpression();
275
298
  }
276
299
  //fields
277
- if (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties) && this.checkNext(lexer_1.TokenKind.As)) {
300
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.As)) {
278
301
  decl = this.interfaceFieldStatement();
279
302
  //methods (function/sub keyword followed by opening paren)
280
303
  }
281
- else if (this.checkAny(lexer_1.TokenKind.Function, lexer_1.TokenKind.Sub) && this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties)) {
304
+ else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
282
305
  decl = this.interfaceMethodStatement();
283
306
  //comments
284
307
  }
285
- else if (this.check(lexer_1.TokenKind.Comment)) {
308
+ else if (this.check(TokenKind_1.TokenKind.Comment)) {
286
309
  decl = this.commentStatement();
287
310
  }
288
311
  if (decl) {
@@ -291,39 +314,87 @@ class Parser {
291
314
  }
292
315
  else {
293
316
  //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);
317
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
295
318
  }
296
319
  }
297
320
  catch (e) {
298
321
  //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);
322
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
300
323
  }
301
324
  //ensure statement separator
302
325
  this.consumeStatementSeparators();
303
326
  //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)) {
327
+ if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
305
328
  break;
306
329
  }
307
330
  }
308
331
  //consume the final `end interface` token
309
- const endInterfaceToken = this.consumeToken(lexer_1.TokenKind.EndInterface);
310
- this.consumeStatementSeparators();
332
+ const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
311
333
  const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endInterfaceToken, this.currentNamespaceName);
312
334
  this._references.interfaceStatements.push(statement);
313
335
  this.exitAnnotationBlock(parentAnnotations);
314
336
  return statement;
315
337
  }
338
+ enumDeclaration() {
339
+ const result = new Statement_1.EnumStatement({}, [], this.currentNamespaceName);
340
+ this.warnIfNotBrighterScriptMode('enum declarations');
341
+ const parentAnnotations = this.enterAnnotationBlock();
342
+ result.tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
343
+ result.tokens.name = this.tryIdentifier();
344
+ this.consumeStatementSeparators();
345
+ //gather up all members
346
+ while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
347
+ try {
348
+ let decl;
349
+ //collect leading annotations
350
+ if (this.check(TokenKind_1.TokenKind.At)) {
351
+ this.annotationExpression();
352
+ }
353
+ //members
354
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
355
+ decl = this.enumMemberStatement();
356
+ //comments
357
+ }
358
+ else if (this.check(TokenKind_1.TokenKind.Comment)) {
359
+ decl = this.commentStatement();
360
+ }
361
+ if (decl) {
362
+ this.consumePendingAnnotations(decl);
363
+ result.body.push(decl);
364
+ }
365
+ else {
366
+ //we didn't find a declaration...flag tokens until next line
367
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
368
+ }
369
+ }
370
+ catch (e) {
371
+ //throw out any failed members and move on to the next line
372
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
373
+ }
374
+ //ensure statement separator
375
+ this.consumeStatementSeparators();
376
+ //break out of this loop if we encountered the `EndEnum` token
377
+ if (this.check(TokenKind_1.TokenKind.EndEnum)) {
378
+ break;
379
+ }
380
+ }
381
+ //consume the final `end interface` token
382
+ result.tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
383
+ this._references.enumStatements.push(result);
384
+ this.exitAnnotationBlock(parentAnnotations);
385
+ return result;
386
+ }
316
387
  /**
317
388
  * A BrighterScript class declaration
318
389
  */
319
390
  classDeclaration() {
320
391
  this.warnIfNotBrighterScriptMode('class declarations');
321
392
  const parentAnnotations = this.enterAnnotationBlock();
322
- let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(lexer_1.TokenKind.Class), lexer_1.TokenKind.Class);
393
+ let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Class), TokenKind_1.TokenKind.Class);
323
394
  let extendsKeyword;
324
395
  let parentClassName;
325
396
  //get the class name
326
- let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
397
+ let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
327
398
  //see if the class inherits from parent
328
399
  if (this.peek().text.toLowerCase() === 'extends') {
329
400
  extendsKeyword = this.advance();
@@ -333,14 +404,14 @@ class Parser {
333
404
  this.consumeStatementSeparators();
334
405
  //gather up all class members (Fields, Methods)
335
406
  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)) {
407
+ 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
408
  try {
338
409
  let decl;
339
410
  let accessModifier;
340
- if (this.check(lexer_1.TokenKind.At)) {
411
+ if (this.check(TokenKind_1.TokenKind.At)) {
341
412
  this.annotationExpression();
342
413
  }
343
- if (this.checkAny(lexer_1.TokenKind.Public, lexer_1.TokenKind.Protected, lexer_1.TokenKind.Private)) {
414
+ if (this.checkAny(TokenKind_1.TokenKind.Public, TokenKind_1.TokenKind.Protected, TokenKind_1.TokenKind.Private)) {
344
415
  //use actual access modifier
345
416
  accessModifier = this.advance();
346
417
  }
@@ -349,7 +420,7 @@ class Parser {
349
420
  overrideKeyword = this.advance();
350
421
  }
351
422
  //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))) {
423
+ 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
424
  const funcDeclaration = this.functionDeclaration(false, false, true);
354
425
  //remove this function from the lists because it's not a callable
355
426
  const functionStatement = this._references.functionStatements.pop();
@@ -362,7 +433,7 @@ class Parser {
362
433
  functionStatement.func.functionStatement = decl;
363
434
  //fields
364
435
  }
365
- else if (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties)) {
436
+ else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
366
437
  decl = this.classFieldDeclaration(accessModifier);
367
438
  //class fields cannot be overridden
368
439
  if (overrideKeyword) {
@@ -370,7 +441,7 @@ class Parser {
370
441
  }
371
442
  //comments
372
443
  }
373
- else if (this.check(lexer_1.TokenKind.Comment)) {
444
+ else if (this.check(TokenKind_1.TokenKind.Comment)) {
374
445
  decl = this.commentStatement();
375
446
  }
376
447
  if (decl) {
@@ -380,13 +451,13 @@ class Parser {
380
451
  }
381
452
  catch (e) {
382
453
  //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);
454
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
384
455
  }
385
456
  //ensure statement separator
386
457
  this.consumeStatementSeparators();
387
458
  }
388
459
  let endingKeyword = this.advance();
389
- if (endingKeyword.kind !== lexer_1.TokenKind.EndClass) {
460
+ if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
390
461
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
391
462
  }
392
463
  const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName, this.currentSymbolTable);
@@ -398,11 +469,11 @@ class Parser {
398
469
  return result;
399
470
  }
400
471
  classFieldDeclaration(accessModifier) {
401
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
472
+ let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
402
473
  let asToken;
403
474
  let fieldType;
404
475
  //look for `as SOME_TYPE`
405
- if (this.check(lexer_1.TokenKind.As)) {
476
+ if (this.check(TokenKind_1.TokenKind.As)) {
406
477
  asToken = this.advance();
407
478
  fieldType = this.typeToken();
408
479
  //no field type specified
@@ -413,7 +484,7 @@ class Parser {
413
484
  let initialValue;
414
485
  let equal;
415
486
  //if there is a field initializer
416
- if (this.check(lexer_1.TokenKind.Equal)) {
487
+ if (this.check(TokenKind_1.TokenKind.Equal)) {
417
488
  equal = this.advance();
418
489
  initialValue = this.expression();
419
490
  }
@@ -427,14 +498,14 @@ class Parser {
427
498
  //track depth to help certain statements need to know if they are contained within a function body
428
499
  this.namespaceAndFunctionDepth++;
429
500
  let functionType;
430
- if (this.checkAny(lexer_1.TokenKind.Sub, lexer_1.TokenKind.Function)) {
501
+ if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
431
502
  functionType = this.advance();
432
503
  }
433
504
  else {
434
505
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
435
506
  functionType = {
436
507
  isReserved: true,
437
- kind: lexer_1.TokenKind.Function,
508
+ kind: TokenKind_1.TokenKind.Function,
438
509
  text: 'function',
439
510
  //zero-length location means derived
440
511
  range: {
@@ -444,16 +515,16 @@ class Parser {
444
515
  leadingWhitespace: ''
445
516
  };
446
517
  }
447
- let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === lexer_1.TokenKind.Sub;
518
+ let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === TokenKind_1.TokenKind.Sub;
448
519
  let functionTypeText = isSub ? 'sub' : 'function';
449
520
  let name;
450
521
  let leftParen;
451
522
  if (isAnonymous) {
452
- leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), lexer_1.TokenKind.LeftParen);
523
+ leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), TokenKind_1.TokenKind.LeftParen);
453
524
  }
454
525
  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);
526
+ name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
527
+ leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), TokenKind_1.TokenKind.LeftParen);
457
528
  //prevent functions from ending with type designators
458
529
  let lastChar = name.text[name.text.length - 1];
459
530
  if (['$', '%', '!', '#', '&'].includes(lastChar)) {
@@ -461,23 +532,23 @@ class Parser {
461
532
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionTypeText, name.text, lastChar)), { range: name.range }));
462
533
  }
463
534
  //flag functions with keywords for names (only for standard functions)
464
- if (checkIdentifier && lexer_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
535
+ if (checkIdentifier && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
465
536
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
466
537
  }
467
538
  }
468
539
  let params = [];
469
540
  let asToken;
470
541
  let typeToken;
471
- if (!this.check(lexer_1.TokenKind.RightParen)) {
542
+ if (!this.check(TokenKind_1.TokenKind.RightParen)) {
472
543
  do {
473
544
  if (params.length >= Expression_1.CallExpression.MaximumArguments) {
474
545
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(params.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
475
546
  }
476
547
  params.push(this.functionParameter());
477
- } while (this.match(lexer_1.TokenKind.Comma));
548
+ } while (this.match(TokenKind_1.TokenKind.Comma));
478
549
  }
479
550
  let rightParen = this.advance();
480
- if (this.check(lexer_1.TokenKind.As)) {
551
+ if (this.check(TokenKind_1.TokenKind.As)) {
481
552
  asToken = this.advance();
482
553
  typeToken = this.typeToken();
483
554
  if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
@@ -529,7 +600,7 @@ class Parser {
529
600
  }
530
601
  // consume 'end sub' or 'end function'
531
602
  func.end = this.advance();
532
- let expectedEndKind = isSub ? lexer_1.TokenKind.EndSub : lexer_1.TokenKind.EndFunction;
603
+ let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
533
604
  //if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
534
605
  //add an error but don't hard-fail so the AST can continue more gracefully
535
606
  if (func.end.kind !== expectedEndKind) {
@@ -553,22 +624,22 @@ class Parser {
553
624
  }
554
625
  }
555
626
  functionParameter() {
556
- if (!this.checkAny(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
627
+ if (!this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
557
628
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
558
629
  throw this.lastDiagnosticAsError();
559
630
  }
560
- const name = this.identifier(...lexer_1.AllowedLocalIdentifiers);
631
+ const name = this.identifier(...TokenKind_1.AllowedLocalIdentifiers);
561
632
  let typeToken;
562
633
  let defaultValue;
563
634
  let equalsToken;
564
635
  // parse argument default value
565
- if (this.match(lexer_1.TokenKind.Equal)) {
636
+ if (this.match(TokenKind_1.TokenKind.Equal)) {
566
637
  equalsToken = this.previous();
567
638
  // it seems any expression is allowed here -- including ones that operate on other arguments!
568
639
  defaultValue = this.expression();
569
640
  }
570
641
  let asToken = null;
571
- if (this.check(lexer_1.TokenKind.As)) {
642
+ if (this.check(TokenKind_1.TokenKind.As)) {
572
643
  asToken = this.advance();
573
644
  typeToken = this.typeToken();
574
645
  if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
@@ -594,17 +665,20 @@ class Parser {
594
665
  assignment() {
595
666
  let name = this.identifier(...this.allowedLocalIdentifiers);
596
667
  //add diagnostic if name is a reserved word that cannot be used as an identifier
597
- if (lexer_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
668
+ if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
598
669
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
599
670
  }
600
- let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(lexer_1.AssignmentOperators, name.text), ...lexer_1.AssignmentOperators);
671
+ let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(TokenKind_1.AssignmentOperators, name.text), ...TokenKind_1.AssignmentOperators);
601
672
  let value = this.expression();
602
673
  let result;
603
- if (operator.kind === lexer_1.TokenKind.Equal) {
674
+ if (operator.kind === TokenKind_1.TokenKind.Equal) {
604
675
  result = new Statement_1.AssignmentStatement(name, operator, value, this.currentFunctionExpression);
605
676
  }
606
677
  else {
607
678
  result = new Statement_1.AssignmentStatement(name, operator, new Expression_1.BinaryExpression(new Expression_1.VariableExpression(name, this.currentNamespaceName), operator, value), this.currentFunctionExpression);
679
+ //remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
680
+ this._references.expressions.delete(value);
681
+ this._references.expressions.add(result);
608
682
  }
609
683
  this._references.assignmentStatements.push(result);
610
684
  const assignmentType = getBscTypeFromExpression(result.value, this.currentFunctionExpression);
@@ -612,14 +686,14 @@ class Parser {
612
686
  return result;
613
687
  }
614
688
  checkLibrary() {
615
- let isLibraryToken = this.check(lexer_1.TokenKind.Library);
689
+ let isLibraryToken = this.check(TokenKind_1.TokenKind.Library);
616
690
  //if we are at the top level, any line that starts with "library" should be considered a library statement
617
691
  if (this.isAtRootLevel() && isLibraryToken) {
618
692
  return true;
619
693
  //not at root level, library statements are all invalid here, but try to detect if the tokens look
620
694
  //like a library statement (and let the libraryStatement function handle emitting the diagnostics)
621
695
  }
622
- else if (isLibraryToken && this.checkNext(lexer_1.TokenKind.StringLiteral)) {
696
+ else if (isLibraryToken && this.checkNext(TokenKind_1.TokenKind.StringLiteral)) {
623
697
  return true;
624
698
  //definitely not a library statement
625
699
  }
@@ -631,54 +705,54 @@ class Parser {
631
705
  if (this.checkLibrary()) {
632
706
  return this.libraryStatement();
633
707
  }
634
- if (this.check(lexer_1.TokenKind.Import)) {
708
+ if (this.check(TokenKind_1.TokenKind.Import)) {
635
709
  return this.importStatement();
636
710
  }
637
- if (this.check(lexer_1.TokenKind.Stop)) {
711
+ if (this.check(TokenKind_1.TokenKind.Stop)) {
638
712
  return this.stopStatement();
639
713
  }
640
- if (this.check(lexer_1.TokenKind.If)) {
714
+ if (this.check(TokenKind_1.TokenKind.If)) {
641
715
  return this.ifStatement();
642
716
  }
643
717
  //`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)) {
718
+ if (this.check(TokenKind_1.TokenKind.Try) && this.checkAnyNext(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
645
719
  return this.tryCatchStatement();
646
720
  }
647
- if (this.check(lexer_1.TokenKind.Throw)) {
721
+ if (this.check(TokenKind_1.TokenKind.Throw)) {
648
722
  return this.throwStatement();
649
723
  }
650
- if (this.checkAny(lexer_1.TokenKind.Print, lexer_1.TokenKind.Question)) {
724
+ if (this.checkAny(TokenKind_1.TokenKind.Print, TokenKind_1.TokenKind.Question)) {
651
725
  return this.printStatement();
652
726
  }
653
- if (this.check(lexer_1.TokenKind.Dim)) {
727
+ if (this.check(TokenKind_1.TokenKind.Dim)) {
654
728
  return this.dimStatement();
655
729
  }
656
- if (this.check(lexer_1.TokenKind.While)) {
730
+ if (this.check(TokenKind_1.TokenKind.While)) {
657
731
  return this.whileStatement();
658
732
  }
659
- if (this.check(lexer_1.TokenKind.ExitWhile)) {
733
+ if (this.check(TokenKind_1.TokenKind.ExitWhile)) {
660
734
  return this.exitWhile();
661
735
  }
662
- if (this.check(lexer_1.TokenKind.For)) {
736
+ if (this.check(TokenKind_1.TokenKind.For)) {
663
737
  return this.forStatement();
664
738
  }
665
- if (this.check(lexer_1.TokenKind.ForEach)) {
739
+ if (this.check(TokenKind_1.TokenKind.ForEach)) {
666
740
  return this.forEachStatement();
667
741
  }
668
- if (this.check(lexer_1.TokenKind.ExitFor)) {
742
+ if (this.check(TokenKind_1.TokenKind.ExitFor)) {
669
743
  return this.exitFor();
670
744
  }
671
- if (this.check(lexer_1.TokenKind.End)) {
745
+ if (this.check(TokenKind_1.TokenKind.End)) {
672
746
  return this.endStatement();
673
747
  }
674
- if (this.match(lexer_1.TokenKind.Return)) {
748
+ if (this.match(TokenKind_1.TokenKind.Return)) {
675
749
  return this.returnStatement();
676
750
  }
677
- if (this.check(lexer_1.TokenKind.Goto)) {
751
+ if (this.check(TokenKind_1.TokenKind.Goto)) {
678
752
  return this.gotoStatement();
679
753
  }
680
754
  //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)) {
755
+ if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
682
756
  try {
683
757
  return this.labelStatement();
684
758
  }
@@ -692,20 +766,23 @@ class Parser {
692
766
  // BrightScript is like python, in that variables can be declared without a `var`,
693
767
  // `let`, (...) keyword. As such, we must check the token *after* an identifier to figure
694
768
  // out what to do with it.
695
- if (this.checkAny(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers) &&
696
- this.checkAnyNext(...lexer_1.AssignmentOperators)) {
769
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers) &&
770
+ this.checkAnyNext(...TokenKind_1.AssignmentOperators)) {
697
771
  return this.assignment();
698
772
  }
699
773
  //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)) {
774
+ if (this.check(TokenKind_1.TokenKind.Interface)) {
701
775
  return this.interfaceDeclaration();
702
776
  }
703
- if (this.check(lexer_1.TokenKind.Class)) {
777
+ if (this.check(TokenKind_1.TokenKind.Class)) {
704
778
  return this.classDeclaration();
705
779
  }
706
- if (this.check(lexer_1.TokenKind.Namespace)) {
780
+ if (this.check(TokenKind_1.TokenKind.Namespace)) {
707
781
  return this.namespaceStatement();
708
782
  }
783
+ if (this.check(TokenKind_1.TokenKind.Enum)) {
784
+ return this.enumDeclaration();
785
+ }
709
786
  // TODO: support multi-statements
710
787
  return this.setStatement();
711
788
  }
@@ -713,9 +790,9 @@ class Parser {
713
790
  const whileKeyword = this.advance();
714
791
  const condition = this.expression();
715
792
  this.consumeStatementSeparators();
716
- const whileBlock = this.block(lexer_1.TokenKind.EndWhile);
793
+ const whileBlock = this.block(TokenKind_1.TokenKind.EndWhile);
717
794
  let endWhile;
718
- if (!whileBlock || this.peek().kind !== lexer_1.TokenKind.EndWhile) {
795
+ if (!whileBlock || this.peek().kind !== TokenKind_1.TokenKind.EndWhile) {
719
796
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('while')), { range: this.peek().range }));
720
797
  if (!whileBlock) {
721
798
  throw this.lastDiagnosticAsError();
@@ -738,7 +815,7 @@ class Parser {
738
815
  const finalValue = this.expression();
739
816
  let incrementExpression;
740
817
  let stepToken;
741
- if (this.check(lexer_1.TokenKind.Step)) {
818
+ if (this.check(TokenKind_1.TokenKind.Step)) {
742
819
  stepToken = this.advance();
743
820
  incrementExpression = this.expression();
744
821
  }
@@ -746,9 +823,9 @@ class Parser {
746
823
  // BrightScript for/to/step loops default to a step of 1 if no `step` is provided
747
824
  }
748
825
  this.consumeStatementSeparators();
749
- let body = this.block(lexer_1.TokenKind.EndFor, lexer_1.TokenKind.Next);
826
+ let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
750
827
  let endForToken;
751
- if (!body || !this.checkAny(lexer_1.TokenKind.EndFor, lexer_1.TokenKind.Next)) {
828
+ if (!body || !this.checkAny(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next)) {
752
829
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
753
830
  if (!body) {
754
831
  throw this.lastDiagnosticAsError();
@@ -765,7 +842,7 @@ class Parser {
765
842
  let forEach = this.advance();
766
843
  let name = this.identifier(...this.allowedLocalIdentifiers);
767
844
  let maybeIn = this.peek();
768
- if (this.check(lexer_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
845
+ if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
769
846
  this.advance();
770
847
  }
771
848
  else {
@@ -778,14 +855,17 @@ class Parser {
778
855
  throw this.lastDiagnosticAsError();
779
856
  }
780
857
  this.consumeStatementSeparators();
781
- let body = this.block(lexer_1.TokenKind.EndFor, lexer_1.TokenKind.Next);
858
+ let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
782
859
  if (!body) {
783
860
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
784
861
  throw this.lastDiagnosticAsError();
785
862
  }
786
863
  let endFor = this.advance();
787
- //TODO TYPES infer type from `target`
788
- const itemType = new DynamicType_1.DynamicType();
864
+ let itemType = new DynamicType_1.DynamicType();
865
+ const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
866
+ if ((0, reflection_1.isArrayType)(targetType)) {
867
+ itemType = targetType.getDefaultType();
868
+ }
789
869
  this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
790
870
  return new Statement_1.ForEachStatement(forEach, name, maybeIn, target, body, endFor);
791
871
  }
@@ -802,7 +882,7 @@ class Parser {
802
882
  }
803
883
  else {
804
884
  let comments = [this.advance()];
805
- while (this.check(lexer_1.TokenKind.Newline) && this.checkNext(lexer_1.TokenKind.Comment)) {
885
+ while (this.check(TokenKind_1.TokenKind.Newline) && this.checkNext(TokenKind_1.TokenKind.Comment)) {
806
886
  this.advance();
807
887
  comments.push(this.advance());
808
888
  }
@@ -820,13 +900,13 @@ class Parser {
820
900
  //set the current namespace name
821
901
  let result = new Statement_1.NamespaceStatement(keyword, name, null, null, this.currentSymbolTable);
822
902
  this.currentNamespace = result;
823
- this.globalTerminators.push([lexer_1.TokenKind.EndNamespace]);
903
+ this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
824
904
  let body = this.body();
825
905
  this.globalTerminators.pop();
826
906
  //unset the current namespace name
827
907
  this.currentNamespace = undefined;
828
908
  let endKeyword;
829
- if (this.check(lexer_1.TokenKind.EndNamespace)) {
909
+ if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
830
910
  endKeyword = this.advance();
831
911
  }
832
912
  else {
@@ -843,24 +923,25 @@ class Parser {
843
923
  * Get an expression with identifiers separated by periods. Useful for namespaces and class extends
844
924
  */
845
925
  getNamespacedVariableNameExpression() {
846
- let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
926
+ let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
847
927
  let expr;
848
928
  if (firstIdentifier) {
849
929
  // force it into an identifier so the AST makes some sense
850
- firstIdentifier.kind = lexer_1.TokenKind.Identifier;
851
- expr = new Expression_1.VariableExpression(firstIdentifier, null);
930
+ firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
931
+ const varExpr = new Expression_1.VariableExpression(firstIdentifier, null);
932
+ expr = varExpr;
852
933
  //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);
934
+ while (this.check(TokenKind_1.TokenKind.Dot)) {
935
+ let dot = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.Dot);
855
936
  if (!dot) {
856
937
  break;
857
938
  }
858
- let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, ...lexer_1.AllowedProperties);
939
+ let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, ...TokenKind_1.AllowedProperties);
859
940
  if (!identifier) {
860
941
  break;
861
942
  }
862
943
  // force it into an identifier so the AST makes some sense
863
- identifier.kind = lexer_1.TokenKind.Identifier;
944
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
864
945
  expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
865
946
  }
866
947
  }
@@ -892,7 +973,7 @@ class Parser {
892
973
  let libStatement = new Statement_1.LibraryStatement({
893
974
  library: this.advance(),
894
975
  //grab the next token only if it's a string
895
- filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), lexer_1.TokenKind.StringLiteral)
976
+ filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
896
977
  });
897
978
  this._references.libraryStatements.push(libStatement);
898
979
  return libStatement;
@@ -901,20 +982,20 @@ class Parser {
901
982
  this.warnIfNotBrighterScriptMode('import statements');
902
983
  let importStatement = new Statement_1.ImportStatement(this.advance(),
903
984
  //grab the next token only if it's a string
904
- this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), lexer_1.TokenKind.StringLiteral));
985
+ this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
905
986
  this._references.importStatements.push(importStatement);
906
987
  return importStatement;
907
988
  }
908
989
  annotationExpression() {
909
990
  const atToken = this.advance();
910
- const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
991
+ const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
911
992
  if (identifier) {
912
- identifier.kind = lexer_1.TokenKind.Identifier;
993
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
913
994
  }
914
995
  let annotation = new Expression_1.AnnotationExpression(atToken, identifier);
915
996
  this.pendingAnnotations.push(annotation);
916
997
  //optional arguments
917
- if (this.check(lexer_1.TokenKind.LeftParen)) {
998
+ if (this.check(TokenKind_1.TokenKind.LeftParen)) {
918
999
  let leftParen = this.advance();
919
1000
  annotation.call = this.finishCall(leftParen, annotation, false);
920
1001
  }
@@ -927,7 +1008,7 @@ class Parser {
927
1008
  }
928
1009
  const questionMarkToken = this.advance();
929
1010
  //consume newlines or comments
930
- while (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
1011
+ while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
931
1012
  this.advance();
932
1013
  }
933
1014
  let consequent;
@@ -936,12 +1017,12 @@ class Parser {
936
1017
  }
937
1018
  catch (_a) { }
938
1019
  //consume newlines or comments
939
- while (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
1020
+ while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
940
1021
  this.advance();
941
1022
  }
942
- const colonToken = this.tryConsumeToken(lexer_1.TokenKind.Colon);
1023
+ const colonToken = this.tryConsumeToken(TokenKind_1.TokenKind.Colon);
943
1024
  //consume newlines
944
- while (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
1025
+ while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
945
1026
  this.advance();
946
1027
  }
947
1028
  let alternate;
@@ -959,7 +1040,7 @@ class Parser {
959
1040
  }
960
1041
  regexLiteralExpression() {
961
1042
  this.warnIfNotBrighterScriptMode('regular expression literal');
962
- return new _1.RegexLiteralExpression({
1043
+ return new Expression_1.RegexLiteralExpression({
963
1044
  regexLiteral: this.advance()
964
1045
  });
965
1046
  }
@@ -968,23 +1049,23 @@ class Parser {
968
1049
  //get the tag name
969
1050
  let tagName;
970
1051
  if (isTagged) {
971
- tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1052
+ tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
972
1053
  // force it into an identifier so the AST makes some sense
973
- tagName.kind = lexer_1.TokenKind.Identifier;
1054
+ tagName.kind = TokenKind_1.TokenKind.Identifier;
974
1055
  }
975
1056
  let quasis = [];
976
1057
  let expressions = [];
977
1058
  let openingBacktick = this.peek();
978
1059
  this.advance();
979
1060
  let currentQuasiExpressionParts = [];
980
- while (!this.isAtEnd() && !this.check(lexer_1.TokenKind.BackTick)) {
1061
+ while (!this.isAtEnd() && !this.check(TokenKind_1.TokenKind.BackTick)) {
981
1062
  let next = this.peek();
982
- if (next.kind === lexer_1.TokenKind.TemplateStringQuasi) {
1063
+ if (next.kind === TokenKind_1.TokenKind.TemplateStringQuasi) {
983
1064
  //a quasi can actually be made up of multiple quasis when it includes char literals
984
1065
  currentQuasiExpressionParts.push(new Expression_1.LiteralExpression(next));
985
1066
  this.advance();
986
1067
  }
987
- else if (next.kind === lexer_1.TokenKind.EscapedCharCodeLiteral) {
1068
+ else if (next.kind === TokenKind_1.TokenKind.EscapedCharCodeLiteral) {
988
1069
  currentQuasiExpressionParts.push(new Expression_1.EscapedCharCodeLiteralExpression(next));
989
1070
  this.advance();
990
1071
  }
@@ -992,12 +1073,12 @@ class Parser {
992
1073
  //finish up the current quasi
993
1074
  quasis.push(new Expression_1.TemplateStringQuasiExpression(currentQuasiExpressionParts));
994
1075
  currentQuasiExpressionParts = [];
995
- if (next.kind === lexer_1.TokenKind.TemplateStringExpressionBegin) {
1076
+ if (next.kind === TokenKind_1.TokenKind.TemplateStringExpressionBegin) {
996
1077
  this.advance();
997
1078
  }
998
1079
  //now keep this expression
999
1080
  expressions.push(this.expression());
1000
- if (!this.isAtEnd() && this.check(lexer_1.TokenKind.TemplateStringExpressionEnd)) {
1081
+ if (!this.isAtEnd() && this.check(TokenKind_1.TokenKind.TemplateStringExpressionEnd)) {
1001
1082
  //TODO is it an error if this is not present?
1002
1083
  this.advance();
1003
1084
  }
@@ -1029,12 +1110,12 @@ class Parser {
1029
1110
  const statement = new Statement_1.TryCatchStatement(tryToken);
1030
1111
  //ensure statement separator
1031
1112
  this.consumeStatementSeparators();
1032
- statement.tryBranch = this.block(lexer_1.TokenKind.Catch, lexer_1.TokenKind.EndTry);
1113
+ statement.tryBranch = this.block(TokenKind_1.TokenKind.Catch, TokenKind_1.TokenKind.EndTry);
1033
1114
  const peek = this.peek();
1034
- if (peek.kind !== lexer_1.TokenKind.Catch) {
1115
+ if (peek.kind !== TokenKind_1.TokenKind.Catch) {
1035
1116
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedCatchBlockInTryCatch()), { range: this.peek().range }));
1036
1117
  //gracefully handle end-try
1037
- if (peek.kind === lexer_1.TokenKind.EndTry) {
1118
+ if (peek.kind === TokenKind_1.TokenKind.EndTry) {
1038
1119
  statement.endTryToken = this.advance();
1039
1120
  }
1040
1121
  return statement;
@@ -1042,16 +1123,16 @@ class Parser {
1042
1123
  else {
1043
1124
  statement.catchToken = this.advance();
1044
1125
  }
1045
- const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1126
+ const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1046
1127
  if (exceptionVarToken) {
1047
1128
  // force it into an identifier so the AST makes some sense
1048
- exceptionVarToken.kind = lexer_1.TokenKind.Identifier;
1129
+ exceptionVarToken.kind = TokenKind_1.TokenKind.Identifier;
1049
1130
  statement.exceptionVariable = exceptionVarToken;
1050
1131
  }
1051
1132
  //ensure statement sepatator
1052
1133
  this.consumeStatementSeparators();
1053
- statement.catchBranch = this.block(lexer_1.TokenKind.EndTry);
1054
- if (this.peek().kind !== lexer_1.TokenKind.EndTry) {
1134
+ statement.catchBranch = this.block(TokenKind_1.TokenKind.EndTry);
1135
+ if (this.peek().kind !== TokenKind_1.TokenKind.EndTry) {
1055
1136
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndTryToTerminateTryCatch()), { range: this.peek().range }));
1056
1137
  }
1057
1138
  else {
@@ -1062,7 +1143,7 @@ class Parser {
1062
1143
  throwStatement() {
1063
1144
  const throwToken = this.advance();
1064
1145
  let expression;
1065
- if (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon)) {
1146
+ if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
1066
1147
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExceptionExpressionAfterThrowKeyword()), { range: throwToken.range }));
1067
1148
  }
1068
1149
  else {
@@ -1072,19 +1153,19 @@ class Parser {
1072
1153
  }
1073
1154
  dimStatement() {
1074
1155
  const dim = this.advance();
1075
- let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1156
+ let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1076
1157
  // force to an identifier so the AST makes some sense
1077
1158
  if (identifier) {
1078
- identifier.kind = lexer_1.TokenKind.Identifier;
1159
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
1079
1160
  }
1080
- let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(), lexer_1.TokenKind.LeftSquareBracket);
1161
+ let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.LeftSquareBracket);
1081
1162
  let expressions = [];
1082
1163
  let expression;
1083
1164
  do {
1084
1165
  try {
1085
1166
  expression = this.expression();
1086
1167
  expressions.push(expression);
1087
- if (this.check(lexer_1.TokenKind.Comma)) {
1168
+ if (this.check(TokenKind_1.TokenKind.Comma)) {
1088
1169
  this.advance();
1089
1170
  }
1090
1171
  else {
@@ -1098,15 +1179,15 @@ class Parser {
1098
1179
  if (expressions.length === 0) {
1099
1180
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
1100
1181
  }
1101
- let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), lexer_1.TokenKind.RightSquareBracket);
1182
+ let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
1102
1183
  return new Statement_1.DimStatement(dim, identifier, leftSquareBracket, expressions, rightSquareBracket);
1103
1184
  }
1104
1185
  ifStatement() {
1105
1186
  // colon before `if` is usually not allowed, unless it's after `then`
1106
1187
  if (this.current > 0) {
1107
1188
  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) {
1189
+ if (prev.kind === TokenKind_1.TokenKind.Colon) {
1190
+ if (this.current > 1 && this.tokens[this.current - 2].kind !== TokenKind_1.TokenKind.Then) {
1110
1191
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedColonBeforeIfStatement()), { range: prev.range }));
1111
1192
  }
1112
1193
  }
@@ -1120,14 +1201,14 @@ class Parser {
1120
1201
  let endIfToken;
1121
1202
  let elseToken;
1122
1203
  //optional `then`
1123
- if (this.check(lexer_1.TokenKind.Then)) {
1204
+ if (this.check(TokenKind_1.TokenKind.Then)) {
1124
1205
  thenToken = this.advance();
1125
1206
  }
1126
1207
  //is it inline or multi-line if?
1127
- const isInlineIfThen = !this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Comment);
1208
+ const isInlineIfThen = !this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment);
1128
1209
  if (isInlineIfThen) {
1129
1210
  /*** PARSE INLINE IF STATEMENT ***/
1130
- thenBranch = this.inlineConditionalBranch(lexer_1.TokenKind.Else, lexer_1.TokenKind.EndIf);
1211
+ thenBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
1131
1212
  if (!thenBranch) {
1132
1213
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementToFollowConditionalCondition(ifToken.text)), { range: this.peek().range }));
1133
1214
  throw this.lastDiagnosticAsError();
@@ -1136,9 +1217,9 @@ class Parser {
1136
1217
  this.ensureInline(thenBranch.statements);
1137
1218
  }
1138
1219
  //else branch
1139
- if (this.check(lexer_1.TokenKind.Else)) {
1220
+ if (this.check(TokenKind_1.TokenKind.Else)) {
1140
1221
  elseToken = this.advance();
1141
- if (this.check(lexer_1.TokenKind.If)) {
1222
+ if (this.check(TokenKind_1.TokenKind.If)) {
1142
1223
  // recurse-read `else if`
1143
1224
  elseBranch = this.ifStatement();
1144
1225
  //no multi-line if chained with an inline if
@@ -1146,13 +1227,13 @@ class Parser {
1146
1227
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: elseBranch.range }));
1147
1228
  }
1148
1229
  }
1149
- else if (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon)) {
1230
+ else if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
1150
1231
  //expecting inline else branch
1151
1232
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: this.peek().range }));
1152
1233
  throw this.lastDiagnosticAsError();
1153
1234
  }
1154
1235
  else {
1155
- elseBranch = this.inlineConditionalBranch(lexer_1.TokenKind.Else, lexer_1.TokenKind.EndIf);
1236
+ elseBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
1156
1237
  if (elseBranch) {
1157
1238
  this.ensureInline(elseBranch.statements);
1158
1239
  }
@@ -1166,9 +1247,9 @@ class Parser {
1166
1247
  if (!elseBranch || !(0, reflection_1.isIfStatement)(elseBranch)) {
1167
1248
  //enforce newline at the end of the inline if statement
1168
1249
  const peek = this.peek();
1169
- if (peek.kind !== lexer_1.TokenKind.Newline && peek.kind !== lexer_1.TokenKind.Comment && !this.isAtEnd()) {
1250
+ if (peek.kind !== TokenKind_1.TokenKind.Newline && peek.kind !== TokenKind_1.TokenKind.Comment && !this.isAtEnd()) {
1170
1251
  //ignore last error if it was about a colon
1171
- if (this.previous().kind === lexer_1.TokenKind.Colon) {
1252
+ if (this.previous().kind === TokenKind_1.TokenKind.Colon) {
1172
1253
  this.diagnostics.pop();
1173
1254
  this.current--;
1174
1255
  }
@@ -1183,9 +1264,9 @@ class Parser {
1183
1264
  //ensure newline/colon before next keyword
1184
1265
  this.ensureNewLineOrColon();
1185
1266
  //else branch
1186
- if (this.check(lexer_1.TokenKind.Else)) {
1267
+ if (this.check(TokenKind_1.TokenKind.Else)) {
1187
1268
  elseToken = this.advance();
1188
- if (this.check(lexer_1.TokenKind.If)) {
1269
+ if (this.check(TokenKind_1.TokenKind.If)) {
1189
1270
  // recurse-read `else if`
1190
1271
  elseBranch = this.ifStatement();
1191
1272
  }
@@ -1196,7 +1277,7 @@ class Parser {
1196
1277
  }
1197
1278
  }
1198
1279
  if (!(0, reflection_1.isIfStatement)(elseBranch)) {
1199
- if (this.check(lexer_1.TokenKind.EndIf)) {
1280
+ if (this.check(TokenKind_1.TokenKind.EndIf)) {
1200
1281
  endIfToken = this.advance();
1201
1282
  }
1202
1283
  else {
@@ -1219,7 +1300,7 @@ class Parser {
1219
1300
  let diagnosticsLengthBeforeBlock = this.diagnostics.length;
1220
1301
  // we're parsing a multi-line ("block") form of the BrightScript if/then and must find
1221
1302
  // a trailing "end if" or "else if"
1222
- let branch = this.block(lexer_1.TokenKind.EndIf, lexer_1.TokenKind.Else);
1303
+ let branch = this.block(TokenKind_1.TokenKind.EndIf, TokenKind_1.TokenKind.Else);
1223
1304
  if (!branch) {
1224
1305
  //throw out any new diagnostics created as a result of a `then` block parse failure.
1225
1306
  //the block() function will discard the current line, so any discarded diagnostics will
@@ -1233,7 +1314,7 @@ class Parser {
1233
1314
  }
1234
1315
  ensureNewLineOrColon(silent = false) {
1235
1316
  const prev = this.previous().kind;
1236
- if (prev !== lexer_1.TokenKind.Newline && prev !== lexer_1.TokenKind.Colon) {
1317
+ if (prev !== TokenKind_1.TokenKind.Newline && prev !== TokenKind_1.TokenKind.Colon) {
1237
1318
  if (!silent) {
1238
1319
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedNewlineOrColon()), { range: this.peek().range }));
1239
1320
  }
@@ -1262,12 +1343,12 @@ class Parser {
1262
1343
  const startingRange = statement.range;
1263
1344
  //look for colon statement separator
1264
1345
  let foundColon = false;
1265
- while (this.match(lexer_1.TokenKind.Colon)) {
1346
+ while (this.match(TokenKind_1.TokenKind.Colon)) {
1266
1347
  foundColon = true;
1267
1348
  }
1268
1349
  //if a colon was found, add the next statement or err if unexpected
1269
1350
  if (foundColon) {
1270
- if (!this.checkAny(lexer_1.TokenKind.Newline, ...additionalTerminators)) {
1351
+ if (!this.checkAny(TokenKind_1.TokenKind.Newline, ...additionalTerminators)) {
1271
1352
  //if not an ending keyword, add next statement
1272
1353
  let extra = this.inlineConditionalBranch(...additionalTerminators);
1273
1354
  if (!extra) {
@@ -1285,9 +1366,9 @@ class Parser {
1285
1366
  }
1286
1367
  expressionStatement(expr) {
1287
1368
  let expressionStart = this.peek();
1288
- if (this.checkAny(lexer_1.TokenKind.PlusPlus, lexer_1.TokenKind.MinusMinus)) {
1369
+ if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
1289
1370
  let operator = this.advance();
1290
- if (this.checkAny(lexer_1.TokenKind.PlusPlus, lexer_1.TokenKind.MinusMinus)) {
1371
+ if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
1291
1372
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.consecutiveIncrementDecrementOperatorsAreNotAllowed()), { range: this.peek().range }));
1292
1373
  throw this.lastDiagnosticAsError();
1293
1374
  }
@@ -1295,7 +1376,9 @@ class Parser {
1295
1376
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incrementDecrementOperatorsAreNotAllowedAsResultOfFunctionCall()), { range: expressionStart.range }));
1296
1377
  throw this.lastDiagnosticAsError();
1297
1378
  }
1298
- return new Statement_1.IncrementStatement(expr, operator);
1379
+ const result = new Statement_1.IncrementStatement(expr, operator);
1380
+ this._references.expressions.add(result);
1381
+ return result;
1299
1382
  }
1300
1383
  if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
1301
1384
  return new Statement_1.ExpressionStatement(expr);
@@ -1312,18 +1395,18 @@ class Parser {
1312
1395
  * priority as standalone function calls though, so we can parse them in the same way.
1313
1396
  */
1314
1397
  let expr = this.call();
1315
- if (this.checkAny(...lexer_1.AssignmentOperators) && !((0, reflection_1.isCallExpression)(expr))) {
1398
+ if (this.checkAny(...TokenKind_1.AssignmentOperators) && !((0, reflection_1.isCallExpression)(expr))) {
1316
1399
  let left = expr;
1317
1400
  let operator = this.advance();
1318
1401
  let right = this.expression();
1319
1402
  // Create a dotted or indexed "set" based on the left-hand side's type
1320
1403
  if ((0, reflection_1.isIndexedGetExpression)(left)) {
1321
- return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === lexer_1.TokenKind.Equal
1404
+ return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
1322
1405
  ? right
1323
1406
  : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
1324
1407
  }
1325
1408
  else if ((0, reflection_1.isDottedGetExpression)(left)) {
1326
- const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === lexer_1.TokenKind.Equal
1409
+ const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
1327
1410
  ? right
1328
1411
  : new Expression_1.BinaryExpression(left, operator, right));
1329
1412
  this._references.dottedSetStatements.push(dottedSetStmt);
@@ -1336,13 +1419,13 @@ class Parser {
1336
1419
  let printKeyword = this.advance();
1337
1420
  let values = [];
1338
1421
  while (!this.checkEndOfStatement()) {
1339
- if (this.check(lexer_1.TokenKind.Semicolon)) {
1422
+ if (this.check(TokenKind_1.TokenKind.Semicolon)) {
1340
1423
  values.push(this.advance());
1341
1424
  }
1342
- else if (this.check(lexer_1.TokenKind.Comma)) {
1425
+ else if (this.check(TokenKind_1.TokenKind.Comma)) {
1343
1426
  values.push(this.advance());
1344
1427
  }
1345
- else if (this.check(lexer_1.TokenKind.Else)) {
1428
+ else if (this.check(TokenKind_1.TokenKind.Else)) {
1346
1429
  break; // inline branch
1347
1430
  }
1348
1431
  else {
@@ -1355,7 +1438,7 @@ class Parser {
1355
1438
  values.push(emptyStringLiteral);
1356
1439
  }
1357
1440
  let last = values[values.length - 1];
1358
- if ((0, lexer_1.isToken)(last)) {
1441
+ if ((0, Token_1.isToken)(last)) {
1359
1442
  // TODO: error, expected value
1360
1443
  }
1361
1444
  return new Statement_1.PrintStatement({ print: printKeyword }, values);
@@ -1369,7 +1452,7 @@ class Parser {
1369
1452
  if (this.checkEndOfStatement()) {
1370
1453
  return new Statement_1.ReturnStatement(tokens);
1371
1454
  }
1372
- let toReturn = this.check(lexer_1.TokenKind.Else) ? undefined : this.expression();
1455
+ let toReturn = this.check(TokenKind_1.TokenKind.Else) ? undefined : this.expression();
1373
1456
  return new Statement_1.ReturnStatement(tokens, toReturn);
1374
1457
  }
1375
1458
  /**
@@ -1382,7 +1465,7 @@ class Parser {
1382
1465
  colon: this.advance()
1383
1466
  };
1384
1467
  //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)) {
1468
+ if (!this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1386
1469
  //rewind and cancel
1387
1470
  this.current -= 2;
1388
1471
  throw new CancelStatementError();
@@ -1398,7 +1481,7 @@ class Parser {
1398
1481
  gotoStatement() {
1399
1482
  let tokens = {
1400
1483
  goto: this.advance(),
1401
- label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(), lexer_1.TokenKind.Identifier)
1484
+ label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(), TokenKind_1.TokenKind.Identifier)
1402
1485
  };
1403
1486
  return new Statement_1.GotoStatement(tokens);
1404
1487
  }
@@ -1429,7 +1512,7 @@ class Parser {
1429
1512
  this.consumeStatementSeparators(true);
1430
1513
  let startingToken = this.peek();
1431
1514
  const statements = [];
1432
- while (!this.isAtEnd() && !this.checkAny(lexer_1.TokenKind.EndSub, lexer_1.TokenKind.EndFunction, ...terminators)) {
1515
+ while (!this.isAtEnd() && !this.checkAny(TokenKind_1.TokenKind.EndSub, TokenKind_1.TokenKind.EndFunction, ...terminators)) {
1433
1516
  //grab the location of the current token
1434
1517
  let loopCurrent = this.current;
1435
1518
  let dec = this.declaration();
@@ -1445,7 +1528,7 @@ class Parser {
1445
1528
  //something went wrong. reset to the top of the loop
1446
1529
  this.current = loopCurrent;
1447
1530
  //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);
1531
+ this.consumeUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
1449
1532
  //trash the next token. this prevents an infinite loop. not exactly sure why we need this,
1450
1533
  //but there's already an error in the file being parsed, so just leave this line here
1451
1534
  this.advance();
@@ -1462,8 +1545,8 @@ class Parser {
1462
1545
  //if so, we need to restore the statement separator
1463
1546
  let prev = this.previous().kind;
1464
1547
  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)) {
1548
+ if ((peek === TokenKind_1.TokenKind.EndSub || peek === TokenKind_1.TokenKind.EndFunction) &&
1549
+ (prev === TokenKind_1.TokenKind.Newline || prev === TokenKind_1.TokenKind.Colon)) {
1467
1550
  this.current--;
1468
1551
  }
1469
1552
  }
@@ -1495,13 +1578,15 @@ class Parser {
1495
1578
  this.pendingAnnotations = parentAnnotations;
1496
1579
  }
1497
1580
  expression() {
1498
- return this.anonymousFunction();
1581
+ const expression = this.anonymousFunction();
1582
+ this._references.expressions.add(expression);
1583
+ return expression;
1499
1584
  }
1500
1585
  anonymousFunction() {
1501
- if (this.checkAny(lexer_1.TokenKind.Sub, lexer_1.TokenKind.Function)) {
1586
+ if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
1502
1587
  const func = this.functionDeclaration(true);
1503
1588
  //if there's an open paren after this, this is an IIFE
1504
- if (this.check(lexer_1.TokenKind.LeftParen)) {
1589
+ if (this.check(TokenKind_1.TokenKind.LeftParen)) {
1505
1590
  return this.finishCall(this.advance(), func);
1506
1591
  }
1507
1592
  else {
@@ -1509,10 +1594,10 @@ class Parser {
1509
1594
  }
1510
1595
  }
1511
1596
  let expr = this.boolean();
1512
- if (this.check(lexer_1.TokenKind.Question)) {
1597
+ if (this.check(TokenKind_1.TokenKind.Question)) {
1513
1598
  return this.ternaryExpression(expr);
1514
1599
  }
1515
- else if (this.check(lexer_1.TokenKind.QuestionQuestion)) {
1600
+ else if (this.check(TokenKind_1.TokenKind.QuestionQuestion)) {
1516
1601
  return this.nullCoalescingExpression(expr);
1517
1602
  }
1518
1603
  else {
@@ -1521,7 +1606,7 @@ class Parser {
1521
1606
  }
1522
1607
  boolean() {
1523
1608
  let expr = this.relational();
1524
- while (this.matchAny(lexer_1.TokenKind.And, lexer_1.TokenKind.Or)) {
1609
+ while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
1525
1610
  let operator = this.previous();
1526
1611
  let right = this.relational();
1527
1612
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1530,7 +1615,7 @@ class Parser {
1530
1615
  }
1531
1616
  relational() {
1532
1617
  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)) {
1618
+ 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
1619
  let operator = this.previous();
1535
1620
  let right = this.additive();
1536
1621
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1540,7 +1625,7 @@ class Parser {
1540
1625
  // TODO: bitshift
1541
1626
  additive() {
1542
1627
  let expr = this.multiplicative();
1543
- while (this.matchAny(lexer_1.TokenKind.Plus, lexer_1.TokenKind.Minus)) {
1628
+ while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
1544
1629
  let operator = this.previous();
1545
1630
  let right = this.multiplicative();
1546
1631
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1549,7 +1634,7 @@ class Parser {
1549
1634
  }
1550
1635
  multiplicative() {
1551
1636
  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)) {
1637
+ 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
1638
  let operator = this.previous();
1554
1639
  let right = this.exponential();
1555
1640
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1558,7 +1643,7 @@ class Parser {
1558
1643
  }
1559
1644
  exponential() {
1560
1645
  let expr = this.prefixUnary();
1561
- while (this.match(lexer_1.TokenKind.Caret)) {
1646
+ while (this.match(TokenKind_1.TokenKind.Caret)) {
1562
1647
  let operator = this.previous();
1563
1648
  let right = this.prefixUnary();
1564
1649
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1567,7 +1652,7 @@ class Parser {
1567
1652
  }
1568
1653
  prefixUnary() {
1569
1654
  const nextKind = this.peek().kind;
1570
- if (nextKind === lexer_1.TokenKind.Not || nextKind === lexer_1.TokenKind.Minus) {
1655
+ if (nextKind === TokenKind_1.TokenKind.Not || nextKind === TokenKind_1.TokenKind.Minus) {
1571
1656
  this.current++; //advance
1572
1657
  let operator = this.previous();
1573
1658
  let right = this.prefixUnary();
@@ -1577,17 +1662,17 @@ class Parser {
1577
1662
  }
1578
1663
  indexedGet(expr) {
1579
1664
  let openingSquare = this.previous();
1580
- while (this.match(lexer_1.TokenKind.Newline)) { }
1665
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1581
1666
  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);
1667
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1668
+ let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
1584
1669
  return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare);
1585
1670
  }
1586
1671
  newExpression() {
1587
1672
  this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
1588
1673
  let newToken = this.advance();
1589
1674
  let nameExpr = this.getNamespacedVariableNameExpression();
1590
- let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), lexer_1.TokenKind.LeftParen);
1675
+ let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.LeftParen);
1591
1676
  let call = this.finishCall(leftParen, nameExpr);
1592
1677
  //pop the call from the callExpressions list because this is technically something else
1593
1678
  this.callExpressions.pop();
@@ -1601,46 +1686,52 @@ class Parser {
1601
1686
  callfunc(callee) {
1602
1687
  this.warnIfNotBrighterScriptMode('callfunc operator');
1603
1688
  let operator = this.previous();
1604
- let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1689
+ let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1605
1690
  // 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);
1691
+ methodName.kind = TokenKind_1.TokenKind.Identifier;
1692
+ let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(), TokenKind_1.TokenKind.LeftParen);
1608
1693
  let call = this.finishCall(openParen, callee, false);
1609
1694
  return new Expression_1.CallfuncExpression(callee, operator, methodName, openParen, call.args, call.closingParen);
1610
1695
  }
1611
1696
  call() {
1612
- if (this.check(lexer_1.TokenKind.New) && this.checkAnyNext(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
1697
+ if (this.check(TokenKind_1.TokenKind.New) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
1613
1698
  return this.newExpression();
1614
1699
  }
1615
1700
  let expr = this.primary();
1701
+ //an expression to keep for _references
1702
+ let referenceCallExpression;
1616
1703
  while (true) {
1617
- if (this.match(lexer_1.TokenKind.LeftParen)) {
1704
+ if (this.match(TokenKind_1.TokenKind.LeftParen)) {
1618
1705
  expr = this.finishCall(this.previous(), expr);
1706
+ //store this call expression in references
1707
+ referenceCallExpression = expr;
1619
1708
  }
1620
- else if (this.match(lexer_1.TokenKind.LeftSquareBracket)) {
1709
+ else if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
1621
1710
  expr = this.indexedGet(expr);
1622
1711
  }
1623
- else if (this.match(lexer_1.TokenKind.Callfunc)) {
1712
+ else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
1624
1713
  expr = this.callfunc(expr);
1714
+ //store this callfunc expression in references
1715
+ referenceCallExpression = expr;
1625
1716
  }
1626
- else if (this.match(lexer_1.TokenKind.Dot)) {
1627
- if (this.match(lexer_1.TokenKind.LeftSquareBracket)) {
1717
+ else if (this.match(TokenKind_1.TokenKind.Dot)) {
1718
+ if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
1628
1719
  expr = this.indexedGet(expr);
1629
1720
  }
1630
1721
  else {
1631
1722
  let dot = this.previous();
1632
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1723
+ let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1633
1724
  // force it into an identifier so the AST makes some sense
1634
- name.kind = lexer_1.TokenKind.Identifier;
1725
+ name.kind = TokenKind_1.TokenKind.Identifier;
1635
1726
  expr = new Expression_1.DottedGetExpression(expr, name, dot);
1636
1727
  this.addPropertyHints(name);
1637
1728
  }
1638
1729
  }
1639
- else if (this.check(lexer_1.TokenKind.At)) {
1730
+ else if (this.check(TokenKind_1.TokenKind.At)) {
1640
1731
  let dot = this.advance();
1641
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1732
+ let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1642
1733
  // force it into an identifier so the AST makes some sense
1643
- name.kind = lexer_1.TokenKind.Identifier;
1734
+ name.kind = TokenKind_1.TokenKind.Identifier;
1644
1735
  expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
1645
1736
  //only allow a single `@` expression
1646
1737
  break;
@@ -1649,24 +1740,28 @@ class Parser {
1649
1740
  break;
1650
1741
  }
1651
1742
  }
1743
+ //if we found a callExpression, add it to `expressions` in references
1744
+ if (referenceCallExpression) {
1745
+ this._references.expressions.add(referenceCallExpression);
1746
+ }
1652
1747
  return expr;
1653
1748
  }
1654
1749
  finishCall(openingParen, callee, addToCallExpressionList = true) {
1655
1750
  let args = [];
1656
- while (this.match(lexer_1.TokenKind.Newline)) {
1751
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1657
1752
  }
1658
- if (!this.check(lexer_1.TokenKind.RightParen)) {
1753
+ if (!this.check(TokenKind_1.TokenKind.RightParen)) {
1659
1754
  do {
1660
- while (this.match(lexer_1.TokenKind.Newline)) { }
1755
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1661
1756
  if (args.length >= Expression_1.CallExpression.MaximumArguments) {
1662
1757
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
1663
1758
  throw this.lastDiagnosticAsError();
1664
1759
  }
1665
1760
  args.push(this.expression());
1666
- } while (this.match(lexer_1.TokenKind.Comma));
1761
+ } while (this.match(TokenKind_1.TokenKind.Comma));
1667
1762
  }
1668
- while (this.match(lexer_1.TokenKind.Newline)) { }
1669
- const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), lexer_1.TokenKind.RightParen);
1763
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1764
+ const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
1670
1765
  if ((0, reflection_1.isVariableExpression)(callee)) {
1671
1766
  callee.isCalled = true;
1672
1767
  }
@@ -1683,15 +1778,15 @@ class Parser {
1683
1778
  */
1684
1779
  typeToken() {
1685
1780
  let typeToken;
1686
- if (this.checkAny(...lexer_1.DeclarableTypes)) {
1781
+ if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
1687
1782
  // Token is a built in type
1688
1783
  typeToken = this.advance();
1689
1784
  }
1690
1785
  else if (this.options.mode === ParseMode.BrighterScript) {
1691
1786
  try {
1692
- // see if we can get a namespaced identifer
1787
+ // see if we can get a namespaced identifier
1693
1788
  const qualifiedType = this.getNamespacedVariableNameExpression();
1694
- typeToken = (0, creators_1.createToken)(lexer_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
1789
+ typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
1695
1790
  }
1696
1791
  catch (_a) {
1697
1792
  //could not get an identifier - just get whatever's next
@@ -1702,57 +1797,68 @@ class Parser {
1702
1797
  // just get whatever's next
1703
1798
  typeToken = this.advance();
1704
1799
  }
1800
+ if (typeToken && this.options.mode === ParseMode.BrighterScript) {
1801
+ // Check if it is an array - that is, if it has `[]` after the type
1802
+ // eg. `string[]` or `SomeKlass[]`
1803
+ if (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
1804
+ this.advance();
1805
+ if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1806
+ const rightBracket = this.advance();
1807
+ typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, typeToken.text + '[]', util_1.util.getRange(typeToken, rightBracket));
1808
+ }
1809
+ }
1810
+ }
1705
1811
  return typeToken;
1706
1812
  }
1707
1813
  primary() {
1708
1814
  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):
1815
+ 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
1816
  return new Expression_1.LiteralExpression(this.previous());
1711
1817
  //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)):
1818
+ case this.matchAny(TokenKind_1.TokenKind.LineNumLiteral, ...(this.options.mode === ParseMode.BrightScript ? [] : TokenKind_1.BrighterScriptSourceLiterals)):
1713
1819
  return new Expression_1.SourceLiteralExpression(this.previous());
1714
1820
  //template string
1715
- case this.check(lexer_1.TokenKind.BackTick):
1821
+ case this.check(TokenKind_1.TokenKind.BackTick):
1716
1822
  return this.templateString(false);
1717
1823
  //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):
1824
+ case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
1719
1825
  return this.templateString(true);
1720
- case this.matchAny(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
1826
+ case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
1721
1827
  return new Expression_1.VariableExpression(this.previous(), this.currentNamespaceName);
1722
- case this.match(lexer_1.TokenKind.LeftParen):
1828
+ case this.match(TokenKind_1.TokenKind.LeftParen):
1723
1829
  let left = this.previous();
1724
1830
  let expr = this.expression();
1725
- let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), lexer_1.TokenKind.RightParen);
1831
+ let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), TokenKind_1.TokenKind.RightParen);
1726
1832
  return new Expression_1.GroupingExpression({ left: left, right: right }, expr);
1727
- case this.match(lexer_1.TokenKind.LeftSquareBracket):
1833
+ case this.match(TokenKind_1.TokenKind.LeftSquareBracket):
1728
1834
  let elements = [];
1729
1835
  let openingSquare = this.previous();
1730
1836
  //add any comment found right after the opening square
1731
- if (this.check(lexer_1.TokenKind.Comment)) {
1837
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
1732
1838
  elements.push(new Statement_1.CommentStatement([this.advance()]));
1733
1839
  }
1734
- while (this.match(lexer_1.TokenKind.Newline)) {
1840
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1735
1841
  }
1736
- if (!this.match(lexer_1.TokenKind.RightSquareBracket)) {
1842
+ if (!this.match(TokenKind_1.TokenKind.RightSquareBracket)) {
1737
1843
  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();
1844
+ while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1845
+ if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
1846
+ let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
1741
1847
  elements.push(new Statement_1.CommentStatement([comment]));
1742
1848
  }
1743
- while (this.match(lexer_1.TokenKind.Newline)) {
1849
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1744
1850
  }
1745
- if (this.check(lexer_1.TokenKind.RightSquareBracket)) {
1851
+ if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1746
1852
  break;
1747
1853
  }
1748
1854
  elements.push(this.expression());
1749
1855
  }
1750
- this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), lexer_1.TokenKind.RightSquareBracket);
1856
+ this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
1751
1857
  }
1752
1858
  let closingSquare = this.previous();
1753
1859
  //this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
1754
1860
  return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
1755
- case this.match(lexer_1.TokenKind.LeftCurlyBrace):
1861
+ case this.match(TokenKind_1.TokenKind.LeftCurlyBrace):
1756
1862
  let openingBrace = this.previous();
1757
1863
  let members = [];
1758
1864
  let key = () => {
@@ -1761,25 +1867,25 @@ class Parser {
1761
1867
  keyToken: null,
1762
1868
  range: null
1763
1869
  };
1764
- if (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties)) {
1870
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
1765
1871
  result.keyToken = this.advance();
1766
1872
  }
1767
- else if (this.check(lexer_1.TokenKind.StringLiteral)) {
1873
+ else if (this.check(TokenKind_1.TokenKind.StringLiteral)) {
1768
1874
  result.keyToken = this.advance();
1769
1875
  }
1770
1876
  else {
1771
1877
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedAAKey()), { range: this.peek().range }));
1772
1878
  throw this.lastDiagnosticAsError();
1773
1879
  }
1774
- result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(), lexer_1.TokenKind.Colon);
1880
+ result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(), TokenKind_1.TokenKind.Colon);
1775
1881
  result.range = util_1.util.getRange(result.keyToken, result.colonToken);
1776
1882
  return result;
1777
1883
  };
1778
- while (this.match(lexer_1.TokenKind.Newline)) {
1884
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1779
1885
  }
1780
- if (!this.match(lexer_1.TokenKind.RightCurlyBrace)) {
1886
+ if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
1781
1887
  let lastAAMember;
1782
- if (this.check(lexer_1.TokenKind.Comment)) {
1888
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
1783
1889
  lastAAMember = null;
1784
1890
  members.push(new Statement_1.CommentStatement([this.advance()]));
1785
1891
  }
@@ -1789,26 +1895,26 @@ class Parser {
1789
1895
  lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
1790
1896
  members.push(lastAAMember);
1791
1897
  }
1792
- while (this.matchAny(lexer_1.TokenKind.Comma, lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Comment)) {
1898
+ while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
1793
1899
  // collect comma at end of expression
1794
- if (lastAAMember && this.checkPrevious(lexer_1.TokenKind.Comma)) {
1900
+ if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
1795
1901
  lastAAMember.commaToken = this.previous();
1796
1902
  }
1797
1903
  //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();
1904
+ if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1905
+ let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1800
1906
  members.push(new Statement_1.CommentStatement([token]));
1801
1907
  }
1802
1908
  else {
1803
1909
  this.consumeStatementSeparators(true);
1804
1910
  //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();
1911
+ if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1912
+ let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1807
1913
  lastAAMember = null;
1808
1914
  members.push(new Statement_1.CommentStatement([token]));
1809
1915
  continue;
1810
1916
  }
1811
- if (this.check(lexer_1.TokenKind.RightCurlyBrace)) {
1917
+ if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
1812
1918
  break;
1813
1919
  }
1814
1920
  let k = key();
@@ -1817,23 +1923,23 @@ class Parser {
1817
1923
  members.push(lastAAMember);
1818
1924
  }
1819
1925
  }
1820
- this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), lexer_1.TokenKind.RightCurlyBrace);
1926
+ this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), TokenKind_1.TokenKind.RightCurlyBrace);
1821
1927
  }
1822
1928
  let closingBrace = this.previous();
1823
1929
  const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace, this.currentFunctionExpression);
1824
1930
  this._references.aaLiterals.push(aaExpr);
1825
1931
  this.addPropertyHints(aaExpr);
1826
1932
  return aaExpr;
1827
- case this.matchAny(lexer_1.TokenKind.Pos, lexer_1.TokenKind.Tab):
1933
+ case this.matchAny(TokenKind_1.TokenKind.Pos, TokenKind_1.TokenKind.Tab):
1828
1934
  let token = Object.assign(this.previous(), {
1829
- kind: lexer_1.TokenKind.Identifier
1935
+ kind: TokenKind_1.TokenKind.Identifier
1830
1936
  });
1831
1937
  return new Expression_1.VariableExpression(token, this.currentNamespaceName);
1832
- case this.checkAny(lexer_1.TokenKind.Function, lexer_1.TokenKind.Sub):
1938
+ case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
1833
1939
  return this.anonymousFunction();
1834
- case this.check(lexer_1.TokenKind.RegexLiteral):
1940
+ case this.check(TokenKind_1.TokenKind.RegexLiteral):
1835
1941
  return this.regexLiteralExpression();
1836
- case this.check(lexer_1.TokenKind.Comment):
1942
+ case this.check(TokenKind_1.TokenKind.Comment):
1837
1943
  return new Statement_1.CommentStatement([this.advance()]);
1838
1944
  default:
1839
1945
  //if we found an expected terminator, don't throw a diagnostic...just return undefined
@@ -1903,12 +2009,12 @@ class Parser {
1903
2009
  }
1904
2010
  consumeStatementSeparators(optional = false) {
1905
2011
  //a comment or EOF mark the end of the statement
1906
- if (this.isAtEnd() || this.check(lexer_1.TokenKind.Comment)) {
2012
+ if (this.isAtEnd() || this.check(TokenKind_1.TokenKind.Comment)) {
1907
2013
  return true;
1908
2014
  }
1909
2015
  let consumed = false;
1910
2016
  //consume any newlines and colons
1911
- while (this.matchAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon)) {
2017
+ while (this.matchAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
1912
2018
  consumed = true;
1913
2019
  }
1914
2020
  if (!optional && !consumed) {
@@ -1924,7 +2030,7 @@ class Parser {
1924
2030
  }
1925
2031
  checkEndOfStatement() {
1926
2032
  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);
2033
+ return [TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Eof].includes(nextKind);
1928
2034
  }
1929
2035
  checkPrevious(tokenKind) {
1930
2036
  var _a;
@@ -1932,14 +2038,14 @@ class Parser {
1932
2038
  }
1933
2039
  check(tokenKind) {
1934
2040
  const nextKind = this.peek().kind;
1935
- if (nextKind === lexer_1.TokenKind.Eof) {
2041
+ if (nextKind === TokenKind_1.TokenKind.Eof) {
1936
2042
  return false;
1937
2043
  }
1938
2044
  return nextKind === tokenKind;
1939
2045
  }
1940
2046
  checkAny(...tokenKinds) {
1941
2047
  const nextKind = this.peek().kind;
1942
- if (nextKind === lexer_1.TokenKind.Eof) {
2048
+ if (nextKind === TokenKind_1.TokenKind.Eof) {
1943
2049
  return false;
1944
2050
  }
1945
2051
  return tokenKinds.includes(nextKind);
@@ -1958,7 +2064,7 @@ class Parser {
1958
2064
  return tokenKinds.includes(nextKind);
1959
2065
  }
1960
2066
  isAtEnd() {
1961
- return this.peek().kind === lexer_1.TokenKind.Eof;
2067
+ return this.peek().kind === TokenKind_1.TokenKind.Eof;
1962
2068
  }
1963
2069
  peekNext() {
1964
2070
  if (this.isAtEnd()) {
@@ -1980,16 +2086,16 @@ class Parser {
1980
2086
  return;
1981
2087
  }
1982
2088
  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:
2089
+ case TokenKind_1.TokenKind.Namespace:
2090
+ case TokenKind_1.TokenKind.Class:
2091
+ case TokenKind_1.TokenKind.Function:
2092
+ case TokenKind_1.TokenKind.Sub:
2093
+ case TokenKind_1.TokenKind.If:
2094
+ case TokenKind_1.TokenKind.For:
2095
+ case TokenKind_1.TokenKind.ForEach:
2096
+ case TokenKind_1.TokenKind.While:
2097
+ case TokenKind_1.TokenKind.Print:
2098
+ case TokenKind_1.TokenKind.Return:
1993
2099
  // start parsing again from the next block starter or obvious
1994
2100
  // expression start
1995
2101
  return;
@@ -2035,17 +2141,17 @@ class Parser {
2035
2141
  const previousToken = this.getPreviousToken(closestToken);
2036
2142
  const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
2037
2143
  //next to matched token
2038
- if (!closestToken || closestToken.kind === lexer_1.TokenKind.Eof) {
2144
+ if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
2039
2145
  return false;
2040
2146
  }
2041
2147
  else if (closestToken.kind === tokenKind) {
2042
2148
  return true;
2043
2149
  }
2044
- else if (closestToken.kind === lexer_1.TokenKind.Newline || previousTokenKind === lexer_1.TokenKind.Newline) {
2150
+ else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
2045
2151
  return false;
2046
2152
  //next to an identifier, which is next to token kind
2047
2153
  }
2048
- else if (closestToken.kind === lexer_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
2154
+ else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
2049
2155
  return true;
2050
2156
  }
2051
2157
  else {
@@ -2056,7 +2162,7 @@ class Parser {
2056
2162
  const index = this.tokens.indexOf(currentToken);
2057
2163
  for (let i = index - 1; i >= 0; i--) {
2058
2164
  currentToken = this.tokens[i];
2059
- if (currentToken.kind === lexer_1.TokenKind.Newline) {
2165
+ if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
2060
2166
  break;
2061
2167
  }
2062
2168
  else if (currentToken.kind === tokenKind) {
@@ -2076,7 +2182,7 @@ class Parser {
2076
2182
  let tokens = [];
2077
2183
  for (let i = this.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.tokens.length; i += direction) {
2078
2184
  currentToken = this.tokens[i];
2079
- if (currentToken.kind === lexer_1.TokenKind.Newline || currentToken.kind === tokenKind) {
2185
+ if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
2080
2186
  break;
2081
2187
  }
2082
2188
  tokens.push(currentToken);
@@ -2147,12 +2253,12 @@ class Parser {
2147
2253
  currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2148
2254
  currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2149
2255
  }
2150
- if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === lexer_1.TokenKind.Dot) {
2256
+ if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.Dot) {
2151
2257
  previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
2152
2258
  currentToken = previousTokenResult.token;
2153
2259
  currentTokenIndex = previousTokenResult.index;
2154
2260
  }
2155
- previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, lexer_1.TokenKind.LeftParen, lexer_1.TokenKind.RightParen);
2261
+ previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.RightParen);
2156
2262
  currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2157
2263
  currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2158
2264
  if (previousTokenResult.hasBrackets) {
@@ -2160,7 +2266,7 @@ class Parser {
2160
2266
  }
2161
2267
  let tokenTypeIsNotKnowable = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable;
2162
2268
  if (currentTokenIndex) {
2163
- previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, lexer_1.TokenKind.LeftSquareBracket, lexer_1.TokenKind.RightSquareBracket);
2269
+ previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.RightSquareBracket);
2164
2270
  currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
2165
2271
  currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
2166
2272
  if (previousTokenResult.hasBrackets) {
@@ -2178,15 +2284,15 @@ class Parser {
2178
2284
  if (!currentToken || lastTokenHasWhitespace) {
2179
2285
  return false;
2180
2286
  }
2181
- if (currentToken.kind === lexer_1.TokenKind.Identifier) {
2287
+ if (currentToken.kind === TokenKind_1.TokenKind.Identifier) {
2182
2288
  return true;
2183
2289
  }
2184
2290
  if (currentToken.leadingWhitespace.length === 0) {
2185
2291
  // start of the chain
2186
- return lexer_1.AllowedLocalIdentifiers.includes(currentToken.kind);
2292
+ return TokenKind_1.AllowedLocalIdentifiers.includes(currentToken.kind);
2187
2293
  }
2188
2294
  // not the start of the chain
2189
- return lexer_1.AllowedProperties.includes(currentToken.kind);
2295
+ return TokenKind_1.AllowedProperties.includes(currentToken.kind);
2190
2296
  }
2191
2297
  /**
2192
2298
  * Builds up a chain of tokens, starting with the first in the chain, and ending with currentToken
@@ -2233,32 +2339,67 @@ class Parser {
2233
2339
  */
2234
2340
  findReferences() {
2235
2341
  this._references = new References();
2342
+ const excludedExpressions = new Set();
2343
+ const visitCallExpression = (e) => {
2344
+ for (const p of e.args) {
2345
+ this._references.expressions.add(p);
2346
+ }
2347
+ //add calls that were not excluded (from loop below)
2348
+ if (!excludedExpressions.has(e)) {
2349
+ this._references.expressions.add(e);
2350
+ }
2351
+ //if this call is part of a longer expression that includes a call higher up, find that higher one and remove it
2352
+ if (e.callee) {
2353
+ let node = e.callee;
2354
+ while (node) {
2355
+ //the primary goal for this loop. If we found a parent call expression, remove it from `references`
2356
+ if ((0, reflection_1.isCallExpression)(node)) {
2357
+ this.references.expressions.delete(node);
2358
+ excludedExpressions.add(node);
2359
+ //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.
2360
+ break;
2361
+ //when we hit a variable expression, we're definitely at the leftmost expression so stop
2362
+ }
2363
+ else if ((0, reflection_1.isVariableExpression)(node)) {
2364
+ break;
2365
+ //if
2366
+ }
2367
+ else if ((0, reflection_1.isDottedGetExpression)(node) || (0, reflection_1.isIndexedGetExpression)(node)) {
2368
+ node = node.obj;
2369
+ }
2370
+ else {
2371
+ //some expression we don't understand. log it and quit the loop
2372
+ this.logger.info('Encountered unknown expression while calculating function expression chain', node);
2373
+ break;
2374
+ }
2375
+ }
2376
+ }
2377
+ };
2236
2378
  //gather up all the top-level statements
2237
2379
  this.ast.walk((0, visitors_1.createVisitor)({
2380
+ AssignmentStatement: s => {
2381
+ this._references.assignmentStatements.push(s);
2382
+ this.references.expressions.add(s.value);
2383
+ },
2238
2384
  ClassStatement: s => {
2239
2385
  this._references.classStatements.push(s);
2240
2386
  },
2387
+ ClassFieldStatement: s => {
2388
+ if (s.initialValue) {
2389
+ this._references.expressions.add(s.initialValue);
2390
+ }
2391
+ },
2241
2392
  NamespaceStatement: s => {
2242
2393
  this._references.namespaceStatements.push(s);
2243
2394
  },
2244
2395
  FunctionStatement: s => {
2245
2396
  this._references.functionStatements.push(s);
2246
- //add the initial set of function expressions for function statements
2247
- this._references.functionExpressions.push(s.func);
2248
2397
  },
2249
2398
  ImportStatement: s => {
2250
2399
  this._references.importStatements.push(s);
2251
2400
  },
2252
2401
  LibraryStatement: s => {
2253
2402
  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
2403
  },
2263
2404
  FunctionExpression: (expression, parent) => {
2264
2405
  if (!(0, reflection_1.isClassMethodStatement)(parent)) {
@@ -2267,25 +2408,54 @@ class Parser {
2267
2408
  },
2268
2409
  NewExpression: e => {
2269
2410
  this._references.newExpressions.push(e);
2411
+ for (const p of e.call.args) {
2412
+ this._references.expressions.add(p);
2413
+ }
2414
+ },
2415
+ ExpressionStatement: s => {
2416
+ this._references.expressions.add(s.expression);
2417
+ },
2418
+ CallfuncExpression: e => {
2419
+ visitCallExpression(e);
2420
+ },
2421
+ CallExpression: e => {
2422
+ visitCallExpression(e);
2270
2423
  },
2271
2424
  AALiteralExpression: e => {
2272
2425
  this.addPropertyHints(e);
2426
+ this._references.expressions.add(e);
2427
+ for (const member of e.elements) {
2428
+ if ((0, reflection_1.isAAMemberExpression)(member)) {
2429
+ this._references.expressions.add(member.value);
2430
+ }
2431
+ }
2432
+ },
2433
+ ArrayLiteralExpression: e => {
2434
+ for (const element of e.elements) {
2435
+ //keep everything except comments
2436
+ if (!(0, reflection_1.isCommentStatement)(element)) {
2437
+ this._references.expressions.add(element);
2438
+ }
2439
+ }
2273
2440
  },
2274
2441
  DottedGetExpression: e => {
2275
2442
  this.addPropertyHints(e.name);
2276
2443
  },
2277
2444
  DottedSetStatement: e => {
2278
2445
  this.addPropertyHints(e.name);
2446
+ },
2447
+ EnumStatement: e => {
2448
+ this._references.enumStatements.push(e);
2449
+ },
2450
+ UnaryExpression: e => {
2451
+ this._references.expressions.add(e);
2452
+ },
2453
+ IncrementStatement: e => {
2454
+ this._references.expressions.add(e);
2279
2455
  }
2456
+ }), {
2457
+ walkMode: visitors_1.WalkMode.visitAllRecursive
2280
2458
  });
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
2459
  }
2290
2460
  getContainingClass(currentToken) {
2291
2461
  return this.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
@@ -2297,7 +2467,10 @@ class Parser {
2297
2467
  return this.references.namespaceStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
2298
2468
  }
2299
2469
  getContainingFunctionExpression(currentToken) {
2300
- return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, currentToken.range.start));
2470
+ return this.getContainingFunctionExpressionByPosition(currentToken.range.start);
2471
+ }
2472
+ getContainingFunctionExpressionByPosition(position) {
2473
+ return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, position));
2301
2474
  }
2302
2475
  dispose() {
2303
2476
  }
@@ -2310,6 +2483,7 @@ var ParseMode;
2310
2483
  })(ParseMode = exports.ParseMode || (exports.ParseMode = {}));
2311
2484
  class References {
2312
2485
  constructor() {
2486
+ this.cache = new Cache_1.Cache();
2313
2487
  this.assignmentStatements = [];
2314
2488
  this.classStatements = [];
2315
2489
  this.dottedSetStatements = [];
@@ -2317,6 +2491,18 @@ class References {
2317
2491
  this.functionExpressions = [];
2318
2492
  this.functionStatements = [];
2319
2493
  this.interfaceStatements = [];
2494
+ this.enumStatements = [];
2495
+ /**
2496
+ * A collection of full expressions. This excludes intermediary expressions.
2497
+ *
2498
+ * Example 1:
2499
+ * `a.b.c` is composed of `a` (variableExpression) `.b` (DottedGetExpression) `.c` (DottedGetExpression)
2500
+ * This will only contain the final `.c` DottedGetExpression because `.b` and `a` can both be derived by walking back from the `.c` DottedGetExpression.
2501
+ *
2502
+ * Example 2:
2503
+ * `name.space.doSomething(a.b.c)` will result in 2 entries in this list. the `CallExpression` for `doSomething`, and the `.c` DottedGetExpression.
2504
+ */
2505
+ this.expressions = new Set();
2320
2506
  this.importStatements = [];
2321
2507
  this.libraryStatements = [];
2322
2508
  this.namespaceStatements = [];
@@ -2353,6 +2539,15 @@ class References {
2353
2539
  }
2354
2540
  return this._interfaceStatementLookup;
2355
2541
  }
2542
+ get enumStatementLookup() {
2543
+ return this.cache.getOrAdd('enums', () => {
2544
+ const result = new Map();
2545
+ for (const stmt of this.enumStatements) {
2546
+ result.set(stmt.fullName.toLowerCase(), stmt);
2547
+ }
2548
+ return result;
2549
+ });
2550
+ }
2356
2551
  }
2357
2552
  exports.References = References;
2358
2553
  var TokenUsage;
@@ -2388,7 +2583,10 @@ function getBscTypeFromExpression(expression, functionExpression) {
2388
2583
  //Array literal
2389
2584
  }
2390
2585
  else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {
2391
- return new ArrayType_1.ArrayType();
2586
+ const innerTypes = expression.elements.filter((element) => !(0, reflection_1.isCommentStatement)(element)).map((element) => {
2587
+ return getBscTypeFromExpression(element, functionExpression);
2588
+ });
2589
+ return new ArrayType_1.ArrayType(...innerTypes);
2392
2590
  //function call
2393
2591
  }
2394
2592
  else if ((0, reflection_1.isNewExpression)(expression)) {
@@ -2404,6 +2602,12 @@ function getBscTypeFromExpression(expression, functionExpression) {
2404
2602
  else if ((0, reflection_1.isDottedGetExpression)(expression)) {
2405
2603
  return (0, helpers_1.getTypeFromDottedGetExpression)(expression, functionExpression);
2406
2604
  }
2605
+ else if ((0, reflection_1.isIndexedGetExpression)(expression)) {
2606
+ const source = getBscTypeFromExpression(expression.obj, functionExpression);
2607
+ if ((0, reflection_1.isArrayType)(source)) {
2608
+ return source.getDefaultType();
2609
+ }
2610
+ }
2407
2611
  }
2408
2612
  catch (e) {
2409
2613
  //do nothing. Just return dynamic