brighterscript 0.42.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/Cache.d.ts +3 -8
  3. package/dist/Cache.js +9 -14
  4. package/dist/Cache.js.map +1 -1
  5. package/dist/DiagnosticMessages.d.ts +21 -1
  6. package/dist/DiagnosticMessages.js +20 -0
  7. package/dist/DiagnosticMessages.js.map +1 -1
  8. package/dist/LanguageServer.d.ts +1 -6
  9. package/dist/LanguageServer.js +3 -12
  10. package/dist/LanguageServer.js.map +1 -1
  11. package/dist/PluginInterface.d.ts +3 -3
  12. package/dist/PluginInterface.js +3 -0
  13. package/dist/PluginInterface.js.map +1 -1
  14. package/dist/Program.d.ts +68 -25
  15. package/dist/Program.js +169 -76
  16. package/dist/Program.js.map +1 -1
  17. package/dist/ProgramBuilder.js +6 -6
  18. package/dist/ProgramBuilder.js.map +1 -1
  19. package/dist/Scope.d.ts +18 -11
  20. package/dist/Scope.js +41 -14
  21. package/dist/Scope.js.map +1 -1
  22. package/dist/XmlScope.d.ts +3 -3
  23. package/dist/astUtils/AstEditor.d.ts +6 -0
  24. package/dist/astUtils/AstEditor.js +10 -0
  25. package/dist/astUtils/AstEditor.js.map +1 -1
  26. package/dist/astUtils/AstEditor.spec.js +37 -0
  27. package/dist/astUtils/AstEditor.spec.js.map +1 -1
  28. package/dist/astUtils/reflection.d.ts +5 -2
  29. package/dist/astUtils/reflection.js +14 -2
  30. package/dist/astUtils/reflection.js.map +1 -1
  31. package/dist/astUtils/reflection.spec.js +6 -6
  32. package/dist/astUtils/reflection.spec.js.map +1 -1
  33. package/dist/astUtils/visitors.d.ts +3 -1
  34. package/dist/astUtils/visitors.js.map +1 -1
  35. package/dist/astUtils/visitors.spec.js +15 -18
  36. package/dist/astUtils/visitors.spec.js.map +1 -1
  37. package/dist/bscPlugin/BscPlugin.d.ts +4 -1
  38. package/dist/bscPlugin/BscPlugin.js +21 -2
  39. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  40. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +3 -3
  41. package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
  42. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +18 -16
  43. package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
  44. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
  45. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
  46. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
  47. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.d.ts → BrsFileSemanticTokensProcessor.spec.d.ts} +0 -0
  48. package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +32 -4
  49. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
  50. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
  51. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +36 -0
  52. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
  53. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
  54. package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
  55. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  56. package/dist/bscPlugin/validation/ScopeValidator.d.ts +11 -0
  57. package/dist/bscPlugin/validation/ScopeValidator.js +94 -0
  58. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  59. package/dist/files/BrsFile.Class.spec.js +218 -114
  60. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  61. package/dist/files/BrsFile.d.ts +27 -8
  62. package/dist/files/BrsFile.js +216 -95
  63. package/dist/files/BrsFile.js.map +1 -1
  64. package/dist/files/BrsFile.spec.js +338 -190
  65. package/dist/files/BrsFile.spec.js.map +1 -1
  66. package/dist/files/XmlFile.d.ts +11 -5
  67. package/dist/files/XmlFile.js +15 -9
  68. package/dist/files/XmlFile.js.map +1 -1
  69. package/dist/files/XmlFile.spec.js +118 -114
  70. package/dist/files/XmlFile.spec.js.map +1 -1
  71. package/dist/files/tests/imports.spec.js +29 -27
  72. package/dist/files/tests/imports.spec.js.map +1 -1
  73. package/dist/index.d.ts +12 -3
  74. package/dist/index.js +21 -4
  75. package/dist/index.js.map +1 -1
  76. package/dist/interfaces.d.ts +50 -9
  77. package/dist/lexer/Lexer.js +1 -2
  78. package/dist/lexer/Lexer.js.map +1 -1
  79. package/dist/lexer/Lexer.spec.js +470 -462
  80. package/dist/lexer/Lexer.spec.js.map +1 -1
  81. package/dist/lexer/TokenKind.d.ts +2 -0
  82. package/dist/lexer/TokenKind.js +5 -0
  83. package/dist/lexer/TokenKind.js.map +1 -1
  84. package/dist/parser/Expression.d.ts +1 -1
  85. package/dist/parser/Expression.js +10 -10
  86. package/dist/parser/Expression.js.map +1 -1
  87. package/dist/parser/Parser.Class.spec.js +32 -31
  88. package/dist/parser/Parser.Class.spec.js.map +1 -1
  89. package/dist/parser/Parser.d.ts +23 -2
  90. package/dist/parser/Parser.js +445 -254
  91. package/dist/parser/Parser.js.map +1 -1
  92. package/dist/parser/Parser.spec.js +86 -24
  93. package/dist/parser/Parser.spec.js.map +1 -1
  94. package/dist/parser/SGParser.spec.js +1 -1
  95. package/dist/parser/SGParser.spec.js.map +1 -1
  96. package/dist/parser/Statement.d.ts +54 -2
  97. package/dist/parser/Statement.js +162 -9
  98. package/dist/parser/Statement.js.map +1 -1
  99. package/dist/parser/Statement.spec.js +5 -5
  100. package/dist/parser/Statement.spec.js.map +1 -1
  101. package/dist/parser/tests/Parser.spec.d.ts +3 -3
  102. package/dist/parser/tests/Parser.spec.js +4 -4
  103. package/dist/parser/tests/Parser.spec.js.map +1 -1
  104. package/dist/parser/tests/controlFlow/For.spec.js +40 -40
  105. package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
  106. package/dist/parser/tests/controlFlow/ForEach.spec.js +22 -21
  107. package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
  108. package/dist/parser/tests/controlFlow/If.spec.js +100 -99
  109. package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
  110. package/dist/parser/tests/controlFlow/While.spec.js +25 -25
  111. package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
  112. package/dist/parser/tests/expression/Additive.spec.js +21 -21
  113. package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
  114. package/dist/parser/tests/expression/ArrayLiterals.spec.js +91 -91
  115. package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
  116. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +102 -102
  117. package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
  118. package/dist/parser/tests/expression/Boolean.spec.js +15 -15
  119. package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
  120. package/dist/parser/tests/expression/Call.spec.js +22 -21
  121. package/dist/parser/tests/expression/Call.spec.js.map +1 -1
  122. package/dist/parser/tests/expression/Exponential.spec.js +11 -11
  123. package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
  124. package/dist/parser/tests/expression/Function.spec.js +171 -171
  125. package/dist/parser/tests/expression/Function.spec.js.map +1 -1
  126. package/dist/parser/tests/expression/Indexing.spec.js +50 -50
  127. package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
  128. package/dist/parser/tests/expression/Multiplicative.spec.js +25 -25
  129. package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
  130. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +17 -17
  131. package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
  132. package/dist/parser/tests/expression/PrefixUnary.spec.js +26 -26
  133. package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
  134. package/dist/parser/tests/expression/Primary.spec.js +27 -27
  135. package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
  136. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +4 -3
  137. package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
  138. package/dist/parser/tests/expression/Relational.spec.js +25 -25
  139. package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
  140. package/dist/parser/tests/expression/TemplateStringExpression.spec.js +8 -8
  141. package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
  142. package/dist/parser/tests/expression/TernaryExpression.spec.js +7 -7
  143. package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
  144. package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
  145. package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
  146. package/dist/parser/tests/statement/Declaration.spec.js +20 -20
  147. package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
  148. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  149. package/dist/parser/tests/statement/Enum.spec.js +774 -0
  150. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  151. package/dist/parser/tests/statement/Function.spec.js +121 -120
  152. package/dist/parser/tests/statement/Function.spec.js.map +1 -1
  153. package/dist/parser/tests/statement/Goto.spec.js +9 -8
  154. package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
  155. package/dist/parser/tests/statement/Increment.spec.js +22 -22
  156. package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
  157. package/dist/parser/tests/statement/InterfaceStatement.spec.js +12 -0
  158. package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
  159. package/dist/parser/tests/statement/LibraryStatement.spec.js +7 -7
  160. package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
  161. package/dist/parser/tests/statement/Misc.spec.js +71 -70
  162. package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
  163. package/dist/parser/tests/statement/PrintStatement.spec.js +17 -17
  164. package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
  165. package/dist/parser/tests/statement/ReturnStatement.spec.js +33 -33
  166. package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
  167. package/dist/parser/tests/statement/Set.spec.js +53 -53
  168. package/dist/parser/tests/statement/Set.spec.js.map +1 -1
  169. package/dist/parser/tests/statement/Stop.spec.js +7 -6
  170. package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
  171. package/dist/preprocessor/Chunk.d.ts +1 -1
  172. package/dist/preprocessor/Preprocessor.d.ts +1 -1
  173. package/dist/preprocessor/Preprocessor.js +7 -7
  174. package/dist/preprocessor/Preprocessor.js.map +1 -1
  175. package/dist/types/FunctionType.d.ts +2 -2
  176. package/dist/types/FunctionType.js +3 -3
  177. package/dist/types/FunctionType.js.map +1 -1
  178. package/dist/types/FunctionType.spec.js +2 -2
  179. package/dist/types/FunctionType.spec.js.map +1 -1
  180. package/dist/util.d.ts +27 -1
  181. package/dist/util.js +96 -29
  182. package/dist/util.js.map +1 -1
  183. package/dist/validators/ClassValidator.js +20 -27
  184. package/dist/validators/ClassValidator.js.map +1 -1
  185. package/package.json +2 -1
  186. package/dist/astUtils/index.d.ts +0 -7
  187. package/dist/astUtils/index.js +0 -26
  188. package/dist/astUtils/index.js.map +0 -1
  189. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
  190. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
  191. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
  192. package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
  193. package/dist/lexer/index.d.ts +0 -3
  194. package/dist/lexer/index.js +0 -18
  195. package/dist/lexer/index.js.map +0 -1
  196. package/dist/parser/index.d.ts +0 -3
  197. package/dist/parser/index.js +0 -16
  198. package/dist/parser/index.js.map +0 -1
  199. package/dist/preprocessor/index.d.ts +0 -3
  200. package/dist/preprocessor/index.js +0 -16
  201. package/dist/preprocessor/index.js.map +0 -1
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  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,7 +12,7 @@ const Logger_1 = require("../Logger");
10
12
  const reflection_1 = require("../astUtils/reflection");
11
13
  const visitors_1 = require("../astUtils/visitors");
12
14
  const creators_1 = require("../astUtils/creators");
13
- const _1 = require(".");
15
+ const Cache_1 = require("../Cache");
14
16
  class Parser {
15
17
  constructor() {
16
18
  /**
@@ -51,7 +53,7 @@ class Parser {
51
53
  this._references = undefined;
52
54
  }
53
55
  addPropertyHints(item) {
54
- if ((0, lexer_1.isToken)(item)) {
56
+ if ((0, Token_1.isToken)(item)) {
55
57
  const name = item.text;
56
58
  this._references.propertyHints[name.toLowerCase()] = name;
57
59
  }
@@ -79,7 +81,7 @@ class Parser {
79
81
  static parse(toParse, options) {
80
82
  let tokens;
81
83
  if (typeof toParse === 'string') {
82
- tokens = lexer_1.Lexer.scan(toParse).tokens;
84
+ tokens = Lexer_1.Lexer.scan(toParse).tokens;
83
85
  }
84
86
  else {
85
87
  tokens = toParse;
@@ -97,9 +99,9 @@ class Parser {
97
99
  this.tokens = tokens;
98
100
  this.options = this.sanitizeParseOptions(options);
99
101
  this.allowedLocalIdentifiers = [
100
- ...lexer_1.AllowedLocalIdentifiers,
102
+ ...TokenKind_1.AllowedLocalIdentifiers,
101
103
  //when in plain brightscript mode, the BrighterScript source literals can be used as regular variables
102
- ...(this.options.mode === ParseMode.BrightScript ? lexer_1.BrighterScriptSourceLiterals : [])
104
+ ...(this.options.mode === ParseMode.BrightScript ? TokenKind_1.BrighterScriptSourceLiterals : [])
103
105
  ];
104
106
  this.current = 0;
105
107
  this.diagnostics = [];
@@ -170,16 +172,16 @@ class Parser {
170
172
  }
171
173
  declaration() {
172
174
  try {
173
- if (this.checkAny(lexer_1.TokenKind.Sub, lexer_1.TokenKind.Function)) {
175
+ if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
174
176
  return this.functionDeclaration(false);
175
177
  }
176
178
  if (this.checkLibrary()) {
177
179
  return this.libraryStatement();
178
180
  }
179
- if (this.check(lexer_1.TokenKind.At) && this.checkNext(lexer_1.TokenKind.Identifier)) {
181
+ if (this.check(TokenKind_1.TokenKind.At) && this.checkNext(TokenKind_1.TokenKind.Identifier)) {
180
182
  return this.annotationExpression();
181
183
  }
182
- if (this.check(lexer_1.TokenKind.Comment)) {
184
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
183
185
  return this.commentStatement();
184
186
  }
185
187
  //catch certain global terminators to prevent unnecessary lookahead (i.e. like `end namespace`, no need to continue)
@@ -196,18 +198,39 @@ class Parser {
196
198
  this.synchronize();
197
199
  }
198
200
  }
201
+ /**
202
+ * Try to get an identifier. If not found, add diagnostic and return undefined
203
+ */
204
+ tryIdentifier(...additionalTokenKinds) {
205
+ const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
206
+ if (identifier) {
207
+ // force the name into an identifier so the AST makes some sense
208
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
209
+ return identifier;
210
+ }
211
+ }
199
212
  identifier(...additionalTokenKinds) {
200
- const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...additionalTokenKinds);
213
+ const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
201
214
  // force the name into an identifier so the AST makes some sense
202
- identifier.kind = lexer_1.TokenKind.Identifier;
215
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
203
216
  return identifier;
204
217
  }
218
+ enumMemberStatement() {
219
+ const statement = new Statement_1.EnumMemberStatement({});
220
+ statement.tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
221
+ //look for `= SOME_EXPRESSION`
222
+ if (this.check(TokenKind_1.TokenKind.Equal)) {
223
+ statement.tokens.equal = this.advance();
224
+ statement.value = this.expression();
225
+ }
226
+ return statement;
227
+ }
205
228
  /**
206
229
  * Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration`
207
230
  */
208
231
  interfaceFieldStatement() {
209
- const name = this.identifier(...lexer_1.AllowedProperties);
210
- let asToken = this.consumeToken(lexer_1.TokenKind.As);
232
+ const name = this.identifier(...TokenKind_1.AllowedProperties);
233
+ let asToken = this.consumeToken(TokenKind_1.TokenKind.As);
211
234
  let typeToken = this.typeToken();
212
235
  const type = util_1.util.tokenToBscType(typeToken);
213
236
  if (!type) {
@@ -221,13 +244,13 @@ class Parser {
221
244
  */
222
245
  interfaceMethodStatement() {
223
246
  const functionType = this.advance();
224
- const name = this.identifier(...lexer_1.AllowedProperties);
225
- const leftParen = this.consumeToken(lexer_1.TokenKind.LeftParen);
247
+ const name = this.identifier(...TokenKind_1.AllowedProperties);
248
+ const leftParen = this.consumeToken(TokenKind_1.TokenKind.LeftParen);
226
249
  const params = [];
227
- const rightParen = this.consumeToken(lexer_1.TokenKind.RightParen);
250
+ const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
228
251
  let asToken = null;
229
252
  let returnTypeToken = null;
230
- if (this.check(lexer_1.TokenKind.As)) {
253
+ if (this.check(TokenKind_1.TokenKind.As)) {
231
254
  asToken = this.advance();
232
255
  returnTypeToken = this.typeToken();
233
256
  const returnType = util_1.util.tokenToBscType(returnTypeToken);
@@ -241,7 +264,7 @@ class Parser {
241
264
  interfaceDeclaration() {
242
265
  this.warnIfNotBrighterScriptMode('interface declarations');
243
266
  const parentAnnotations = this.enterAnnotationBlock();
244
- const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(lexer_1.TokenKind.Interface), lexer_1.TokenKind.Interface);
267
+ const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
245
268
  const nameToken = this.identifier();
246
269
  let extendsToken;
247
270
  let parentInterfaceName;
@@ -252,23 +275,23 @@ class Parser {
252
275
  this.consumeStatementSeparators();
253
276
  //gather up all interface members (Fields, Methods)
254
277
  let body = [];
255
- while (this.checkAny(lexer_1.TokenKind.Comment, lexer_1.TokenKind.Identifier, lexer_1.TokenKind.At, ...lexer_1.AllowedProperties)) {
278
+ while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
256
279
  try {
257
280
  let decl;
258
281
  //collect leading annotations
259
- if (this.check(lexer_1.TokenKind.At)) {
282
+ if (this.check(TokenKind_1.TokenKind.At)) {
260
283
  this.annotationExpression();
261
284
  }
262
285
  //fields
263
- if (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties) && this.checkNext(lexer_1.TokenKind.As)) {
286
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.As)) {
264
287
  decl = this.interfaceFieldStatement();
265
288
  //methods (function/sub keyword followed by opening paren)
266
289
  }
267
- else if (this.checkAny(lexer_1.TokenKind.Function, lexer_1.TokenKind.Sub) && this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties)) {
290
+ else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
268
291
  decl = this.interfaceMethodStatement();
269
292
  //comments
270
293
  }
271
- else if (this.check(lexer_1.TokenKind.Comment)) {
294
+ else if (this.check(TokenKind_1.TokenKind.Comment)) {
272
295
  decl = this.commentStatement();
273
296
  }
274
297
  if (decl) {
@@ -277,39 +300,87 @@ class Parser {
277
300
  }
278
301
  else {
279
302
  //we didn't find a declaration...flag tokens until next line
280
- this.flagUntil(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Eof);
303
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
281
304
  }
282
305
  }
283
306
  catch (e) {
284
307
  //throw out any failed members and move on to the next line
285
- this.flagUntil(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Eof);
308
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
286
309
  }
287
310
  //ensure statement separator
288
311
  this.consumeStatementSeparators();
289
312
  //break out of this loop if we encountered the `EndInterface` token not followed by `as`
290
- if (this.check(lexer_1.TokenKind.EndInterface) && !this.checkNext(lexer_1.TokenKind.As)) {
313
+ if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
291
314
  break;
292
315
  }
293
316
  }
294
317
  //consume the final `end interface` token
295
- const endInterfaceToken = this.consumeToken(lexer_1.TokenKind.EndInterface);
296
- this.consumeStatementSeparators();
318
+ const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
297
319
  const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endInterfaceToken, this.currentNamespaceName);
298
320
  this._references.interfaceStatements.push(statement);
299
321
  this.exitAnnotationBlock(parentAnnotations);
300
322
  return statement;
301
323
  }
324
+ enumDeclaration() {
325
+ const result = new Statement_1.EnumStatement({}, [], this.currentNamespaceName);
326
+ this.warnIfNotBrighterScriptMode('enum declarations');
327
+ const parentAnnotations = this.enterAnnotationBlock();
328
+ result.tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
329
+ result.tokens.name = this.tryIdentifier();
330
+ this.consumeStatementSeparators();
331
+ //gather up all members
332
+ while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
333
+ try {
334
+ let decl;
335
+ //collect leading annotations
336
+ if (this.check(TokenKind_1.TokenKind.At)) {
337
+ this.annotationExpression();
338
+ }
339
+ //members
340
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
341
+ decl = this.enumMemberStatement();
342
+ //comments
343
+ }
344
+ else if (this.check(TokenKind_1.TokenKind.Comment)) {
345
+ decl = this.commentStatement();
346
+ }
347
+ if (decl) {
348
+ this.consumePendingAnnotations(decl);
349
+ result.body.push(decl);
350
+ }
351
+ else {
352
+ //we didn't find a declaration...flag tokens until next line
353
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
354
+ }
355
+ }
356
+ catch (e) {
357
+ //throw out any failed members and move on to the next line
358
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
359
+ }
360
+ //ensure statement separator
361
+ this.consumeStatementSeparators();
362
+ //break out of this loop if we encountered the `EndEnum` token
363
+ if (this.check(TokenKind_1.TokenKind.EndEnum)) {
364
+ break;
365
+ }
366
+ }
367
+ //consume the final `end interface` token
368
+ result.tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
369
+ this._references.enumStatements.push(result);
370
+ this.exitAnnotationBlock(parentAnnotations);
371
+ return result;
372
+ }
302
373
  /**
303
374
  * A BrighterScript class declaration
304
375
  */
305
376
  classDeclaration() {
306
377
  this.warnIfNotBrighterScriptMode('class declarations');
307
378
  const parentAnnotations = this.enterAnnotationBlock();
308
- let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(lexer_1.TokenKind.Class), lexer_1.TokenKind.Class);
379
+ let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Class), TokenKind_1.TokenKind.Class);
309
380
  let extendsKeyword;
310
381
  let parentClassName;
311
382
  //get the class name
312
- let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
383
+ let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
313
384
  //see if the class inherits from parent
314
385
  if (this.peek().text.toLowerCase() === 'extends') {
315
386
  extendsKeyword = this.advance();
@@ -319,14 +390,14 @@ class Parser {
319
390
  this.consumeStatementSeparators();
320
391
  //gather up all class members (Fields, Methods)
321
392
  let body = [];
322
- 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)) {
393
+ 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)) {
323
394
  try {
324
395
  let decl;
325
396
  let accessModifier;
326
- if (this.check(lexer_1.TokenKind.At)) {
397
+ if (this.check(TokenKind_1.TokenKind.At)) {
327
398
  this.annotationExpression();
328
399
  }
329
- if (this.checkAny(lexer_1.TokenKind.Public, lexer_1.TokenKind.Protected, lexer_1.TokenKind.Private)) {
400
+ if (this.checkAny(TokenKind_1.TokenKind.Public, TokenKind_1.TokenKind.Protected, TokenKind_1.TokenKind.Private)) {
330
401
  //use actual access modifier
331
402
  accessModifier = this.advance();
332
403
  }
@@ -335,7 +406,7 @@ class Parser {
335
406
  overrideKeyword = this.advance();
336
407
  }
337
408
  //methods (function/sub keyword OR identifier followed by opening paren)
338
- 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))) {
409
+ 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))) {
339
410
  const funcDeclaration = this.functionDeclaration(false, false);
340
411
  //remove this function from the lists because it's not a callable
341
412
  const functionStatement = this._references.functionStatements.pop();
@@ -348,7 +419,7 @@ class Parser {
348
419
  functionStatement.func.functionStatement = decl;
349
420
  //fields
350
421
  }
351
- else if (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties)) {
422
+ else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
352
423
  decl = this.classFieldDeclaration(accessModifier);
353
424
  //class fields cannot be overridden
354
425
  if (overrideKeyword) {
@@ -356,7 +427,7 @@ class Parser {
356
427
  }
357
428
  //comments
358
429
  }
359
- else if (this.check(lexer_1.TokenKind.Comment)) {
430
+ else if (this.check(TokenKind_1.TokenKind.Comment)) {
360
431
  decl = this.commentStatement();
361
432
  }
362
433
  if (decl) {
@@ -366,13 +437,13 @@ class Parser {
366
437
  }
367
438
  catch (e) {
368
439
  //throw out any failed members and move on to the next line
369
- this.flagUntil(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Eof);
440
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
370
441
  }
371
442
  //ensure statement separator
372
443
  this.consumeStatementSeparators();
373
444
  }
374
445
  let endingKeyword = this.advance();
375
- if (endingKeyword.kind !== lexer_1.TokenKind.EndClass) {
446
+ if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
376
447
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
377
448
  }
378
449
  const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName);
@@ -381,11 +452,11 @@ class Parser {
381
452
  return result;
382
453
  }
383
454
  classFieldDeclaration(accessModifier) {
384
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
455
+ let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
385
456
  let asToken;
386
457
  let fieldType;
387
458
  //look for `as SOME_TYPE`
388
- if (this.check(lexer_1.TokenKind.As)) {
459
+ if (this.check(TokenKind_1.TokenKind.As)) {
389
460
  asToken = this.advance();
390
461
  fieldType = this.typeToken();
391
462
  //no field type specified
@@ -396,7 +467,7 @@ class Parser {
396
467
  let initialValue;
397
468
  let equal;
398
469
  //if there is a field initializer
399
- if (this.check(lexer_1.TokenKind.Equal)) {
470
+ if (this.check(TokenKind_1.TokenKind.Equal)) {
400
471
  equal = this.advance();
401
472
  initialValue = this.expression();
402
473
  }
@@ -410,14 +481,14 @@ class Parser {
410
481
  //track depth to help certain statements need to know if they are contained within a function body
411
482
  this.namespaceAndFunctionDepth++;
412
483
  let functionType;
413
- if (this.checkAny(lexer_1.TokenKind.Sub, lexer_1.TokenKind.Function)) {
484
+ if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
414
485
  functionType = this.advance();
415
486
  }
416
487
  else {
417
488
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
418
489
  functionType = {
419
490
  isReserved: true,
420
- kind: lexer_1.TokenKind.Function,
491
+ kind: TokenKind_1.TokenKind.Function,
421
492
  text: 'function',
422
493
  //zero-length location means derived
423
494
  range: {
@@ -427,16 +498,16 @@ class Parser {
427
498
  leadingWhitespace: ''
428
499
  };
429
500
  }
430
- let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === lexer_1.TokenKind.Sub;
501
+ let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === TokenKind_1.TokenKind.Sub;
431
502
  let functionTypeText = isSub ? 'sub' : 'function';
432
503
  let name;
433
504
  let leftParen;
434
505
  if (isAnonymous) {
435
- leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), lexer_1.TokenKind.LeftParen);
506
+ leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), TokenKind_1.TokenKind.LeftParen);
436
507
  }
437
508
  else {
438
- name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
439
- leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), lexer_1.TokenKind.LeftParen);
509
+ name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
510
+ leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), TokenKind_1.TokenKind.LeftParen);
440
511
  //prevent functions from ending with type designators
441
512
  let lastChar = name.text[name.text.length - 1];
442
513
  if (['$', '%', '!', '#', '&'].includes(lastChar)) {
@@ -444,23 +515,23 @@ class Parser {
444
515
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionTypeText, name.text, lastChar)), { range: name.range }));
445
516
  }
446
517
  //flag functions with keywords for names (only for standard functions)
447
- if (checkIdentifier && lexer_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
518
+ if (checkIdentifier && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
448
519
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
449
520
  }
450
521
  }
451
522
  let params = [];
452
523
  let asToken;
453
524
  let typeToken;
454
- if (!this.check(lexer_1.TokenKind.RightParen)) {
525
+ if (!this.check(TokenKind_1.TokenKind.RightParen)) {
455
526
  do {
456
527
  if (params.length >= Expression_1.CallExpression.MaximumArguments) {
457
528
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(params.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
458
529
  }
459
530
  params.push(this.functionParameter());
460
- } while (this.match(lexer_1.TokenKind.Comma));
531
+ } while (this.match(TokenKind_1.TokenKind.Comma));
461
532
  }
462
533
  let rightParen = this.advance();
463
- if (this.check(lexer_1.TokenKind.As)) {
534
+ if (this.check(TokenKind_1.TokenKind.As)) {
464
535
  asToken = this.advance();
465
536
  typeToken = this.typeToken();
466
537
  if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript)) {
@@ -498,7 +569,7 @@ class Parser {
498
569
  }
499
570
  // consume 'end sub' or 'end function'
500
571
  func.end = this.advance();
501
- let expectedEndKind = isSub ? lexer_1.TokenKind.EndSub : lexer_1.TokenKind.EndFunction;
572
+ let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
502
573
  //if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
503
574
  //add an error but don't hard-fail so the AST can continue more gracefully
504
575
  if (func.end.kind !== expectedEndKind) {
@@ -522,22 +593,22 @@ class Parser {
522
593
  }
523
594
  }
524
595
  functionParameter() {
525
- if (!this.checkAny(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
596
+ if (!this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
526
597
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
527
598
  throw this.lastDiagnosticAsError();
528
599
  }
529
600
  let name = this.advance();
530
601
  // force the name into an identifier so the AST makes some sense
531
- name.kind = lexer_1.TokenKind.Identifier;
602
+ name.kind = TokenKind_1.TokenKind.Identifier;
532
603
  let typeToken;
533
604
  let defaultValue;
534
605
  // parse argument default value
535
- if (this.match(lexer_1.TokenKind.Equal)) {
606
+ if (this.match(TokenKind_1.TokenKind.Equal)) {
536
607
  // it seems any expression is allowed here -- including ones that operate on other arguments!
537
608
  defaultValue = this.expression();
538
609
  }
539
610
  let asToken = null;
540
- if (this.check(lexer_1.TokenKind.As)) {
611
+ if (this.check(TokenKind_1.TokenKind.As)) {
541
612
  asToken = this.advance();
542
613
  typeToken = this.typeToken();
543
614
  if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript)) {
@@ -550,30 +621,33 @@ class Parser {
550
621
  assignment() {
551
622
  let name = this.advance();
552
623
  //add diagnostic if name is a reserved word that cannot be used as an identifier
553
- if (lexer_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
624
+ if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
554
625
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
555
626
  }
556
- let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(lexer_1.AssignmentOperators, name.text), ...lexer_1.AssignmentOperators);
627
+ let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(TokenKind_1.AssignmentOperators, name.text), ...TokenKind_1.AssignmentOperators);
557
628
  let value = this.expression();
558
629
  let result;
559
- if (operator.kind === lexer_1.TokenKind.Equal) {
630
+ if (operator.kind === TokenKind_1.TokenKind.Equal) {
560
631
  result = new Statement_1.AssignmentStatement(operator, name, value, this.currentFunctionExpression);
561
632
  }
562
633
  else {
563
634
  result = new Statement_1.AssignmentStatement(operator, name, new Expression_1.BinaryExpression(new Expression_1.VariableExpression(name, this.currentNamespaceName), operator, value), this.currentFunctionExpression);
635
+ //remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
636
+ this._references.expressions.delete(value);
637
+ this._references.expressions.add(result);
564
638
  }
565
639
  this._references.assignmentStatements.push(result);
566
640
  return result;
567
641
  }
568
642
  checkLibrary() {
569
- let isLibraryToken = this.check(lexer_1.TokenKind.Library);
643
+ let isLibraryToken = this.check(TokenKind_1.TokenKind.Library);
570
644
  //if we are at the top level, any line that starts with "library" should be considered a library statement
571
645
  if (this.isAtRootLevel() && isLibraryToken) {
572
646
  return true;
573
647
  //not at root level, library statements are all invalid here, but try to detect if the tokens look
574
648
  //like a library statement (and let the libraryStatement function handle emitting the diagnostics)
575
649
  }
576
- else if (isLibraryToken && this.checkNext(lexer_1.TokenKind.StringLiteral)) {
650
+ else if (isLibraryToken && this.checkNext(TokenKind_1.TokenKind.StringLiteral)) {
577
651
  return true;
578
652
  //definitely not a library statement
579
653
  }
@@ -585,54 +659,54 @@ class Parser {
585
659
  if (this.checkLibrary()) {
586
660
  return this.libraryStatement();
587
661
  }
588
- if (this.check(lexer_1.TokenKind.Import)) {
662
+ if (this.check(TokenKind_1.TokenKind.Import)) {
589
663
  return this.importStatement();
590
664
  }
591
- if (this.check(lexer_1.TokenKind.Stop)) {
665
+ if (this.check(TokenKind_1.TokenKind.Stop)) {
592
666
  return this.stopStatement();
593
667
  }
594
- if (this.check(lexer_1.TokenKind.If)) {
668
+ if (this.check(TokenKind_1.TokenKind.If)) {
595
669
  return this.ifStatement();
596
670
  }
597
671
  //`try` must be followed by a block, otherwise it could be a local variable
598
- if (this.check(lexer_1.TokenKind.Try) && this.checkAnyNext(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Comment)) {
672
+ if (this.check(TokenKind_1.TokenKind.Try) && this.checkAnyNext(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
599
673
  return this.tryCatchStatement();
600
674
  }
601
- if (this.check(lexer_1.TokenKind.Throw)) {
675
+ if (this.check(TokenKind_1.TokenKind.Throw)) {
602
676
  return this.throwStatement();
603
677
  }
604
- if (this.checkAny(lexer_1.TokenKind.Print, lexer_1.TokenKind.Question)) {
678
+ if (this.checkAny(TokenKind_1.TokenKind.Print, TokenKind_1.TokenKind.Question)) {
605
679
  return this.printStatement();
606
680
  }
607
- if (this.check(lexer_1.TokenKind.Dim)) {
681
+ if (this.check(TokenKind_1.TokenKind.Dim)) {
608
682
  return this.dimStatement();
609
683
  }
610
- if (this.check(lexer_1.TokenKind.While)) {
684
+ if (this.check(TokenKind_1.TokenKind.While)) {
611
685
  return this.whileStatement();
612
686
  }
613
- if (this.check(lexer_1.TokenKind.ExitWhile)) {
687
+ if (this.check(TokenKind_1.TokenKind.ExitWhile)) {
614
688
  return this.exitWhile();
615
689
  }
616
- if (this.check(lexer_1.TokenKind.For)) {
690
+ if (this.check(TokenKind_1.TokenKind.For)) {
617
691
  return this.forStatement();
618
692
  }
619
- if (this.check(lexer_1.TokenKind.ForEach)) {
693
+ if (this.check(TokenKind_1.TokenKind.ForEach)) {
620
694
  return this.forEachStatement();
621
695
  }
622
- if (this.check(lexer_1.TokenKind.ExitFor)) {
696
+ if (this.check(TokenKind_1.TokenKind.ExitFor)) {
623
697
  return this.exitFor();
624
698
  }
625
- if (this.check(lexer_1.TokenKind.End)) {
699
+ if (this.check(TokenKind_1.TokenKind.End)) {
626
700
  return this.endStatement();
627
701
  }
628
- if (this.match(lexer_1.TokenKind.Return)) {
702
+ if (this.match(TokenKind_1.TokenKind.Return)) {
629
703
  return this.returnStatement();
630
704
  }
631
- if (this.check(lexer_1.TokenKind.Goto)) {
705
+ if (this.check(TokenKind_1.TokenKind.Goto)) {
632
706
  return this.gotoStatement();
633
707
  }
634
708
  //does this line look like a label? (i.e. `someIdentifier:` )
635
- if (this.check(lexer_1.TokenKind.Identifier) && this.checkNext(lexer_1.TokenKind.Colon) && this.checkPrevious(lexer_1.TokenKind.Newline)) {
709
+ if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
636
710
  try {
637
711
  return this.labelStatement();
638
712
  }
@@ -646,20 +720,23 @@ class Parser {
646
720
  // BrightScript is like python, in that variables can be declared without a `var`,
647
721
  // `let`, (...) keyword. As such, we must check the token *after* an identifier to figure
648
722
  // out what to do with it.
649
- if (this.checkAny(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers) &&
650
- this.checkAnyNext(...lexer_1.AssignmentOperators)) {
723
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers) &&
724
+ this.checkAnyNext(...TokenKind_1.AssignmentOperators)) {
651
725
  return this.assignment();
652
726
  }
653
727
  //some BrighterScript keywords are allowed as a local identifiers, so we need to check for them AFTER the assignment check
654
- if (this.check(lexer_1.TokenKind.Interface)) {
728
+ if (this.check(TokenKind_1.TokenKind.Interface)) {
655
729
  return this.interfaceDeclaration();
656
730
  }
657
- if (this.check(lexer_1.TokenKind.Class)) {
731
+ if (this.check(TokenKind_1.TokenKind.Class)) {
658
732
  return this.classDeclaration();
659
733
  }
660
- if (this.check(lexer_1.TokenKind.Namespace)) {
734
+ if (this.check(TokenKind_1.TokenKind.Namespace)) {
661
735
  return this.namespaceStatement();
662
736
  }
737
+ if (this.check(TokenKind_1.TokenKind.Enum)) {
738
+ return this.enumDeclaration();
739
+ }
663
740
  // TODO: support multi-statements
664
741
  return this.setStatement();
665
742
  }
@@ -667,9 +744,9 @@ class Parser {
667
744
  const whileKeyword = this.advance();
668
745
  const condition = this.expression();
669
746
  this.consumeStatementSeparators();
670
- const whileBlock = this.block(lexer_1.TokenKind.EndWhile);
747
+ const whileBlock = this.block(TokenKind_1.TokenKind.EndWhile);
671
748
  let endWhile;
672
- if (!whileBlock || this.peek().kind !== lexer_1.TokenKind.EndWhile) {
749
+ if (!whileBlock || this.peek().kind !== TokenKind_1.TokenKind.EndWhile) {
673
750
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('while')), { range: this.peek().range }));
674
751
  if (!whileBlock) {
675
752
  throw this.lastDiagnosticAsError();
@@ -692,7 +769,7 @@ class Parser {
692
769
  const finalValue = this.expression();
693
770
  let incrementExpression;
694
771
  let stepToken;
695
- if (this.check(lexer_1.TokenKind.Step)) {
772
+ if (this.check(TokenKind_1.TokenKind.Step)) {
696
773
  stepToken = this.advance();
697
774
  incrementExpression = this.expression();
698
775
  }
@@ -700,9 +777,9 @@ class Parser {
700
777
  // BrightScript for/to/step loops default to a step of 1 if no `step` is provided
701
778
  }
702
779
  this.consumeStatementSeparators();
703
- let body = this.block(lexer_1.TokenKind.EndFor, lexer_1.TokenKind.Next);
780
+ let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
704
781
  let endForToken;
705
- if (!body || !this.checkAny(lexer_1.TokenKind.EndFor, lexer_1.TokenKind.Next)) {
782
+ if (!body || !this.checkAny(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next)) {
706
783
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
707
784
  if (!body) {
708
785
  throw this.lastDiagnosticAsError();
@@ -719,7 +796,7 @@ class Parser {
719
796
  let forEach = this.advance();
720
797
  let name = this.advance();
721
798
  let maybeIn = this.peek();
722
- if (this.check(lexer_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
799
+ if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
723
800
  this.advance();
724
801
  }
725
802
  else {
@@ -732,7 +809,7 @@ class Parser {
732
809
  throw this.lastDiagnosticAsError();
733
810
  }
734
811
  this.consumeStatementSeparators();
735
- let body = this.block(lexer_1.TokenKind.EndFor, lexer_1.TokenKind.Next);
812
+ let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
736
813
  if (!body) {
737
814
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
738
815
  throw this.lastDiagnosticAsError();
@@ -757,7 +834,7 @@ class Parser {
757
834
  }
758
835
  else {
759
836
  let comments = [this.advance()];
760
- while (this.check(lexer_1.TokenKind.Newline) && this.checkNext(lexer_1.TokenKind.Comment)) {
837
+ while (this.check(TokenKind_1.TokenKind.Newline) && this.checkNext(TokenKind_1.TokenKind.Comment)) {
761
838
  this.advance();
762
839
  comments.push(this.advance());
763
840
  }
@@ -774,13 +851,13 @@ class Parser {
774
851
  let name = this.getNamespacedVariableNameExpression();
775
852
  //set the current namespace name
776
853
  this.currentNamespaceName = name;
777
- this.globalTerminators.push([lexer_1.TokenKind.EndNamespace]);
854
+ this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
778
855
  let body = this.body();
779
856
  this.globalTerminators.pop();
780
857
  //unset the current namespace name
781
858
  this.currentNamespaceName = undefined;
782
859
  let endKeyword;
783
- if (this.check(lexer_1.TokenKind.EndNamespace)) {
860
+ if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
784
861
  endKeyword = this.advance();
785
862
  }
786
863
  else {
@@ -796,24 +873,25 @@ class Parser {
796
873
  * Get an expression with identifiers separated by periods. Useful for namespaces and class extends
797
874
  */
798
875
  getNamespacedVariableNameExpression() {
799
- let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
876
+ let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
800
877
  let expr;
801
878
  if (firstIdentifier) {
802
879
  // force it into an identifier so the AST makes some sense
803
- firstIdentifier.kind = lexer_1.TokenKind.Identifier;
804
- expr = new Expression_1.VariableExpression(firstIdentifier, null);
880
+ firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
881
+ const varExpr = new Expression_1.VariableExpression(firstIdentifier, null);
882
+ expr = varExpr;
805
883
  //consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
806
- while (this.check(lexer_1.TokenKind.Dot)) {
807
- let dot = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), lexer_1.TokenKind.Dot);
884
+ while (this.check(TokenKind_1.TokenKind.Dot)) {
885
+ let dot = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.Dot);
808
886
  if (!dot) {
809
887
  break;
810
888
  }
811
- let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, ...lexer_1.AllowedProperties);
889
+ let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, ...TokenKind_1.AllowedProperties);
812
890
  if (!identifier) {
813
891
  break;
814
892
  }
815
893
  // force it into an identifier so the AST makes some sense
816
- identifier.kind = lexer_1.TokenKind.Identifier;
894
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
817
895
  expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
818
896
  }
819
897
  }
@@ -845,7 +923,7 @@ class Parser {
845
923
  let libStatement = new Statement_1.LibraryStatement({
846
924
  library: this.advance(),
847
925
  //grab the next token only if it's a string
848
- filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), lexer_1.TokenKind.StringLiteral)
926
+ filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
849
927
  });
850
928
  this._references.libraryStatements.push(libStatement);
851
929
  return libStatement;
@@ -854,20 +932,20 @@ class Parser {
854
932
  this.warnIfNotBrighterScriptMode('import statements');
855
933
  let importStatement = new Statement_1.ImportStatement(this.advance(),
856
934
  //grab the next token only if it's a string
857
- this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), lexer_1.TokenKind.StringLiteral));
935
+ this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
858
936
  this._references.importStatements.push(importStatement);
859
937
  return importStatement;
860
938
  }
861
939
  annotationExpression() {
862
940
  const atToken = this.advance();
863
- const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
941
+ const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
864
942
  if (identifier) {
865
- identifier.kind = lexer_1.TokenKind.Identifier;
943
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
866
944
  }
867
945
  let annotation = new Expression_1.AnnotationExpression(atToken, identifier);
868
946
  this.pendingAnnotations.push(annotation);
869
947
  //optional arguments
870
- if (this.check(lexer_1.TokenKind.LeftParen)) {
948
+ if (this.check(TokenKind_1.TokenKind.LeftParen)) {
871
949
  let leftParen = this.advance();
872
950
  annotation.call = this.finishCall(leftParen, annotation, false);
873
951
  }
@@ -880,7 +958,7 @@ class Parser {
880
958
  }
881
959
  const questionMarkToken = this.advance();
882
960
  //consume newlines or comments
883
- while (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
961
+ while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
884
962
  this.advance();
885
963
  }
886
964
  let consequent;
@@ -889,12 +967,12 @@ class Parser {
889
967
  }
890
968
  catch (_a) { }
891
969
  //consume newlines or comments
892
- while (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
970
+ while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
893
971
  this.advance();
894
972
  }
895
- const colonToken = this.tryConsumeToken(lexer_1.TokenKind.Colon);
973
+ const colonToken = this.tryConsumeToken(TokenKind_1.TokenKind.Colon);
896
974
  //consume newlines
897
- while (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
975
+ while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
898
976
  this.advance();
899
977
  }
900
978
  let alternate;
@@ -912,7 +990,7 @@ class Parser {
912
990
  }
913
991
  regexLiteralExpression() {
914
992
  this.warnIfNotBrighterScriptMode('regular expression literal');
915
- return new _1.RegexLiteralExpression({
993
+ return new Expression_1.RegexLiteralExpression({
916
994
  regexLiteral: this.advance()
917
995
  });
918
996
  }
@@ -921,23 +999,23 @@ class Parser {
921
999
  //get the tag name
922
1000
  let tagName;
923
1001
  if (isTagged) {
924
- tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1002
+ tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
925
1003
  // force it into an identifier so the AST makes some sense
926
- tagName.kind = lexer_1.TokenKind.Identifier;
1004
+ tagName.kind = TokenKind_1.TokenKind.Identifier;
927
1005
  }
928
1006
  let quasis = [];
929
1007
  let expressions = [];
930
1008
  let openingBacktick = this.peek();
931
1009
  this.advance();
932
1010
  let currentQuasiExpressionParts = [];
933
- while (!this.isAtEnd() && !this.check(lexer_1.TokenKind.BackTick)) {
1011
+ while (!this.isAtEnd() && !this.check(TokenKind_1.TokenKind.BackTick)) {
934
1012
  let next = this.peek();
935
- if (next.kind === lexer_1.TokenKind.TemplateStringQuasi) {
1013
+ if (next.kind === TokenKind_1.TokenKind.TemplateStringQuasi) {
936
1014
  //a quasi can actually be made up of multiple quasis when it includes char literals
937
1015
  currentQuasiExpressionParts.push(new Expression_1.LiteralExpression(next));
938
1016
  this.advance();
939
1017
  }
940
- else if (next.kind === lexer_1.TokenKind.EscapedCharCodeLiteral) {
1018
+ else if (next.kind === TokenKind_1.TokenKind.EscapedCharCodeLiteral) {
941
1019
  currentQuasiExpressionParts.push(new Expression_1.EscapedCharCodeLiteralExpression(next));
942
1020
  this.advance();
943
1021
  }
@@ -945,12 +1023,12 @@ class Parser {
945
1023
  //finish up the current quasi
946
1024
  quasis.push(new Expression_1.TemplateStringQuasiExpression(currentQuasiExpressionParts));
947
1025
  currentQuasiExpressionParts = [];
948
- if (next.kind === lexer_1.TokenKind.TemplateStringExpressionBegin) {
1026
+ if (next.kind === TokenKind_1.TokenKind.TemplateStringExpressionBegin) {
949
1027
  this.advance();
950
1028
  }
951
1029
  //now keep this expression
952
1030
  expressions.push(this.expression());
953
- if (!this.isAtEnd() && this.check(lexer_1.TokenKind.TemplateStringExpressionEnd)) {
1031
+ if (!this.isAtEnd() && this.check(TokenKind_1.TokenKind.TemplateStringExpressionEnd)) {
954
1032
  //TODO is it an error if this is not present?
955
1033
  this.advance();
956
1034
  }
@@ -982,12 +1060,12 @@ class Parser {
982
1060
  const statement = new Statement_1.TryCatchStatement(tryToken);
983
1061
  //ensure statement separator
984
1062
  this.consumeStatementSeparators();
985
- statement.tryBranch = this.block(lexer_1.TokenKind.Catch, lexer_1.TokenKind.EndTry);
1063
+ statement.tryBranch = this.block(TokenKind_1.TokenKind.Catch, TokenKind_1.TokenKind.EndTry);
986
1064
  const peek = this.peek();
987
- if (peek.kind !== lexer_1.TokenKind.Catch) {
1065
+ if (peek.kind !== TokenKind_1.TokenKind.Catch) {
988
1066
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedCatchBlockInTryCatch()), { range: this.peek().range }));
989
1067
  //gracefully handle end-try
990
- if (peek.kind === lexer_1.TokenKind.EndTry) {
1068
+ if (peek.kind === TokenKind_1.TokenKind.EndTry) {
991
1069
  statement.endTryToken = this.advance();
992
1070
  }
993
1071
  return statement;
@@ -995,16 +1073,16 @@ class Parser {
995
1073
  else {
996
1074
  statement.catchToken = this.advance();
997
1075
  }
998
- const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1076
+ const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
999
1077
  if (exceptionVarToken) {
1000
1078
  // force it into an identifier so the AST makes some sense
1001
- exceptionVarToken.kind = lexer_1.TokenKind.Identifier;
1079
+ exceptionVarToken.kind = TokenKind_1.TokenKind.Identifier;
1002
1080
  statement.exceptionVariable = exceptionVarToken;
1003
1081
  }
1004
1082
  //ensure statement sepatator
1005
1083
  this.consumeStatementSeparators();
1006
- statement.catchBranch = this.block(lexer_1.TokenKind.EndTry);
1007
- if (this.peek().kind !== lexer_1.TokenKind.EndTry) {
1084
+ statement.catchBranch = this.block(TokenKind_1.TokenKind.EndTry);
1085
+ if (this.peek().kind !== TokenKind_1.TokenKind.EndTry) {
1008
1086
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndTryToTerminateTryCatch()), { range: this.peek().range }));
1009
1087
  }
1010
1088
  else {
@@ -1015,7 +1093,7 @@ class Parser {
1015
1093
  throwStatement() {
1016
1094
  const throwToken = this.advance();
1017
1095
  let expression;
1018
- if (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon)) {
1096
+ if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
1019
1097
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExceptionExpressionAfterThrowKeyword()), { range: throwToken.range }));
1020
1098
  }
1021
1099
  else {
@@ -1025,19 +1103,19 @@ class Parser {
1025
1103
  }
1026
1104
  dimStatement() {
1027
1105
  const dim = this.advance();
1028
- let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'), lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1106
+ let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
1029
1107
  // force to an identifier so the AST makes some sense
1030
1108
  if (identifier) {
1031
- identifier.kind = lexer_1.TokenKind.Identifier;
1109
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
1032
1110
  }
1033
- let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(), lexer_1.TokenKind.LeftSquareBracket);
1111
+ let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.LeftSquareBracket);
1034
1112
  let expressions = [];
1035
1113
  let expression;
1036
1114
  do {
1037
1115
  try {
1038
1116
  expression = this.expression();
1039
1117
  expressions.push(expression);
1040
- if (this.check(lexer_1.TokenKind.Comma)) {
1118
+ if (this.check(TokenKind_1.TokenKind.Comma)) {
1041
1119
  this.advance();
1042
1120
  }
1043
1121
  else {
@@ -1051,15 +1129,15 @@ class Parser {
1051
1129
  if (expressions.length === 0) {
1052
1130
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
1053
1131
  }
1054
- let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), lexer_1.TokenKind.RightSquareBracket);
1132
+ let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
1055
1133
  return new Statement_1.DimStatement(dim, identifier, leftSquareBracket, expressions, rightSquareBracket);
1056
1134
  }
1057
1135
  ifStatement() {
1058
1136
  // colon before `if` is usually not allowed, unless it's after `then`
1059
1137
  if (this.current > 0) {
1060
1138
  const prev = this.previous();
1061
- if (prev.kind === lexer_1.TokenKind.Colon) {
1062
- if (this.current > 1 && this.tokens[this.current - 2].kind !== lexer_1.TokenKind.Then) {
1139
+ if (prev.kind === TokenKind_1.TokenKind.Colon) {
1140
+ if (this.current > 1 && this.tokens[this.current - 2].kind !== TokenKind_1.TokenKind.Then) {
1063
1141
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedColonBeforeIfStatement()), { range: prev.range }));
1064
1142
  }
1065
1143
  }
@@ -1073,14 +1151,14 @@ class Parser {
1073
1151
  let endIfToken;
1074
1152
  let elseToken;
1075
1153
  //optional `then`
1076
- if (this.check(lexer_1.TokenKind.Then)) {
1154
+ if (this.check(TokenKind_1.TokenKind.Then)) {
1077
1155
  thenToken = this.advance();
1078
1156
  }
1079
1157
  //is it inline or multi-line if?
1080
- const isInlineIfThen = !this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Comment);
1158
+ const isInlineIfThen = !this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment);
1081
1159
  if (isInlineIfThen) {
1082
1160
  /*** PARSE INLINE IF STATEMENT ***/
1083
- thenBranch = this.inlineConditionalBranch(lexer_1.TokenKind.Else, lexer_1.TokenKind.EndIf);
1161
+ thenBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
1084
1162
  if (!thenBranch) {
1085
1163
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementToFollowConditionalCondition(ifToken.text)), { range: this.peek().range }));
1086
1164
  throw this.lastDiagnosticAsError();
@@ -1089,9 +1167,9 @@ class Parser {
1089
1167
  this.ensureInline(thenBranch.statements);
1090
1168
  }
1091
1169
  //else branch
1092
- if (this.check(lexer_1.TokenKind.Else)) {
1170
+ if (this.check(TokenKind_1.TokenKind.Else)) {
1093
1171
  elseToken = this.advance();
1094
- if (this.check(lexer_1.TokenKind.If)) {
1172
+ if (this.check(TokenKind_1.TokenKind.If)) {
1095
1173
  // recurse-read `else if`
1096
1174
  elseBranch = this.ifStatement();
1097
1175
  //no multi-line if chained with an inline if
@@ -1099,13 +1177,13 @@ class Parser {
1099
1177
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: elseBranch.range }));
1100
1178
  }
1101
1179
  }
1102
- else if (this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon)) {
1180
+ else if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
1103
1181
  //expecting inline else branch
1104
1182
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: this.peek().range }));
1105
1183
  throw this.lastDiagnosticAsError();
1106
1184
  }
1107
1185
  else {
1108
- elseBranch = this.inlineConditionalBranch(lexer_1.TokenKind.Else, lexer_1.TokenKind.EndIf);
1186
+ elseBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
1109
1187
  if (elseBranch) {
1110
1188
  this.ensureInline(elseBranch.statements);
1111
1189
  }
@@ -1119,9 +1197,9 @@ class Parser {
1119
1197
  if (!elseBranch || !(0, reflection_1.isIfStatement)(elseBranch)) {
1120
1198
  //enforce newline at the end of the inline if statement
1121
1199
  const peek = this.peek();
1122
- if (peek.kind !== lexer_1.TokenKind.Newline && peek.kind !== lexer_1.TokenKind.Comment && !this.isAtEnd()) {
1200
+ if (peek.kind !== TokenKind_1.TokenKind.Newline && peek.kind !== TokenKind_1.TokenKind.Comment && !this.isAtEnd()) {
1123
1201
  //ignore last error if it was about a colon
1124
- if (this.previous().kind === lexer_1.TokenKind.Colon) {
1202
+ if (this.previous().kind === TokenKind_1.TokenKind.Colon) {
1125
1203
  this.diagnostics.pop();
1126
1204
  this.current--;
1127
1205
  }
@@ -1136,9 +1214,9 @@ class Parser {
1136
1214
  //ensure newline/colon before next keyword
1137
1215
  this.ensureNewLineOrColon();
1138
1216
  //else branch
1139
- if (this.check(lexer_1.TokenKind.Else)) {
1217
+ if (this.check(TokenKind_1.TokenKind.Else)) {
1140
1218
  elseToken = this.advance();
1141
- if (this.check(lexer_1.TokenKind.If)) {
1219
+ if (this.check(TokenKind_1.TokenKind.If)) {
1142
1220
  // recurse-read `else if`
1143
1221
  elseBranch = this.ifStatement();
1144
1222
  }
@@ -1149,7 +1227,7 @@ class Parser {
1149
1227
  }
1150
1228
  }
1151
1229
  if (!(0, reflection_1.isIfStatement)(elseBranch)) {
1152
- if (this.check(lexer_1.TokenKind.EndIf)) {
1230
+ if (this.check(TokenKind_1.TokenKind.EndIf)) {
1153
1231
  endIfToken = this.advance();
1154
1232
  }
1155
1233
  else {
@@ -1172,7 +1250,7 @@ class Parser {
1172
1250
  let diagnosticsLengthBeforeBlock = this.diagnostics.length;
1173
1251
  // we're parsing a multi-line ("block") form of the BrightScript if/then and must find
1174
1252
  // a trailing "end if" or "else if"
1175
- let branch = this.block(lexer_1.TokenKind.EndIf, lexer_1.TokenKind.Else);
1253
+ let branch = this.block(TokenKind_1.TokenKind.EndIf, TokenKind_1.TokenKind.Else);
1176
1254
  if (!branch) {
1177
1255
  //throw out any new diagnostics created as a result of a `then` block parse failure.
1178
1256
  //the block() function will discard the current line, so any discarded diagnostics will
@@ -1186,7 +1264,7 @@ class Parser {
1186
1264
  }
1187
1265
  ensureNewLineOrColon(silent = false) {
1188
1266
  const prev = this.previous().kind;
1189
- if (prev !== lexer_1.TokenKind.Newline && prev !== lexer_1.TokenKind.Colon) {
1267
+ if (prev !== TokenKind_1.TokenKind.Newline && prev !== TokenKind_1.TokenKind.Colon) {
1190
1268
  if (!silent) {
1191
1269
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedNewlineOrColon()), { range: this.peek().range }));
1192
1270
  }
@@ -1215,12 +1293,12 @@ class Parser {
1215
1293
  const startingRange = statement.range;
1216
1294
  //look for colon statement separator
1217
1295
  let foundColon = false;
1218
- while (this.match(lexer_1.TokenKind.Colon)) {
1296
+ while (this.match(TokenKind_1.TokenKind.Colon)) {
1219
1297
  foundColon = true;
1220
1298
  }
1221
1299
  //if a colon was found, add the next statement or err if unexpected
1222
1300
  if (foundColon) {
1223
- if (!this.checkAny(lexer_1.TokenKind.Newline, ...additionalTerminators)) {
1301
+ if (!this.checkAny(TokenKind_1.TokenKind.Newline, ...additionalTerminators)) {
1224
1302
  //if not an ending keyword, add next statement
1225
1303
  let extra = this.inlineConditionalBranch(...additionalTerminators);
1226
1304
  if (!extra) {
@@ -1238,9 +1316,9 @@ class Parser {
1238
1316
  }
1239
1317
  expressionStatement(expr) {
1240
1318
  let expressionStart = this.peek();
1241
- if (this.checkAny(lexer_1.TokenKind.PlusPlus, lexer_1.TokenKind.MinusMinus)) {
1319
+ if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
1242
1320
  let operator = this.advance();
1243
- if (this.checkAny(lexer_1.TokenKind.PlusPlus, lexer_1.TokenKind.MinusMinus)) {
1321
+ if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
1244
1322
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.consecutiveIncrementDecrementOperatorsAreNotAllowed()), { range: this.peek().range }));
1245
1323
  throw this.lastDiagnosticAsError();
1246
1324
  }
@@ -1248,7 +1326,9 @@ class Parser {
1248
1326
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incrementDecrementOperatorsAreNotAllowedAsResultOfFunctionCall()), { range: expressionStart.range }));
1249
1327
  throw this.lastDiagnosticAsError();
1250
1328
  }
1251
- return new Statement_1.IncrementStatement(expr, operator);
1329
+ const result = new Statement_1.IncrementStatement(expr, operator);
1330
+ this._references.expressions.add(result);
1331
+ return result;
1252
1332
  }
1253
1333
  if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
1254
1334
  return new Statement_1.ExpressionStatement(expr);
@@ -1265,18 +1345,18 @@ class Parser {
1265
1345
  * priority as standalone function calls though, so we can parse them in the same way.
1266
1346
  */
1267
1347
  let expr = this.call();
1268
- if (this.checkAny(...lexer_1.AssignmentOperators) && !((0, reflection_1.isCallExpression)(expr))) {
1348
+ if (this.checkAny(...TokenKind_1.AssignmentOperators) && !((0, reflection_1.isCallExpression)(expr))) {
1269
1349
  let left = expr;
1270
1350
  let operator = this.advance();
1271
1351
  let right = this.expression();
1272
1352
  // Create a dotted or indexed "set" based on the left-hand side's type
1273
1353
  if ((0, reflection_1.isIndexedGetExpression)(left)) {
1274
- return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === lexer_1.TokenKind.Equal
1354
+ return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
1275
1355
  ? right
1276
1356
  : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
1277
1357
  }
1278
1358
  else if ((0, reflection_1.isDottedGetExpression)(left)) {
1279
- return new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === lexer_1.TokenKind.Equal
1359
+ return new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
1280
1360
  ? right
1281
1361
  : new Expression_1.BinaryExpression(left, operator, right));
1282
1362
  }
@@ -1287,13 +1367,13 @@ class Parser {
1287
1367
  let printKeyword = this.advance();
1288
1368
  let values = [];
1289
1369
  while (!this.checkEndOfStatement()) {
1290
- if (this.check(lexer_1.TokenKind.Semicolon)) {
1370
+ if (this.check(TokenKind_1.TokenKind.Semicolon)) {
1291
1371
  values.push(this.advance());
1292
1372
  }
1293
- else if (this.check(lexer_1.TokenKind.Comma)) {
1373
+ else if (this.check(TokenKind_1.TokenKind.Comma)) {
1294
1374
  values.push(this.advance());
1295
1375
  }
1296
- else if (this.check(lexer_1.TokenKind.Else)) {
1376
+ else if (this.check(TokenKind_1.TokenKind.Else)) {
1297
1377
  break; // inline branch
1298
1378
  }
1299
1379
  else {
@@ -1306,7 +1386,7 @@ class Parser {
1306
1386
  values.push(emptyStringLiteral);
1307
1387
  }
1308
1388
  let last = values[values.length - 1];
1309
- if ((0, lexer_1.isToken)(last)) {
1389
+ if ((0, Token_1.isToken)(last)) {
1310
1390
  // TODO: error, expected value
1311
1391
  }
1312
1392
  return new Statement_1.PrintStatement({ print: printKeyword }, values);
@@ -1320,7 +1400,7 @@ class Parser {
1320
1400
  if (this.checkEndOfStatement()) {
1321
1401
  return new Statement_1.ReturnStatement(tokens);
1322
1402
  }
1323
- let toReturn = this.check(lexer_1.TokenKind.Else) ? undefined : this.expression();
1403
+ let toReturn = this.check(TokenKind_1.TokenKind.Else) ? undefined : this.expression();
1324
1404
  return new Statement_1.ReturnStatement(tokens, toReturn);
1325
1405
  }
1326
1406
  /**
@@ -1333,7 +1413,7 @@ class Parser {
1333
1413
  colon: this.advance()
1334
1414
  };
1335
1415
  //label must be alone on its line, this is probably not a label
1336
- if (!this.checkAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
1416
+ if (!this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1337
1417
  //rewind and cancel
1338
1418
  this.current -= 2;
1339
1419
  throw new CancelStatementError();
@@ -1347,7 +1427,7 @@ class Parser {
1347
1427
  gotoStatement() {
1348
1428
  let tokens = {
1349
1429
  goto: this.advance(),
1350
- label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(), lexer_1.TokenKind.Identifier)
1430
+ label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(), TokenKind_1.TokenKind.Identifier)
1351
1431
  };
1352
1432
  return new Statement_1.GotoStatement(tokens);
1353
1433
  }
@@ -1378,7 +1458,7 @@ class Parser {
1378
1458
  this.consumeStatementSeparators(true);
1379
1459
  let startingToken = this.peek();
1380
1460
  const statements = [];
1381
- while (!this.isAtEnd() && !this.checkAny(lexer_1.TokenKind.EndSub, lexer_1.TokenKind.EndFunction, ...terminators)) {
1461
+ while (!this.isAtEnd() && !this.checkAny(TokenKind_1.TokenKind.EndSub, TokenKind_1.TokenKind.EndFunction, ...terminators)) {
1382
1462
  //grab the location of the current token
1383
1463
  let loopCurrent = this.current;
1384
1464
  let dec = this.declaration();
@@ -1394,7 +1474,7 @@ class Parser {
1394
1474
  //something went wrong. reset to the top of the loop
1395
1475
  this.current = loopCurrent;
1396
1476
  //scrap the entire line (hopefully whatever failed has added a diagnostic)
1397
- this.consumeUntil(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Eof);
1477
+ this.consumeUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
1398
1478
  //trash the next token. this prevents an infinite loop. not exactly sure why we need this,
1399
1479
  //but there's already an error in the file being parsed, so just leave this line here
1400
1480
  this.advance();
@@ -1411,8 +1491,8 @@ class Parser {
1411
1491
  //if so, we need to restore the statement separator
1412
1492
  let prev = this.previous().kind;
1413
1493
  let peek = this.peek().kind;
1414
- if ((peek === lexer_1.TokenKind.EndSub || peek === lexer_1.TokenKind.EndFunction) &&
1415
- (prev === lexer_1.TokenKind.Newline || prev === lexer_1.TokenKind.Colon)) {
1494
+ if ((peek === TokenKind_1.TokenKind.EndSub || peek === TokenKind_1.TokenKind.EndFunction) &&
1495
+ (prev === TokenKind_1.TokenKind.Newline || prev === TokenKind_1.TokenKind.Colon)) {
1416
1496
  this.current--;
1417
1497
  }
1418
1498
  }
@@ -1444,13 +1524,15 @@ class Parser {
1444
1524
  this.pendingAnnotations = parentAnnotations;
1445
1525
  }
1446
1526
  expression() {
1447
- return this.anonymousFunction();
1527
+ const expression = this.anonymousFunction();
1528
+ this._references.expressions.add(expression);
1529
+ return expression;
1448
1530
  }
1449
1531
  anonymousFunction() {
1450
- if (this.checkAny(lexer_1.TokenKind.Sub, lexer_1.TokenKind.Function)) {
1532
+ if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
1451
1533
  const func = this.functionDeclaration(true);
1452
1534
  //if there's an open paren after this, this is an IIFE
1453
- if (this.check(lexer_1.TokenKind.LeftParen)) {
1535
+ if (this.check(TokenKind_1.TokenKind.LeftParen)) {
1454
1536
  return this.finishCall(this.advance(), func);
1455
1537
  }
1456
1538
  else {
@@ -1458,10 +1540,10 @@ class Parser {
1458
1540
  }
1459
1541
  }
1460
1542
  let expr = this.boolean();
1461
- if (this.check(lexer_1.TokenKind.Question)) {
1543
+ if (this.check(TokenKind_1.TokenKind.Question)) {
1462
1544
  return this.ternaryExpression(expr);
1463
1545
  }
1464
- else if (this.check(lexer_1.TokenKind.QuestionQuestion)) {
1546
+ else if (this.check(TokenKind_1.TokenKind.QuestionQuestion)) {
1465
1547
  return this.nullCoalescingExpression(expr);
1466
1548
  }
1467
1549
  else {
@@ -1470,7 +1552,7 @@ class Parser {
1470
1552
  }
1471
1553
  boolean() {
1472
1554
  let expr = this.relational();
1473
- while (this.matchAny(lexer_1.TokenKind.And, lexer_1.TokenKind.Or)) {
1555
+ while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
1474
1556
  let operator = this.previous();
1475
1557
  let right = this.relational();
1476
1558
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1479,7 +1561,7 @@ class Parser {
1479
1561
  }
1480
1562
  relational() {
1481
1563
  let expr = this.additive();
1482
- 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)) {
1564
+ 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)) {
1483
1565
  let operator = this.previous();
1484
1566
  let right = this.additive();
1485
1567
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1489,7 +1571,7 @@ class Parser {
1489
1571
  // TODO: bitshift
1490
1572
  additive() {
1491
1573
  let expr = this.multiplicative();
1492
- while (this.matchAny(lexer_1.TokenKind.Plus, lexer_1.TokenKind.Minus)) {
1574
+ while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
1493
1575
  let operator = this.previous();
1494
1576
  let right = this.multiplicative();
1495
1577
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1498,7 +1580,7 @@ class Parser {
1498
1580
  }
1499
1581
  multiplicative() {
1500
1582
  let expr = this.exponential();
1501
- 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)) {
1583
+ 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)) {
1502
1584
  let operator = this.previous();
1503
1585
  let right = this.exponential();
1504
1586
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1507,7 +1589,7 @@ class Parser {
1507
1589
  }
1508
1590
  exponential() {
1509
1591
  let expr = this.prefixUnary();
1510
- while (this.match(lexer_1.TokenKind.Caret)) {
1592
+ while (this.match(TokenKind_1.TokenKind.Caret)) {
1511
1593
  let operator = this.previous();
1512
1594
  let right = this.prefixUnary();
1513
1595
  expr = new Expression_1.BinaryExpression(expr, operator, right);
@@ -1516,7 +1598,7 @@ class Parser {
1516
1598
  }
1517
1599
  prefixUnary() {
1518
1600
  const nextKind = this.peek().kind;
1519
- if (nextKind === lexer_1.TokenKind.Not || nextKind === lexer_1.TokenKind.Minus) {
1601
+ if (nextKind === TokenKind_1.TokenKind.Not || nextKind === TokenKind_1.TokenKind.Minus) {
1520
1602
  this.current++; //advance
1521
1603
  let operator = this.previous();
1522
1604
  let right = this.prefixUnary();
@@ -1526,17 +1608,17 @@ class Parser {
1526
1608
  }
1527
1609
  indexedGet(expr) {
1528
1610
  let openingSquare = this.previous();
1529
- while (this.match(lexer_1.TokenKind.Newline)) { }
1611
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1530
1612
  let index = this.expression();
1531
- while (this.match(lexer_1.TokenKind.Newline)) { }
1532
- let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), lexer_1.TokenKind.RightSquareBracket);
1613
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1614
+ let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
1533
1615
  return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare);
1534
1616
  }
1535
1617
  newExpression() {
1536
1618
  this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
1537
1619
  let newToken = this.advance();
1538
1620
  let nameExpr = this.getNamespacedVariableNameExpression();
1539
- let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), lexer_1.TokenKind.LeftParen);
1621
+ let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.LeftParen);
1540
1622
  let call = this.finishCall(leftParen, nameExpr);
1541
1623
  //pop the call from the callExpressions list because this is technically something else
1542
1624
  this.callExpressions.pop();
@@ -1550,46 +1632,52 @@ class Parser {
1550
1632
  callfunc(callee) {
1551
1633
  this.warnIfNotBrighterScriptMode('callfunc operator');
1552
1634
  let operator = this.previous();
1553
- let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1635
+ let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1554
1636
  // force it into an identifier so the AST makes some sense
1555
- methodName.kind = lexer_1.TokenKind.Identifier;
1556
- let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(), lexer_1.TokenKind.LeftParen);
1637
+ methodName.kind = TokenKind_1.TokenKind.Identifier;
1638
+ let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(), TokenKind_1.TokenKind.LeftParen);
1557
1639
  let call = this.finishCall(openParen, callee, false);
1558
1640
  return new Expression_1.CallfuncExpression(callee, operator, methodName, openParen, call.args, call.closingParen);
1559
1641
  }
1560
1642
  call() {
1561
- if (this.check(lexer_1.TokenKind.New) && this.checkAnyNext(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
1643
+ if (this.check(TokenKind_1.TokenKind.New) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
1562
1644
  return this.newExpression();
1563
1645
  }
1564
1646
  let expr = this.primary();
1647
+ //an expression to keep for _references
1648
+ let referenceCallExpression;
1565
1649
  while (true) {
1566
- if (this.match(lexer_1.TokenKind.LeftParen)) {
1650
+ if (this.match(TokenKind_1.TokenKind.LeftParen)) {
1567
1651
  expr = this.finishCall(this.previous(), expr);
1652
+ //store this call expression in references
1653
+ referenceCallExpression = expr;
1568
1654
  }
1569
- else if (this.match(lexer_1.TokenKind.LeftSquareBracket)) {
1655
+ else if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
1570
1656
  expr = this.indexedGet(expr);
1571
1657
  }
1572
- else if (this.match(lexer_1.TokenKind.Callfunc)) {
1658
+ else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
1573
1659
  expr = this.callfunc(expr);
1660
+ //store this callfunc expression in references
1661
+ referenceCallExpression = expr;
1574
1662
  }
1575
- else if (this.match(lexer_1.TokenKind.Dot)) {
1576
- if (this.match(lexer_1.TokenKind.LeftSquareBracket)) {
1663
+ else if (this.match(TokenKind_1.TokenKind.Dot)) {
1664
+ if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
1577
1665
  expr = this.indexedGet(expr);
1578
1666
  }
1579
1667
  else {
1580
1668
  let dot = this.previous();
1581
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1669
+ let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1582
1670
  // force it into an identifier so the AST makes some sense
1583
- name.kind = lexer_1.TokenKind.Identifier;
1671
+ name.kind = TokenKind_1.TokenKind.Identifier;
1584
1672
  expr = new Expression_1.DottedGetExpression(expr, name, dot);
1585
1673
  this.addPropertyHints(name);
1586
1674
  }
1587
1675
  }
1588
- else if (this.check(lexer_1.TokenKind.At)) {
1676
+ else if (this.check(TokenKind_1.TokenKind.At)) {
1589
1677
  let dot = this.advance();
1590
- let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties);
1678
+ let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
1591
1679
  // force it into an identifier so the AST makes some sense
1592
- name.kind = lexer_1.TokenKind.Identifier;
1680
+ name.kind = TokenKind_1.TokenKind.Identifier;
1593
1681
  expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
1594
1682
  //only allow a single `@` expression
1595
1683
  break;
@@ -1598,24 +1686,28 @@ class Parser {
1598
1686
  break;
1599
1687
  }
1600
1688
  }
1689
+ //if we found a callExpression, add it to `expressions` in references
1690
+ if (referenceCallExpression) {
1691
+ this._references.expressions.add(referenceCallExpression);
1692
+ }
1601
1693
  return expr;
1602
1694
  }
1603
1695
  finishCall(openingParen, callee, addToCallExpressionList = true) {
1604
1696
  let args = [];
1605
- while (this.match(lexer_1.TokenKind.Newline)) {
1697
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1606
1698
  }
1607
- if (!this.check(lexer_1.TokenKind.RightParen)) {
1699
+ if (!this.check(TokenKind_1.TokenKind.RightParen)) {
1608
1700
  do {
1609
- while (this.match(lexer_1.TokenKind.Newline)) { }
1701
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1610
1702
  if (args.length >= Expression_1.CallExpression.MaximumArguments) {
1611
1703
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
1612
1704
  throw this.lastDiagnosticAsError();
1613
1705
  }
1614
1706
  args.push(this.expression());
1615
- } while (this.match(lexer_1.TokenKind.Comma));
1707
+ } while (this.match(TokenKind_1.TokenKind.Comma));
1616
1708
  }
1617
- while (this.match(lexer_1.TokenKind.Newline)) { }
1618
- const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), lexer_1.TokenKind.RightParen);
1709
+ while (this.match(TokenKind_1.TokenKind.Newline)) { }
1710
+ const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
1619
1711
  if ((0, reflection_1.isVariableExpression)(callee)) {
1620
1712
  callee.isCalled = true;
1621
1713
  }
@@ -1632,7 +1724,7 @@ class Parser {
1632
1724
  */
1633
1725
  typeToken() {
1634
1726
  let typeToken;
1635
- if (this.checkAny(...lexer_1.DeclarableTypes)) {
1727
+ if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
1636
1728
  // Token is a built in type
1637
1729
  typeToken = this.advance();
1638
1730
  }
@@ -1640,7 +1732,7 @@ class Parser {
1640
1732
  try {
1641
1733
  // see if we can get a namespaced identifer
1642
1734
  const qualifiedType = this.getNamespacedVariableNameExpression();
1643
- typeToken = (0, creators_1.createToken)(lexer_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
1735
+ typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
1644
1736
  }
1645
1737
  catch (_a) {
1646
1738
  //could not get an identifier - just get whatever's next
@@ -1655,53 +1747,53 @@ class Parser {
1655
1747
  }
1656
1748
  primary() {
1657
1749
  switch (true) {
1658
- 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):
1750
+ 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):
1659
1751
  return new Expression_1.LiteralExpression(this.previous());
1660
1752
  //capture source literals (LINE_NUM if brightscript, or a bunch of them if brighterscript)
1661
- case this.matchAny(lexer_1.TokenKind.LineNumLiteral, ...(this.options.mode === ParseMode.BrightScript ? [] : lexer_1.BrighterScriptSourceLiterals)):
1753
+ case this.matchAny(TokenKind_1.TokenKind.LineNumLiteral, ...(this.options.mode === ParseMode.BrightScript ? [] : TokenKind_1.BrighterScriptSourceLiterals)):
1662
1754
  return new Expression_1.SourceLiteralExpression(this.previous());
1663
1755
  //template string
1664
- case this.check(lexer_1.TokenKind.BackTick):
1756
+ case this.check(TokenKind_1.TokenKind.BackTick):
1665
1757
  return this.templateString(false);
1666
1758
  //tagged template string (currently we do not support spaces between the identifier and the backtick)
1667
- case this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedLocalIdentifiers) && this.checkNext(lexer_1.TokenKind.BackTick):
1759
+ case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
1668
1760
  return this.templateString(true);
1669
- case this.matchAny(lexer_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
1761
+ case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
1670
1762
  return new Expression_1.VariableExpression(this.previous(), this.currentNamespaceName);
1671
- case this.match(lexer_1.TokenKind.LeftParen):
1763
+ case this.match(TokenKind_1.TokenKind.LeftParen):
1672
1764
  let left = this.previous();
1673
1765
  let expr = this.expression();
1674
- let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), lexer_1.TokenKind.RightParen);
1766
+ let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), TokenKind_1.TokenKind.RightParen);
1675
1767
  return new Expression_1.GroupingExpression({ left: left, right: right }, expr);
1676
- case this.match(lexer_1.TokenKind.LeftSquareBracket):
1768
+ case this.match(TokenKind_1.TokenKind.LeftSquareBracket):
1677
1769
  let elements = [];
1678
1770
  let openingSquare = this.previous();
1679
1771
  //add any comment found right after the opening square
1680
- if (this.check(lexer_1.TokenKind.Comment)) {
1772
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
1681
1773
  elements.push(new Statement_1.CommentStatement([this.advance()]));
1682
1774
  }
1683
- while (this.match(lexer_1.TokenKind.Newline)) {
1775
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1684
1776
  }
1685
- if (!this.match(lexer_1.TokenKind.RightSquareBracket)) {
1777
+ if (!this.match(TokenKind_1.TokenKind.RightSquareBracket)) {
1686
1778
  elements.push(this.expression());
1687
- while (this.matchAny(lexer_1.TokenKind.Comma, lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment)) {
1688
- if (this.checkPrevious(lexer_1.TokenKind.Comment) || this.check(lexer_1.TokenKind.Comment)) {
1689
- let comment = this.check(lexer_1.TokenKind.Comment) ? this.advance() : this.previous();
1779
+ while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
1780
+ if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
1781
+ let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
1690
1782
  elements.push(new Statement_1.CommentStatement([comment]));
1691
1783
  }
1692
- while (this.match(lexer_1.TokenKind.Newline)) {
1784
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1693
1785
  }
1694
- if (this.check(lexer_1.TokenKind.RightSquareBracket)) {
1786
+ if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1695
1787
  break;
1696
1788
  }
1697
1789
  elements.push(this.expression());
1698
1790
  }
1699
- this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), lexer_1.TokenKind.RightSquareBracket);
1791
+ this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
1700
1792
  }
1701
1793
  let closingSquare = this.previous();
1702
1794
  //this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
1703
1795
  return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
1704
- case this.match(lexer_1.TokenKind.LeftCurlyBrace):
1796
+ case this.match(TokenKind_1.TokenKind.LeftCurlyBrace):
1705
1797
  let openingBrace = this.previous();
1706
1798
  let members = [];
1707
1799
  let key = () => {
@@ -1710,25 +1802,25 @@ class Parser {
1710
1802
  keyToken: null,
1711
1803
  range: null
1712
1804
  };
1713
- if (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties)) {
1805
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
1714
1806
  result.keyToken = this.advance();
1715
1807
  }
1716
- else if (this.check(lexer_1.TokenKind.StringLiteral)) {
1808
+ else if (this.check(TokenKind_1.TokenKind.StringLiteral)) {
1717
1809
  result.keyToken = this.advance();
1718
1810
  }
1719
1811
  else {
1720
1812
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedAAKey()), { range: this.peek().range }));
1721
1813
  throw this.lastDiagnosticAsError();
1722
1814
  }
1723
- result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(), lexer_1.TokenKind.Colon);
1815
+ result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(), TokenKind_1.TokenKind.Colon);
1724
1816
  result.range = util_1.util.getRange(result.keyToken, result.colonToken);
1725
1817
  return result;
1726
1818
  };
1727
- while (this.match(lexer_1.TokenKind.Newline)) {
1819
+ while (this.match(TokenKind_1.TokenKind.Newline)) {
1728
1820
  }
1729
- if (!this.match(lexer_1.TokenKind.RightCurlyBrace)) {
1821
+ if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
1730
1822
  let lastAAMember;
1731
- if (this.check(lexer_1.TokenKind.Comment)) {
1823
+ if (this.check(TokenKind_1.TokenKind.Comment)) {
1732
1824
  lastAAMember = null;
1733
1825
  members.push(new Statement_1.CommentStatement([this.advance()]));
1734
1826
  }
@@ -1738,26 +1830,26 @@ class Parser {
1738
1830
  lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
1739
1831
  members.push(lastAAMember);
1740
1832
  }
1741
- while (this.matchAny(lexer_1.TokenKind.Comma, lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Comment)) {
1833
+ while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
1742
1834
  // collect comma at end of expression
1743
- if (lastAAMember && this.checkPrevious(lexer_1.TokenKind.Comma)) {
1835
+ if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
1744
1836
  lastAAMember.commaToken = this.previous();
1745
1837
  }
1746
1838
  //check for comment at the end of the current line
1747
- if (this.check(lexer_1.TokenKind.Comment) || this.checkPrevious(lexer_1.TokenKind.Comment)) {
1748
- let token = this.checkPrevious(lexer_1.TokenKind.Comment) ? this.previous() : this.advance();
1839
+ if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1840
+ let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1749
1841
  members.push(new Statement_1.CommentStatement([token]));
1750
1842
  }
1751
1843
  else {
1752
1844
  this.consumeStatementSeparators(true);
1753
1845
  //check for a comment on its own line
1754
- if (this.check(lexer_1.TokenKind.Comment) || this.checkPrevious(lexer_1.TokenKind.Comment)) {
1755
- let token = this.checkPrevious(lexer_1.TokenKind.Comment) ? this.previous() : this.advance();
1846
+ if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
1847
+ let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
1756
1848
  lastAAMember = null;
1757
1849
  members.push(new Statement_1.CommentStatement([token]));
1758
1850
  continue;
1759
1851
  }
1760
- if (this.check(lexer_1.TokenKind.RightCurlyBrace)) {
1852
+ if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
1761
1853
  break;
1762
1854
  }
1763
1855
  let k = key();
@@ -1766,22 +1858,22 @@ class Parser {
1766
1858
  members.push(lastAAMember);
1767
1859
  }
1768
1860
  }
1769
- this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), lexer_1.TokenKind.RightCurlyBrace);
1861
+ this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), TokenKind_1.TokenKind.RightCurlyBrace);
1770
1862
  }
1771
1863
  let closingBrace = this.previous();
1772
1864
  const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace);
1773
1865
  this.addPropertyHints(aaExpr);
1774
1866
  return aaExpr;
1775
- case this.matchAny(lexer_1.TokenKind.Pos, lexer_1.TokenKind.Tab):
1867
+ case this.matchAny(TokenKind_1.TokenKind.Pos, TokenKind_1.TokenKind.Tab):
1776
1868
  let token = Object.assign(this.previous(), {
1777
- kind: lexer_1.TokenKind.Identifier
1869
+ kind: TokenKind_1.TokenKind.Identifier
1778
1870
  });
1779
1871
  return new Expression_1.VariableExpression(token, this.currentNamespaceName);
1780
- case this.checkAny(lexer_1.TokenKind.Function, lexer_1.TokenKind.Sub):
1872
+ case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
1781
1873
  return this.anonymousFunction();
1782
- case this.check(lexer_1.TokenKind.RegexLiteral):
1874
+ case this.check(TokenKind_1.TokenKind.RegexLiteral):
1783
1875
  return this.regexLiteralExpression();
1784
- case this.check(lexer_1.TokenKind.Comment):
1876
+ case this.check(TokenKind_1.TokenKind.Comment):
1785
1877
  return new Statement_1.CommentStatement([this.advance()]);
1786
1878
  default:
1787
1879
  //if we found an expected terminator, don't throw a diagnostic...just return undefined
@@ -1851,12 +1943,12 @@ class Parser {
1851
1943
  }
1852
1944
  consumeStatementSeparators(optional = false) {
1853
1945
  //a comment or EOF mark the end of the statement
1854
- if (this.isAtEnd() || this.check(lexer_1.TokenKind.Comment)) {
1946
+ if (this.isAtEnd() || this.check(TokenKind_1.TokenKind.Comment)) {
1855
1947
  return true;
1856
1948
  }
1857
1949
  let consumed = false;
1858
1950
  //consume any newlines and colons
1859
- while (this.matchAny(lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon)) {
1951
+ while (this.matchAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
1860
1952
  consumed = true;
1861
1953
  }
1862
1954
  if (!optional && !consumed) {
@@ -1872,7 +1964,7 @@ class Parser {
1872
1964
  }
1873
1965
  checkEndOfStatement() {
1874
1966
  const nextKind = this.peek().kind;
1875
- return [lexer_1.TokenKind.Colon, lexer_1.TokenKind.Newline, lexer_1.TokenKind.Comment, lexer_1.TokenKind.Eof].includes(nextKind);
1967
+ return [TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Eof].includes(nextKind);
1876
1968
  }
1877
1969
  checkPrevious(tokenKind) {
1878
1970
  var _a;
@@ -1880,14 +1972,14 @@ class Parser {
1880
1972
  }
1881
1973
  check(tokenKind) {
1882
1974
  const nextKind = this.peek().kind;
1883
- if (nextKind === lexer_1.TokenKind.Eof) {
1975
+ if (nextKind === TokenKind_1.TokenKind.Eof) {
1884
1976
  return false;
1885
1977
  }
1886
1978
  return nextKind === tokenKind;
1887
1979
  }
1888
1980
  checkAny(...tokenKinds) {
1889
1981
  const nextKind = this.peek().kind;
1890
- if (nextKind === lexer_1.TokenKind.Eof) {
1982
+ if (nextKind === TokenKind_1.TokenKind.Eof) {
1891
1983
  return false;
1892
1984
  }
1893
1985
  return tokenKinds.includes(nextKind);
@@ -1906,7 +1998,7 @@ class Parser {
1906
1998
  return tokenKinds.includes(nextKind);
1907
1999
  }
1908
2000
  isAtEnd() {
1909
- return this.peek().kind === lexer_1.TokenKind.Eof;
2001
+ return this.peek().kind === TokenKind_1.TokenKind.Eof;
1910
2002
  }
1911
2003
  peekNext() {
1912
2004
  if (this.isAtEnd()) {
@@ -1928,16 +2020,16 @@ class Parser {
1928
2020
  return;
1929
2021
  }
1930
2022
  switch (this.peek().kind) { //eslint-disable-line @typescript-eslint/switch-exhaustiveness-check
1931
- case lexer_1.TokenKind.Namespace:
1932
- case lexer_1.TokenKind.Class:
1933
- case lexer_1.TokenKind.Function:
1934
- case lexer_1.TokenKind.Sub:
1935
- case lexer_1.TokenKind.If:
1936
- case lexer_1.TokenKind.For:
1937
- case lexer_1.TokenKind.ForEach:
1938
- case lexer_1.TokenKind.While:
1939
- case lexer_1.TokenKind.Print:
1940
- case lexer_1.TokenKind.Return:
2023
+ case TokenKind_1.TokenKind.Namespace:
2024
+ case TokenKind_1.TokenKind.Class:
2025
+ case TokenKind_1.TokenKind.Function:
2026
+ case TokenKind_1.TokenKind.Sub:
2027
+ case TokenKind_1.TokenKind.If:
2028
+ case TokenKind_1.TokenKind.For:
2029
+ case TokenKind_1.TokenKind.ForEach:
2030
+ case TokenKind_1.TokenKind.While:
2031
+ case TokenKind_1.TokenKind.Print:
2032
+ case TokenKind_1.TokenKind.Return:
1941
2033
  // start parsing again from the next block starter or obvious
1942
2034
  // expression start
1943
2035
  return;
@@ -1952,13 +2044,55 @@ class Parser {
1952
2044
  */
1953
2045
  findReferences() {
1954
2046
  this._references = new References();
2047
+ const excludedExpressions = new Set();
2048
+ const visitCallExpression = (e) => {
2049
+ for (const p of e.args) {
2050
+ this._references.expressions.add(p);
2051
+ }
2052
+ //add calls that were not excluded (from loop below)
2053
+ if (!excludedExpressions.has(e)) {
2054
+ this._references.expressions.add(e);
2055
+ }
2056
+ //if this call is part of a longer expression that includes a call higher up, find that higher one and remove it
2057
+ if (e.callee) {
2058
+ let node = e.callee;
2059
+ while (node) {
2060
+ //the primary goal for this loop. If we found a parent call expression, remove it from `references`
2061
+ if ((0, reflection_1.isCallExpression)(node)) {
2062
+ this.references.expressions.delete(node);
2063
+ excludedExpressions.add(node);
2064
+ //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.
2065
+ break;
2066
+ //when we hit a variable expression, we're definitely at the leftmost expression so stop
2067
+ }
2068
+ else if ((0, reflection_1.isVariableExpression)(node)) {
2069
+ break;
2070
+ //if
2071
+ }
2072
+ else if ((0, reflection_1.isDottedGetExpression)(node) || (0, reflection_1.isIndexedGetExpression)(node)) {
2073
+ node = node.obj;
2074
+ }
2075
+ else {
2076
+ //some expression we don't understand. log it and quit the loop
2077
+ this.logger.info('Encountered unknown expression while calculating function expression chain', node);
2078
+ break;
2079
+ }
2080
+ }
2081
+ }
2082
+ };
1955
2083
  this.ast.walk((0, visitors_1.createVisitor)({
1956
2084
  AssignmentStatement: s => {
1957
2085
  this._references.assignmentStatements.push(s);
2086
+ this.references.expressions.add(s.value);
1958
2087
  },
1959
2088
  ClassStatement: s => {
1960
2089
  this._references.classStatements.push(s);
1961
2090
  },
2091
+ ClassFieldStatement: s => {
2092
+ if (s.initialValue) {
2093
+ this._references.expressions.add(s.initialValue);
2094
+ }
2095
+ },
1962
2096
  NamespaceStatement: s => {
1963
2097
  this._references.namespaceStatements.push(s);
1964
2098
  },
@@ -1978,15 +2112,50 @@ class Parser {
1978
2112
  },
1979
2113
  NewExpression: e => {
1980
2114
  this._references.newExpressions.push(e);
2115
+ for (const p of e.call.args) {
2116
+ this._references.expressions.add(p);
2117
+ }
2118
+ },
2119
+ ExpressionStatement: s => {
2120
+ this._references.expressions.add(s.expression);
2121
+ },
2122
+ CallfuncExpression: e => {
2123
+ visitCallExpression(e);
2124
+ },
2125
+ CallExpression: e => {
2126
+ visitCallExpression(e);
1981
2127
  },
1982
2128
  AALiteralExpression: e => {
1983
2129
  this.addPropertyHints(e);
2130
+ this._references.expressions.add(e);
2131
+ for (const member of e.elements) {
2132
+ if ((0, reflection_1.isAAMemberExpression)(member)) {
2133
+ this._references.expressions.add(member.value);
2134
+ }
2135
+ }
2136
+ },
2137
+ ArrayLiteralExpression: e => {
2138
+ for (const element of e.elements) {
2139
+ //keep everything except comments
2140
+ if (!(0, reflection_1.isCommentStatement)(element)) {
2141
+ this._references.expressions.add(element);
2142
+ }
2143
+ }
1984
2144
  },
1985
2145
  DottedGetExpression: e => {
1986
2146
  this.addPropertyHints(e.name);
1987
2147
  },
1988
2148
  DottedSetStatement: e => {
1989
2149
  this.addPropertyHints(e.name);
2150
+ },
2151
+ EnumStatement: e => {
2152
+ this._references.enumStatements.push(e);
2153
+ },
2154
+ UnaryExpression: e => {
2155
+ this._references.expressions.add(e);
2156
+ },
2157
+ IncrementStatement: e => {
2158
+ this._references.expressions.add(e);
1990
2159
  }
1991
2160
  }), {
1992
2161
  walkMode: visitors_1.WalkMode.visitAllRecursive
@@ -2003,11 +2172,24 @@ var ParseMode;
2003
2172
  })(ParseMode = exports.ParseMode || (exports.ParseMode = {}));
2004
2173
  class References {
2005
2174
  constructor() {
2175
+ this.cache = new Cache_1.Cache();
2006
2176
  this.assignmentStatements = [];
2007
2177
  this.classStatements = [];
2008
2178
  this.functionExpressions = [];
2009
2179
  this.functionStatements = [];
2010
2180
  this.interfaceStatements = [];
2181
+ this.enumStatements = [];
2182
+ /**
2183
+ * A collection of full expressions. This excludes intermediary expressions.
2184
+ *
2185
+ * Example 1:
2186
+ * `a.b.c` is composed of `a` (variableExpression) `.b` (DottedGetExpression) `.c` (DottedGetExpression)
2187
+ * This will only contain the final `.c` DottedGetExpression because `.b` and `a` can both be derived by walking back from the `.c` DottedGetExpression.
2188
+ *
2189
+ * Example 2:
2190
+ * `name.space.doSomething(a.b.c)` will result in 2 entries in this list. the `CallExpression` for `doSomething`, and the `.c` DottedGetExpression.
2191
+ */
2192
+ this.expressions = new Set();
2011
2193
  this.importStatements = [];
2012
2194
  this.libraryStatements = [];
2013
2195
  this.namespaceStatements = [];
@@ -2044,6 +2226,15 @@ class References {
2044
2226
  }
2045
2227
  return this._interfaceStatementLookup;
2046
2228
  }
2229
+ get enumStatementLookup() {
2230
+ return this.cache.getOrAdd('enums', () => {
2231
+ const result = new Map();
2232
+ for (const stmt of this.enumStatements) {
2233
+ result.set(stmt.fullName.toLowerCase(), stmt);
2234
+ }
2235
+ return result;
2236
+ });
2237
+ }
2047
2238
  }
2048
2239
  exports.References = References;
2049
2240
  class CancelStatementError extends Error {