brighterscript 1.0.0-alpha.14 → 1.0.0-alpha.17

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 (151) hide show
  1. package/CHANGELOG.md +83 -1
  2. package/README.md +28 -9
  3. package/dist/Cache.d.ts +2 -7
  4. package/dist/Cache.js +4 -13
  5. package/dist/Cache.js.map +1 -1
  6. package/dist/DependencyGraph.js +5 -4
  7. package/dist/DependencyGraph.js.map +1 -1
  8. package/dist/DiagnosticMessages.d.ts +21 -1
  9. package/dist/DiagnosticMessages.js +21 -1
  10. package/dist/DiagnosticMessages.js.map +1 -1
  11. package/dist/Logger.js +5 -5
  12. package/dist/Logger.js.map +1 -1
  13. package/dist/Program.d.ts +3 -3
  14. package/dist/Program.js +9 -7
  15. package/dist/Program.js.map +1 -1
  16. package/dist/ProgramBuilder.js +1 -1
  17. package/dist/ProgramBuilder.js.map +1 -1
  18. package/dist/Scope.d.ts +16 -11
  19. package/dist/Scope.js +42 -12
  20. package/dist/Scope.js.map +1 -1
  21. package/dist/XmlScope.d.ts +3 -3
  22. package/dist/XmlScope.js +1 -1
  23. package/dist/XmlScope.js.map +1 -1
  24. package/dist/astUtils/AstEditor.d.ts +6 -0
  25. package/dist/astUtils/AstEditor.js +10 -0
  26. package/dist/astUtils/AstEditor.js.map +1 -1
  27. package/dist/astUtils/AstEditor.spec.js +37 -0
  28. package/dist/astUtils/AstEditor.spec.js.map +1 -1
  29. package/dist/astUtils/creators.d.ts +10 -6
  30. package/dist/astUtils/creators.js +93 -12
  31. package/dist/astUtils/creators.js.map +1 -1
  32. package/dist/astUtils/creators.spec.js +10 -0
  33. package/dist/astUtils/creators.spec.js.map +1 -1
  34. package/dist/astUtils/reflection.d.ts +7 -2
  35. package/dist/astUtils/reflection.js +19 -3
  36. package/dist/astUtils/reflection.js.map +1 -1
  37. package/dist/astUtils/reflection.spec.js +5 -4
  38. package/dist/astUtils/reflection.spec.js.map +1 -1
  39. package/dist/astUtils/visitors.d.ts +3 -1
  40. package/dist/astUtils/visitors.js.map +1 -1
  41. package/dist/astUtils/visitors.spec.js +2 -0
  42. package/dist/astUtils/visitors.spec.js.map +1 -1
  43. package/dist/bscPlugin/BscPlugin.d.ts +4 -1
  44. package/dist/bscPlugin/BscPlugin.js +16 -0
  45. package/dist/bscPlugin/BscPlugin.js.map +1 -1
  46. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +1 -0
  47. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +38 -2
  48. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
  49. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +28 -0
  50. package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
  51. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
  52. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +40 -0
  53. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
  54. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.d.ts +1 -0
  55. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +32 -0
  56. package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +1 -0
  57. package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
  58. package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
  59. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
  60. package/dist/bscPlugin/validation/ScopeValidator.d.ts +11 -0
  61. package/dist/bscPlugin/validation/ScopeValidator.js +94 -0
  62. package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
  63. package/dist/diagnosticUtils.js +3 -3
  64. package/dist/diagnosticUtils.js.map +1 -1
  65. package/dist/examples/plugins/removePrint.js +12 -14
  66. package/dist/examples/plugins/removePrint.js.map +1 -1
  67. package/dist/files/BrsFile.Class.spec.js +22 -23
  68. package/dist/files/BrsFile.Class.spec.js.map +1 -1
  69. package/dist/files/BrsFile.d.ts +10 -3
  70. package/dist/files/BrsFile.js +133 -49
  71. package/dist/files/BrsFile.js.map +1 -1
  72. package/dist/files/BrsFile.spec.js +299 -123
  73. package/dist/files/BrsFile.spec.js.map +1 -1
  74. package/dist/files/XmlFile.d.ts +5 -5
  75. package/dist/files/XmlFile.js +3 -3
  76. package/dist/files/XmlFile.js.map +1 -1
  77. package/dist/files/XmlFile.spec.js +9 -9
  78. package/dist/files/XmlFile.spec.js.map +1 -1
  79. package/dist/interfaces.d.ts +29 -37
  80. package/dist/lexer/Lexer.spec.js +8 -0
  81. package/dist/lexer/Lexer.spec.js.map +1 -1
  82. package/dist/lexer/TokenKind.d.ts +2 -0
  83. package/dist/lexer/TokenKind.js +5 -0
  84. package/dist/lexer/TokenKind.js.map +1 -1
  85. package/dist/parser/Expression.d.ts +85 -21
  86. package/dist/parser/Expression.js +177 -53
  87. package/dist/parser/Expression.js.map +1 -1
  88. package/dist/parser/Parser.Class.spec.js +1 -1
  89. package/dist/parser/Parser.Class.spec.js.map +1 -1
  90. package/dist/parser/Parser.d.ts +12 -3
  91. package/dist/parser/Parser.js +156 -56
  92. package/dist/parser/Parser.js.map +1 -1
  93. package/dist/parser/Parser.spec.js +57 -2
  94. package/dist/parser/Parser.spec.js.map +1 -1
  95. package/dist/parser/Statement.d.ts +94 -30
  96. package/dist/parser/Statement.js +281 -106
  97. package/dist/parser/Statement.js.map +1 -1
  98. package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
  99. package/dist/parser/tests/statement/Enum.spec.js +774 -0
  100. package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
  101. package/dist/parser/tests/statement/For.spec.d.ts +1 -0
  102. package/dist/parser/tests/statement/For.spec.js +46 -0
  103. package/dist/parser/tests/statement/For.spec.js.map +1 -0
  104. package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
  105. package/dist/parser/tests/statement/ForEach.spec.js +37 -0
  106. package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
  107. package/dist/types/BooleanType.d.ts +4 -2
  108. package/dist/types/BooleanType.js +5 -1
  109. package/dist/types/BooleanType.js.map +1 -1
  110. package/dist/types/DoubleType.d.ts +2 -0
  111. package/dist/types/DoubleType.js +5 -1
  112. package/dist/types/DoubleType.js.map +1 -1
  113. package/dist/types/DynamicType.d.ts +2 -0
  114. package/dist/types/DynamicType.js +5 -1
  115. package/dist/types/DynamicType.js.map +1 -1
  116. package/dist/types/FloatType.d.ts +3 -1
  117. package/dist/types/FloatType.js +5 -1
  118. package/dist/types/FloatType.js.map +1 -1
  119. package/dist/types/FunctionType.d.ts +2 -1
  120. package/dist/types/FunctionType.js +11 -8
  121. package/dist/types/FunctionType.js.map +1 -1
  122. package/dist/types/FunctionType.spec.js +6 -0
  123. package/dist/types/FunctionType.spec.js.map +1 -1
  124. package/dist/types/IntegerType.d.ts +3 -1
  125. package/dist/types/IntegerType.js +5 -1
  126. package/dist/types/IntegerType.js.map +1 -1
  127. package/dist/types/InvalidType.d.ts +4 -2
  128. package/dist/types/InvalidType.js +5 -1
  129. package/dist/types/InvalidType.js.map +1 -1
  130. package/dist/types/LongIntegerType.d.ts +3 -1
  131. package/dist/types/LongIntegerType.js +5 -1
  132. package/dist/types/LongIntegerType.js.map +1 -1
  133. package/dist/types/ObjectType.d.ts +2 -1
  134. package/dist/types/ObjectType.js +4 -2
  135. package/dist/types/ObjectType.js.map +1 -1
  136. package/dist/types/StringType.d.ts +4 -2
  137. package/dist/types/StringType.js +5 -1
  138. package/dist/types/StringType.js.map +1 -1
  139. package/dist/types/UninitializedType.js.map +1 -1
  140. package/dist/types/UniversalFunctionType.d.ts +9 -0
  141. package/dist/types/UniversalFunctionType.js +25 -0
  142. package/dist/types/UniversalFunctionType.js.map +1 -0
  143. package/dist/types/VoidType.d.ts +4 -2
  144. package/dist/types/VoidType.js +5 -1
  145. package/dist/types/VoidType.js.map +1 -1
  146. package/dist/util.d.ts +12 -2
  147. package/dist/util.js +74 -44
  148. package/dist/util.js.map +1 -1
  149. package/dist/validators/ClassValidator.js +3 -3
  150. package/dist/validators/ClassValidator.js.map +1 -1
  151. package/package.json +2 -3
@@ -12,11 +12,12 @@ const Logger_1 = require("../Logger");
12
12
  const reflection_1 = require("../astUtils/reflection");
13
13
  const visitors_1 = require("../astUtils/visitors");
14
14
  const creators_1 = require("../astUtils/creators");
15
- const SymbolTable_1 = require("../SymbolTable");
15
+ const Cache_1 = require("../Cache");
16
16
  const DynamicType_1 = require("../types/DynamicType");
17
- const ObjectType_1 = require("../types/ObjectType");
18
17
  const ArrayType_1 = require("../types/ArrayType");
19
18
  const helpers_1 = require("../types/helpers");
19
+ const SymbolTable_1 = require("../SymbolTable");
20
+ const ObjectType_1 = require("../types/ObjectType");
20
21
  class Parser {
21
22
  constructor() {
22
23
  /**
@@ -211,25 +212,46 @@ class Parser {
211
212
  this.synchronize();
212
213
  }
213
214
  }
215
+ /**
216
+ * Try to get an identifier. If not found, add diagnostic and return undefined
217
+ */
218
+ tryIdentifier(...additionalTokenKinds) {
219
+ const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
220
+ if (identifier) {
221
+ // force the name into an identifier so the AST makes some sense
222
+ identifier.kind = TokenKind_1.TokenKind.Identifier;
223
+ return identifier;
224
+ }
225
+ }
214
226
  identifier(...additionalTokenKinds) {
215
227
  const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
216
228
  // force the name into an identifier so the AST makes some sense
217
229
  identifier.kind = TokenKind_1.TokenKind.Identifier;
218
230
  return identifier;
219
231
  }
232
+ enumMemberStatement() {
233
+ const tokens = {};
234
+ let value;
235
+ tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
236
+ //look for `= SOME_EXPRESSION`
237
+ if (this.check(TokenKind_1.TokenKind.Equal)) {
238
+ tokens.equal = this.advance();
239
+ value = this.expression();
240
+ }
241
+ return new Statement_1.EnumMemberStatement(tokens, value);
242
+ }
220
243
  /**
221
244
  * Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration`
222
245
  */
223
246
  interfaceFieldStatement() {
224
247
  const name = this.identifier(...TokenKind_1.AllowedProperties);
225
248
  let asToken = this.consumeToken(TokenKind_1.TokenKind.As);
226
- let typeToken = this.typeToken();
227
- const type = util_1.util.tokenToBscType(typeToken);
228
- if (!type) {
229
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeToken.text)), { range: typeToken.range }));
249
+ let typeExpr = this.typeExpression();
250
+ if (!typeExpr.isValidType()) {
251
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
230
252
  throw this.lastDiagnosticAsError();
231
253
  }
232
- return new Statement_1.InterfaceFieldStatement(name, asToken, typeToken, type);
254
+ return new Statement_1.InterfaceFieldStatement(name, asToken, typeExpr);
233
255
  }
234
256
  /**
235
257
  * Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration()`
@@ -241,17 +263,16 @@ class Parser {
241
263
  const params = [];
242
264
  const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
243
265
  let asToken = null;
244
- let returnTypeToken = null;
266
+ let returnTypeExpr;
245
267
  if (this.check(TokenKind_1.TokenKind.As)) {
246
268
  asToken = this.advance();
247
- returnTypeToken = this.typeToken();
248
- const returnType = util_1.util.tokenToBscType(returnTypeToken);
249
- if (!returnType) {
250
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, returnTypeToken.text)), { range: returnTypeToken.range }));
269
+ returnTypeExpr = this.typeExpression();
270
+ if (!returnTypeExpr.isValidType(this.options.mode)) {
271
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, returnTypeExpr.getText())), { range: returnTypeExpr.range }));
251
272
  throw this.lastDiagnosticAsError();
252
273
  }
253
274
  }
254
- return new Statement_1.InterfaceMethodStatement(functionType, name, leftParen, params, rightParen, asToken, returnTypeToken, util_1.util.tokenToBscType(returnTypeToken));
275
+ return new Statement_1.InterfaceMethodStatement(functionType, name, leftParen, params, rightParen, asToken, returnTypeExpr);
255
276
  }
256
277
  interfaceDeclaration() {
257
278
  this.warnIfNotBrighterScriptMode('interface declarations');
@@ -313,6 +334,57 @@ class Parser {
313
334
  this.exitAnnotationBlock(parentAnnotations);
314
335
  return statement;
315
336
  }
337
+ enumDeclaration() {
338
+ this.warnIfNotBrighterScriptMode('enum declarations');
339
+ const parentAnnotations = this.enterAnnotationBlock();
340
+ const tokens = {};
341
+ const body = [];
342
+ tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
343
+ tokens.name = this.tryIdentifier();
344
+ this.consumeStatementSeparators();
345
+ //gather up all members
346
+ while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
347
+ try {
348
+ let decl;
349
+ //collect leading annotations
350
+ if (this.check(TokenKind_1.TokenKind.At)) {
351
+ this.annotationExpression();
352
+ }
353
+ //members
354
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
355
+ decl = this.enumMemberStatement();
356
+ //comments
357
+ }
358
+ else if (this.check(TokenKind_1.TokenKind.Comment)) {
359
+ decl = this.commentStatement();
360
+ }
361
+ if (decl) {
362
+ this.consumePendingAnnotations(decl);
363
+ body.push(decl);
364
+ }
365
+ else {
366
+ //we didn't find a declaration...flag tokens until next line
367
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
368
+ }
369
+ }
370
+ catch (e) {
371
+ //throw out any failed members and move on to the next line
372
+ this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
373
+ }
374
+ //ensure statement separator
375
+ this.consumeStatementSeparators();
376
+ //break out of this loop if we encountered the `EndEnum` token
377
+ if (this.check(TokenKind_1.TokenKind.EndEnum)) {
378
+ break;
379
+ }
380
+ }
381
+ //consume the final `end interface` token
382
+ tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
383
+ const result = new Statement_1.EnumStatement(tokens, body, this.currentNamespaceName);
384
+ this._references.enumStatements.push(result);
385
+ this.exitAnnotationBlock(parentAnnotations);
386
+ return result;
387
+ }
316
388
  /**
317
389
  * A BrighterScript class declaration
318
390
  */
@@ -360,6 +432,8 @@ class Parser {
360
432
  decl = new Statement_1.ClassMethodStatement(accessModifier, funcDeclaration.name, funcDeclaration.func, overrideKeyword);
361
433
  //refer to this statement as parent of the expression
362
434
  functionStatement.func.functionStatement = decl;
435
+ //cache the range property so that plugins can't affect it
436
+ decl.cacheRange();
363
437
  //fields
364
438
  }
365
439
  else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
@@ -400,13 +474,13 @@ class Parser {
400
474
  classFieldDeclaration(accessModifier) {
401
475
  let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
402
476
  let asToken;
403
- let fieldType;
477
+ let fieldTypeExpr;
404
478
  //look for `as SOME_TYPE`
405
479
  if (this.check(TokenKind_1.TokenKind.As)) {
406
480
  asToken = this.advance();
407
- fieldType = this.typeToken();
481
+ fieldTypeExpr = this.typeExpression();
408
482
  //no field type specified
409
- if (!util_1.util.tokenToBscType(fieldType, true, this.currentNamespaceName)) {
483
+ if (!fieldTypeExpr.isValidType(this.options.mode)) {
410
484
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedValidTypeToFollowAsKeyword()), { range: this.peek().range }));
411
485
  }
412
486
  }
@@ -417,7 +491,7 @@ class Parser {
417
491
  equal = this.advance();
418
492
  initialValue = this.expression();
419
493
  }
420
- return new Statement_1.ClassFieldStatement(accessModifier, name, asToken, fieldType, equal, initialValue, this.currentNamespaceName);
494
+ return new Statement_1.ClassFieldStatement(accessModifier, name, asToken, fieldTypeExpr, equal, initialValue, this.currentNamespaceName);
421
495
  }
422
496
  functionDeclaration(isAnonymous, checkIdentifier = true, forClassMethod = false) {
423
497
  var _a, _b, _c, _d;
@@ -467,7 +541,7 @@ class Parser {
467
541
  }
468
542
  let params = [];
469
543
  let asToken;
470
- let typeToken;
544
+ let typeExpr;
471
545
  if (!this.check(TokenKind_1.TokenKind.RightParen)) {
472
546
  do {
473
547
  if (params.length >= Expression_1.CallExpression.MaximumArguments) {
@@ -479,9 +553,9 @@ class Parser {
479
553
  let rightParen = this.advance();
480
554
  if (this.check(TokenKind_1.TokenKind.As)) {
481
555
  asToken = this.advance();
482
- typeToken = this.typeToken();
483
- if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
484
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType((_a = typeToken.text) !== null && _a !== void 0 ? _a : '')), { range: typeToken.range }));
556
+ typeExpr = this.typeExpression();
557
+ if (!typeExpr.isValidType(this.options.mode)) {
558
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType((_a = typeExpr.getText()) !== null && _a !== void 0 ? _a : '')), { range: typeExpr.range }));
485
559
  }
486
560
  }
487
561
  params.reduce((haveFoundOptional, param) => {
@@ -493,7 +567,7 @@ class Parser {
493
567
  this.consumeStatementSeparators(true);
494
568
  let func = new Expression_1.FunctionExpression(params, undefined, //body
495
569
  functionType, undefined, //ending keyword
496
- leftParen, rightParen, asToken, typeToken, //return type
570
+ leftParen, rightParen, asToken, typeExpr, //return type
497
571
  this.currentFunctionExpression, this.currentNamespaceName, (_c = (_b = this.currentNamespace) === null || _b === void 0 ? void 0 : _b.symbolTable) !== null && _c !== void 0 ? _c : this.symbolTable);
498
572
  //if there is a parent function, register this function with the parent
499
573
  if (this.currentFunctionExpression) {
@@ -537,12 +611,16 @@ class Parser {
537
611
  }
538
612
  func.callExpressions = this.callExpressions;
539
613
  if (isAnonymous) {
614
+ //cache the range property so that plugins can't affect it
615
+ func.cacheRange();
540
616
  return func;
541
617
  }
542
618
  else {
543
619
  let result = new Statement_1.FunctionStatement(name, func, this.currentNamespaceName);
544
620
  func.functionStatement = result;
545
621
  this._references.functionStatements.push(result);
622
+ //cache the range property so that plugins can't affect it
623
+ result.cacheRange();
546
624
  return result;
547
625
  }
548
626
  }
@@ -558,7 +636,7 @@ class Parser {
558
636
  throw this.lastDiagnosticAsError();
559
637
  }
560
638
  const name = this.identifier(...TokenKind_1.AllowedLocalIdentifiers);
561
- let typeToken;
639
+ let typeExpr;
562
640
  let defaultValue;
563
641
  let equalsToken;
564
642
  // parse argument default value
@@ -570,26 +648,26 @@ class Parser {
570
648
  let asToken = null;
571
649
  if (this.check(TokenKind_1.TokenKind.As)) {
572
650
  asToken = this.advance();
573
- typeToken = this.typeToken();
574
- if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
575
- this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeToken.text)), { range: typeToken.range }));
651
+ typeExpr = this.typeExpression();
652
+ if (!typeExpr.isValidType(this.options.mode)) {
653
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
576
654
  throw this.lastDiagnosticAsError();
577
655
  }
578
656
  }
579
- let type;
580
- if (typeToken) {
581
- type = util_1.util.tokenToBscType(typeToken, true, this.currentNamespaceName);
657
+ let typeInContext;
658
+ if (typeExpr) {
659
+ typeInContext = typeExpr.type;
582
660
  }
583
661
  else if (defaultValue) {
584
- type = getBscTypeFromExpression(defaultValue, this.currentFunctionExpression);
585
- if ((0, reflection_1.isInvalidType)(type)) {
586
- type = new DynamicType_1.DynamicType();
662
+ typeInContext = getBscTypeFromExpression(defaultValue, this.currentFunctionExpression);
663
+ if ((0, reflection_1.isInvalidType)(typeInContext)) {
664
+ typeInContext = new DynamicType_1.DynamicType();
587
665
  }
588
666
  }
589
667
  else {
590
- type = new DynamicType_1.DynamicType();
668
+ typeInContext = new DynamicType_1.DynamicType();
591
669
  }
592
- return new Expression_1.FunctionParameterExpression(name, type, equalsToken, defaultValue, asToken, typeToken, this.currentNamespaceName);
670
+ return new Expression_1.FunctionParameterExpression(name, typeInContext, equalsToken, defaultValue, asToken, typeExpr, this.currentNamespaceName);
593
671
  }
594
672
  assignment() {
595
673
  let name = this.identifier(...this.allowedLocalIdentifiers);
@@ -709,6 +787,9 @@ class Parser {
709
787
  if (this.check(TokenKind_1.TokenKind.Namespace)) {
710
788
  return this.namespaceStatement();
711
789
  }
790
+ if (this.check(TokenKind_1.TokenKind.Enum)) {
791
+ return this.enumDeclaration();
792
+ }
712
793
  // TODO: support multi-statements
713
794
  return this.setStatement();
714
795
  }
@@ -780,6 +861,12 @@ class Parser {
780
861
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedExpressionAfterForEachIn()), { range: this.peek().range }));
781
862
  throw this.lastDiagnosticAsError();
782
863
  }
864
+ let itemType = new DynamicType_1.DynamicType();
865
+ const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
866
+ if ((0, reflection_1.isArrayType)(targetType)) {
867
+ itemType = targetType.getDefaultType();
868
+ }
869
+ this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
783
870
  this.consumeStatementSeparators();
784
871
  let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
785
872
  if (!body) {
@@ -787,12 +874,6 @@ class Parser {
787
874
  throw this.lastDiagnosticAsError();
788
875
  }
789
876
  let endFor = this.advance();
790
- let itemType = new DynamicType_1.DynamicType();
791
- const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
792
- if ((0, reflection_1.isArrayType)(targetType)) {
793
- itemType = targetType.getDefaultType();
794
- }
795
- this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
796
877
  return new Statement_1.ForEachStatement(forEach, name, maybeIn, target, body, endFor);
797
878
  }
798
879
  exitFor() {
@@ -843,6 +924,8 @@ class Parser {
843
924
  result.body = body;
844
925
  result.endKeyword = endKeyword;
845
926
  this._references.namespaceStatements.push(result);
927
+ //cache the range property so that plugins can't affect it
928
+ result.cacheRange();
846
929
  return result;
847
930
  }
848
931
  /**
@@ -854,7 +937,8 @@ class Parser {
854
937
  if (firstIdentifier) {
855
938
  // force it into an identifier so the AST makes some sense
856
939
  firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
857
- expr = new Expression_1.VariableExpression(firstIdentifier, null);
940
+ const varExpr = new Expression_1.VariableExpression(firstIdentifier, null);
941
+ expr = varExpr;
858
942
  //consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
859
943
  while (this.check(TokenKind_1.TokenKind.Dot)) {
860
944
  let dot = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.Dot);
@@ -924,6 +1008,8 @@ class Parser {
924
1008
  let leftParen = this.advance();
925
1009
  annotation.call = this.finishCall(leftParen, annotation, false);
926
1010
  }
1011
+ //cache the range property so that plugins can't affect it
1012
+ annotation.cacheRange();
927
1013
  return annotation;
928
1014
  }
929
1015
  ternaryExpression(test) {
@@ -1328,12 +1414,10 @@ class Parser {
1328
1414
  if ((0, reflection_1.isIndexedGetExpression)(left)) {
1329
1415
  return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
1330
1416
  ? right
1331
- : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
1417
+ : new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare, operator);
1332
1418
  }
1333
1419
  else if ((0, reflection_1.isDottedGetExpression)(left)) {
1334
- const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
1335
- ? right
1336
- : new Expression_1.BinaryExpression(left, operator, right));
1420
+ const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal ? right : new Expression_1.BinaryExpression(left, operator, right), left.dot, operator);
1337
1421
  this._references.dottedSetStatements.push(dottedSetStmt);
1338
1422
  return dottedSetStmt;
1339
1423
  }
@@ -1687,9 +1771,6 @@ class Parser {
1687
1771
  }
1688
1772
  while (this.match(TokenKind_1.TokenKind.Newline)) { }
1689
1773
  const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
1690
- if ((0, reflection_1.isVariableExpression)(callee)) {
1691
- callee.isCalled = true;
1692
- }
1693
1774
  let expression = new Expression_1.CallExpression(callee, openingParen, closingParen, args, this.currentNamespaceName);
1694
1775
  if (addToCallExpressionList) {
1695
1776
  this.callExpressions.push(expression);
@@ -1701,7 +1782,7 @@ class Parser {
1701
1782
  * Allows for built-in types (double, string, etc.) or namespaced custom types in Brighterscript mode
1702
1783
  * Will return a token of whatever is next to be parsed (unless `advanceIfUnknown` is false, in which case undefined will be returned instead
1703
1784
  */
1704
- typeToken() {
1785
+ typeExpression() {
1705
1786
  let typeToken;
1706
1787
  if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
1707
1788
  // Token is a built in type
@@ -1722,18 +1803,23 @@ class Parser {
1722
1803
  // just get whatever's next
1723
1804
  typeToken = this.advance();
1724
1805
  }
1725
- if (typeToken && this.options.mode === ParseMode.BrighterScript) {
1806
+ //TODO: to support InterfaceTypeLiterals - (eg. `{name as string; age as integer}`), check if "typeToken" is a curly bracket, and do something else
1807
+ let typeExpr = new Expression_1.TypeExpression({ type: typeToken }, this.currentNamespaceName);
1808
+ if (this.options.mode === ParseMode.BrighterScript) {
1726
1809
  // Check if it is an array - that is, if it has `[]` after the type
1727
- // eg. `string[]` or `SomeKlass[]`
1728
- if (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
1729
- this.advance();
1810
+ // eg. `string[]` or `SomeKlass[]` or `float[][][]`
1811
+ while (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
1812
+ const leftBracket = this.advance();
1730
1813
  if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
1731
1814
  const rightBracket = this.advance();
1732
- typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, typeToken.text + '[]', util_1.util.getRange(typeToken, rightBracket));
1815
+ typeExpr = new Expression_1.ArrayTypeExpression([typeExpr], { leftBracket: leftBracket, rightBracket: rightBracket }, this.currentNamespaceName);
1816
+ }
1817
+ else {
1818
+ break;
1733
1819
  }
1734
1820
  }
1735
1821
  }
1736
- return typeToken;
1822
+ return typeExpr;
1737
1823
  }
1738
1824
  primary() {
1739
1825
  switch (true) {
@@ -2369,6 +2455,9 @@ class Parser {
2369
2455
  DottedSetStatement: e => {
2370
2456
  this.addPropertyHints(e.name);
2371
2457
  },
2458
+ EnumStatement: e => {
2459
+ this._references.enumStatements.push(e);
2460
+ },
2372
2461
  UnaryExpression: e => {
2373
2462
  this._references.expressions.add(e);
2374
2463
  },
@@ -2405,6 +2494,7 @@ var ParseMode;
2405
2494
  })(ParseMode = exports.ParseMode || (exports.ParseMode = {}));
2406
2495
  class References {
2407
2496
  constructor() {
2497
+ this.cache = new Cache_1.Cache();
2408
2498
  this.assignmentStatements = [];
2409
2499
  this.classStatements = [];
2410
2500
  this.dottedSetStatements = [];
@@ -2412,6 +2502,7 @@ class References {
2412
2502
  this.functionExpressions = [];
2413
2503
  this.functionStatements = [];
2414
2504
  this.interfaceStatements = [];
2505
+ this.enumStatements = [];
2415
2506
  /**
2416
2507
  * A collection of full expressions. This excludes intermediary expressions.
2417
2508
  *
@@ -2459,6 +2550,15 @@ class References {
2459
2550
  }
2460
2551
  return this._interfaceStatementLookup;
2461
2552
  }
2553
+ get enumStatementLookup() {
2554
+ return this.cache.getOrAdd('enums', () => {
2555
+ const result = new Map();
2556
+ for (const stmt of this.enumStatements) {
2557
+ result.set(stmt.fullName.toLowerCase(), stmt);
2558
+ }
2559
+ return result;
2560
+ });
2561
+ }
2462
2562
  }
2463
2563
  exports.References = References;
2464
2564
  var TokenUsage;
@@ -2490,7 +2590,7 @@ function getBscTypeFromExpression(expression, functionExpression) {
2490
2590
  //Associative array literal
2491
2591
  }
2492
2592
  else if ((0, reflection_1.isAALiteralExpression)(expression)) {
2493
- return new ObjectType_1.ObjectType(expression.memberTable);
2593
+ return new ObjectType_1.ObjectType('object', expression.memberTable);
2494
2594
  //Array literal
2495
2595
  }
2496
2596
  else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {