brighterscript 0.52.3 → 0.54.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.
- package/CHANGELOG.md +29 -0
- package/dist/DiagnosticMessages.d.ts +14 -3
- package/dist/DiagnosticMessages.js +14 -3
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.js +51 -9
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Program.d.ts +8 -4
- package/dist/Program.js +70 -35
- package/dist/Program.js.map +1 -1
- package/dist/Scope.d.ts +24 -9
- package/dist/Scope.js +96 -50
- package/dist/Scope.js.map +1 -1
- package/dist/SymbolTable.d.ts +62 -0
- package/dist/SymbolTable.js +101 -0
- package/dist/SymbolTable.js.map +1 -0
- package/dist/astUtils/reflection.d.ts +2 -1
- package/dist/astUtils/reflection.js +6 -2
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +2 -1
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +3 -1
- package/dist/bscPlugin/BscPlugin.js +8 -0
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +11 -5
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +75 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +6 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.js +45 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
- package/dist/bscPlugin/hover/HoverProcessor.d.ts +13 -0
- package/dist/bscPlugin/hover/HoverProcessor.js +146 -0
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +167 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +7 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +81 -22
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +5 -1
- package/dist/bscPlugin/validation/BrsFileValidator.js +28 -2
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +18 -3
- package/dist/bscPlugin/validation/ScopeValidator.js +139 -47
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +10 -10
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +14 -9
- package/dist/files/BrsFile.js +121 -142
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +164 -109
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +1 -2
- package/dist/files/XmlFile.js +0 -5
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/tests/imports.spec.js +1 -1
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/files/tests/optionalChaning.spec.js +20 -16
- package/dist/files/tests/optionalChaning.spec.js.map +1 -1
- package/dist/globalCallables.js +3 -0
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +44 -2
- package/dist/lexer/Lexer.spec.js +7 -0
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +1 -0
- package/dist/lexer/TokenKind.js +7 -3
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/Expression.d.ts +4 -1
- package/dist/parser/Expression.js +8 -2
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +1 -1
- package/dist/parser/Parser.d.ts +13 -2
- package/dist/parser/Parser.js +137 -60
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Statement.d.ts +29 -1
- package/dist/parser/Statement.js +66 -4
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +73 -31
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +148 -47
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +219 -37
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/ConstStatement.spec.d.ts +1 -0
- package/dist/parser/tests/statement/ConstStatement.spec.js +182 -0
- package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -0
- package/dist/parser/tests/statement/Enum.spec.js +17 -2
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +72 -57
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/types/DynamicType.d.ts +1 -0
- package/dist/types/DynamicType.js +1 -0
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/util.d.ts +37 -6
- package/dist/util.js +90 -6
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.js +4 -6
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +1 -1
package/dist/parser/Parser.js
CHANGED
|
@@ -5,6 +5,7 @@ const Token_1 = require("../lexer/Token");
|
|
|
5
5
|
const Lexer_1 = require("../lexer/Lexer");
|
|
6
6
|
const TokenKind_1 = require("../lexer/TokenKind");
|
|
7
7
|
const Statement_1 = require("./Statement");
|
|
8
|
+
const Statement_2 = require("./Statement");
|
|
8
9
|
const DiagnosticMessages_1 = require("../DiagnosticMessages");
|
|
9
10
|
const util_1 = require("../util");
|
|
10
11
|
const Expression_1 = require("./Expression");
|
|
@@ -13,6 +14,8 @@ const reflection_1 = require("../astUtils/reflection");
|
|
|
13
14
|
const visitors_1 = require("../astUtils/visitors");
|
|
14
15
|
const creators_1 = require("../astUtils/creators");
|
|
15
16
|
const Cache_1 = require("../Cache");
|
|
17
|
+
const SymbolTable_1 = require("../SymbolTable");
|
|
18
|
+
const DynamicType_1 = require("../types/DynamicType");
|
|
16
19
|
class Parser {
|
|
17
20
|
constructor() {
|
|
18
21
|
/**
|
|
@@ -22,7 +25,11 @@ class Parser {
|
|
|
22
25
|
/**
|
|
23
26
|
* The list of statements for the parsed file
|
|
24
27
|
*/
|
|
25
|
-
this.ast = new
|
|
28
|
+
this.ast = new Statement_2.Body([]);
|
|
29
|
+
/**
|
|
30
|
+
* The top-level symbol table for this file. Things like top-level namespaces, non-namespaced classes, enums, interfaces, and functions beling here.
|
|
31
|
+
*/
|
|
32
|
+
this.symbolTable = new SymbolTable_1.SymbolTable();
|
|
26
33
|
this._references = new References();
|
|
27
34
|
this.globalTerminators = [];
|
|
28
35
|
/**
|
|
@@ -33,6 +40,10 @@ class Parser {
|
|
|
33
40
|
get statements() {
|
|
34
41
|
return this.ast.statements;
|
|
35
42
|
}
|
|
43
|
+
get currentSymbolTable() {
|
|
44
|
+
var _a, _b, _c, _d;
|
|
45
|
+
return (_d = (_b = (_a = this.currentFunctionExpression) === null || _a === void 0 ? void 0 : _a.symbolTable) !== null && _b !== void 0 ? _b : (_c = this.currentNamespace) === null || _c === void 0 ? void 0 : _c.symbolTable) !== null && _d !== void 0 ? _d : this.symbolTable;
|
|
46
|
+
}
|
|
36
47
|
/**
|
|
37
48
|
* References for significant statements/expressions in the parser.
|
|
38
49
|
* These are initially extracted during parse-time to improve performance, but will also be dynamically regenerated if need be.
|
|
@@ -68,6 +79,10 @@ class Parser {
|
|
|
68
79
|
}
|
|
69
80
|
}
|
|
70
81
|
}
|
|
82
|
+
get currentNamespaceName() {
|
|
83
|
+
var _a;
|
|
84
|
+
return (_a = this.currentNamespace) === null || _a === void 0 ? void 0 : _a.nameExpression;
|
|
85
|
+
}
|
|
71
86
|
/**
|
|
72
87
|
* Get the currently active global terminators
|
|
73
88
|
*/
|
|
@@ -79,22 +94,22 @@ class Parser {
|
|
|
79
94
|
* Static wrapper around creating a new parser and parsing a list of tokens
|
|
80
95
|
*/
|
|
81
96
|
static parse(toParse, options) {
|
|
82
|
-
|
|
83
|
-
if (typeof toParse === 'string') {
|
|
84
|
-
tokens = Lexer_1.Lexer.scan(toParse).tokens;
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
tokens = toParse;
|
|
88
|
-
}
|
|
89
|
-
return new Parser().parse(tokens, options);
|
|
97
|
+
return new Parser().parse(toParse, options);
|
|
90
98
|
}
|
|
91
99
|
/**
|
|
92
100
|
* Parses an array of `Token`s into an abstract syntax tree
|
|
93
101
|
* @param toParse the array of tokens to parse. May not contain any whitespace tokens
|
|
94
102
|
* @returns the same instance of the parser which contains the diagnostics and statements
|
|
95
103
|
*/
|
|
96
|
-
parse(
|
|
104
|
+
parse(toParse, options) {
|
|
97
105
|
var _a;
|
|
106
|
+
let tokens;
|
|
107
|
+
if (typeof toParse === 'string') {
|
|
108
|
+
tokens = Lexer_1.Lexer.scan(toParse).tokens;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
tokens = toParse;
|
|
112
|
+
}
|
|
98
113
|
this.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) !== null && _a !== void 0 ? _a : new Logger_1.Logger();
|
|
99
114
|
this.tokens = tokens;
|
|
100
115
|
this.options = this.sanitizeParseOptions(options);
|
|
@@ -112,7 +127,7 @@ class Parser {
|
|
|
112
127
|
}
|
|
113
128
|
body() {
|
|
114
129
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
115
|
-
let body = new
|
|
130
|
+
let body = new Statement_2.Body([]);
|
|
116
131
|
if (this.tokens.length > 0) {
|
|
117
132
|
this.consumeStatementSeparators(true);
|
|
118
133
|
try {
|
|
@@ -178,6 +193,9 @@ class Parser {
|
|
|
178
193
|
if (this.checkLibrary()) {
|
|
179
194
|
return this.libraryStatement();
|
|
180
195
|
}
|
|
196
|
+
if (this.check(TokenKind_1.TokenKind.Const)) {
|
|
197
|
+
return this.constDeclaration();
|
|
198
|
+
}
|
|
181
199
|
if (this.check(TokenKind_1.TokenKind.At) && this.checkNext(TokenKind_1.TokenKind.Identifier)) {
|
|
182
200
|
return this.annotationExpression();
|
|
183
201
|
}
|
|
@@ -216,7 +234,7 @@ class Parser {
|
|
|
216
234
|
return identifier;
|
|
217
235
|
}
|
|
218
236
|
enumMemberStatement() {
|
|
219
|
-
const statement = new
|
|
237
|
+
const statement = new Statement_2.EnumMemberStatement({});
|
|
220
238
|
statement.tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
221
239
|
//look for `= SOME_EXPRESSION`
|
|
222
240
|
if (this.check(TokenKind_1.TokenKind.Equal)) {
|
|
@@ -237,7 +255,7 @@ class Parser {
|
|
|
237
255
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeToken.text)), { range: typeToken.range }));
|
|
238
256
|
throw this.lastDiagnosticAsError();
|
|
239
257
|
}
|
|
240
|
-
return new
|
|
258
|
+
return new Statement_2.InterfaceFieldStatement(name, asToken, typeToken, type);
|
|
241
259
|
}
|
|
242
260
|
/**
|
|
243
261
|
* Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration()`
|
|
@@ -259,7 +277,7 @@ class Parser {
|
|
|
259
277
|
throw this.lastDiagnosticAsError();
|
|
260
278
|
}
|
|
261
279
|
}
|
|
262
|
-
return new
|
|
280
|
+
return new Statement_2.InterfaceMethodStatement(functionType, name, leftParen, params, rightParen, asToken, returnTypeToken, util_1.util.tokenToBscType(returnTypeToken));
|
|
263
281
|
}
|
|
264
282
|
interfaceDeclaration() {
|
|
265
283
|
this.warnIfNotBrighterScriptMode('interface declarations');
|
|
@@ -316,13 +334,13 @@ class Parser {
|
|
|
316
334
|
}
|
|
317
335
|
//consume the final `end interface` token
|
|
318
336
|
const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
|
|
319
|
-
const statement = new
|
|
337
|
+
const statement = new Statement_2.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endInterfaceToken, this.currentNamespaceName);
|
|
320
338
|
this._references.interfaceStatements.push(statement);
|
|
321
339
|
this.exitAnnotationBlock(parentAnnotations);
|
|
322
340
|
return statement;
|
|
323
341
|
}
|
|
324
342
|
enumDeclaration() {
|
|
325
|
-
const result = new
|
|
343
|
+
const result = new Statement_2.EnumStatement({}, [], this.currentNamespaceName);
|
|
326
344
|
this.warnIfNotBrighterScriptMode('enum declarations');
|
|
327
345
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
328
346
|
result.tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
|
|
@@ -366,6 +384,9 @@ class Parser {
|
|
|
366
384
|
}
|
|
367
385
|
//consume the final `end interface` token
|
|
368
386
|
result.tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
|
|
387
|
+
if (result.name) {
|
|
388
|
+
this.currentSymbolTable.addSymbol(result.tokens.name.text, result.tokens.name.range, DynamicType_1.DynamicType.instance);
|
|
389
|
+
}
|
|
369
390
|
this._references.enumStatements.push(result);
|
|
370
391
|
this.exitAnnotationBlock(parentAnnotations);
|
|
371
392
|
return result;
|
|
@@ -414,9 +435,11 @@ class Parser {
|
|
|
414
435
|
if (overrideKeyword && funcDeclaration.name.text.toLowerCase() === 'new') {
|
|
415
436
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseOverrideKeywordOnConstructorFunction()), { range: overrideKeyword.range }));
|
|
416
437
|
}
|
|
417
|
-
decl = new
|
|
438
|
+
decl = new Statement_2.MethodStatement(accessModifier, funcDeclaration.name, funcDeclaration.func, overrideKeyword);
|
|
418
439
|
//refer to this statement as parent of the expression
|
|
419
440
|
functionStatement.func.functionStatement = decl;
|
|
441
|
+
//add the `super` symbol to class methods
|
|
442
|
+
funcDeclaration.func.symbolTable.addSymbol('super', undefined, DynamicType_1.DynamicType.instance);
|
|
420
443
|
//fields
|
|
421
444
|
}
|
|
422
445
|
else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
@@ -446,7 +469,10 @@ class Parser {
|
|
|
446
469
|
if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
|
|
447
470
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
|
|
448
471
|
}
|
|
449
|
-
const result = new
|
|
472
|
+
const result = new Statement_2.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName);
|
|
473
|
+
if (className) {
|
|
474
|
+
this.currentSymbolTable.addSymbol(className.text, className.range, DynamicType_1.DynamicType.instance);
|
|
475
|
+
}
|
|
450
476
|
this._references.classStatements.push(result);
|
|
451
477
|
this.exitAnnotationBlock(parentAnnotations);
|
|
452
478
|
return result;
|
|
@@ -471,9 +497,9 @@ class Parser {
|
|
|
471
497
|
equal = this.advance();
|
|
472
498
|
initialValue = this.expression();
|
|
473
499
|
}
|
|
474
|
-
return new
|
|
500
|
+
return new Statement_2.FieldStatement(accessModifier, name, asToken, fieldType, equal, initialValue);
|
|
475
501
|
}
|
|
476
|
-
functionDeclaration(isAnonymous, checkIdentifier = true) {
|
|
502
|
+
functionDeclaration(isAnonymous, checkIdentifier = true, onlyCallableAsMember = false) {
|
|
477
503
|
var _a;
|
|
478
504
|
let previousCallExpressions = this.callExpressions;
|
|
479
505
|
this.callExpressions = [];
|
|
@@ -547,11 +573,21 @@ class Parser {
|
|
|
547
573
|
this.consumeStatementSeparators(true);
|
|
548
574
|
let func = new Expression_1.FunctionExpression(params, undefined, //body
|
|
549
575
|
functionType, undefined, //ending keyword
|
|
550
|
-
leftParen, rightParen, asToken, typeToken, this.currentFunctionExpression, this.currentNamespaceName);
|
|
576
|
+
leftParen, rightParen, asToken, typeToken, this.currentFunctionExpression, this.currentNamespaceName, this.currentSymbolTable);
|
|
577
|
+
if (!func.symbolTable.hasSymbol('m')) {
|
|
578
|
+
func.symbolTable.addSymbol('m', undefined, DynamicType_1.DynamicType.instance);
|
|
579
|
+
}
|
|
551
580
|
//if there is a parent function, register this function with the parent
|
|
552
581
|
if (this.currentFunctionExpression) {
|
|
553
582
|
this.currentFunctionExpression.childFunctionExpressions.push(func);
|
|
554
583
|
}
|
|
584
|
+
// add the function to the relevant symbol tables
|
|
585
|
+
if (!onlyCallableAsMember && name) {
|
|
586
|
+
const funcType = func.getFunctionType();
|
|
587
|
+
funcType.setName(name.text);
|
|
588
|
+
// add the function as declared to the current symbol table
|
|
589
|
+
this.currentSymbolTable.addSymbol(name.text, name.range, funcType);
|
|
590
|
+
}
|
|
555
591
|
this._references.functionExpressions.push(func);
|
|
556
592
|
let previousFunctionExpression = this.currentFunctionExpression;
|
|
557
593
|
this.currentFunctionExpression = func;
|
|
@@ -580,7 +616,7 @@ class Parser {
|
|
|
580
616
|
return func;
|
|
581
617
|
}
|
|
582
618
|
else {
|
|
583
|
-
let result = new
|
|
619
|
+
let result = new Statement_2.FunctionStatement(name, func, this.currentNamespaceName);
|
|
584
620
|
func.functionStatement = result;
|
|
585
621
|
this._references.functionStatements.push(result);
|
|
586
622
|
return result;
|
|
@@ -628,16 +664,17 @@ class Parser {
|
|
|
628
664
|
let value = this.expression();
|
|
629
665
|
let result;
|
|
630
666
|
if (operator.kind === TokenKind_1.TokenKind.Equal) {
|
|
631
|
-
result = new
|
|
667
|
+
result = new Statement_2.AssignmentStatement(operator, name, value, this.currentFunctionExpression);
|
|
632
668
|
}
|
|
633
669
|
else {
|
|
634
670
|
const nameExpression = new Expression_1.VariableExpression(name, this.currentNamespaceName);
|
|
635
|
-
result = new
|
|
671
|
+
result = new Statement_2.AssignmentStatement(operator, name, new Expression_1.BinaryExpression(nameExpression, operator, value), this.currentFunctionExpression);
|
|
636
672
|
this.addExpressionsToReferences(nameExpression);
|
|
637
673
|
//remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
|
|
638
674
|
this._references.expressions.delete(value);
|
|
639
675
|
this._references.expressions.add(result);
|
|
640
676
|
}
|
|
677
|
+
this.currentSymbolTable.addSymbol(name.text, name.range, DynamicType_1.DynamicType.instance);
|
|
641
678
|
this._references.assignmentStatements.push(result);
|
|
642
679
|
return result;
|
|
643
680
|
}
|
|
@@ -757,11 +794,11 @@ class Parser {
|
|
|
757
794
|
else {
|
|
758
795
|
endWhile = this.advance();
|
|
759
796
|
}
|
|
760
|
-
return new
|
|
797
|
+
return new Statement_2.WhileStatement({ while: whileKeyword, endWhile: endWhile }, condition, whileBlock);
|
|
761
798
|
}
|
|
762
799
|
exitWhile() {
|
|
763
800
|
let keyword = this.advance();
|
|
764
|
-
return new
|
|
801
|
+
return new Statement_2.ExitWhileStatement({ exitWhile: keyword });
|
|
765
802
|
}
|
|
766
803
|
forStatement() {
|
|
767
804
|
const forToken = this.advance();
|
|
@@ -792,7 +829,7 @@ class Parser {
|
|
|
792
829
|
}
|
|
793
830
|
// WARNING: BrightScript doesn't delete the loop initial value after a for/to loop! It just
|
|
794
831
|
// stays around in scope with whatever value it was when the loop exited.
|
|
795
|
-
return new
|
|
832
|
+
return new Statement_2.ForStatement(forToken, initializer, toToken, finalValue, body, endForToken, stepToken, incrementExpression);
|
|
796
833
|
}
|
|
797
834
|
forEachStatement() {
|
|
798
835
|
let forEach = this.advance();
|
|
@@ -810,6 +847,7 @@ class Parser {
|
|
|
810
847
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedExpressionAfterForEachIn()), { range: this.peek().range }));
|
|
811
848
|
throw this.lastDiagnosticAsError();
|
|
812
849
|
}
|
|
850
|
+
this.currentSymbolTable.addSymbol(name.text, name.range, DynamicType_1.DynamicType.instance);
|
|
813
851
|
this.consumeStatementSeparators();
|
|
814
852
|
let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
|
|
815
853
|
if (!body) {
|
|
@@ -817,7 +855,7 @@ class Parser {
|
|
|
817
855
|
throw this.lastDiagnosticAsError();
|
|
818
856
|
}
|
|
819
857
|
let endFor = this.advance();
|
|
820
|
-
return new
|
|
858
|
+
return new Statement_2.ForEachStatement({
|
|
821
859
|
forEach: forEach,
|
|
822
860
|
in: maybeIn,
|
|
823
861
|
endFor: endFor
|
|
@@ -825,14 +863,14 @@ class Parser {
|
|
|
825
863
|
}
|
|
826
864
|
exitFor() {
|
|
827
865
|
let keyword = this.advance();
|
|
828
|
-
return new
|
|
866
|
+
return new Statement_2.ExitForStatement({ exitFor: keyword });
|
|
829
867
|
}
|
|
830
868
|
commentStatement() {
|
|
831
869
|
//if this comment is on the same line as the previous statement,
|
|
832
870
|
//then this comment should be treated as a single-line comment
|
|
833
871
|
let prev = this.previous();
|
|
834
872
|
if ((prev === null || prev === void 0 ? void 0 : prev.range.end.line) === this.peek().range.start.line) {
|
|
835
|
-
return new
|
|
873
|
+
return new Statement_2.CommentStatement([this.advance()]);
|
|
836
874
|
}
|
|
837
875
|
else {
|
|
838
876
|
let comments = [this.advance()];
|
|
@@ -840,7 +878,7 @@ class Parser {
|
|
|
840
878
|
this.advance();
|
|
841
879
|
comments.push(this.advance());
|
|
842
880
|
}
|
|
843
|
-
return new
|
|
881
|
+
return new Statement_2.CommentStatement(comments);
|
|
844
882
|
}
|
|
845
883
|
}
|
|
846
884
|
namespaceStatement() {
|
|
@@ -852,12 +890,13 @@ class Parser {
|
|
|
852
890
|
this.namespaceAndFunctionDepth++;
|
|
853
891
|
let name = this.getNamespacedVariableNameExpression();
|
|
854
892
|
//set the current namespace name
|
|
855
|
-
|
|
893
|
+
let result = new Statement_2.NamespaceStatement(keyword, name, null, null, this.currentSymbolTable);
|
|
894
|
+
this.currentNamespace = result;
|
|
856
895
|
this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
|
|
857
896
|
let body = this.body();
|
|
858
897
|
this.globalTerminators.pop();
|
|
859
898
|
//unset the current namespace name
|
|
860
|
-
this.
|
|
899
|
+
this.currentNamespace = undefined;
|
|
861
900
|
let endKeyword;
|
|
862
901
|
if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
|
|
863
902
|
endKeyword = this.advance();
|
|
@@ -867,8 +906,14 @@ class Parser {
|
|
|
867
906
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('namespace')), { range: keyword.range }));
|
|
868
907
|
}
|
|
869
908
|
this.namespaceAndFunctionDepth--;
|
|
870
|
-
|
|
909
|
+
result.body = body;
|
|
910
|
+
result.endKeyword = endKeyword;
|
|
871
911
|
this._references.namespaceStatements.push(result);
|
|
912
|
+
//cache the range property so that plugins can't affect it
|
|
913
|
+
result.cacheRange();
|
|
914
|
+
if (result.name) {
|
|
915
|
+
this.symbolTable.addSymbol(result.name.split('.')[0], result.nameExpression.range, DynamicType_1.DynamicType.instance);
|
|
916
|
+
}
|
|
872
917
|
return result;
|
|
873
918
|
}
|
|
874
919
|
/**
|
|
@@ -921,8 +966,24 @@ class Parser {
|
|
|
921
966
|
}
|
|
922
967
|
return result;
|
|
923
968
|
}
|
|
969
|
+
constDeclaration() {
|
|
970
|
+
const constToken = this.advance();
|
|
971
|
+
const nameToken = this.identifier();
|
|
972
|
+
const equalToken = this.consumeToken(TokenKind_1.TokenKind.Equal);
|
|
973
|
+
const expression = this.expression();
|
|
974
|
+
const statement = new Statement_1.ConstStatement({
|
|
975
|
+
const: constToken,
|
|
976
|
+
name: nameToken,
|
|
977
|
+
equals: equalToken
|
|
978
|
+
}, expression, this.currentNamespaceName);
|
|
979
|
+
if (nameToken) {
|
|
980
|
+
this.currentSymbolTable.addSymbol(nameToken.text, nameToken.range, DynamicType_1.DynamicType.instance);
|
|
981
|
+
}
|
|
982
|
+
this._references.constStatements.push(statement);
|
|
983
|
+
return statement;
|
|
984
|
+
}
|
|
924
985
|
libraryStatement() {
|
|
925
|
-
let libStatement = new
|
|
986
|
+
let libStatement = new Statement_2.LibraryStatement({
|
|
926
987
|
library: this.advance(),
|
|
927
988
|
//grab the next token only if it's a string
|
|
928
989
|
filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
|
|
@@ -932,7 +993,7 @@ class Parser {
|
|
|
932
993
|
}
|
|
933
994
|
importStatement() {
|
|
934
995
|
this.warnIfNotBrighterScriptMode('import statements');
|
|
935
|
-
let importStatement = new
|
|
996
|
+
let importStatement = new Statement_2.ImportStatement(this.advance(),
|
|
936
997
|
//grab the next token only if it's a string
|
|
937
998
|
this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
|
|
938
999
|
this._references.importStatements.push(importStatement);
|
|
@@ -1059,7 +1120,7 @@ class Parser {
|
|
|
1059
1120
|
}
|
|
1060
1121
|
tryCatchStatement() {
|
|
1061
1122
|
const tryToken = this.advance();
|
|
1062
|
-
const statement = new
|
|
1123
|
+
const statement = new Statement_2.TryCatchStatement({ try: tryToken });
|
|
1063
1124
|
//ensure statement separator
|
|
1064
1125
|
this.consumeStatementSeparators();
|
|
1065
1126
|
statement.tryBranch = this.block(TokenKind_1.TokenKind.Catch, TokenKind_1.TokenKind.EndTry);
|
|
@@ -1072,7 +1133,7 @@ class Parser {
|
|
|
1072
1133
|
}
|
|
1073
1134
|
return statement;
|
|
1074
1135
|
}
|
|
1075
|
-
const catchStmt = new
|
|
1136
|
+
const catchStmt = new Statement_2.CatchStatement({ catch: this.advance() });
|
|
1076
1137
|
statement.catchStatement = catchStmt;
|
|
1077
1138
|
const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
1078
1139
|
if (exceptionVarToken) {
|
|
@@ -1089,6 +1150,9 @@ class Parser {
|
|
|
1089
1150
|
else {
|
|
1090
1151
|
statement.tokens.endTry = this.advance();
|
|
1091
1152
|
}
|
|
1153
|
+
if (exceptionVarToken) {
|
|
1154
|
+
this.currentSymbolTable.addSymbol(exceptionVarToken.text, exceptionVarToken.range, DynamicType_1.DynamicType.instance);
|
|
1155
|
+
}
|
|
1092
1156
|
return statement;
|
|
1093
1157
|
}
|
|
1094
1158
|
throwStatement() {
|
|
@@ -1100,7 +1164,7 @@ class Parser {
|
|
|
1100
1164
|
else {
|
|
1101
1165
|
expression = this.expression();
|
|
1102
1166
|
}
|
|
1103
|
-
return new
|
|
1167
|
+
return new Statement_2.ThrowStatement(throwToken, expression);
|
|
1104
1168
|
}
|
|
1105
1169
|
dimStatement() {
|
|
1106
1170
|
const dim = this.advance();
|
|
@@ -1131,7 +1195,7 @@ class Parser {
|
|
|
1131
1195
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
|
|
1132
1196
|
}
|
|
1133
1197
|
let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1134
|
-
return new
|
|
1198
|
+
return new Statement_2.DimStatement(dim, identifier, leftSquareBracket, expressions, rightSquareBracket);
|
|
1135
1199
|
}
|
|
1136
1200
|
ifStatement() {
|
|
1137
1201
|
// colon before `if` is usually not allowed, unless it's after `then`
|
|
@@ -1237,7 +1301,7 @@ class Parser {
|
|
|
1237
1301
|
}
|
|
1238
1302
|
}
|
|
1239
1303
|
}
|
|
1240
|
-
return new
|
|
1304
|
+
return new Statement_2.IfStatement({
|
|
1241
1305
|
if: ifToken,
|
|
1242
1306
|
then: thenToken,
|
|
1243
1307
|
endIf: endIfToken,
|
|
@@ -1313,7 +1377,7 @@ class Parser {
|
|
|
1313
1377
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(colon.text)), { range: colon.range }));
|
|
1314
1378
|
}
|
|
1315
1379
|
}
|
|
1316
|
-
return new
|
|
1380
|
+
return new Statement_2.Block(statements, startingRange);
|
|
1317
1381
|
}
|
|
1318
1382
|
expressionStatement(expr) {
|
|
1319
1383
|
let expressionStart = this.peek();
|
|
@@ -1327,12 +1391,12 @@ class Parser {
|
|
|
1327
1391
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incrementDecrementOperatorsAreNotAllowedAsResultOfFunctionCall()), { range: expressionStart.range }));
|
|
1328
1392
|
throw this.lastDiagnosticAsError();
|
|
1329
1393
|
}
|
|
1330
|
-
const result = new
|
|
1394
|
+
const result = new Statement_2.IncrementStatement(expr, operator);
|
|
1331
1395
|
this._references.expressions.add(result);
|
|
1332
1396
|
return result;
|
|
1333
1397
|
}
|
|
1334
1398
|
if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
|
|
1335
|
-
return new
|
|
1399
|
+
return new Statement_2.ExpressionStatement(expr);
|
|
1336
1400
|
}
|
|
1337
1401
|
//at this point, it's probably an error. However, we recover a little more gracefully by creating an assignment
|
|
1338
1402
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()), { range: expressionStart.range }));
|
|
@@ -1352,12 +1416,12 @@ class Parser {
|
|
|
1352
1416
|
let right = this.expression();
|
|
1353
1417
|
// Create a dotted or indexed "set" based on the left-hand side's type
|
|
1354
1418
|
if ((0, reflection_1.isIndexedGetExpression)(left)) {
|
|
1355
|
-
return new
|
|
1419
|
+
return new Statement_2.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
|
|
1356
1420
|
? right
|
|
1357
1421
|
: new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
|
|
1358
1422
|
}
|
|
1359
1423
|
else if ((0, reflection_1.isDottedGetExpression)(left)) {
|
|
1360
|
-
return new
|
|
1424
|
+
return new Statement_2.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
|
|
1361
1425
|
? right
|
|
1362
1426
|
: new Expression_1.BinaryExpression(left, operator, right));
|
|
1363
1427
|
}
|
|
@@ -1390,7 +1454,7 @@ class Parser {
|
|
|
1390
1454
|
if ((0, Token_1.isToken)(last)) {
|
|
1391
1455
|
// TODO: error, expected value
|
|
1392
1456
|
}
|
|
1393
|
-
return new
|
|
1457
|
+
return new Statement_2.PrintStatement({ print: printKeyword }, values);
|
|
1394
1458
|
}
|
|
1395
1459
|
/**
|
|
1396
1460
|
* Parses a return statement with an optional return value.
|
|
@@ -1399,10 +1463,10 @@ class Parser {
|
|
|
1399
1463
|
returnStatement() {
|
|
1400
1464
|
let tokens = { return: this.previous() };
|
|
1401
1465
|
if (this.checkEndOfStatement()) {
|
|
1402
|
-
return new
|
|
1466
|
+
return new Statement_2.ReturnStatement(tokens);
|
|
1403
1467
|
}
|
|
1404
1468
|
let toReturn = this.check(TokenKind_1.TokenKind.Else) ? undefined : this.expression();
|
|
1405
|
-
return new
|
|
1469
|
+
return new Statement_2.ReturnStatement(tokens, toReturn);
|
|
1406
1470
|
}
|
|
1407
1471
|
/**
|
|
1408
1472
|
* Parses a `label` statement
|
|
@@ -1419,7 +1483,7 @@ class Parser {
|
|
|
1419
1483
|
this.current -= 2;
|
|
1420
1484
|
throw new CancelStatementError();
|
|
1421
1485
|
}
|
|
1422
|
-
return new
|
|
1486
|
+
return new Statement_2.LabelStatement(tokens);
|
|
1423
1487
|
}
|
|
1424
1488
|
/**
|
|
1425
1489
|
* Parses a `goto` statement
|
|
@@ -1430,7 +1494,7 @@ class Parser {
|
|
|
1430
1494
|
goto: this.advance(),
|
|
1431
1495
|
label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(), TokenKind_1.TokenKind.Identifier)
|
|
1432
1496
|
};
|
|
1433
|
-
return new
|
|
1497
|
+
return new Statement_2.GotoStatement(tokens);
|
|
1434
1498
|
}
|
|
1435
1499
|
/**
|
|
1436
1500
|
* Parses an `end` statement
|
|
@@ -1438,7 +1502,7 @@ class Parser {
|
|
|
1438
1502
|
*/
|
|
1439
1503
|
endStatement() {
|
|
1440
1504
|
let endTokens = { end: this.advance() };
|
|
1441
|
-
return new
|
|
1505
|
+
return new Statement_2.EndStatement(endTokens);
|
|
1442
1506
|
}
|
|
1443
1507
|
/**
|
|
1444
1508
|
* Parses a `stop` statement
|
|
@@ -1446,7 +1510,7 @@ class Parser {
|
|
|
1446
1510
|
*/
|
|
1447
1511
|
stopStatement() {
|
|
1448
1512
|
let tokens = { stop: this.advance() };
|
|
1449
|
-
return new
|
|
1513
|
+
return new Statement_2.StopStatement(tokens);
|
|
1450
1514
|
}
|
|
1451
1515
|
/**
|
|
1452
1516
|
* Parses a block, looking for a specific terminating TokenKind to denote completion.
|
|
@@ -1498,7 +1562,7 @@ class Parser {
|
|
|
1498
1562
|
}
|
|
1499
1563
|
}
|
|
1500
1564
|
this.exitAnnotationBlock(parentAnnotations);
|
|
1501
|
-
return new
|
|
1565
|
+
return new Statement_2.Block(statements, startingToken.range);
|
|
1502
1566
|
}
|
|
1503
1567
|
/**
|
|
1504
1568
|
* Attach pending annotations to the provided statement,
|
|
@@ -1789,7 +1853,7 @@ class Parser {
|
|
|
1789
1853
|
case this.check(TokenKind_1.TokenKind.RegexLiteral):
|
|
1790
1854
|
return this.regexLiteralExpression();
|
|
1791
1855
|
case this.check(TokenKind_1.TokenKind.Comment):
|
|
1792
|
-
return new
|
|
1856
|
+
return new Statement_2.CommentStatement([this.advance()]);
|
|
1793
1857
|
default:
|
|
1794
1858
|
//if we found an expected terminator, don't throw a diagnostic...just return undefined
|
|
1795
1859
|
if (this.checkAny(...this.peekGlobalTerminators())) {
|
|
@@ -1807,7 +1871,7 @@ class Parser {
|
|
|
1807
1871
|
let openingSquare = this.previous();
|
|
1808
1872
|
//add any comment found right after the opening square
|
|
1809
1873
|
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1810
|
-
elements.push(new
|
|
1874
|
+
elements.push(new Statement_2.CommentStatement([this.advance()]));
|
|
1811
1875
|
}
|
|
1812
1876
|
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1813
1877
|
}
|
|
@@ -1816,7 +1880,7 @@ class Parser {
|
|
|
1816
1880
|
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
1817
1881
|
if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1818
1882
|
let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
|
|
1819
|
-
elements.push(new
|
|
1883
|
+
elements.push(new Statement_2.CommentStatement([comment]));
|
|
1820
1884
|
}
|
|
1821
1885
|
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1822
1886
|
}
|
|
@@ -1859,7 +1923,7 @@ class Parser {
|
|
|
1859
1923
|
let lastAAMember;
|
|
1860
1924
|
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1861
1925
|
lastAAMember = null;
|
|
1862
|
-
members.push(new
|
|
1926
|
+
members.push(new Statement_2.CommentStatement([this.advance()]));
|
|
1863
1927
|
}
|
|
1864
1928
|
else {
|
|
1865
1929
|
let k = key();
|
|
@@ -1875,7 +1939,7 @@ class Parser {
|
|
|
1875
1939
|
//check for comment at the end of the current line
|
|
1876
1940
|
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
1877
1941
|
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
1878
|
-
members.push(new
|
|
1942
|
+
members.push(new Statement_2.CommentStatement([token]));
|
|
1879
1943
|
}
|
|
1880
1944
|
else {
|
|
1881
1945
|
this.consumeStatementSeparators(true);
|
|
@@ -1883,7 +1947,7 @@ class Parser {
|
|
|
1883
1947
|
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
1884
1948
|
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
1885
1949
|
lastAAMember = null;
|
|
1886
|
-
members.push(new
|
|
1950
|
+
members.push(new Statement_2.CommentStatement([token]));
|
|
1887
1951
|
continue;
|
|
1888
1952
|
}
|
|
1889
1953
|
if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
@@ -2209,6 +2273,9 @@ class Parser {
|
|
|
2209
2273
|
EnumStatement: e => {
|
|
2210
2274
|
this._references.enumStatements.push(e);
|
|
2211
2275
|
},
|
|
2276
|
+
ConstStatement: s => {
|
|
2277
|
+
this._references.constStatements.push(s);
|
|
2278
|
+
},
|
|
2212
2279
|
UnaryExpression: e => {
|
|
2213
2280
|
this._references.expressions.add(e);
|
|
2214
2281
|
},
|
|
@@ -2237,6 +2304,7 @@ class References {
|
|
|
2237
2304
|
this.functionStatements = [];
|
|
2238
2305
|
this.interfaceStatements = [];
|
|
2239
2306
|
this.enumStatements = [];
|
|
2307
|
+
this.constStatements = [];
|
|
2240
2308
|
/**
|
|
2241
2309
|
* A collection of full expressions. This excludes intermediary expressions.
|
|
2242
2310
|
*
|
|
@@ -2296,6 +2364,15 @@ class References {
|
|
|
2296
2364
|
return result;
|
|
2297
2365
|
});
|
|
2298
2366
|
}
|
|
2367
|
+
get constStatementLookup() {
|
|
2368
|
+
return this.cache.getOrAdd('consts', () => {
|
|
2369
|
+
const result = new Map();
|
|
2370
|
+
for (const stmt of this.constStatements) {
|
|
2371
|
+
result.set(stmt.fullName.toLowerCase(), stmt);
|
|
2372
|
+
}
|
|
2373
|
+
return result;
|
|
2374
|
+
});
|
|
2375
|
+
}
|
|
2299
2376
|
}
|
|
2300
2377
|
exports.References = References;
|
|
2301
2378
|
class CancelStatementError extends Error {
|