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