brighterscript 1.0.0-alpha.10 → 1.0.0-alpha.14
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 +247 -267
- package/README.md +2 -2
- package/dist/Cache.d.ts +3 -3
- package/dist/Cache.js +10 -6
- package/dist/Cache.js.map +1 -1
- package/dist/CodeActionUtil.js.map +1 -1
- package/dist/CommentFlagProcessor.d.ts +4 -4
- package/dist/CommentFlagProcessor.js +5 -3
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/DependencyGraph.js.map +1 -1
- package/dist/DiagnosticFilterer.js +1 -1
- package/dist/DiagnosticFilterer.js.map +1 -1
- package/dist/LanguageServer.d.ts +1 -6
- package/dist/LanguageServer.js +5 -14
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.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 +35 -20
- package/dist/Program.js +132 -67
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.js +4 -4
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +22 -13
- package/dist/Scope.js +85 -70
- package/dist/Scope.js.map +1 -1
- package/dist/SymbolTable.d.ts +1 -1
- package/dist/SymbolTable.js +2 -2
- package/dist/SymbolTable.js.map +1 -1
- package/dist/XmlScope.d.ts +2 -2
- package/dist/XmlScope.js +5 -5
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/AstEditor.d.ts +27 -0
- package/dist/astUtils/AstEditor.js +97 -0
- package/dist/astUtils/AstEditor.js.map +1 -0
- package/dist/{bscPlugin/semanticTokens/SemanticTokensProcessor.spec.d.ts → astUtils/AstEditor.spec.d.ts} +0 -0
- package/dist/astUtils/AstEditor.spec.js +133 -0
- package/dist/astUtils/AstEditor.spec.js.map +1 -0
- package/dist/astUtils/creators.spec.js +4 -4
- package/dist/astUtils/creators.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +4 -2
- package/dist/astUtils/reflection.js +10 -1
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +116 -116
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/stackedVisitor.js.map +1 -1
- package/dist/astUtils/stackedVisitor.spec.js +13 -13
- package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
- package/dist/astUtils/visitors.js +1 -1
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +26 -26
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/astUtils/xml.d.ts +1 -0
- package/dist/astUtils/xml.js +6 -1
- package/dist/astUtils/xml.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.js +5 -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 +17 -17
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +8 -0
- package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.js → BrsFileSemanticTokensProcessor.js} +13 -15
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/semanticTokens/{SemanticTokensProcessor.spec.js → BrsFileSemanticTokensProcessor.spec.js} +5 -5
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
- package/dist/diagnosticUtils.d.ts +1 -0
- package/dist/diagnosticUtils.js +14 -7
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/examples/plugins/removePrint.js +2 -2
- package/dist/examples/plugins/removePrint.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +444 -269
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +17 -11
- package/dist/files/BrsFile.js +220 -153
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +620 -272
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +6 -5
- package/dist/files/XmlFile.js +14 -9
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +238 -191
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +29 -27
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/globalCallables.d.ts +3 -1
- package/dist/globalCallables.js +198 -99
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +22 -4
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +71 -10
- package/dist/lexer/Lexer.d.ts +5 -1
- package/dist/lexer/Lexer.js +52 -35
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +564 -534
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +4 -0
- package/dist/lexer/TokenKind.js +44 -1
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/Expression.d.ts +1 -1
- package/dist/parser/Expression.js +66 -66
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +107 -106
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +17 -5
- package/dist/parser/Parser.js +431 -315
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +418 -296
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.js +2 -2
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +22 -22
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/SGTypes.d.ts +3 -0
- package/dist/parser/SGTypes.js +12 -7
- package/dist/parser/SGTypes.js.map +1 -1
- package/dist/parser/SGTypes.spec.js +84 -84
- package/dist/parser/SGTypes.spec.js.map +1 -1
- package/dist/parser/Statement.d.ts +3 -3
- package/dist/parser/Statement.js +61 -61
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +10 -10
- package/dist/parser/Statement.spec.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 +58 -58
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +40 -39
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +201 -200
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +37 -37
- package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
- package/dist/parser/tests/expression/Additive.spec.js +30 -30
- package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +119 -119
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +141 -141
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Boolean.spec.js +24 -24
- package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +41 -40
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Exponential.spec.js +17 -17
- package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
- package/dist/parser/tests/expression/Function.spec.js +256 -256
- package/dist/parser/tests/expression/Function.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +87 -87
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +37 -37
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +74 -62
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +41 -41
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
- package/dist/parser/tests/expression/Primary.spec.js +41 -41
- package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +110 -2
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/Relational.spec.js +43 -43
- package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +6 -6
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +18 -18
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +100 -100
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +36 -36
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
- package/dist/parser/tests/statement/Declaration.spec.js +44 -44
- package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
- package/dist/parser/tests/statement/Dim.spec.js +21 -21
- package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
- package/dist/parser/tests/statement/Function.spec.js +198 -197
- package/dist/parser/tests/statement/Function.spec.js.map +1 -1
- package/dist/parser/tests/statement/Goto.spec.js +15 -14
- package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +50 -50
- package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +14 -2
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/LibraryStatement.spec.js +17 -17
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Misc.spec.js +91 -90
- package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +34 -34
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +46 -46
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +83 -83
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/parser/tests/statement/Stop.spec.js +12 -11
- package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
- package/dist/parser/tests/statement/Throw.spec.js +5 -5
- package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
- package/dist/parser/tests/statement/TryCatch.spec.js +13 -13
- package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
- package/dist/preprocessor/Chunk.d.ts +1 -1
- package/dist/preprocessor/Chunk.js.map +1 -1
- package/dist/preprocessor/Manifest.d.ts +1 -1
- package/dist/preprocessor/Preprocessor.d.ts +1 -1
- package/dist/preprocessor/Preprocessor.js +8 -8
- package/dist/preprocessor/Preprocessor.js.map +1 -1
- package/dist/preprocessor/Preprocessor.spec.js +49 -49
- package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
- package/dist/preprocessor/PreprocessorParser.spec.js +72 -72
- package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
- package/dist/types/ArrayType.d.ts +8 -5
- package/dist/types/ArrayType.js +48 -12
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +69 -10
- package/dist/types/ArrayType.spec.js.map +1 -1
- package/dist/types/BooleanType.js +3 -3
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BooleanType.spec.js +2 -2
- package/dist/types/BooleanType.spec.js.map +1 -1
- package/dist/types/BscType.d.ts +1 -1
- package/dist/types/BscType.js +1 -1
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/CustomType.d.ts +1 -1
- package/dist/types/CustomType.js +6 -4
- package/dist/types/CustomType.js.map +1 -1
- package/dist/types/DoubleType.js +7 -7
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DoubleType.spec.js +2 -2
- package/dist/types/DoubleType.spec.js.map +1 -1
- package/dist/types/DynamicType.js +1 -1
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/DynamicType.spec.js +2 -2
- package/dist/types/DynamicType.spec.js.map +1 -1
- package/dist/types/FloatType.js +7 -7
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FloatType.spec.js +2 -2
- package/dist/types/FloatType.spec.js.map +1 -1
- package/dist/types/FunctionType.d.ts +5 -5
- package/dist/types/FunctionType.js +13 -13
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/FunctionType.spec.js +7 -7
- package/dist/types/FunctionType.spec.js.map +1 -1
- package/dist/types/IntegerType.js +7 -7
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/IntegerType.spec.js +2 -2
- package/dist/types/IntegerType.spec.js.map +1 -1
- package/dist/types/InterfaceType.js +3 -3
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.js +7 -7
- package/dist/types/InterfaceType.spec.js.map +1 -1
- package/dist/types/InvalidType.js +4 -4
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/InvalidType.spec.js +2 -2
- package/dist/types/InvalidType.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/LongIntegerType.js +8 -8
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/LongIntegerType.spec.js +2 -2
- package/dist/types/LongIntegerType.spec.js.map +1 -1
- package/dist/types/ObjectType.js +3 -3
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ObjectType.spec.js +2 -2
- package/dist/types/ObjectType.spec.js.map +1 -1
- package/dist/types/StringType.js +3 -3
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/StringType.spec.js +2 -2
- package/dist/types/StringType.spec.js.map +1 -1
- package/dist/types/UninitializedType.js +3 -3
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/VoidType.js +3 -3
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/VoidType.spec.js +2 -2
- package/dist/types/VoidType.spec.js.map +1 -1
- package/dist/types/helpers.js +6 -6
- package/dist/types/helpers.js.map +1 -1
- package/dist/util.d.ts +15 -9
- package/dist/util.js +104 -57
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.js +40 -40
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +10 -9
- 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.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 -17
- 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,11 @@ const Logger_1 = require("../Logger");
|
|
|
10
12
|
const reflection_1 = require("../astUtils/reflection");
|
|
11
13
|
const visitors_1 = require("../astUtils/visitors");
|
|
12
14
|
const creators_1 = require("../astUtils/creators");
|
|
13
|
-
const DynamicType_1 = require("../types/DynamicType");
|
|
14
15
|
const SymbolTable_1 = require("../SymbolTable");
|
|
16
|
+
const DynamicType_1 = require("../types/DynamicType");
|
|
15
17
|
const ObjectType_1 = require("../types/ObjectType");
|
|
16
18
|
const ArrayType_1 = require("../types/ArrayType");
|
|
17
19
|
const helpers_1 = require("../types/helpers");
|
|
18
|
-
const _1 = require(".");
|
|
19
20
|
class Parser {
|
|
20
21
|
constructor() {
|
|
21
22
|
/**
|
|
@@ -61,13 +62,13 @@ class Parser {
|
|
|
61
62
|
this._references = undefined;
|
|
62
63
|
}
|
|
63
64
|
addPropertyHints(item) {
|
|
64
|
-
if (
|
|
65
|
+
if ((0, Token_1.isToken)(item)) {
|
|
65
66
|
const name = item.text;
|
|
66
67
|
this._references.propertyHints[name.toLowerCase()] = name;
|
|
67
68
|
}
|
|
68
69
|
else {
|
|
69
70
|
for (const member of item.elements) {
|
|
70
|
-
if (!reflection_1.isCommentStatement(member)) {
|
|
71
|
+
if (!(0, reflection_1.isCommentStatement)(member)) {
|
|
71
72
|
const name = member.keyToken.text;
|
|
72
73
|
if (!name.startsWith('"')) {
|
|
73
74
|
this._references.propertyHints[name.toLowerCase()] = name;
|
|
@@ -93,7 +94,7 @@ class Parser {
|
|
|
93
94
|
static parse(toParse, options) {
|
|
94
95
|
let tokens;
|
|
95
96
|
if (typeof toParse === 'string') {
|
|
96
|
-
tokens =
|
|
97
|
+
tokens = Lexer_1.Lexer.scan(toParse).tokens;
|
|
97
98
|
}
|
|
98
99
|
else {
|
|
99
100
|
tokens = toParse;
|
|
@@ -111,9 +112,9 @@ class Parser {
|
|
|
111
112
|
this.tokens = tokens;
|
|
112
113
|
this.options = this.sanitizeParseOptions(options);
|
|
113
114
|
this.allowedLocalIdentifiers = [
|
|
114
|
-
...
|
|
115
|
+
...TokenKind_1.AllowedLocalIdentifiers,
|
|
115
116
|
//when in plain brightscript mode, the BrighterScript source literals can be used as regular variables
|
|
116
|
-
...(this.options.mode === ParseMode.BrightScript ?
|
|
117
|
+
...(this.options.mode === ParseMode.BrightScript ? TokenKind_1.BrighterScriptSourceLiterals : [])
|
|
117
118
|
];
|
|
118
119
|
this.current = 0;
|
|
119
120
|
this.diagnostics = [];
|
|
@@ -135,7 +136,7 @@ class Parser {
|
|
|
135
136
|
!this.checkAny(...this.peekGlobalTerminators())) {
|
|
136
137
|
let dec = this.declaration();
|
|
137
138
|
if (dec) {
|
|
138
|
-
if (!reflection_1.isAnnotationExpression(dec)) {
|
|
139
|
+
if (!(0, reflection_1.isAnnotationExpression)(dec)) {
|
|
139
140
|
this.consumePendingAnnotations(dec);
|
|
140
141
|
body.statements.push(dec);
|
|
141
142
|
//ensure statement separator
|
|
@@ -184,16 +185,16 @@ class Parser {
|
|
|
184
185
|
}
|
|
185
186
|
declaration() {
|
|
186
187
|
try {
|
|
187
|
-
if (this.checkAny(
|
|
188
|
+
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
188
189
|
return this.functionDeclaration(false);
|
|
189
190
|
}
|
|
190
191
|
if (this.checkLibrary()) {
|
|
191
192
|
return this.libraryStatement();
|
|
192
193
|
}
|
|
193
|
-
if (this.check(
|
|
194
|
+
if (this.check(TokenKind_1.TokenKind.At) && this.checkNext(TokenKind_1.TokenKind.Identifier)) {
|
|
194
195
|
return this.annotationExpression();
|
|
195
196
|
}
|
|
196
|
-
if (this.check(
|
|
197
|
+
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
197
198
|
return this.commentStatement();
|
|
198
199
|
}
|
|
199
200
|
//catch certain global terminators to prevent unnecessary lookahead (i.e. like `end namespace`, no need to continue)
|
|
@@ -211,17 +212,17 @@ class Parser {
|
|
|
211
212
|
}
|
|
212
213
|
}
|
|
213
214
|
identifier(...additionalTokenKinds) {
|
|
214
|
-
const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
215
|
+
const identifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...additionalTokenKinds);
|
|
215
216
|
// force the name into an identifier so the AST makes some sense
|
|
216
|
-
identifier.kind =
|
|
217
|
+
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
217
218
|
return identifier;
|
|
218
219
|
}
|
|
219
220
|
/**
|
|
220
221
|
* Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration`
|
|
221
222
|
*/
|
|
222
223
|
interfaceFieldStatement() {
|
|
223
|
-
const name = this.identifier(...
|
|
224
|
-
let asToken = this.consumeToken(
|
|
224
|
+
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
225
|
+
let asToken = this.consumeToken(TokenKind_1.TokenKind.As);
|
|
225
226
|
let typeToken = this.typeToken();
|
|
226
227
|
const type = util_1.util.tokenToBscType(typeToken);
|
|
227
228
|
if (!type) {
|
|
@@ -235,13 +236,13 @@ class Parser {
|
|
|
235
236
|
*/
|
|
236
237
|
interfaceMethodStatement() {
|
|
237
238
|
const functionType = this.advance();
|
|
238
|
-
const name = this.identifier(...
|
|
239
|
-
const leftParen = this.consumeToken(
|
|
239
|
+
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
240
|
+
const leftParen = this.consumeToken(TokenKind_1.TokenKind.LeftParen);
|
|
240
241
|
const params = [];
|
|
241
|
-
const rightParen = this.consumeToken(
|
|
242
|
+
const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
|
|
242
243
|
let asToken = null;
|
|
243
244
|
let returnTypeToken = null;
|
|
244
|
-
if (this.check(
|
|
245
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
245
246
|
asToken = this.advance();
|
|
246
247
|
returnTypeToken = this.typeToken();
|
|
247
248
|
const returnType = util_1.util.tokenToBscType(returnTypeToken);
|
|
@@ -255,7 +256,7 @@ class Parser {
|
|
|
255
256
|
interfaceDeclaration() {
|
|
256
257
|
this.warnIfNotBrighterScriptMode('interface declarations');
|
|
257
258
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
258
|
-
const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(
|
|
259
|
+
const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
|
|
259
260
|
const nameToken = this.identifier(...this.allowedLocalIdentifiers);
|
|
260
261
|
let extendsToken;
|
|
261
262
|
let parentInterfaceName;
|
|
@@ -266,23 +267,23 @@ class Parser {
|
|
|
266
267
|
this.consumeStatementSeparators();
|
|
267
268
|
//gather up all interface members (Fields, Methods)
|
|
268
269
|
let body = [];
|
|
269
|
-
while (this.checkAny(
|
|
270
|
+
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
270
271
|
try {
|
|
271
272
|
let decl;
|
|
272
273
|
//collect leading annotations
|
|
273
|
-
if (this.check(
|
|
274
|
+
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
274
275
|
this.annotationExpression();
|
|
275
276
|
}
|
|
276
277
|
//fields
|
|
277
|
-
if (this.checkAny(
|
|
278
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
278
279
|
decl = this.interfaceFieldStatement();
|
|
279
280
|
//methods (function/sub keyword followed by opening paren)
|
|
280
281
|
}
|
|
281
|
-
else if (this.checkAny(
|
|
282
|
+
else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
282
283
|
decl = this.interfaceMethodStatement();
|
|
283
284
|
//comments
|
|
284
285
|
}
|
|
285
|
-
else if (this.check(
|
|
286
|
+
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
286
287
|
decl = this.commentStatement();
|
|
287
288
|
}
|
|
288
289
|
if (decl) {
|
|
@@ -291,23 +292,22 @@ class Parser {
|
|
|
291
292
|
}
|
|
292
293
|
else {
|
|
293
294
|
//we didn't find a declaration...flag tokens until next line
|
|
294
|
-
this.flagUntil(
|
|
295
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
295
296
|
}
|
|
296
297
|
}
|
|
297
298
|
catch (e) {
|
|
298
299
|
//throw out any failed members and move on to the next line
|
|
299
|
-
this.flagUntil(
|
|
300
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
300
301
|
}
|
|
301
302
|
//ensure statement separator
|
|
302
303
|
this.consumeStatementSeparators();
|
|
303
304
|
//break out of this loop if we encountered the `EndInterface` token not followed by `as`
|
|
304
|
-
if (this.check(
|
|
305
|
+
if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
305
306
|
break;
|
|
306
307
|
}
|
|
307
308
|
}
|
|
308
309
|
//consume the final `end interface` token
|
|
309
|
-
const endInterfaceToken = this.consumeToken(
|
|
310
|
-
this.consumeStatementSeparators();
|
|
310
|
+
const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
|
|
311
311
|
const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endInterfaceToken, this.currentNamespaceName);
|
|
312
312
|
this._references.interfaceStatements.push(statement);
|
|
313
313
|
this.exitAnnotationBlock(parentAnnotations);
|
|
@@ -319,11 +319,11 @@ class Parser {
|
|
|
319
319
|
classDeclaration() {
|
|
320
320
|
this.warnIfNotBrighterScriptMode('class declarations');
|
|
321
321
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
322
|
-
let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(
|
|
322
|
+
let classKeyword = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Class), TokenKind_1.TokenKind.Class);
|
|
323
323
|
let extendsKeyword;
|
|
324
324
|
let parentClassName;
|
|
325
325
|
//get the class name
|
|
326
|
-
let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'),
|
|
326
|
+
let className = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('class'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
327
327
|
//see if the class inherits from parent
|
|
328
328
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
329
329
|
extendsKeyword = this.advance();
|
|
@@ -333,14 +333,14 @@ class Parser {
|
|
|
333
333
|
this.consumeStatementSeparators();
|
|
334
334
|
//gather up all class members (Fields, Methods)
|
|
335
335
|
let body = [];
|
|
336
|
-
while (this.checkAny(
|
|
336
|
+
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
337
|
try {
|
|
338
338
|
let decl;
|
|
339
339
|
let accessModifier;
|
|
340
|
-
if (this.check(
|
|
340
|
+
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
341
341
|
this.annotationExpression();
|
|
342
342
|
}
|
|
343
|
-
if (this.checkAny(
|
|
343
|
+
if (this.checkAny(TokenKind_1.TokenKind.Public, TokenKind_1.TokenKind.Protected, TokenKind_1.TokenKind.Private)) {
|
|
344
344
|
//use actual access modifier
|
|
345
345
|
accessModifier = this.advance();
|
|
346
346
|
}
|
|
@@ -349,7 +349,7 @@ class Parser {
|
|
|
349
349
|
overrideKeyword = this.advance();
|
|
350
350
|
}
|
|
351
351
|
//methods (function/sub keyword OR identifier followed by opening paren)
|
|
352
|
-
if (this.checkAny(
|
|
352
|
+
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
353
|
const funcDeclaration = this.functionDeclaration(false, false, true);
|
|
354
354
|
//remove this function from the lists because it's not a callable
|
|
355
355
|
const functionStatement = this._references.functionStatements.pop();
|
|
@@ -362,7 +362,7 @@ class Parser {
|
|
|
362
362
|
functionStatement.func.functionStatement = decl;
|
|
363
363
|
//fields
|
|
364
364
|
}
|
|
365
|
-
else if (this.checkAny(
|
|
365
|
+
else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
366
366
|
decl = this.classFieldDeclaration(accessModifier);
|
|
367
367
|
//class fields cannot be overridden
|
|
368
368
|
if (overrideKeyword) {
|
|
@@ -370,7 +370,7 @@ class Parser {
|
|
|
370
370
|
}
|
|
371
371
|
//comments
|
|
372
372
|
}
|
|
373
|
-
else if (this.check(
|
|
373
|
+
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
374
374
|
decl = this.commentStatement();
|
|
375
375
|
}
|
|
376
376
|
if (decl) {
|
|
@@ -380,13 +380,13 @@ class Parser {
|
|
|
380
380
|
}
|
|
381
381
|
catch (e) {
|
|
382
382
|
//throw out any failed members and move on to the next line
|
|
383
|
-
this.flagUntil(
|
|
383
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
384
384
|
}
|
|
385
385
|
//ensure statement separator
|
|
386
386
|
this.consumeStatementSeparators();
|
|
387
387
|
}
|
|
388
388
|
let endingKeyword = this.advance();
|
|
389
|
-
if (endingKeyword.kind !==
|
|
389
|
+
if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
|
|
390
390
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
|
|
391
391
|
}
|
|
392
392
|
const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName, this.currentSymbolTable);
|
|
@@ -398,11 +398,11 @@ class Parser {
|
|
|
398
398
|
return result;
|
|
399
399
|
}
|
|
400
400
|
classFieldDeclaration(accessModifier) {
|
|
401
|
-
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(),
|
|
401
|
+
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
402
402
|
let asToken;
|
|
403
403
|
let fieldType;
|
|
404
404
|
//look for `as SOME_TYPE`
|
|
405
|
-
if (this.check(
|
|
405
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
406
406
|
asToken = this.advance();
|
|
407
407
|
fieldType = this.typeToken();
|
|
408
408
|
//no field type specified
|
|
@@ -413,7 +413,7 @@ class Parser {
|
|
|
413
413
|
let initialValue;
|
|
414
414
|
let equal;
|
|
415
415
|
//if there is a field initializer
|
|
416
|
-
if (this.check(
|
|
416
|
+
if (this.check(TokenKind_1.TokenKind.Equal)) {
|
|
417
417
|
equal = this.advance();
|
|
418
418
|
initialValue = this.expression();
|
|
419
419
|
}
|
|
@@ -427,14 +427,14 @@ class Parser {
|
|
|
427
427
|
//track depth to help certain statements need to know if they are contained within a function body
|
|
428
428
|
this.namespaceAndFunctionDepth++;
|
|
429
429
|
let functionType;
|
|
430
|
-
if (this.checkAny(
|
|
430
|
+
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
431
431
|
functionType = this.advance();
|
|
432
432
|
}
|
|
433
433
|
else {
|
|
434
434
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
|
|
435
435
|
functionType = {
|
|
436
436
|
isReserved: true,
|
|
437
|
-
kind:
|
|
437
|
+
kind: TokenKind_1.TokenKind.Function,
|
|
438
438
|
text: 'function',
|
|
439
439
|
//zero-length location means derived
|
|
440
440
|
range: {
|
|
@@ -444,16 +444,16 @@ class Parser {
|
|
|
444
444
|
leadingWhitespace: ''
|
|
445
445
|
};
|
|
446
446
|
}
|
|
447
|
-
let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) ===
|
|
447
|
+
let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === TokenKind_1.TokenKind.Sub;
|
|
448
448
|
let functionTypeText = isSub ? 'sub' : 'function';
|
|
449
449
|
let name;
|
|
450
450
|
let leftParen;
|
|
451
451
|
if (isAnonymous) {
|
|
452
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText),
|
|
452
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), TokenKind_1.TokenKind.LeftParen);
|
|
453
453
|
}
|
|
454
454
|
else {
|
|
455
|
-
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText),
|
|
456
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText),
|
|
455
|
+
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
456
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), TokenKind_1.TokenKind.LeftParen);
|
|
457
457
|
//prevent functions from ending with type designators
|
|
458
458
|
let lastChar = name.text[name.text.length - 1];
|
|
459
459
|
if (['$', '%', '!', '#', '&'].includes(lastChar)) {
|
|
@@ -461,23 +461,23 @@ class Parser {
|
|
|
461
461
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionTypeText, name.text, lastChar)), { range: name.range }));
|
|
462
462
|
}
|
|
463
463
|
//flag functions with keywords for names (only for standard functions)
|
|
464
|
-
if (checkIdentifier &&
|
|
464
|
+
if (checkIdentifier && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
|
|
465
465
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
466
466
|
}
|
|
467
467
|
}
|
|
468
468
|
let params = [];
|
|
469
469
|
let asToken;
|
|
470
470
|
let typeToken;
|
|
471
|
-
if (!this.check(
|
|
471
|
+
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
472
472
|
do {
|
|
473
473
|
if (params.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
474
474
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(params.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
|
|
475
475
|
}
|
|
476
476
|
params.push(this.functionParameter());
|
|
477
|
-
} while (this.match(
|
|
477
|
+
} while (this.match(TokenKind_1.TokenKind.Comma));
|
|
478
478
|
}
|
|
479
479
|
let rightParen = this.advance();
|
|
480
|
-
if (this.check(
|
|
480
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
481
481
|
asToken = this.advance();
|
|
482
482
|
typeToken = this.typeToken();
|
|
483
483
|
if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
|
|
@@ -529,7 +529,7 @@ class Parser {
|
|
|
529
529
|
}
|
|
530
530
|
// consume 'end sub' or 'end function'
|
|
531
531
|
func.end = this.advance();
|
|
532
|
-
let expectedEndKind = isSub ?
|
|
532
|
+
let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
|
|
533
533
|
//if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
|
|
534
534
|
//add an error but don't hard-fail so the AST can continue more gracefully
|
|
535
535
|
if (func.end.kind !== expectedEndKind) {
|
|
@@ -553,22 +553,22 @@ class Parser {
|
|
|
553
553
|
}
|
|
554
554
|
}
|
|
555
555
|
functionParameter() {
|
|
556
|
-
if (!this.checkAny(
|
|
556
|
+
if (!this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
|
|
557
557
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
|
|
558
558
|
throw this.lastDiagnosticAsError();
|
|
559
559
|
}
|
|
560
|
-
const name = this.identifier(...
|
|
560
|
+
const name = this.identifier(...TokenKind_1.AllowedLocalIdentifiers);
|
|
561
561
|
let typeToken;
|
|
562
562
|
let defaultValue;
|
|
563
563
|
let equalsToken;
|
|
564
564
|
// parse argument default value
|
|
565
|
-
if (this.match(
|
|
565
|
+
if (this.match(TokenKind_1.TokenKind.Equal)) {
|
|
566
566
|
equalsToken = this.previous();
|
|
567
567
|
// it seems any expression is allowed here -- including ones that operate on other arguments!
|
|
568
568
|
defaultValue = this.expression();
|
|
569
569
|
}
|
|
570
570
|
let asToken = null;
|
|
571
|
-
if (this.check(
|
|
571
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
572
572
|
asToken = this.advance();
|
|
573
573
|
typeToken = this.typeToken();
|
|
574
574
|
if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
|
|
@@ -582,7 +582,7 @@ class Parser {
|
|
|
582
582
|
}
|
|
583
583
|
else if (defaultValue) {
|
|
584
584
|
type = getBscTypeFromExpression(defaultValue, this.currentFunctionExpression);
|
|
585
|
-
if (reflection_1.isInvalidType(type)) {
|
|
585
|
+
if ((0, reflection_1.isInvalidType)(type)) {
|
|
586
586
|
type = new DynamicType_1.DynamicType();
|
|
587
587
|
}
|
|
588
588
|
}
|
|
@@ -594,17 +594,20 @@ class Parser {
|
|
|
594
594
|
assignment() {
|
|
595
595
|
let name = this.identifier(...this.allowedLocalIdentifiers);
|
|
596
596
|
//add diagnostic if name is a reserved word that cannot be used as an identifier
|
|
597
|
-
if (
|
|
597
|
+
if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
|
|
598
598
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
599
599
|
}
|
|
600
|
-
let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(
|
|
600
|
+
let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(TokenKind_1.AssignmentOperators, name.text), ...TokenKind_1.AssignmentOperators);
|
|
601
601
|
let value = this.expression();
|
|
602
602
|
let result;
|
|
603
|
-
if (operator.kind ===
|
|
603
|
+
if (operator.kind === TokenKind_1.TokenKind.Equal) {
|
|
604
604
|
result = new Statement_1.AssignmentStatement(name, operator, value, this.currentFunctionExpression);
|
|
605
605
|
}
|
|
606
606
|
else {
|
|
607
607
|
result = new Statement_1.AssignmentStatement(name, operator, new Expression_1.BinaryExpression(new Expression_1.VariableExpression(name, this.currentNamespaceName), operator, value), this.currentFunctionExpression);
|
|
608
|
+
//remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
|
|
609
|
+
this._references.expressions.delete(value);
|
|
610
|
+
this._references.expressions.add(result);
|
|
608
611
|
}
|
|
609
612
|
this._references.assignmentStatements.push(result);
|
|
610
613
|
const assignmentType = getBscTypeFromExpression(result.value, this.currentFunctionExpression);
|
|
@@ -612,14 +615,14 @@ class Parser {
|
|
|
612
615
|
return result;
|
|
613
616
|
}
|
|
614
617
|
checkLibrary() {
|
|
615
|
-
let isLibraryToken = this.check(
|
|
618
|
+
let isLibraryToken = this.check(TokenKind_1.TokenKind.Library);
|
|
616
619
|
//if we are at the top level, any line that starts with "library" should be considered a library statement
|
|
617
620
|
if (this.isAtRootLevel() && isLibraryToken) {
|
|
618
621
|
return true;
|
|
619
622
|
//not at root level, library statements are all invalid here, but try to detect if the tokens look
|
|
620
623
|
//like a library statement (and let the libraryStatement function handle emitting the diagnostics)
|
|
621
624
|
}
|
|
622
|
-
else if (isLibraryToken && this.checkNext(
|
|
625
|
+
else if (isLibraryToken && this.checkNext(TokenKind_1.TokenKind.StringLiteral)) {
|
|
623
626
|
return true;
|
|
624
627
|
//definitely not a library statement
|
|
625
628
|
}
|
|
@@ -631,54 +634,54 @@ class Parser {
|
|
|
631
634
|
if (this.checkLibrary()) {
|
|
632
635
|
return this.libraryStatement();
|
|
633
636
|
}
|
|
634
|
-
if (this.check(
|
|
637
|
+
if (this.check(TokenKind_1.TokenKind.Import)) {
|
|
635
638
|
return this.importStatement();
|
|
636
639
|
}
|
|
637
|
-
if (this.check(
|
|
640
|
+
if (this.check(TokenKind_1.TokenKind.Stop)) {
|
|
638
641
|
return this.stopStatement();
|
|
639
642
|
}
|
|
640
|
-
if (this.check(
|
|
643
|
+
if (this.check(TokenKind_1.TokenKind.If)) {
|
|
641
644
|
return this.ifStatement();
|
|
642
645
|
}
|
|
643
646
|
//`try` must be followed by a block, otherwise it could be a local variable
|
|
644
|
-
if (this.check(
|
|
647
|
+
if (this.check(TokenKind_1.TokenKind.Try) && this.checkAnyNext(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
|
|
645
648
|
return this.tryCatchStatement();
|
|
646
649
|
}
|
|
647
|
-
if (this.check(
|
|
650
|
+
if (this.check(TokenKind_1.TokenKind.Throw)) {
|
|
648
651
|
return this.throwStatement();
|
|
649
652
|
}
|
|
650
|
-
if (this.checkAny(
|
|
653
|
+
if (this.checkAny(TokenKind_1.TokenKind.Print, TokenKind_1.TokenKind.Question)) {
|
|
651
654
|
return this.printStatement();
|
|
652
655
|
}
|
|
653
|
-
if (this.check(
|
|
656
|
+
if (this.check(TokenKind_1.TokenKind.Dim)) {
|
|
654
657
|
return this.dimStatement();
|
|
655
658
|
}
|
|
656
|
-
if (this.check(
|
|
659
|
+
if (this.check(TokenKind_1.TokenKind.While)) {
|
|
657
660
|
return this.whileStatement();
|
|
658
661
|
}
|
|
659
|
-
if (this.check(
|
|
662
|
+
if (this.check(TokenKind_1.TokenKind.ExitWhile)) {
|
|
660
663
|
return this.exitWhile();
|
|
661
664
|
}
|
|
662
|
-
if (this.check(
|
|
665
|
+
if (this.check(TokenKind_1.TokenKind.For)) {
|
|
663
666
|
return this.forStatement();
|
|
664
667
|
}
|
|
665
|
-
if (this.check(
|
|
668
|
+
if (this.check(TokenKind_1.TokenKind.ForEach)) {
|
|
666
669
|
return this.forEachStatement();
|
|
667
670
|
}
|
|
668
|
-
if (this.check(
|
|
671
|
+
if (this.check(TokenKind_1.TokenKind.ExitFor)) {
|
|
669
672
|
return this.exitFor();
|
|
670
673
|
}
|
|
671
|
-
if (this.check(
|
|
674
|
+
if (this.check(TokenKind_1.TokenKind.End)) {
|
|
672
675
|
return this.endStatement();
|
|
673
676
|
}
|
|
674
|
-
if (this.match(
|
|
677
|
+
if (this.match(TokenKind_1.TokenKind.Return)) {
|
|
675
678
|
return this.returnStatement();
|
|
676
679
|
}
|
|
677
|
-
if (this.check(
|
|
680
|
+
if (this.check(TokenKind_1.TokenKind.Goto)) {
|
|
678
681
|
return this.gotoStatement();
|
|
679
682
|
}
|
|
680
683
|
//does this line look like a label? (i.e. `someIdentifier:` )
|
|
681
|
-
if (this.check(
|
|
684
|
+
if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
|
|
682
685
|
try {
|
|
683
686
|
return this.labelStatement();
|
|
684
687
|
}
|
|
@@ -692,18 +695,18 @@ class Parser {
|
|
|
692
695
|
// BrightScript is like python, in that variables can be declared without a `var`,
|
|
693
696
|
// `let`, (...) keyword. As such, we must check the token *after* an identifier to figure
|
|
694
697
|
// out what to do with it.
|
|
695
|
-
if (this.checkAny(
|
|
696
|
-
this.checkAnyNext(...
|
|
698
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers) &&
|
|
699
|
+
this.checkAnyNext(...TokenKind_1.AssignmentOperators)) {
|
|
697
700
|
return this.assignment();
|
|
698
701
|
}
|
|
699
702
|
//some BrighterScript keywords are allowed as a local identifiers, so we need to check for them AFTER the assignment check
|
|
700
|
-
if (this.check(
|
|
703
|
+
if (this.check(TokenKind_1.TokenKind.Interface)) {
|
|
701
704
|
return this.interfaceDeclaration();
|
|
702
705
|
}
|
|
703
|
-
if (this.check(
|
|
706
|
+
if (this.check(TokenKind_1.TokenKind.Class)) {
|
|
704
707
|
return this.classDeclaration();
|
|
705
708
|
}
|
|
706
|
-
if (this.check(
|
|
709
|
+
if (this.check(TokenKind_1.TokenKind.Namespace)) {
|
|
707
710
|
return this.namespaceStatement();
|
|
708
711
|
}
|
|
709
712
|
// TODO: support multi-statements
|
|
@@ -713,9 +716,9 @@ class Parser {
|
|
|
713
716
|
const whileKeyword = this.advance();
|
|
714
717
|
const condition = this.expression();
|
|
715
718
|
this.consumeStatementSeparators();
|
|
716
|
-
const whileBlock = this.block(
|
|
719
|
+
const whileBlock = this.block(TokenKind_1.TokenKind.EndWhile);
|
|
717
720
|
let endWhile;
|
|
718
|
-
if (!whileBlock || this.peek().kind !==
|
|
721
|
+
if (!whileBlock || this.peek().kind !== TokenKind_1.TokenKind.EndWhile) {
|
|
719
722
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('while')), { range: this.peek().range }));
|
|
720
723
|
if (!whileBlock) {
|
|
721
724
|
throw this.lastDiagnosticAsError();
|
|
@@ -738,7 +741,7 @@ class Parser {
|
|
|
738
741
|
const finalValue = this.expression();
|
|
739
742
|
let incrementExpression;
|
|
740
743
|
let stepToken;
|
|
741
|
-
if (this.check(
|
|
744
|
+
if (this.check(TokenKind_1.TokenKind.Step)) {
|
|
742
745
|
stepToken = this.advance();
|
|
743
746
|
incrementExpression = this.expression();
|
|
744
747
|
}
|
|
@@ -746,9 +749,9 @@ class Parser {
|
|
|
746
749
|
// BrightScript for/to/step loops default to a step of 1 if no `step` is provided
|
|
747
750
|
}
|
|
748
751
|
this.consumeStatementSeparators();
|
|
749
|
-
let body = this.block(
|
|
752
|
+
let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
|
|
750
753
|
let endForToken;
|
|
751
|
-
if (!body || !this.checkAny(
|
|
754
|
+
if (!body || !this.checkAny(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next)) {
|
|
752
755
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
|
|
753
756
|
if (!body) {
|
|
754
757
|
throw this.lastDiagnosticAsError();
|
|
@@ -765,7 +768,7 @@ class Parser {
|
|
|
765
768
|
let forEach = this.advance();
|
|
766
769
|
let name = this.identifier(...this.allowedLocalIdentifiers);
|
|
767
770
|
let maybeIn = this.peek();
|
|
768
|
-
if (this.check(
|
|
771
|
+
if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
|
|
769
772
|
this.advance();
|
|
770
773
|
}
|
|
771
774
|
else {
|
|
@@ -778,14 +781,17 @@ class Parser {
|
|
|
778
781
|
throw this.lastDiagnosticAsError();
|
|
779
782
|
}
|
|
780
783
|
this.consumeStatementSeparators();
|
|
781
|
-
let body = this.block(
|
|
784
|
+
let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
|
|
782
785
|
if (!body) {
|
|
783
786
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndForOrNextToTerminateForLoop()), { range: this.peek().range }));
|
|
784
787
|
throw this.lastDiagnosticAsError();
|
|
785
788
|
}
|
|
786
789
|
let endFor = this.advance();
|
|
787
|
-
|
|
788
|
-
const
|
|
790
|
+
let itemType = new DynamicType_1.DynamicType();
|
|
791
|
+
const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
|
|
792
|
+
if ((0, reflection_1.isArrayType)(targetType)) {
|
|
793
|
+
itemType = targetType.getDefaultType();
|
|
794
|
+
}
|
|
789
795
|
this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
|
|
790
796
|
return new Statement_1.ForEachStatement(forEach, name, maybeIn, target, body, endFor);
|
|
791
797
|
}
|
|
@@ -802,7 +808,7 @@ class Parser {
|
|
|
802
808
|
}
|
|
803
809
|
else {
|
|
804
810
|
let comments = [this.advance()];
|
|
805
|
-
while (this.check(
|
|
811
|
+
while (this.check(TokenKind_1.TokenKind.Newline) && this.checkNext(TokenKind_1.TokenKind.Comment)) {
|
|
806
812
|
this.advance();
|
|
807
813
|
comments.push(this.advance());
|
|
808
814
|
}
|
|
@@ -820,13 +826,13 @@ class Parser {
|
|
|
820
826
|
//set the current namespace name
|
|
821
827
|
let result = new Statement_1.NamespaceStatement(keyword, name, null, null, this.currentSymbolTable);
|
|
822
828
|
this.currentNamespace = result;
|
|
823
|
-
this.globalTerminators.push([
|
|
829
|
+
this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
|
|
824
830
|
let body = this.body();
|
|
825
831
|
this.globalTerminators.pop();
|
|
826
832
|
//unset the current namespace name
|
|
827
833
|
this.currentNamespace = undefined;
|
|
828
834
|
let endKeyword;
|
|
829
|
-
if (this.check(
|
|
835
|
+
if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
|
|
830
836
|
endKeyword = this.advance();
|
|
831
837
|
}
|
|
832
838
|
else {
|
|
@@ -843,24 +849,24 @@ class Parser {
|
|
|
843
849
|
* Get an expression with identifiers separated by periods. Useful for namespaces and class extends
|
|
844
850
|
*/
|
|
845
851
|
getNamespacedVariableNameExpression() {
|
|
846
|
-
let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text),
|
|
852
|
+
let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
847
853
|
let expr;
|
|
848
854
|
if (firstIdentifier) {
|
|
849
855
|
// force it into an identifier so the AST makes some sense
|
|
850
|
-
firstIdentifier.kind =
|
|
856
|
+
firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
851
857
|
expr = new Expression_1.VariableExpression(firstIdentifier, null);
|
|
852
858
|
//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),
|
|
859
|
+
while (this.check(TokenKind_1.TokenKind.Dot)) {
|
|
860
|
+
let dot = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.Dot);
|
|
855
861
|
if (!dot) {
|
|
856
862
|
break;
|
|
857
863
|
}
|
|
858
|
-
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
864
|
+
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers, ...TokenKind_1.AllowedProperties);
|
|
859
865
|
if (!identifier) {
|
|
860
866
|
break;
|
|
861
867
|
}
|
|
862
868
|
// force it into an identifier so the AST makes some sense
|
|
863
|
-
identifier.kind =
|
|
869
|
+
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
864
870
|
expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
|
|
865
871
|
}
|
|
866
872
|
}
|
|
@@ -892,7 +898,7 @@ class Parser {
|
|
|
892
898
|
let libStatement = new Statement_1.LibraryStatement({
|
|
893
899
|
library: this.advance(),
|
|
894
900
|
//grab the next token only if it's a string
|
|
895
|
-
filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'),
|
|
901
|
+
filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
|
|
896
902
|
});
|
|
897
903
|
this._references.libraryStatements.push(libStatement);
|
|
898
904
|
return libStatement;
|
|
@@ -901,20 +907,20 @@ class Parser {
|
|
|
901
907
|
this.warnIfNotBrighterScriptMode('import statements');
|
|
902
908
|
let importStatement = new Statement_1.ImportStatement(this.advance(),
|
|
903
909
|
//grab the next token only if it's a string
|
|
904
|
-
this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'),
|
|
910
|
+
this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
|
|
905
911
|
this._references.importStatements.push(importStatement);
|
|
906
912
|
return importStatement;
|
|
907
913
|
}
|
|
908
914
|
annotationExpression() {
|
|
909
915
|
const atToken = this.advance();
|
|
910
|
-
const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
916
|
+
const identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
911
917
|
if (identifier) {
|
|
912
|
-
identifier.kind =
|
|
918
|
+
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
913
919
|
}
|
|
914
920
|
let annotation = new Expression_1.AnnotationExpression(atToken, identifier);
|
|
915
921
|
this.pendingAnnotations.push(annotation);
|
|
916
922
|
//optional arguments
|
|
917
|
-
if (this.check(
|
|
923
|
+
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
918
924
|
let leftParen = this.advance();
|
|
919
925
|
annotation.call = this.finishCall(leftParen, annotation, false);
|
|
920
926
|
}
|
|
@@ -927,7 +933,7 @@ class Parser {
|
|
|
927
933
|
}
|
|
928
934
|
const questionMarkToken = this.advance();
|
|
929
935
|
//consume newlines or comments
|
|
930
|
-
while (this.checkAny(
|
|
936
|
+
while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
931
937
|
this.advance();
|
|
932
938
|
}
|
|
933
939
|
let consequent;
|
|
@@ -936,12 +942,12 @@ class Parser {
|
|
|
936
942
|
}
|
|
937
943
|
catch (_a) { }
|
|
938
944
|
//consume newlines or comments
|
|
939
|
-
while (this.checkAny(
|
|
945
|
+
while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
940
946
|
this.advance();
|
|
941
947
|
}
|
|
942
|
-
const colonToken = this.tryConsumeToken(
|
|
948
|
+
const colonToken = this.tryConsumeToken(TokenKind_1.TokenKind.Colon);
|
|
943
949
|
//consume newlines
|
|
944
|
-
while (this.checkAny(
|
|
950
|
+
while (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
945
951
|
this.advance();
|
|
946
952
|
}
|
|
947
953
|
let alternate;
|
|
@@ -958,7 +964,8 @@ class Parser {
|
|
|
958
964
|
return new Expression_1.NullCoalescingExpression(test, questionQuestionToken, alternate);
|
|
959
965
|
}
|
|
960
966
|
regexLiteralExpression() {
|
|
961
|
-
|
|
967
|
+
this.warnIfNotBrighterScriptMode('regular expression literal');
|
|
968
|
+
return new Expression_1.RegexLiteralExpression({
|
|
962
969
|
regexLiteral: this.advance()
|
|
963
970
|
});
|
|
964
971
|
}
|
|
@@ -967,23 +974,23 @@ class Parser {
|
|
|
967
974
|
//get the tag name
|
|
968
975
|
let tagName;
|
|
969
976
|
if (isTagged) {
|
|
970
|
-
tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
977
|
+
tagName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
971
978
|
// force it into an identifier so the AST makes some sense
|
|
972
|
-
tagName.kind =
|
|
979
|
+
tagName.kind = TokenKind_1.TokenKind.Identifier;
|
|
973
980
|
}
|
|
974
981
|
let quasis = [];
|
|
975
982
|
let expressions = [];
|
|
976
983
|
let openingBacktick = this.peek();
|
|
977
984
|
this.advance();
|
|
978
985
|
let currentQuasiExpressionParts = [];
|
|
979
|
-
while (!this.isAtEnd() && !this.check(
|
|
986
|
+
while (!this.isAtEnd() && !this.check(TokenKind_1.TokenKind.BackTick)) {
|
|
980
987
|
let next = this.peek();
|
|
981
|
-
if (next.kind ===
|
|
988
|
+
if (next.kind === TokenKind_1.TokenKind.TemplateStringQuasi) {
|
|
982
989
|
//a quasi can actually be made up of multiple quasis when it includes char literals
|
|
983
990
|
currentQuasiExpressionParts.push(new Expression_1.LiteralExpression(next));
|
|
984
991
|
this.advance();
|
|
985
992
|
}
|
|
986
|
-
else if (next.kind ===
|
|
993
|
+
else if (next.kind === TokenKind_1.TokenKind.EscapedCharCodeLiteral) {
|
|
987
994
|
currentQuasiExpressionParts.push(new Expression_1.EscapedCharCodeLiteralExpression(next));
|
|
988
995
|
this.advance();
|
|
989
996
|
}
|
|
@@ -991,12 +998,12 @@ class Parser {
|
|
|
991
998
|
//finish up the current quasi
|
|
992
999
|
quasis.push(new Expression_1.TemplateStringQuasiExpression(currentQuasiExpressionParts));
|
|
993
1000
|
currentQuasiExpressionParts = [];
|
|
994
|
-
if (next.kind ===
|
|
1001
|
+
if (next.kind === TokenKind_1.TokenKind.TemplateStringExpressionBegin) {
|
|
995
1002
|
this.advance();
|
|
996
1003
|
}
|
|
997
1004
|
//now keep this expression
|
|
998
1005
|
expressions.push(this.expression());
|
|
999
|
-
if (!this.isAtEnd() && this.check(
|
|
1006
|
+
if (!this.isAtEnd() && this.check(TokenKind_1.TokenKind.TemplateStringExpressionEnd)) {
|
|
1000
1007
|
//TODO is it an error if this is not present?
|
|
1001
1008
|
this.advance();
|
|
1002
1009
|
}
|
|
@@ -1028,12 +1035,12 @@ class Parser {
|
|
|
1028
1035
|
const statement = new Statement_1.TryCatchStatement(tryToken);
|
|
1029
1036
|
//ensure statement separator
|
|
1030
1037
|
this.consumeStatementSeparators();
|
|
1031
|
-
statement.tryBranch = this.block(
|
|
1038
|
+
statement.tryBranch = this.block(TokenKind_1.TokenKind.Catch, TokenKind_1.TokenKind.EndTry);
|
|
1032
1039
|
const peek = this.peek();
|
|
1033
|
-
if (peek.kind !==
|
|
1040
|
+
if (peek.kind !== TokenKind_1.TokenKind.Catch) {
|
|
1034
1041
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedCatchBlockInTryCatch()), { range: this.peek().range }));
|
|
1035
1042
|
//gracefully handle end-try
|
|
1036
|
-
if (peek.kind ===
|
|
1043
|
+
if (peek.kind === TokenKind_1.TokenKind.EndTry) {
|
|
1037
1044
|
statement.endTryToken = this.advance();
|
|
1038
1045
|
}
|
|
1039
1046
|
return statement;
|
|
@@ -1041,16 +1048,16 @@ class Parser {
|
|
|
1041
1048
|
else {
|
|
1042
1049
|
statement.catchToken = this.advance();
|
|
1043
1050
|
}
|
|
1044
|
-
const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(),
|
|
1051
|
+
const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
1045
1052
|
if (exceptionVarToken) {
|
|
1046
1053
|
// force it into an identifier so the AST makes some sense
|
|
1047
|
-
exceptionVarToken.kind =
|
|
1054
|
+
exceptionVarToken.kind = TokenKind_1.TokenKind.Identifier;
|
|
1048
1055
|
statement.exceptionVariable = exceptionVarToken;
|
|
1049
1056
|
}
|
|
1050
1057
|
//ensure statement sepatator
|
|
1051
1058
|
this.consumeStatementSeparators();
|
|
1052
|
-
statement.catchBranch = this.block(
|
|
1053
|
-
if (this.peek().kind !==
|
|
1059
|
+
statement.catchBranch = this.block(TokenKind_1.TokenKind.EndTry);
|
|
1060
|
+
if (this.peek().kind !== TokenKind_1.TokenKind.EndTry) {
|
|
1054
1061
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndTryToTerminateTryCatch()), { range: this.peek().range }));
|
|
1055
1062
|
}
|
|
1056
1063
|
else {
|
|
@@ -1061,7 +1068,7 @@ class Parser {
|
|
|
1061
1068
|
throwStatement() {
|
|
1062
1069
|
const throwToken = this.advance();
|
|
1063
1070
|
let expression;
|
|
1064
|
-
if (this.checkAny(
|
|
1071
|
+
if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
|
|
1065
1072
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExceptionExpressionAfterThrowKeyword()), { range: throwToken.range }));
|
|
1066
1073
|
}
|
|
1067
1074
|
else {
|
|
@@ -1071,19 +1078,19 @@ class Parser {
|
|
|
1071
1078
|
}
|
|
1072
1079
|
dimStatement() {
|
|
1073
1080
|
const dim = this.advance();
|
|
1074
|
-
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'),
|
|
1081
|
+
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('dim'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
1075
1082
|
// force to an identifier so the AST makes some sense
|
|
1076
1083
|
if (identifier) {
|
|
1077
|
-
identifier.kind =
|
|
1084
|
+
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
1078
1085
|
}
|
|
1079
|
-
let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(),
|
|
1086
|
+
let leftSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingLeftSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.LeftSquareBracket);
|
|
1080
1087
|
let expressions = [];
|
|
1081
1088
|
let expression;
|
|
1082
1089
|
do {
|
|
1083
1090
|
try {
|
|
1084
1091
|
expression = this.expression();
|
|
1085
1092
|
expressions.push(expression);
|
|
1086
|
-
if (this.check(
|
|
1093
|
+
if (this.check(TokenKind_1.TokenKind.Comma)) {
|
|
1087
1094
|
this.advance();
|
|
1088
1095
|
}
|
|
1089
1096
|
else {
|
|
@@ -1097,15 +1104,15 @@ class Parser {
|
|
|
1097
1104
|
if (expressions.length === 0) {
|
|
1098
1105
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
|
|
1099
1106
|
}
|
|
1100
|
-
let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(),
|
|
1107
|
+
let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1101
1108
|
return new Statement_1.DimStatement(dim, identifier, leftSquareBracket, expressions, rightSquareBracket);
|
|
1102
1109
|
}
|
|
1103
1110
|
ifStatement() {
|
|
1104
1111
|
// colon before `if` is usually not allowed, unless it's after `then`
|
|
1105
1112
|
if (this.current > 0) {
|
|
1106
1113
|
const prev = this.previous();
|
|
1107
|
-
if (prev.kind ===
|
|
1108
|
-
if (this.current > 1 && this.tokens[this.current - 2].kind !==
|
|
1114
|
+
if (prev.kind === TokenKind_1.TokenKind.Colon) {
|
|
1115
|
+
if (this.current > 1 && this.tokens[this.current - 2].kind !== TokenKind_1.TokenKind.Then) {
|
|
1109
1116
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedColonBeforeIfStatement()), { range: prev.range }));
|
|
1110
1117
|
}
|
|
1111
1118
|
}
|
|
@@ -1119,14 +1126,14 @@ class Parser {
|
|
|
1119
1126
|
let endIfToken;
|
|
1120
1127
|
let elseToken;
|
|
1121
1128
|
//optional `then`
|
|
1122
|
-
if (this.check(
|
|
1129
|
+
if (this.check(TokenKind_1.TokenKind.Then)) {
|
|
1123
1130
|
thenToken = this.advance();
|
|
1124
1131
|
}
|
|
1125
1132
|
//is it inline or multi-line if?
|
|
1126
|
-
const isInlineIfThen = !this.checkAny(
|
|
1133
|
+
const isInlineIfThen = !this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment);
|
|
1127
1134
|
if (isInlineIfThen) {
|
|
1128
1135
|
/*** PARSE INLINE IF STATEMENT ***/
|
|
1129
|
-
thenBranch = this.inlineConditionalBranch(
|
|
1136
|
+
thenBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
|
|
1130
1137
|
if (!thenBranch) {
|
|
1131
1138
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementToFollowConditionalCondition(ifToken.text)), { range: this.peek().range }));
|
|
1132
1139
|
throw this.lastDiagnosticAsError();
|
|
@@ -1135,9 +1142,9 @@ class Parser {
|
|
|
1135
1142
|
this.ensureInline(thenBranch.statements);
|
|
1136
1143
|
}
|
|
1137
1144
|
//else branch
|
|
1138
|
-
if (this.check(
|
|
1145
|
+
if (this.check(TokenKind_1.TokenKind.Else)) {
|
|
1139
1146
|
elseToken = this.advance();
|
|
1140
|
-
if (this.check(
|
|
1147
|
+
if (this.check(TokenKind_1.TokenKind.If)) {
|
|
1141
1148
|
// recurse-read `else if`
|
|
1142
1149
|
elseBranch = this.ifStatement();
|
|
1143
1150
|
//no multi-line if chained with an inline if
|
|
@@ -1145,13 +1152,13 @@ class Parser {
|
|
|
1145
1152
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: elseBranch.range }));
|
|
1146
1153
|
}
|
|
1147
1154
|
}
|
|
1148
|
-
else if (this.checkAny(
|
|
1155
|
+
else if (this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
|
|
1149
1156
|
//expecting inline else branch
|
|
1150
1157
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: this.peek().range }));
|
|
1151
1158
|
throw this.lastDiagnosticAsError();
|
|
1152
1159
|
}
|
|
1153
1160
|
else {
|
|
1154
|
-
elseBranch = this.inlineConditionalBranch(
|
|
1161
|
+
elseBranch = this.inlineConditionalBranch(TokenKind_1.TokenKind.Else, TokenKind_1.TokenKind.EndIf);
|
|
1155
1162
|
if (elseBranch) {
|
|
1156
1163
|
this.ensureInline(elseBranch.statements);
|
|
1157
1164
|
}
|
|
@@ -1162,12 +1169,12 @@ class Parser {
|
|
|
1162
1169
|
throw this.lastDiagnosticAsError();
|
|
1163
1170
|
}
|
|
1164
1171
|
}
|
|
1165
|
-
if (!elseBranch || !reflection_1.isIfStatement(elseBranch)) {
|
|
1172
|
+
if (!elseBranch || !(0, reflection_1.isIfStatement)(elseBranch)) {
|
|
1166
1173
|
//enforce newline at the end of the inline if statement
|
|
1167
1174
|
const peek = this.peek();
|
|
1168
|
-
if (peek.kind !==
|
|
1175
|
+
if (peek.kind !== TokenKind_1.TokenKind.Newline && peek.kind !== TokenKind_1.TokenKind.Comment && !this.isAtEnd()) {
|
|
1169
1176
|
//ignore last error if it was about a colon
|
|
1170
|
-
if (this.previous().kind ===
|
|
1177
|
+
if (this.previous().kind === TokenKind_1.TokenKind.Colon) {
|
|
1171
1178
|
this.diagnostics.pop();
|
|
1172
1179
|
this.current--;
|
|
1173
1180
|
}
|
|
@@ -1182,9 +1189,9 @@ class Parser {
|
|
|
1182
1189
|
//ensure newline/colon before next keyword
|
|
1183
1190
|
this.ensureNewLineOrColon();
|
|
1184
1191
|
//else branch
|
|
1185
|
-
if (this.check(
|
|
1192
|
+
if (this.check(TokenKind_1.TokenKind.Else)) {
|
|
1186
1193
|
elseToken = this.advance();
|
|
1187
|
-
if (this.check(
|
|
1194
|
+
if (this.check(TokenKind_1.TokenKind.If)) {
|
|
1188
1195
|
// recurse-read `else if`
|
|
1189
1196
|
elseBranch = this.ifStatement();
|
|
1190
1197
|
}
|
|
@@ -1194,8 +1201,8 @@ class Parser {
|
|
|
1194
1201
|
this.ensureNewLineOrColon();
|
|
1195
1202
|
}
|
|
1196
1203
|
}
|
|
1197
|
-
if (!reflection_1.isIfStatement(elseBranch)) {
|
|
1198
|
-
if (this.check(
|
|
1204
|
+
if (!(0, reflection_1.isIfStatement)(elseBranch)) {
|
|
1205
|
+
if (this.check(TokenKind_1.TokenKind.EndIf)) {
|
|
1199
1206
|
endIfToken = this.advance();
|
|
1200
1207
|
}
|
|
1201
1208
|
else {
|
|
@@ -1218,7 +1225,7 @@ class Parser {
|
|
|
1218
1225
|
let diagnosticsLengthBeforeBlock = this.diagnostics.length;
|
|
1219
1226
|
// we're parsing a multi-line ("block") form of the BrightScript if/then and must find
|
|
1220
1227
|
// a trailing "end if" or "else if"
|
|
1221
|
-
let branch = this.block(
|
|
1228
|
+
let branch = this.block(TokenKind_1.TokenKind.EndIf, TokenKind_1.TokenKind.Else);
|
|
1222
1229
|
if (!branch) {
|
|
1223
1230
|
//throw out any new diagnostics created as a result of a `then` block parse failure.
|
|
1224
1231
|
//the block() function will discard the current line, so any discarded diagnostics will
|
|
@@ -1232,7 +1239,7 @@ class Parser {
|
|
|
1232
1239
|
}
|
|
1233
1240
|
ensureNewLineOrColon(silent = false) {
|
|
1234
1241
|
const prev = this.previous().kind;
|
|
1235
|
-
if (prev !==
|
|
1242
|
+
if (prev !== TokenKind_1.TokenKind.Newline && prev !== TokenKind_1.TokenKind.Colon) {
|
|
1236
1243
|
if (!silent) {
|
|
1237
1244
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedNewlineOrColon()), { range: this.peek().range }));
|
|
1238
1245
|
}
|
|
@@ -1243,7 +1250,7 @@ class Parser {
|
|
|
1243
1250
|
//ensure each statement of an inline block is single-line
|
|
1244
1251
|
ensureInline(statements) {
|
|
1245
1252
|
for (const stat of statements) {
|
|
1246
|
-
if (reflection_1.isIfStatement(stat) && !stat.isInline) {
|
|
1253
|
+
if ((0, reflection_1.isIfStatement)(stat) && !stat.isInline) {
|
|
1247
1254
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedInlineIfStatement()), { range: stat.range }));
|
|
1248
1255
|
}
|
|
1249
1256
|
}
|
|
@@ -1261,12 +1268,12 @@ class Parser {
|
|
|
1261
1268
|
const startingRange = statement.range;
|
|
1262
1269
|
//look for colon statement separator
|
|
1263
1270
|
let foundColon = false;
|
|
1264
|
-
while (this.match(
|
|
1271
|
+
while (this.match(TokenKind_1.TokenKind.Colon)) {
|
|
1265
1272
|
foundColon = true;
|
|
1266
1273
|
}
|
|
1267
1274
|
//if a colon was found, add the next statement or err if unexpected
|
|
1268
1275
|
if (foundColon) {
|
|
1269
|
-
if (!this.checkAny(
|
|
1276
|
+
if (!this.checkAny(TokenKind_1.TokenKind.Newline, ...additionalTerminators)) {
|
|
1270
1277
|
//if not an ending keyword, add next statement
|
|
1271
1278
|
let extra = this.inlineConditionalBranch(...additionalTerminators);
|
|
1272
1279
|
if (!extra) {
|
|
@@ -1284,19 +1291,21 @@ class Parser {
|
|
|
1284
1291
|
}
|
|
1285
1292
|
expressionStatement(expr) {
|
|
1286
1293
|
let expressionStart = this.peek();
|
|
1287
|
-
if (this.checkAny(
|
|
1294
|
+
if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
|
|
1288
1295
|
let operator = this.advance();
|
|
1289
|
-
if (this.checkAny(
|
|
1296
|
+
if (this.checkAny(TokenKind_1.TokenKind.PlusPlus, TokenKind_1.TokenKind.MinusMinus)) {
|
|
1290
1297
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.consecutiveIncrementDecrementOperatorsAreNotAllowed()), { range: this.peek().range }));
|
|
1291
1298
|
throw this.lastDiagnosticAsError();
|
|
1292
1299
|
}
|
|
1293
|
-
else if (reflection_1.isCallExpression(expr)) {
|
|
1300
|
+
else if ((0, reflection_1.isCallExpression)(expr)) {
|
|
1294
1301
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incrementDecrementOperatorsAreNotAllowedAsResultOfFunctionCall()), { range: expressionStart.range }));
|
|
1295
1302
|
throw this.lastDiagnosticAsError();
|
|
1296
1303
|
}
|
|
1297
|
-
|
|
1304
|
+
const result = new Statement_1.IncrementStatement(expr, operator);
|
|
1305
|
+
this._references.expressions.add(result);
|
|
1306
|
+
return result;
|
|
1298
1307
|
}
|
|
1299
|
-
if (reflection_1.isCallExpression(expr) || reflection_1.isCallfuncExpression(expr)) {
|
|
1308
|
+
if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
|
|
1300
1309
|
return new Statement_1.ExpressionStatement(expr);
|
|
1301
1310
|
}
|
|
1302
1311
|
//at this point, it's probably an error. However, we recover a little more gracefully by creating an assignment
|
|
@@ -1311,18 +1320,18 @@ class Parser {
|
|
|
1311
1320
|
* priority as standalone function calls though, so we can parse them in the same way.
|
|
1312
1321
|
*/
|
|
1313
1322
|
let expr = this.call();
|
|
1314
|
-
if (this.checkAny(...
|
|
1323
|
+
if (this.checkAny(...TokenKind_1.AssignmentOperators) && !((0, reflection_1.isCallExpression)(expr))) {
|
|
1315
1324
|
let left = expr;
|
|
1316
1325
|
let operator = this.advance();
|
|
1317
1326
|
let right = this.expression();
|
|
1318
1327
|
// Create a dotted or indexed "set" based on the left-hand side's type
|
|
1319
|
-
if (reflection_1.isIndexedGetExpression(left)) {
|
|
1320
|
-
return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind ===
|
|
1328
|
+
if ((0, reflection_1.isIndexedGetExpression)(left)) {
|
|
1329
|
+
return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
|
|
1321
1330
|
? right
|
|
1322
1331
|
: new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
|
|
1323
1332
|
}
|
|
1324
|
-
else if (reflection_1.isDottedGetExpression(left)) {
|
|
1325
|
-
const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind ===
|
|
1333
|
+
else if ((0, reflection_1.isDottedGetExpression)(left)) {
|
|
1334
|
+
const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
|
|
1326
1335
|
? right
|
|
1327
1336
|
: new Expression_1.BinaryExpression(left, operator, right));
|
|
1328
1337
|
this._references.dottedSetStatements.push(dottedSetStmt);
|
|
@@ -1335,13 +1344,13 @@ class Parser {
|
|
|
1335
1344
|
let printKeyword = this.advance();
|
|
1336
1345
|
let values = [];
|
|
1337
1346
|
while (!this.checkEndOfStatement()) {
|
|
1338
|
-
if (this.check(
|
|
1347
|
+
if (this.check(TokenKind_1.TokenKind.Semicolon)) {
|
|
1339
1348
|
values.push(this.advance());
|
|
1340
1349
|
}
|
|
1341
|
-
else if (this.check(
|
|
1350
|
+
else if (this.check(TokenKind_1.TokenKind.Comma)) {
|
|
1342
1351
|
values.push(this.advance());
|
|
1343
1352
|
}
|
|
1344
|
-
else if (this.check(
|
|
1353
|
+
else if (this.check(TokenKind_1.TokenKind.Else)) {
|
|
1345
1354
|
break; // inline branch
|
|
1346
1355
|
}
|
|
1347
1356
|
else {
|
|
@@ -1350,11 +1359,11 @@ class Parser {
|
|
|
1350
1359
|
}
|
|
1351
1360
|
//print statements can be empty, so look for empty print conditions
|
|
1352
1361
|
if (!values.length) {
|
|
1353
|
-
let emptyStringLiteral = creators_1.createStringLiteral('');
|
|
1362
|
+
let emptyStringLiteral = (0, creators_1.createStringLiteral)('');
|
|
1354
1363
|
values.push(emptyStringLiteral);
|
|
1355
1364
|
}
|
|
1356
1365
|
let last = values[values.length - 1];
|
|
1357
|
-
if (
|
|
1366
|
+
if ((0, Token_1.isToken)(last)) {
|
|
1358
1367
|
// TODO: error, expected value
|
|
1359
1368
|
}
|
|
1360
1369
|
return new Statement_1.PrintStatement({ print: printKeyword }, values);
|
|
@@ -1368,7 +1377,7 @@ class Parser {
|
|
|
1368
1377
|
if (this.checkEndOfStatement()) {
|
|
1369
1378
|
return new Statement_1.ReturnStatement(tokens);
|
|
1370
1379
|
}
|
|
1371
|
-
let toReturn = this.check(
|
|
1380
|
+
let toReturn = this.check(TokenKind_1.TokenKind.Else) ? undefined : this.expression();
|
|
1372
1381
|
return new Statement_1.ReturnStatement(tokens, toReturn);
|
|
1373
1382
|
}
|
|
1374
1383
|
/**
|
|
@@ -1381,7 +1390,7 @@ class Parser {
|
|
|
1381
1390
|
colon: this.advance()
|
|
1382
1391
|
};
|
|
1383
1392
|
//label must be alone on its line, this is probably not a label
|
|
1384
|
-
if (!this.checkAny(
|
|
1393
|
+
if (!this.checkAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
1385
1394
|
//rewind and cancel
|
|
1386
1395
|
this.current -= 2;
|
|
1387
1396
|
throw new CancelStatementError();
|
|
@@ -1397,7 +1406,7 @@ class Parser {
|
|
|
1397
1406
|
gotoStatement() {
|
|
1398
1407
|
let tokens = {
|
|
1399
1408
|
goto: this.advance(),
|
|
1400
|
-
label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(),
|
|
1409
|
+
label: this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLabelIdentifierAfterGotoKeyword(), TokenKind_1.TokenKind.Identifier)
|
|
1401
1410
|
};
|
|
1402
1411
|
return new Statement_1.GotoStatement(tokens);
|
|
1403
1412
|
}
|
|
@@ -1428,12 +1437,12 @@ class Parser {
|
|
|
1428
1437
|
this.consumeStatementSeparators(true);
|
|
1429
1438
|
let startingToken = this.peek();
|
|
1430
1439
|
const statements = [];
|
|
1431
|
-
while (!this.isAtEnd() && !this.checkAny(
|
|
1440
|
+
while (!this.isAtEnd() && !this.checkAny(TokenKind_1.TokenKind.EndSub, TokenKind_1.TokenKind.EndFunction, ...terminators)) {
|
|
1432
1441
|
//grab the location of the current token
|
|
1433
1442
|
let loopCurrent = this.current;
|
|
1434
1443
|
let dec = this.declaration();
|
|
1435
1444
|
if (dec) {
|
|
1436
|
-
if (!reflection_1.isAnnotationExpression(dec)) {
|
|
1445
|
+
if (!(0, reflection_1.isAnnotationExpression)(dec)) {
|
|
1437
1446
|
this.consumePendingAnnotations(dec);
|
|
1438
1447
|
statements.push(dec);
|
|
1439
1448
|
}
|
|
@@ -1444,7 +1453,7 @@ class Parser {
|
|
|
1444
1453
|
//something went wrong. reset to the top of the loop
|
|
1445
1454
|
this.current = loopCurrent;
|
|
1446
1455
|
//scrap the entire line (hopefully whatever failed has added a diagnostic)
|
|
1447
|
-
this.consumeUntil(
|
|
1456
|
+
this.consumeUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
1448
1457
|
//trash the next token. this prevents an infinite loop. not exactly sure why we need this,
|
|
1449
1458
|
//but there's already an error in the file being parsed, so just leave this line here
|
|
1450
1459
|
this.advance();
|
|
@@ -1461,8 +1470,8 @@ class Parser {
|
|
|
1461
1470
|
//if so, we need to restore the statement separator
|
|
1462
1471
|
let prev = this.previous().kind;
|
|
1463
1472
|
let peek = this.peek().kind;
|
|
1464
|
-
if ((peek ===
|
|
1465
|
-
(prev ===
|
|
1473
|
+
if ((peek === TokenKind_1.TokenKind.EndSub || peek === TokenKind_1.TokenKind.EndFunction) &&
|
|
1474
|
+
(prev === TokenKind_1.TokenKind.Newline || prev === TokenKind_1.TokenKind.Colon)) {
|
|
1466
1475
|
this.current--;
|
|
1467
1476
|
}
|
|
1468
1477
|
}
|
|
@@ -1494,13 +1503,15 @@ class Parser {
|
|
|
1494
1503
|
this.pendingAnnotations = parentAnnotations;
|
|
1495
1504
|
}
|
|
1496
1505
|
expression() {
|
|
1497
|
-
|
|
1506
|
+
const expression = this.anonymousFunction();
|
|
1507
|
+
this._references.expressions.add(expression);
|
|
1508
|
+
return expression;
|
|
1498
1509
|
}
|
|
1499
1510
|
anonymousFunction() {
|
|
1500
|
-
if (this.checkAny(
|
|
1511
|
+
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
1501
1512
|
const func = this.functionDeclaration(true);
|
|
1502
1513
|
//if there's an open paren after this, this is an IIFE
|
|
1503
|
-
if (this.check(
|
|
1514
|
+
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
1504
1515
|
return this.finishCall(this.advance(), func);
|
|
1505
1516
|
}
|
|
1506
1517
|
else {
|
|
@@ -1508,10 +1519,10 @@ class Parser {
|
|
|
1508
1519
|
}
|
|
1509
1520
|
}
|
|
1510
1521
|
let expr = this.boolean();
|
|
1511
|
-
if (this.check(
|
|
1522
|
+
if (this.check(TokenKind_1.TokenKind.Question)) {
|
|
1512
1523
|
return this.ternaryExpression(expr);
|
|
1513
1524
|
}
|
|
1514
|
-
else if (this.check(
|
|
1525
|
+
else if (this.check(TokenKind_1.TokenKind.QuestionQuestion)) {
|
|
1515
1526
|
return this.nullCoalescingExpression(expr);
|
|
1516
1527
|
}
|
|
1517
1528
|
else {
|
|
@@ -1520,7 +1531,7 @@ class Parser {
|
|
|
1520
1531
|
}
|
|
1521
1532
|
boolean() {
|
|
1522
1533
|
let expr = this.relational();
|
|
1523
|
-
while (this.matchAny(
|
|
1534
|
+
while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
|
|
1524
1535
|
let operator = this.previous();
|
|
1525
1536
|
let right = this.relational();
|
|
1526
1537
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1529,7 +1540,7 @@ class Parser {
|
|
|
1529
1540
|
}
|
|
1530
1541
|
relational() {
|
|
1531
1542
|
let expr = this.additive();
|
|
1532
|
-
while (this.matchAny(
|
|
1543
|
+
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)) {
|
|
1533
1544
|
let operator = this.previous();
|
|
1534
1545
|
let right = this.additive();
|
|
1535
1546
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1539,7 +1550,7 @@ class Parser {
|
|
|
1539
1550
|
// TODO: bitshift
|
|
1540
1551
|
additive() {
|
|
1541
1552
|
let expr = this.multiplicative();
|
|
1542
|
-
while (this.matchAny(
|
|
1553
|
+
while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
|
|
1543
1554
|
let operator = this.previous();
|
|
1544
1555
|
let right = this.multiplicative();
|
|
1545
1556
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1548,7 +1559,7 @@ class Parser {
|
|
|
1548
1559
|
}
|
|
1549
1560
|
multiplicative() {
|
|
1550
1561
|
let expr = this.exponential();
|
|
1551
|
-
while (this.matchAny(
|
|
1562
|
+
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)) {
|
|
1552
1563
|
let operator = this.previous();
|
|
1553
1564
|
let right = this.exponential();
|
|
1554
1565
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1557,7 +1568,7 @@ class Parser {
|
|
|
1557
1568
|
}
|
|
1558
1569
|
exponential() {
|
|
1559
1570
|
let expr = this.prefixUnary();
|
|
1560
|
-
while (this.match(
|
|
1571
|
+
while (this.match(TokenKind_1.TokenKind.Caret)) {
|
|
1561
1572
|
let operator = this.previous();
|
|
1562
1573
|
let right = this.prefixUnary();
|
|
1563
1574
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
@@ -1566,7 +1577,7 @@ class Parser {
|
|
|
1566
1577
|
}
|
|
1567
1578
|
prefixUnary() {
|
|
1568
1579
|
const nextKind = this.peek().kind;
|
|
1569
|
-
if (nextKind ===
|
|
1580
|
+
if (nextKind === TokenKind_1.TokenKind.Not || nextKind === TokenKind_1.TokenKind.Minus) {
|
|
1570
1581
|
this.current++; //advance
|
|
1571
1582
|
let operator = this.previous();
|
|
1572
1583
|
let right = this.prefixUnary();
|
|
@@ -1576,17 +1587,17 @@ class Parser {
|
|
|
1576
1587
|
}
|
|
1577
1588
|
indexedGet(expr) {
|
|
1578
1589
|
let openingSquare = this.previous();
|
|
1579
|
-
while (this.match(
|
|
1590
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1580
1591
|
let index = this.expression();
|
|
1581
|
-
while (this.match(
|
|
1582
|
-
let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(),
|
|
1592
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1593
|
+
let closingSquare = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1583
1594
|
return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare);
|
|
1584
1595
|
}
|
|
1585
1596
|
newExpression() {
|
|
1586
1597
|
this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
|
|
1587
1598
|
let newToken = this.advance();
|
|
1588
1599
|
let nameExpr = this.getNamespacedVariableNameExpression();
|
|
1589
|
-
let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text),
|
|
1600
|
+
let leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.LeftParen);
|
|
1590
1601
|
let call = this.finishCall(leftParen, nameExpr);
|
|
1591
1602
|
//pop the call from the callExpressions list because this is technically something else
|
|
1592
1603
|
this.callExpressions.pop();
|
|
@@ -1600,46 +1611,52 @@ class Parser {
|
|
|
1600
1611
|
callfunc(callee) {
|
|
1601
1612
|
this.warnIfNotBrighterScriptMode('callfunc operator');
|
|
1602
1613
|
let operator = this.previous();
|
|
1603
|
-
let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(),
|
|
1614
|
+
let methodName = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1604
1615
|
// force it into an identifier so the AST makes some sense
|
|
1605
|
-
methodName.kind =
|
|
1606
|
-
let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(),
|
|
1616
|
+
methodName.kind = TokenKind_1.TokenKind.Identifier;
|
|
1617
|
+
let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(), TokenKind_1.TokenKind.LeftParen);
|
|
1607
1618
|
let call = this.finishCall(openParen, callee, false);
|
|
1608
1619
|
return new Expression_1.CallfuncExpression(callee, operator, methodName, openParen, call.args, call.closingParen);
|
|
1609
1620
|
}
|
|
1610
1621
|
call() {
|
|
1611
|
-
if (this.check(
|
|
1622
|
+
if (this.check(TokenKind_1.TokenKind.New) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
|
|
1612
1623
|
return this.newExpression();
|
|
1613
1624
|
}
|
|
1614
1625
|
let expr = this.primary();
|
|
1626
|
+
//an expression to keep for _references
|
|
1627
|
+
let referenceCallExpression;
|
|
1615
1628
|
while (true) {
|
|
1616
|
-
if (this.match(
|
|
1629
|
+
if (this.match(TokenKind_1.TokenKind.LeftParen)) {
|
|
1617
1630
|
expr = this.finishCall(this.previous(), expr);
|
|
1631
|
+
//store this call expression in references
|
|
1632
|
+
referenceCallExpression = expr;
|
|
1618
1633
|
}
|
|
1619
|
-
else if (this.match(
|
|
1634
|
+
else if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1620
1635
|
expr = this.indexedGet(expr);
|
|
1621
1636
|
}
|
|
1622
|
-
else if (this.match(
|
|
1637
|
+
else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
|
|
1623
1638
|
expr = this.callfunc(expr);
|
|
1639
|
+
//store this callfunc expression in references
|
|
1640
|
+
referenceCallExpression = expr;
|
|
1624
1641
|
}
|
|
1625
|
-
else if (this.match(
|
|
1626
|
-
if (this.match(
|
|
1642
|
+
else if (this.match(TokenKind_1.TokenKind.Dot)) {
|
|
1643
|
+
if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1627
1644
|
expr = this.indexedGet(expr);
|
|
1628
1645
|
}
|
|
1629
1646
|
else {
|
|
1630
1647
|
let dot = this.previous();
|
|
1631
|
-
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(),
|
|
1648
|
+
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1632
1649
|
// force it into an identifier so the AST makes some sense
|
|
1633
|
-
name.kind =
|
|
1650
|
+
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1634
1651
|
expr = new Expression_1.DottedGetExpression(expr, name, dot);
|
|
1635
1652
|
this.addPropertyHints(name);
|
|
1636
1653
|
}
|
|
1637
1654
|
}
|
|
1638
|
-
else if (this.check(
|
|
1655
|
+
else if (this.check(TokenKind_1.TokenKind.At)) {
|
|
1639
1656
|
let dot = this.advance();
|
|
1640
|
-
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(),
|
|
1657
|
+
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1641
1658
|
// force it into an identifier so the AST makes some sense
|
|
1642
|
-
name.kind =
|
|
1659
|
+
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1643
1660
|
expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
|
|
1644
1661
|
//only allow a single `@` expression
|
|
1645
1662
|
break;
|
|
@@ -1648,25 +1665,29 @@ class Parser {
|
|
|
1648
1665
|
break;
|
|
1649
1666
|
}
|
|
1650
1667
|
}
|
|
1668
|
+
//if we found a callExpression, add it to `expressions` in references
|
|
1669
|
+
if (referenceCallExpression) {
|
|
1670
|
+
this._references.expressions.add(referenceCallExpression);
|
|
1671
|
+
}
|
|
1651
1672
|
return expr;
|
|
1652
1673
|
}
|
|
1653
1674
|
finishCall(openingParen, callee, addToCallExpressionList = true) {
|
|
1654
1675
|
let args = [];
|
|
1655
|
-
while (this.match(
|
|
1676
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1656
1677
|
}
|
|
1657
|
-
if (!this.check(
|
|
1678
|
+
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
1658
1679
|
do {
|
|
1659
|
-
while (this.match(
|
|
1680
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1660
1681
|
if (args.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
1661
1682
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
|
|
1662
1683
|
throw this.lastDiagnosticAsError();
|
|
1663
1684
|
}
|
|
1664
1685
|
args.push(this.expression());
|
|
1665
|
-
} while (this.match(
|
|
1686
|
+
} while (this.match(TokenKind_1.TokenKind.Comma));
|
|
1666
1687
|
}
|
|
1667
|
-
while (this.match(
|
|
1668
|
-
const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(),
|
|
1669
|
-
if (reflection_1.isVariableExpression(callee)) {
|
|
1688
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1689
|
+
const closingParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
|
|
1690
|
+
if ((0, reflection_1.isVariableExpression)(callee)) {
|
|
1670
1691
|
callee.isCalled = true;
|
|
1671
1692
|
}
|
|
1672
1693
|
let expression = new Expression_1.CallExpression(callee, openingParen, closingParen, args, this.currentNamespaceName);
|
|
@@ -1682,15 +1703,15 @@ class Parser {
|
|
|
1682
1703
|
*/
|
|
1683
1704
|
typeToken() {
|
|
1684
1705
|
let typeToken;
|
|
1685
|
-
if (this.checkAny(...
|
|
1706
|
+
if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
|
|
1686
1707
|
// Token is a built in type
|
|
1687
1708
|
typeToken = this.advance();
|
|
1688
1709
|
}
|
|
1689
1710
|
else if (this.options.mode === ParseMode.BrighterScript) {
|
|
1690
1711
|
try {
|
|
1691
|
-
// see if we can get a namespaced
|
|
1712
|
+
// see if we can get a namespaced identifier
|
|
1692
1713
|
const qualifiedType = this.getNamespacedVariableNameExpression();
|
|
1693
|
-
typeToken = creators_1.createToken(
|
|
1714
|
+
typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, qualifiedType.getName(this.options.mode), qualifiedType.range);
|
|
1694
1715
|
}
|
|
1695
1716
|
catch (_a) {
|
|
1696
1717
|
//could not get an identifier - just get whatever's next
|
|
@@ -1701,57 +1722,68 @@ class Parser {
|
|
|
1701
1722
|
// just get whatever's next
|
|
1702
1723
|
typeToken = this.advance();
|
|
1703
1724
|
}
|
|
1725
|
+
if (typeToken && this.options.mode === ParseMode.BrighterScript) {
|
|
1726
|
+
// Check if it is an array - that is, if it has `[]` after the type
|
|
1727
|
+
// eg. `string[]` or `SomeKlass[]`
|
|
1728
|
+
if (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1729
|
+
this.advance();
|
|
1730
|
+
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1731
|
+
const rightBracket = this.advance();
|
|
1732
|
+
typeToken = (0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, typeToken.text + '[]', util_1.util.getRange(typeToken, rightBracket));
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1704
1736
|
return typeToken;
|
|
1705
1737
|
}
|
|
1706
1738
|
primary() {
|
|
1707
1739
|
switch (true) {
|
|
1708
|
-
case this.matchAny(
|
|
1740
|
+
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):
|
|
1709
1741
|
return new Expression_1.LiteralExpression(this.previous());
|
|
1710
1742
|
//capture source literals (LINE_NUM if brightscript, or a bunch of them if brighterscript)
|
|
1711
|
-
case this.matchAny(
|
|
1743
|
+
case this.matchAny(TokenKind_1.TokenKind.LineNumLiteral, ...(this.options.mode === ParseMode.BrightScript ? [] : TokenKind_1.BrighterScriptSourceLiterals)):
|
|
1712
1744
|
return new Expression_1.SourceLiteralExpression(this.previous());
|
|
1713
1745
|
//template string
|
|
1714
|
-
case this.check(
|
|
1746
|
+
case this.check(TokenKind_1.TokenKind.BackTick):
|
|
1715
1747
|
return this.templateString(false);
|
|
1716
1748
|
//tagged template string (currently we do not support spaces between the identifier and the backtick)
|
|
1717
|
-
case this.checkAny(
|
|
1749
|
+
case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
|
|
1718
1750
|
return this.templateString(true);
|
|
1719
|
-
case this.matchAny(
|
|
1751
|
+
case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
|
|
1720
1752
|
return new Expression_1.VariableExpression(this.previous(), this.currentNamespaceName);
|
|
1721
|
-
case this.match(
|
|
1753
|
+
case this.match(TokenKind_1.TokenKind.LeftParen):
|
|
1722
1754
|
let left = this.previous();
|
|
1723
1755
|
let expr = this.expression();
|
|
1724
|
-
let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(),
|
|
1756
|
+
let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), TokenKind_1.TokenKind.RightParen);
|
|
1725
1757
|
return new Expression_1.GroupingExpression({ left: left, right: right }, expr);
|
|
1726
|
-
case this.match(
|
|
1758
|
+
case this.match(TokenKind_1.TokenKind.LeftSquareBracket):
|
|
1727
1759
|
let elements = [];
|
|
1728
1760
|
let openingSquare = this.previous();
|
|
1729
1761
|
//add any comment found right after the opening square
|
|
1730
|
-
if (this.check(
|
|
1762
|
+
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1731
1763
|
elements.push(new Statement_1.CommentStatement([this.advance()]));
|
|
1732
1764
|
}
|
|
1733
|
-
while (this.match(
|
|
1765
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1734
1766
|
}
|
|
1735
|
-
if (!this.match(
|
|
1767
|
+
if (!this.match(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1736
1768
|
elements.push(this.expression());
|
|
1737
|
-
while (this.matchAny(
|
|
1738
|
-
if (this.checkPrevious(
|
|
1739
|
-
let comment = this.check(
|
|
1769
|
+
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
1770
|
+
if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1771
|
+
let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
|
|
1740
1772
|
elements.push(new Statement_1.CommentStatement([comment]));
|
|
1741
1773
|
}
|
|
1742
|
-
while (this.match(
|
|
1774
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1743
1775
|
}
|
|
1744
|
-
if (this.check(
|
|
1776
|
+
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1745
1777
|
break;
|
|
1746
1778
|
}
|
|
1747
1779
|
elements.push(this.expression());
|
|
1748
1780
|
}
|
|
1749
|
-
this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(),
|
|
1781
|
+
this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1750
1782
|
}
|
|
1751
1783
|
let closingSquare = this.previous();
|
|
1752
1784
|
//this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
|
|
1753
1785
|
return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
|
|
1754
|
-
case this.match(
|
|
1786
|
+
case this.match(TokenKind_1.TokenKind.LeftCurlyBrace):
|
|
1755
1787
|
let openingBrace = this.previous();
|
|
1756
1788
|
let members = [];
|
|
1757
1789
|
let key = () => {
|
|
@@ -1760,25 +1792,25 @@ class Parser {
|
|
|
1760
1792
|
keyToken: null,
|
|
1761
1793
|
range: null
|
|
1762
1794
|
};
|
|
1763
|
-
if (this.checkAny(
|
|
1795
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
1764
1796
|
result.keyToken = this.advance();
|
|
1765
1797
|
}
|
|
1766
|
-
else if (this.check(
|
|
1798
|
+
else if (this.check(TokenKind_1.TokenKind.StringLiteral)) {
|
|
1767
1799
|
result.keyToken = this.advance();
|
|
1768
1800
|
}
|
|
1769
1801
|
else {
|
|
1770
1802
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedAAKey()), { range: this.peek().range }));
|
|
1771
1803
|
throw this.lastDiagnosticAsError();
|
|
1772
1804
|
}
|
|
1773
|
-
result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(),
|
|
1805
|
+
result.colonToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedColonBetweenAAKeyAndvalue(), TokenKind_1.TokenKind.Colon);
|
|
1774
1806
|
result.range = util_1.util.getRange(result.keyToken, result.colonToken);
|
|
1775
1807
|
return result;
|
|
1776
1808
|
};
|
|
1777
|
-
while (this.match(
|
|
1809
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1778
1810
|
}
|
|
1779
|
-
if (!this.match(
|
|
1811
|
+
if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
1780
1812
|
let lastAAMember;
|
|
1781
|
-
if (this.check(
|
|
1813
|
+
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1782
1814
|
lastAAMember = null;
|
|
1783
1815
|
members.push(new Statement_1.CommentStatement([this.advance()]));
|
|
1784
1816
|
}
|
|
@@ -1788,26 +1820,26 @@ class Parser {
|
|
|
1788
1820
|
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
|
|
1789
1821
|
members.push(lastAAMember);
|
|
1790
1822
|
}
|
|
1791
|
-
while (this.matchAny(
|
|
1823
|
+
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
|
|
1792
1824
|
// collect comma at end of expression
|
|
1793
|
-
if (lastAAMember && this.checkPrevious(
|
|
1825
|
+
if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
|
|
1794
1826
|
lastAAMember.commaToken = this.previous();
|
|
1795
1827
|
}
|
|
1796
1828
|
//check for comment at the end of the current line
|
|
1797
|
-
if (this.check(
|
|
1798
|
-
let token = this.checkPrevious(
|
|
1829
|
+
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
1830
|
+
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
1799
1831
|
members.push(new Statement_1.CommentStatement([token]));
|
|
1800
1832
|
}
|
|
1801
1833
|
else {
|
|
1802
1834
|
this.consumeStatementSeparators(true);
|
|
1803
1835
|
//check for a comment on its own line
|
|
1804
|
-
if (this.check(
|
|
1805
|
-
let token = this.checkPrevious(
|
|
1836
|
+
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
1837
|
+
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
1806
1838
|
lastAAMember = null;
|
|
1807
1839
|
members.push(new Statement_1.CommentStatement([token]));
|
|
1808
1840
|
continue;
|
|
1809
1841
|
}
|
|
1810
|
-
if (this.check(
|
|
1842
|
+
if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
1811
1843
|
break;
|
|
1812
1844
|
}
|
|
1813
1845
|
let k = key();
|
|
@@ -1816,23 +1848,23 @@ class Parser {
|
|
|
1816
1848
|
members.push(lastAAMember);
|
|
1817
1849
|
}
|
|
1818
1850
|
}
|
|
1819
|
-
this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(),
|
|
1851
|
+
this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), TokenKind_1.TokenKind.RightCurlyBrace);
|
|
1820
1852
|
}
|
|
1821
1853
|
let closingBrace = this.previous();
|
|
1822
1854
|
const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace, this.currentFunctionExpression);
|
|
1823
1855
|
this._references.aaLiterals.push(aaExpr);
|
|
1824
1856
|
this.addPropertyHints(aaExpr);
|
|
1825
1857
|
return aaExpr;
|
|
1826
|
-
case this.matchAny(
|
|
1858
|
+
case this.matchAny(TokenKind_1.TokenKind.Pos, TokenKind_1.TokenKind.Tab):
|
|
1827
1859
|
let token = Object.assign(this.previous(), {
|
|
1828
|
-
kind:
|
|
1860
|
+
kind: TokenKind_1.TokenKind.Identifier
|
|
1829
1861
|
});
|
|
1830
1862
|
return new Expression_1.VariableExpression(token, this.currentNamespaceName);
|
|
1831
|
-
case this.checkAny(
|
|
1863
|
+
case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
|
|
1832
1864
|
return this.anonymousFunction();
|
|
1833
|
-
case this.check(
|
|
1865
|
+
case this.check(TokenKind_1.TokenKind.RegexLiteral):
|
|
1834
1866
|
return this.regexLiteralExpression();
|
|
1835
|
-
case this.check(
|
|
1867
|
+
case this.check(TokenKind_1.TokenKind.Comment):
|
|
1836
1868
|
return new Statement_1.CommentStatement([this.advance()]);
|
|
1837
1869
|
default:
|
|
1838
1870
|
//if we found an expected terminator, don't throw a diagnostic...just return undefined
|
|
@@ -1902,12 +1934,12 @@ class Parser {
|
|
|
1902
1934
|
}
|
|
1903
1935
|
consumeStatementSeparators(optional = false) {
|
|
1904
1936
|
//a comment or EOF mark the end of the statement
|
|
1905
|
-
if (this.isAtEnd() || this.check(
|
|
1937
|
+
if (this.isAtEnd() || this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1906
1938
|
return true;
|
|
1907
1939
|
}
|
|
1908
1940
|
let consumed = false;
|
|
1909
1941
|
//consume any newlines and colons
|
|
1910
|
-
while (this.matchAny(
|
|
1942
|
+
while (this.matchAny(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon)) {
|
|
1911
1943
|
consumed = true;
|
|
1912
1944
|
}
|
|
1913
1945
|
if (!optional && !consumed) {
|
|
@@ -1923,7 +1955,7 @@ class Parser {
|
|
|
1923
1955
|
}
|
|
1924
1956
|
checkEndOfStatement() {
|
|
1925
1957
|
const nextKind = this.peek().kind;
|
|
1926
|
-
return [
|
|
1958
|
+
return [TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Eof].includes(nextKind);
|
|
1927
1959
|
}
|
|
1928
1960
|
checkPrevious(tokenKind) {
|
|
1929
1961
|
var _a;
|
|
@@ -1931,14 +1963,14 @@ class Parser {
|
|
|
1931
1963
|
}
|
|
1932
1964
|
check(tokenKind) {
|
|
1933
1965
|
const nextKind = this.peek().kind;
|
|
1934
|
-
if (nextKind ===
|
|
1966
|
+
if (nextKind === TokenKind_1.TokenKind.Eof) {
|
|
1935
1967
|
return false;
|
|
1936
1968
|
}
|
|
1937
1969
|
return nextKind === tokenKind;
|
|
1938
1970
|
}
|
|
1939
1971
|
checkAny(...tokenKinds) {
|
|
1940
1972
|
const nextKind = this.peek().kind;
|
|
1941
|
-
if (nextKind ===
|
|
1973
|
+
if (nextKind === TokenKind_1.TokenKind.Eof) {
|
|
1942
1974
|
return false;
|
|
1943
1975
|
}
|
|
1944
1976
|
return tokenKinds.includes(nextKind);
|
|
@@ -1957,7 +1989,7 @@ class Parser {
|
|
|
1957
1989
|
return tokenKinds.includes(nextKind);
|
|
1958
1990
|
}
|
|
1959
1991
|
isAtEnd() {
|
|
1960
|
-
return this.peek().kind ===
|
|
1992
|
+
return this.peek().kind === TokenKind_1.TokenKind.Eof;
|
|
1961
1993
|
}
|
|
1962
1994
|
peekNext() {
|
|
1963
1995
|
if (this.isAtEnd()) {
|
|
@@ -1979,16 +2011,16 @@ class Parser {
|
|
|
1979
2011
|
return;
|
|
1980
2012
|
}
|
|
1981
2013
|
switch (this.peek().kind) { //eslint-disable-line @typescript-eslint/switch-exhaustiveness-check
|
|
1982
|
-
case
|
|
1983
|
-
case
|
|
1984
|
-
case
|
|
1985
|
-
case
|
|
1986
|
-
case
|
|
1987
|
-
case
|
|
1988
|
-
case
|
|
1989
|
-
case
|
|
1990
|
-
case
|
|
1991
|
-
case
|
|
2014
|
+
case TokenKind_1.TokenKind.Namespace:
|
|
2015
|
+
case TokenKind_1.TokenKind.Class:
|
|
2016
|
+
case TokenKind_1.TokenKind.Function:
|
|
2017
|
+
case TokenKind_1.TokenKind.Sub:
|
|
2018
|
+
case TokenKind_1.TokenKind.If:
|
|
2019
|
+
case TokenKind_1.TokenKind.For:
|
|
2020
|
+
case TokenKind_1.TokenKind.ForEach:
|
|
2021
|
+
case TokenKind_1.TokenKind.While:
|
|
2022
|
+
case TokenKind_1.TokenKind.Print:
|
|
2023
|
+
case TokenKind_1.TokenKind.Return:
|
|
1992
2024
|
// start parsing again from the next block starter or obvious
|
|
1993
2025
|
// expression start
|
|
1994
2026
|
return;
|
|
@@ -2034,17 +2066,17 @@ class Parser {
|
|
|
2034
2066
|
const previousToken = this.getPreviousToken(closestToken);
|
|
2035
2067
|
const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
|
|
2036
2068
|
//next to matched token
|
|
2037
|
-
if (!closestToken || closestToken.kind ===
|
|
2069
|
+
if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
|
|
2038
2070
|
return false;
|
|
2039
2071
|
}
|
|
2040
2072
|
else if (closestToken.kind === tokenKind) {
|
|
2041
2073
|
return true;
|
|
2042
2074
|
}
|
|
2043
|
-
else if (closestToken.kind ===
|
|
2075
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
|
|
2044
2076
|
return false;
|
|
2045
2077
|
//next to an identifier, which is next to token kind
|
|
2046
2078
|
}
|
|
2047
|
-
else if (closestToken.kind ===
|
|
2079
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
|
|
2048
2080
|
return true;
|
|
2049
2081
|
}
|
|
2050
2082
|
else {
|
|
@@ -2055,7 +2087,7 @@ class Parser {
|
|
|
2055
2087
|
const index = this.tokens.indexOf(currentToken);
|
|
2056
2088
|
for (let i = index - 1; i >= 0; i--) {
|
|
2057
2089
|
currentToken = this.tokens[i];
|
|
2058
|
-
if (currentToken.kind ===
|
|
2090
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
|
|
2059
2091
|
break;
|
|
2060
2092
|
}
|
|
2061
2093
|
else if (currentToken.kind === tokenKind) {
|
|
@@ -2075,7 +2107,7 @@ class Parser {
|
|
|
2075
2107
|
let tokens = [];
|
|
2076
2108
|
for (let i = this.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.tokens.length; i += direction) {
|
|
2077
2109
|
currentToken = this.tokens[i];
|
|
2078
|
-
if (currentToken.kind ===
|
|
2110
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
|
|
2079
2111
|
break;
|
|
2080
2112
|
}
|
|
2081
2113
|
tokens.push(currentToken);
|
|
@@ -2146,12 +2178,12 @@ class Parser {
|
|
|
2146
2178
|
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2147
2179
|
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2148
2180
|
}
|
|
2149
|
-
if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) ===
|
|
2181
|
+
if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.Dot) {
|
|
2150
2182
|
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2151
2183
|
currentToken = previousTokenResult.token;
|
|
2152
2184
|
currentTokenIndex = previousTokenResult.index;
|
|
2153
2185
|
}
|
|
2154
|
-
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex,
|
|
2186
|
+
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.RightParen);
|
|
2155
2187
|
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2156
2188
|
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2157
2189
|
if (previousTokenResult.hasBrackets) {
|
|
@@ -2159,7 +2191,7 @@ class Parser {
|
|
|
2159
2191
|
}
|
|
2160
2192
|
let tokenTypeIsNotKnowable = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable;
|
|
2161
2193
|
if (currentTokenIndex) {
|
|
2162
|
-
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex,
|
|
2194
|
+
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.RightSquareBracket);
|
|
2163
2195
|
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2164
2196
|
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2165
2197
|
if (previousTokenResult.hasBrackets) {
|
|
@@ -2177,15 +2209,15 @@ class Parser {
|
|
|
2177
2209
|
if (!currentToken || lastTokenHasWhitespace) {
|
|
2178
2210
|
return false;
|
|
2179
2211
|
}
|
|
2180
|
-
if (currentToken.kind ===
|
|
2212
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Identifier) {
|
|
2181
2213
|
return true;
|
|
2182
2214
|
}
|
|
2183
2215
|
if (currentToken.leadingWhitespace.length === 0) {
|
|
2184
2216
|
// start of the chain
|
|
2185
|
-
return
|
|
2217
|
+
return TokenKind_1.AllowedLocalIdentifiers.includes(currentToken.kind);
|
|
2186
2218
|
}
|
|
2187
2219
|
// not the start of the chain
|
|
2188
|
-
return
|
|
2220
|
+
return TokenKind_1.AllowedProperties.includes(currentToken.kind);
|
|
2189
2221
|
}
|
|
2190
2222
|
/**
|
|
2191
2223
|
* Builds up a chain of tokens, starting with the first in the chain, and ending with currentToken
|
|
@@ -2232,59 +2264,120 @@ class Parser {
|
|
|
2232
2264
|
*/
|
|
2233
2265
|
findReferences() {
|
|
2234
2266
|
this._references = new References();
|
|
2267
|
+
const excludedExpressions = new Set();
|
|
2268
|
+
const visitCallExpression = (e) => {
|
|
2269
|
+
for (const p of e.args) {
|
|
2270
|
+
this._references.expressions.add(p);
|
|
2271
|
+
}
|
|
2272
|
+
//add calls that were not excluded (from loop below)
|
|
2273
|
+
if (!excludedExpressions.has(e)) {
|
|
2274
|
+
this._references.expressions.add(e);
|
|
2275
|
+
}
|
|
2276
|
+
//if this call is part of a longer expression that includes a call higher up, find that higher one and remove it
|
|
2277
|
+
if (e.callee) {
|
|
2278
|
+
let node = e.callee;
|
|
2279
|
+
while (node) {
|
|
2280
|
+
//the primary goal for this loop. If we found a parent call expression, remove it from `references`
|
|
2281
|
+
if ((0, reflection_1.isCallExpression)(node)) {
|
|
2282
|
+
this.references.expressions.delete(node);
|
|
2283
|
+
excludedExpressions.add(node);
|
|
2284
|
+
//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.
|
|
2285
|
+
break;
|
|
2286
|
+
//when we hit a variable expression, we're definitely at the leftmost expression so stop
|
|
2287
|
+
}
|
|
2288
|
+
else if ((0, reflection_1.isVariableExpression)(node)) {
|
|
2289
|
+
break;
|
|
2290
|
+
//if
|
|
2291
|
+
}
|
|
2292
|
+
else if ((0, reflection_1.isDottedGetExpression)(node) || (0, reflection_1.isIndexedGetExpression)(node)) {
|
|
2293
|
+
node = node.obj;
|
|
2294
|
+
}
|
|
2295
|
+
else {
|
|
2296
|
+
//some expression we don't understand. log it and quit the loop
|
|
2297
|
+
this.logger.info('Encountered unknown expression while calculating function expression chain', node);
|
|
2298
|
+
break;
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
};
|
|
2235
2303
|
//gather up all the top-level statements
|
|
2236
|
-
this.ast.walk(visitors_1.createVisitor({
|
|
2304
|
+
this.ast.walk((0, visitors_1.createVisitor)({
|
|
2305
|
+
AssignmentStatement: s => {
|
|
2306
|
+
this._references.assignmentStatements.push(s);
|
|
2307
|
+
this.references.expressions.add(s.value);
|
|
2308
|
+
},
|
|
2237
2309
|
ClassStatement: s => {
|
|
2238
2310
|
this._references.classStatements.push(s);
|
|
2239
2311
|
},
|
|
2312
|
+
ClassFieldStatement: s => {
|
|
2313
|
+
if (s.initialValue) {
|
|
2314
|
+
this._references.expressions.add(s.initialValue);
|
|
2315
|
+
}
|
|
2316
|
+
},
|
|
2240
2317
|
NamespaceStatement: s => {
|
|
2241
2318
|
this._references.namespaceStatements.push(s);
|
|
2242
2319
|
},
|
|
2243
2320
|
FunctionStatement: s => {
|
|
2244
2321
|
this._references.functionStatements.push(s);
|
|
2245
|
-
//add the initial set of function expressions for function statements
|
|
2246
|
-
this._references.functionExpressions.push(s.func);
|
|
2247
2322
|
},
|
|
2248
2323
|
ImportStatement: s => {
|
|
2249
2324
|
this._references.importStatements.push(s);
|
|
2250
2325
|
},
|
|
2251
2326
|
LibraryStatement: s => {
|
|
2252
2327
|
this._references.libraryStatements.push(s);
|
|
2253
|
-
}
|
|
2254
|
-
}), {
|
|
2255
|
-
walkMode: visitors_1.WalkMode.visitStatements
|
|
2256
|
-
});
|
|
2257
|
-
let func;
|
|
2258
|
-
let visitor = visitors_1.createVisitor({
|
|
2259
|
-
AssignmentStatement: s => {
|
|
2260
|
-
this._references.assignmentStatements.push(s);
|
|
2261
2328
|
},
|
|
2262
2329
|
FunctionExpression: (expression, parent) => {
|
|
2263
|
-
if (!reflection_1.isClassMethodStatement(parent)) {
|
|
2330
|
+
if (!(0, reflection_1.isClassMethodStatement)(parent)) {
|
|
2264
2331
|
this._references.functionExpressions.push(expression);
|
|
2265
2332
|
}
|
|
2266
2333
|
},
|
|
2267
2334
|
NewExpression: e => {
|
|
2268
2335
|
this._references.newExpressions.push(e);
|
|
2336
|
+
for (const p of e.call.args) {
|
|
2337
|
+
this._references.expressions.add(p);
|
|
2338
|
+
}
|
|
2339
|
+
},
|
|
2340
|
+
ExpressionStatement: s => {
|
|
2341
|
+
this._references.expressions.add(s.expression);
|
|
2342
|
+
},
|
|
2343
|
+
CallfuncExpression: e => {
|
|
2344
|
+
visitCallExpression(e);
|
|
2345
|
+
},
|
|
2346
|
+
CallExpression: e => {
|
|
2347
|
+
visitCallExpression(e);
|
|
2269
2348
|
},
|
|
2270
2349
|
AALiteralExpression: e => {
|
|
2271
2350
|
this.addPropertyHints(e);
|
|
2351
|
+
this._references.expressions.add(e);
|
|
2352
|
+
for (const member of e.elements) {
|
|
2353
|
+
if ((0, reflection_1.isAAMemberExpression)(member)) {
|
|
2354
|
+
this._references.expressions.add(member.value);
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
},
|
|
2358
|
+
ArrayLiteralExpression: e => {
|
|
2359
|
+
for (const element of e.elements) {
|
|
2360
|
+
//keep everything except comments
|
|
2361
|
+
if (!(0, reflection_1.isCommentStatement)(element)) {
|
|
2362
|
+
this._references.expressions.add(element);
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2272
2365
|
},
|
|
2273
2366
|
DottedGetExpression: e => {
|
|
2274
2367
|
this.addPropertyHints(e.name);
|
|
2275
2368
|
},
|
|
2276
2369
|
DottedSetStatement: e => {
|
|
2277
2370
|
this.addPropertyHints(e.name);
|
|
2371
|
+
},
|
|
2372
|
+
UnaryExpression: e => {
|
|
2373
|
+
this._references.expressions.add(e);
|
|
2374
|
+
},
|
|
2375
|
+
IncrementStatement: e => {
|
|
2376
|
+
this._references.expressions.add(e);
|
|
2278
2377
|
}
|
|
2378
|
+
}), {
|
|
2379
|
+
walkMode: visitors_1.WalkMode.visitAllRecursive
|
|
2279
2380
|
});
|
|
2280
|
-
//walk all function expressions (we'll add new ones as we move along too)
|
|
2281
|
-
for (let i = 0; i < this._references.functionExpressions.length; i++) {
|
|
2282
|
-
func = this._references.functionExpressions[i];
|
|
2283
|
-
//walk this function expression
|
|
2284
|
-
func.body.walk(visitor, {
|
|
2285
|
-
walkMode: visitors_1.WalkMode.visitAll
|
|
2286
|
-
});
|
|
2287
|
-
}
|
|
2288
2381
|
}
|
|
2289
2382
|
getContainingClass(currentToken) {
|
|
2290
2383
|
return this.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
|
|
@@ -2296,7 +2389,10 @@ class Parser {
|
|
|
2296
2389
|
return this.references.namespaceStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
|
|
2297
2390
|
}
|
|
2298
2391
|
getContainingFunctionExpression(currentToken) {
|
|
2299
|
-
return this.
|
|
2392
|
+
return this.getContainingFunctionExpressionByPosition(currentToken.range.start);
|
|
2393
|
+
}
|
|
2394
|
+
getContainingFunctionExpressionByPosition(position) {
|
|
2395
|
+
return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, position));
|
|
2300
2396
|
}
|
|
2301
2397
|
dispose() {
|
|
2302
2398
|
}
|
|
@@ -2316,6 +2412,17 @@ class References {
|
|
|
2316
2412
|
this.functionExpressions = [];
|
|
2317
2413
|
this.functionStatements = [];
|
|
2318
2414
|
this.interfaceStatements = [];
|
|
2415
|
+
/**
|
|
2416
|
+
* A collection of full expressions. This excludes intermediary expressions.
|
|
2417
|
+
*
|
|
2418
|
+
* Example 1:
|
|
2419
|
+
* `a.b.c` is composed of `a` (variableExpression) `.b` (DottedGetExpression) `.c` (DottedGetExpression)
|
|
2420
|
+
* This will only contain the final `.c` DottedGetExpression because `.b` and `a` can both be derived by walking back from the `.c` DottedGetExpression.
|
|
2421
|
+
*
|
|
2422
|
+
* Example 2:
|
|
2423
|
+
* `name.space.doSomething(a.b.c)` will result in 2 entries in this list. the `CallExpression` for `doSomething`, and the `.c` DottedGetExpression.
|
|
2424
|
+
*/
|
|
2425
|
+
this.expressions = new Set();
|
|
2319
2426
|
this.importStatements = [];
|
|
2320
2427
|
this.libraryStatements = [];
|
|
2321
2428
|
this.namespaceStatements = [];
|
|
@@ -2374,34 +2481,43 @@ class CancelStatementError extends Error {
|
|
|
2374
2481
|
*/
|
|
2375
2482
|
function getBscTypeFromExpression(expression, functionExpression) {
|
|
2376
2483
|
try {
|
|
2377
|
-
if (reflection_1.isFunctionExpression(expression)) {
|
|
2484
|
+
if ((0, reflection_1.isFunctionExpression)(expression)) {
|
|
2378
2485
|
return expression.getFunctionType();
|
|
2379
2486
|
//literal
|
|
2380
2487
|
}
|
|
2381
|
-
else if (reflection_1.isLiteralExpression(expression)) {
|
|
2488
|
+
else if ((0, reflection_1.isLiteralExpression)(expression)) {
|
|
2382
2489
|
return expression.type;
|
|
2383
2490
|
//Associative array literal
|
|
2384
2491
|
}
|
|
2385
|
-
else if (reflection_1.isAALiteralExpression(expression)) {
|
|
2492
|
+
else if ((0, reflection_1.isAALiteralExpression)(expression)) {
|
|
2386
2493
|
return new ObjectType_1.ObjectType(expression.memberTable);
|
|
2387
2494
|
//Array literal
|
|
2388
2495
|
}
|
|
2389
|
-
else if (reflection_1.isArrayLiteralExpression(expression)) {
|
|
2390
|
-
|
|
2496
|
+
else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {
|
|
2497
|
+
const innerTypes = expression.elements.filter((element) => !(0, reflection_1.isCommentStatement)(element)).map((element) => {
|
|
2498
|
+
return getBscTypeFromExpression(element, functionExpression);
|
|
2499
|
+
});
|
|
2500
|
+
return new ArrayType_1.ArrayType(...innerTypes);
|
|
2391
2501
|
//function call
|
|
2392
2502
|
}
|
|
2393
|
-
else if (reflection_1.isNewExpression(expression)) {
|
|
2394
|
-
return helpers_1.getTypeFromNewExpression(expression, functionExpression); // new CustomType(expression.className.getName(ParseMode.BrighterScript));
|
|
2503
|
+
else if ((0, reflection_1.isNewExpression)(expression)) {
|
|
2504
|
+
return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression); // new CustomType(expression.className.getName(ParseMode.BrighterScript));
|
|
2395
2505
|
//Function call
|
|
2396
2506
|
}
|
|
2397
|
-
else if (reflection_1.isCallExpression(expression)) {
|
|
2398
|
-
return helpers_1.getTypeFromCallExpression(expression, functionExpression);
|
|
2507
|
+
else if ((0, reflection_1.isCallExpression)(expression)) {
|
|
2508
|
+
return (0, helpers_1.getTypeFromCallExpression)(expression, functionExpression);
|
|
2509
|
+
}
|
|
2510
|
+
else if ((0, reflection_1.isVariableExpression)(expression)) {
|
|
2511
|
+
return (0, helpers_1.getTypeFromVariableExpression)(expression, functionExpression);
|
|
2399
2512
|
}
|
|
2400
|
-
else if (reflection_1.
|
|
2401
|
-
return helpers_1.
|
|
2513
|
+
else if ((0, reflection_1.isDottedGetExpression)(expression)) {
|
|
2514
|
+
return (0, helpers_1.getTypeFromDottedGetExpression)(expression, functionExpression);
|
|
2402
2515
|
}
|
|
2403
|
-
else if (reflection_1.
|
|
2404
|
-
|
|
2516
|
+
else if ((0, reflection_1.isIndexedGetExpression)(expression)) {
|
|
2517
|
+
const source = getBscTypeFromExpression(expression.obj, functionExpression);
|
|
2518
|
+
if ((0, reflection_1.isArrayType)(source)) {
|
|
2519
|
+
return source.getDefaultType();
|
|
2520
|
+
}
|
|
2405
2521
|
}
|
|
2406
2522
|
}
|
|
2407
2523
|
catch (e) {
|