brighterscript 0.70.3 → 0.70.4

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 (45) hide show
  1. package/README.md +3 -0
  2. package/dist/DiagnosticMessages.d.ts +7 -2
  3. package/dist/DiagnosticMessages.js +7 -2
  4. package/dist/DiagnosticMessages.js.map +1 -1
  5. package/dist/LanguageServer.d.ts +24 -0
  6. package/dist/LanguageServer.js +40 -1
  7. package/dist/LanguageServer.js.map +1 -1
  8. package/dist/ProgramBuilder.d.ts +1 -1
  9. package/dist/Scope.d.ts +14 -1
  10. package/dist/Scope.js +43 -2
  11. package/dist/Scope.js.map +1 -1
  12. package/dist/astUtils/reflection.d.ts +2 -1
  13. package/dist/astUtils/reflection.js +7 -2
  14. package/dist/astUtils/reflection.js.map +1 -1
  15. package/dist/astUtils/visitors.d.ts +2 -1
  16. package/dist/astUtils/visitors.js.map +1 -1
  17. package/dist/bscPlugin/definition/DefinitionProvider.js +8 -0
  18. package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -1
  19. package/dist/bscPlugin/definition/DefinitionProvider.spec.js +84 -0
  20. package/dist/bscPlugin/definition/DefinitionProvider.spec.js.map +1 -1
  21. package/dist/bscPlugin/validation/BrsFileValidator.js +2 -1
  22. package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
  23. package/dist/files/BrsFile.spec.js +251 -0
  24. package/dist/files/BrsFile.spec.js.map +1 -1
  25. package/dist/lexer/TokenKind.js +4 -2
  26. package/dist/lexer/TokenKind.js.map +1 -1
  27. package/dist/lsp/ProjectManager.d.ts +10 -0
  28. package/dist/lsp/ProjectManager.js +21 -4
  29. package/dist/lsp/ProjectManager.js.map +1 -1
  30. package/dist/lsp/ProjectManager.spec.js +30 -0
  31. package/dist/lsp/ProjectManager.spec.js.map +1 -1
  32. package/dist/parser/Expression.d.ts +1 -0
  33. package/dist/parser/Expression.js +6 -1
  34. package/dist/parser/Expression.js.map +1 -1
  35. package/dist/parser/Parser.d.ts +7 -1
  36. package/dist/parser/Parser.js +175 -13
  37. package/dist/parser/Parser.js.map +1 -1
  38. package/dist/parser/Parser.spec.js +418 -0
  39. package/dist/parser/Parser.spec.js.map +1 -1
  40. package/dist/parser/Statement.d.ts +20 -0
  41. package/dist/parser/Statement.js +51 -1
  42. package/dist/parser/Statement.js.map +1 -1
  43. package/dist/validators/ClassValidator.js +1 -1
  44. package/dist/validators/ClassValidator.js.map +1 -1
  45. package/package.json +6 -13
@@ -1,5 +1,5 @@
1
1
  import type { Token } from '../lexer/Token';
2
- import { AssignmentStatement, Body, ClassStatement, ConstStatement, EnumStatement, FunctionStatement, ImportStatement, InterfaceStatement, LibraryStatement, NamespaceStatement } from './Statement';
2
+ import { AssignmentStatement, Body, ClassStatement, ConstStatement, EnumStatement, FunctionStatement, ImportStatement, InterfaceStatement, LibraryStatement, NamespaceStatement, TypeStatement } from './Statement';
3
3
  import { AnnotationExpression, FunctionExpression, NewExpression } from './Expression';
4
4
  import type { Diagnostic } from 'vscode-languageserver';
5
5
  import type { Logger } from '../logging';
@@ -118,6 +118,7 @@ export declare class Parser {
118
118
  private assignment;
119
119
  private checkLibrary;
120
120
  private checkAlias;
121
+ private checkTypeStatement;
121
122
  private statement;
122
123
  private whileStatement;
123
124
  private exitWhile;
@@ -146,6 +147,7 @@ export declare class Parser {
146
147
  private typecastStatement;
147
148
  private aliasStatement;
148
149
  private annotationExpression;
150
+ private typeStatement;
149
151
  private ternaryExpression;
150
152
  private nullCoalescingExpression;
151
153
  private regexLiteralExpression;
@@ -228,6 +230,9 @@ export declare class Parser {
228
230
  * Will allow v1 type syntax (typed arrays, union types), but there is no validation on types used this way
229
231
  */
230
232
  private typeToken;
233
+ private inlineInterface;
234
+ private groupedTypeExpression;
235
+ private typedFunctionType;
231
236
  private primary;
232
237
  private arrayLiteral;
233
238
  private aaLiteral;
@@ -359,6 +364,7 @@ export declare class References {
359
364
  importStatements: ImportStatement[];
360
365
  libraryStatements: LibraryStatement[];
361
366
  namespaceStatements: NamespaceStatement[];
367
+ typeStatements: TypeStatement[];
362
368
  newExpressions: NewExpression[];
363
369
  propertyHints: Record<string, string>;
364
370
  }
@@ -743,6 +743,22 @@ class Parser {
743
743
  return false;
744
744
  }
745
745
  }
746
+ checkTypeStatement() {
747
+ let isTypeToken = this.check(TokenKind_1.TokenKind.Type);
748
+ //if we are at the top level, any line that starts with "type" should be considered a type statement
749
+ if (this.isAtRootLevel() && isTypeToken) {
750
+ return true;
751
+ //not at root level, type statements are all invalid here, but try to detect if the tokens look
752
+ //like a type statement (and let the type function handle emitting the diagnostics)
753
+ }
754
+ else if (isTypeToken && this.checkNext(TokenKind_1.TokenKind.Identifier)) {
755
+ return true;
756
+ //definitely not a type statement
757
+ }
758
+ else {
759
+ return false;
760
+ }
761
+ }
746
762
  statement() {
747
763
  if (this.checkLibrary()) {
748
764
  return this.libraryStatement();
@@ -756,6 +772,9 @@ class Parser {
756
772
  if (this.checkAlias()) {
757
773
  return this.aliasStatement();
758
774
  }
775
+ if (this.checkTypeStatement()) {
776
+ return this.typeStatement();
777
+ }
759
778
  if (this.check(TokenKind_1.TokenKind.Stop)) {
760
779
  return this.stopStatement();
761
780
  }
@@ -919,6 +938,11 @@ class Parser {
919
938
  forEachStatement() {
920
939
  let forEach = this.advance();
921
940
  let name = this.advance();
941
+ if (this.check(TokenKind_1.TokenKind.As)) {
942
+ this.warnIfNotBrighterScriptMode('typed for each item');
943
+ this.advance(); // get 'as'
944
+ this.typeToken(); // get type
945
+ }
922
946
  let maybeIn = this.peek();
923
947
  if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
924
948
  this.advance();
@@ -1126,6 +1150,21 @@ class Parser {
1126
1150
  }
1127
1151
  return annotation;
1128
1152
  }
1153
+ typeStatement() {
1154
+ this.warnIfNotBrighterScriptMode('type statements');
1155
+ const typeToken = this.advance();
1156
+ const name = this.identifier(...this.allowedLocalIdentifiers);
1157
+ const equals = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(TokenKind_1.TokenKind.Equal), TokenKind_1.TokenKind.Equal);
1158
+ let value = this.typeToken();
1159
+ let typeStmt = new Statement_1.TypeStatement({
1160
+ type: typeToken,
1161
+ name: name,
1162
+ equals: equals,
1163
+ value: value
1164
+ });
1165
+ this._references.typeStatements.push(typeStmt);
1166
+ return typeStmt;
1167
+ }
1129
1168
  ternaryExpression(test) {
1130
1169
  this.warnIfNotBrighterScriptMode('ternary operator');
1131
1170
  if (!test) {
@@ -1507,6 +1546,24 @@ class Parser {
1507
1546
  if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
1508
1547
  return new Statement_1.ExpressionStatement(expr);
1509
1548
  }
1549
+ //you're not allowed to do dottedGet or XmlAttrGet after a function call
1550
+ if ((0, reflection_1.isDottedGetExpression)(expr)) {
1551
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.propAccessNotPermittedAfterFunctionCallInExpressionStatement('Property')), { range: util_1.util.createBoundingRange(expr.dot, expr.name) }));
1552
+ //we can recover gracefully here even though it's invalid syntax
1553
+ return new Statement_1.ExpressionStatement(expr);
1554
+ //you're not allowed to do indexedGet expressions after a function call
1555
+ }
1556
+ else if ((0, reflection_1.isIndexedGetExpression)(expr)) {
1557
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.propAccessNotPermittedAfterFunctionCallInExpressionStatement('Index')), { range: util_1.util.createBoundingRange(expr.openingSquare, expr.index, expr.closingSquare) }));
1558
+ //we can recover gracefully here even though it's invalid syntax
1559
+ return new Statement_1.ExpressionStatement(expr);
1560
+ //you're not allowed to do XmlAttrGet after a function call
1561
+ }
1562
+ else if ((0, reflection_1.isXmlAttributeGetExpression)(expr)) {
1563
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.propAccessNotPermittedAfterFunctionCallInExpressionStatement('XML attribute')), { range: util_1.util.createBoundingRange(expr.at, expr.name) }));
1564
+ //we can recover gracefully here even though it's invalid syntax
1565
+ return new Statement_1.ExpressionStatement(expr);
1566
+ }
1510
1567
  //at this point, it's probably an error. However, we recover a little more gracefully by creating an assignment
1511
1568
  this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()), { range: expressionStart.range }));
1512
1569
  throw this.lastDiagnosticAsError();
@@ -1974,20 +2031,35 @@ class Parser {
1974
2031
  */
1975
2032
  typeToken(ignoreDiagnostics = false) {
1976
2033
  let typeToken;
1977
- let lookForUnions = true;
1978
- let isAUnion = false;
2034
+ let lookForCompounds = true;
2035
+ let isACompound = false;
1979
2036
  let resultToken;
1980
- while (lookForUnions) {
1981
- lookForUnions = false;
1982
- if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
2037
+ while (lookForCompounds) {
2038
+ lookForCompounds = false;
2039
+ const isTypedFunction = this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkNext(TokenKind_1.TokenKind.LeftParen);
2040
+ if (this.checkAny(...TokenKind_1.DeclarableTypes) && !isTypedFunction) {
1983
2041
  // Token is a built in type
1984
2042
  typeToken = this.advance();
1985
2043
  }
1986
2044
  else if (this.options.mode === ParseMode.BrighterScript) {
1987
2045
  try {
1988
- // see if we can get a namespaced identifer
1989
- const qualifiedType = this.getNamespacedVariableNameExpression(ignoreDiagnostics);
1990
- typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
2046
+ if (this.check(TokenKind_1.TokenKind.LeftCurlyBrace)) {
2047
+ // could be an inline interface
2048
+ typeToken = this.inlineInterface();
2049
+ }
2050
+ else if (this.check(TokenKind_1.TokenKind.LeftParen)) {
2051
+ // could be an inline interface
2052
+ typeToken = this.groupedTypeExpression();
2053
+ }
2054
+ else if (isTypedFunction) {
2055
+ //typed function type
2056
+ typeToken = this.typedFunctionType();
2057
+ }
2058
+ else {
2059
+ // see if we can get a namespaced identifer
2060
+ const qualifiedType = this.getNamespacedVariableNameExpression(ignoreDiagnostics);
2061
+ typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
2062
+ }
1991
2063
  }
1992
2064
  catch (_a) {
1993
2065
  //could not get an identifier - just get whatever's next
@@ -2000,26 +2072,112 @@ class Parser {
2000
2072
  }
2001
2073
  resultToken = resultToken !== null && resultToken !== void 0 ? resultToken : typeToken;
2002
2074
  if (resultToken && this.options.mode === ParseMode.BrighterScript) {
2003
- // check for brackets
2075
+ // check for brackets for typed arrays
2004
2076
  while (this.check(TokenKind_1.TokenKind.LeftSquareBracket) && this.peekNext().kind === TokenKind_1.TokenKind.RightSquareBracket) {
2005
2077
  const leftBracket = this.advance();
2006
2078
  const rightBracket = this.advance();
2007
2079
  typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, typeToken.text + leftBracket.text + rightBracket.text, util_1.util.createBoundingRange(typeToken, leftBracket, rightBracket));
2008
2080
  resultToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Dynamic, null, typeToken.range);
2009
2081
  }
2010
- if (this.check(TokenKind_1.TokenKind.Or)) {
2011
- lookForUnions = true;
2082
+ if (this.checkAny(TokenKind_1.TokenKind.Or, TokenKind_1.TokenKind.And)) {
2083
+ lookForCompounds = true;
2012
2084
  let orToken = this.advance();
2013
2085
  resultToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Dynamic, null, util_1.util.createBoundingRange(resultToken, typeToken, orToken));
2014
- isAUnion = true;
2086
+ isACompound = true;
2015
2087
  }
2016
2088
  }
2017
2089
  }
2018
- if (isAUnion) {
2090
+ if (isACompound) {
2019
2091
  resultToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Dynamic, null, util_1.util.createBoundingRange(resultToken, typeToken));
2020
2092
  }
2021
2093
  return resultToken;
2022
2094
  }
2095
+ inlineInterface() {
2096
+ const openToken = this.advance();
2097
+ const memberTokens = [];
2098
+ memberTokens.push(openToken);
2099
+ while (this.matchAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) { }
2100
+ while (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties, TokenKind_1.TokenKind.StringLiteral, TokenKind_1.TokenKind.Optional)) {
2101
+ let optionalKeyword = this.consumeTokenIf(TokenKind_1.TokenKind.Optional);
2102
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties, TokenKind_1.TokenKind.StringLiteral)) {
2103
+ if (this.check(TokenKind_1.TokenKind.As)) {
2104
+ if (this.checkAnyNext(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Newline)) {
2105
+ // as <EOL>
2106
+ // `as` is the field name
2107
+ }
2108
+ else if (this.checkNext(TokenKind_1.TokenKind.As)) {
2109
+ // as as ____
2110
+ // first `as` is the field name
2111
+ }
2112
+ else if (optionalKeyword) {
2113
+ // optional as ____
2114
+ // optional is the field name, `as` starts type
2115
+ // rewind current token
2116
+ optionalKeyword = null;
2117
+ this.current--;
2118
+ }
2119
+ }
2120
+ }
2121
+ else {
2122
+ // no name after `optional` ... optional is the name
2123
+ // rewind current token
2124
+ optionalKeyword = null;
2125
+ this.current--;
2126
+ }
2127
+ if (optionalKeyword) {
2128
+ memberTokens.push(optionalKeyword);
2129
+ }
2130
+ if (!this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, TokenKind_1.TokenKind.StringLiteral)) {
2131
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text)), { range: this.peek().range }));
2132
+ throw this.lastDiagnosticAsError();
2133
+ }
2134
+ if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties, TokenKind_1.TokenKind.StringLiteral)) {
2135
+ this.advance();
2136
+ }
2137
+ else {
2138
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text)), { range: this.peek().range }));
2139
+ throw this.lastDiagnosticAsError();
2140
+ }
2141
+ if (this.check(TokenKind_1.TokenKind.As)) {
2142
+ memberTokens.push(this.advance()); // as
2143
+ memberTokens.push(this.typeToken()); // type
2144
+ }
2145
+ while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) { }
2146
+ }
2147
+ if (!this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
2148
+ this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text)), { range: this.peek().range }));
2149
+ throw this.lastDiagnosticAsError();
2150
+ }
2151
+ const closeToken = this.advance();
2152
+ memberTokens.push(closeToken);
2153
+ const completeInlineInterfaceToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Dynamic, null, util_1.util.createBoundingRange(...memberTokens));
2154
+ return completeInlineInterfaceToken;
2155
+ }
2156
+ groupedTypeExpression() {
2157
+ const leftParen = this.advance();
2158
+ const typeToken = this.typeToken();
2159
+ const rightParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(TokenKind_1.TokenKind.RightParen), TokenKind_1.TokenKind.RightParen);
2160
+ return (0, creators_1.createToken)(TokenKind_1.TokenKind.Dynamic, null, util_1.util.createBoundingRange(leftParen, typeToken, rightParen));
2161
+ }
2162
+ typedFunctionType() {
2163
+ const funcOrSub = this.advance();
2164
+ const leftParen = this.advance();
2165
+ let params = [];
2166
+ if (!this.check(TokenKind_1.TokenKind.RightParen)) {
2167
+ do {
2168
+ params.push(this.functionParameter());
2169
+ } while (this.match(TokenKind_1.TokenKind.Comma));
2170
+ }
2171
+ const rightParen = this.advance();
2172
+ let asToken;
2173
+ let returnType;
2174
+ if ((this.check(TokenKind_1.TokenKind.As))) {
2175
+ // this is a function type with a return type, e.g. `function(string) as void`
2176
+ asToken = this.advance();
2177
+ returnType = this.typeToken();
2178
+ }
2179
+ return (0, creators_1.createToken)(TokenKind_1.TokenKind.Function, null, util_1.util.createBoundingRange(funcOrSub, leftParen, rightParen, asToken, returnType));
2180
+ }
2023
2181
  primary() {
2024
2182
  switch (true) {
2025
2183
  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):
@@ -2523,6 +2681,9 @@ class Parser {
2523
2681
  },
2524
2682
  IncrementStatement: e => {
2525
2683
  this._references.expressions.add(e);
2684
+ },
2685
+ TypeStatement: (s) => {
2686
+ this._references.typeStatements.push(s);
2526
2687
  }
2527
2688
  }), {
2528
2689
  walkMode: visitors_1.WalkMode.visitAllRecursive
@@ -2564,6 +2725,7 @@ class References {
2564
2725
  this.importStatements = [];
2565
2726
  this.libraryStatements = [];
2566
2727
  this.namespaceStatements = [];
2728
+ this.typeStatements = [];
2567
2729
  this.newExpressions = [];
2568
2730
  this.propertyHints = {};
2569
2731
  }