brighterscript 0.41.2 → 1.0.0-alpha.12
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 +112 -0
- package/README.md +2 -2
- package/dist/DiagnosticCollection.js +2 -2
- package/dist/DiagnosticCollection.js.map +1 -1
- package/dist/DiagnosticFilterer.js +2 -2
- package/dist/DiagnosticFilterer.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +6 -1
- package/dist/DiagnosticMessages.js +5 -0
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.d.ts +8 -2
- package/dist/LanguageServer.js +50 -44
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Program.d.ts +61 -45
- package/dist/Program.js +305 -188
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +7 -7
- package/dist/ProgramBuilder.js +60 -51
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +42 -19
- package/dist/Scope.js +261 -129
- package/dist/Scope.js.map +1 -1
- package/dist/SymbolTable.d.ts +73 -0
- package/dist/SymbolTable.js +157 -0
- package/dist/SymbolTable.js.map +1 -0
- package/dist/XmlScope.d.ts +5 -0
- package/dist/XmlScope.js +66 -28
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/creators.d.ts +15 -1
- package/dist/astUtils/creators.js +39 -9
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +28 -16
- package/dist/astUtils/reflection.js +52 -30
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +3 -3
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +12 -13
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/astUtils/xml.d.ts +3 -3
- package/dist/astUtils/xml.js +2 -2
- package/dist/astUtils/xml.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +5 -6
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +24 -22
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js +2 -2
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +1 -1
- package/dist/examples/plugins/removePrint.js +1 -1
- package/dist/examples/plugins/removePrint.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +356 -41
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +55 -37
- package/dist/files/BrsFile.js +430 -399
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +199 -158
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +20 -9
- package/dist/files/XmlFile.js +36 -31
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +113 -113
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +32 -32
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/globalCallables.js +17 -6
- package/dist/globalCallables.js.map +1 -1
- package/dist/interfaces.d.ts +155 -39
- package/dist/parser/BrsTranspileState.d.ts +7 -0
- package/dist/parser/BrsTranspileState.js +10 -1
- package/dist/parser/BrsTranspileState.js.map +1 -1
- package/dist/parser/Expression.d.ts +23 -12
- package/dist/parser/Expression.js +45 -30
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +100 -1
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +118 -5
- package/dist/parser/Parser.js +398 -37
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +404 -7
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.d.ts +41 -4
- package/dist/parser/SGParser.js +185 -174
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +17 -4
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/SGTypes.d.ts +203 -38
- package/dist/parser/SGTypes.js +464 -160
- package/dist/parser/SGTypes.js.map +1 -1
- package/dist/parser/SGTypes.spec.d.ts +1 -0
- package/dist/parser/SGTypes.spec.js +351 -0
- package/dist/parser/SGTypes.spec.js.map +1 -0
- package/dist/parser/Statement.d.ts +37 -26
- package/dist/parser/Statement.js +81 -20
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +5 -5
- package/dist/parser/Statement.spec.js.map +1 -1
- package/dist/parser/TranspileState.d.ts +1 -1
- package/dist/parser/TranspileState.js +15 -7
- package/dist/parser/TranspileState.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +5 -4
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/types/ArrayType.d.ts +1 -0
- package/dist/types/ArrayType.js +23 -19
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/BooleanType.d.ts +3 -2
- package/dist/types/BooleanType.js +6 -3
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BscType.d.ts +19 -4
- package/dist/types/BscType.js +9 -0
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/CustomType.d.ts +8 -5
- package/dist/types/CustomType.js +12 -12
- package/dist/types/CustomType.js.map +1 -1
- package/dist/types/DoubleType.d.ts +1 -0
- package/dist/types/DoubleType.js +11 -11
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DynamicType.d.ts +1 -0
- package/dist/types/DynamicType.js +4 -0
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/FloatType.d.ts +2 -1
- package/dist/types/FloatType.js +11 -11
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FunctionType.d.ts +13 -10
- package/dist/types/FunctionType.js +34 -18
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/FunctionType.spec.js +8 -2
- package/dist/types/FunctionType.spec.js.map +1 -1
- package/dist/types/IntegerType.d.ts +2 -1
- package/dist/types/IntegerType.js +11 -11
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/InvalidType.d.ts +3 -2
- package/dist/types/InvalidType.js +7 -4
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/LazyType.d.ts +17 -0
- package/dist/types/LazyType.js +44 -0
- package/dist/types/LazyType.js.map +1 -0
- package/dist/types/LongIntegerType.d.ts +2 -1
- package/dist/types/LongIntegerType.js +11 -11
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/ObjectType.d.ts +6 -2
- package/dist/types/ObjectType.js +9 -3
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/StringType.d.ts +3 -2
- package/dist/types/StringType.js +6 -3
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/UninitializedType.d.ts +4 -2
- package/dist/types/UninitializedType.js +8 -3
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/VoidType.d.ts +3 -2
- package/dist/types/VoidType.js +6 -3
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/helpers.d.ts +42 -0
- package/dist/types/helpers.js +113 -0
- package/dist/types/helpers.js.map +1 -0
- package/dist/util.d.ts +68 -15
- package/dist/util.js +193 -45
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +5 -1
- package/dist/validators/ClassValidator.js +31 -17
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +1 -1
- package/dist/FunctionScope.d.ts +0 -27
- package/dist/FunctionScope.js +0 -49
- package/dist/FunctionScope.js.map +0 -1
package/dist/parser/Parser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.References = exports.ParseMode = exports.Parser = void 0;
|
|
3
|
+
exports.getBscTypeFromExpression = exports.TokenUsage = exports.References = exports.ParseMode = exports.Parser = void 0;
|
|
4
4
|
const lexer_1 = require("../lexer");
|
|
5
5
|
const Statement_1 = require("./Statement");
|
|
6
6
|
const DiagnosticMessages_1 = require("../DiagnosticMessages");
|
|
@@ -10,6 +10,11 @@ const Logger_1 = require("../Logger");
|
|
|
10
10
|
const reflection_1 = require("../astUtils/reflection");
|
|
11
11
|
const visitors_1 = require("../astUtils/visitors");
|
|
12
12
|
const creators_1 = require("../astUtils/creators");
|
|
13
|
+
const DynamicType_1 = require("../types/DynamicType");
|
|
14
|
+
const SymbolTable_1 = require("../SymbolTable");
|
|
15
|
+
const ObjectType_1 = require("../types/ObjectType");
|
|
16
|
+
const ArrayType_1 = require("../types/ArrayType");
|
|
17
|
+
const helpers_1 = require("../types/helpers");
|
|
13
18
|
const _1 = require(".");
|
|
14
19
|
class Parser {
|
|
15
20
|
constructor() {
|
|
@@ -21,6 +26,7 @@ class Parser {
|
|
|
21
26
|
* The list of statements for the parsed file
|
|
22
27
|
*/
|
|
23
28
|
this.ast = new Statement_1.Body([]);
|
|
29
|
+
this.symbolTable = new SymbolTable_1.SymbolTable();
|
|
24
30
|
this._references = new References();
|
|
25
31
|
this.globalTerminators = [];
|
|
26
32
|
/**
|
|
@@ -31,6 +37,10 @@ class Parser {
|
|
|
31
37
|
get statements() {
|
|
32
38
|
return this.ast.statements;
|
|
33
39
|
}
|
|
40
|
+
get currentSymbolTable() {
|
|
41
|
+
var _a, _b;
|
|
42
|
+
return (_b = (_a = this.currentFunctionExpression) === null || _a === void 0 ? void 0 : _a.symbolTable) !== null && _b !== void 0 ? _b : this.symbolTable;
|
|
43
|
+
}
|
|
34
44
|
/**
|
|
35
45
|
* References for significant statements/expressions in the parser.
|
|
36
46
|
* These are initially extracted during parse-time to improve performance, but will also be dynamically regenerated if need be.
|
|
@@ -66,6 +76,10 @@ class Parser {
|
|
|
66
76
|
}
|
|
67
77
|
}
|
|
68
78
|
}
|
|
79
|
+
get currentNamespaceName() {
|
|
80
|
+
var _a;
|
|
81
|
+
return (_a = this.currentNamespace) === null || _a === void 0 ? void 0 : _a.nameExpression;
|
|
82
|
+
}
|
|
69
83
|
/**
|
|
70
84
|
* Get the currently active global terminators
|
|
71
85
|
*/
|
|
@@ -242,7 +256,7 @@ class Parser {
|
|
|
242
256
|
this.warnIfNotBrighterScriptMode('interface declarations');
|
|
243
257
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
244
258
|
const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(lexer_1.TokenKind.Interface), lexer_1.TokenKind.Interface);
|
|
245
|
-
const nameToken = this.identifier();
|
|
259
|
+
const nameToken = this.identifier(...this.allowedLocalIdentifiers);
|
|
246
260
|
let extendsToken;
|
|
247
261
|
let parentInterfaceName;
|
|
248
262
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
@@ -336,7 +350,7 @@ class Parser {
|
|
|
336
350
|
}
|
|
337
351
|
//methods (function/sub keyword OR identifier followed by opening paren)
|
|
338
352
|
if (this.checkAny(lexer_1.TokenKind.Function, lexer_1.TokenKind.Sub) || (this.checkAny(lexer_1.TokenKind.Identifier, ...lexer_1.AllowedProperties) && this.checkNext(lexer_1.TokenKind.LeftParen))) {
|
|
339
|
-
const funcDeclaration = this.functionDeclaration(false, false);
|
|
353
|
+
const funcDeclaration = this.functionDeclaration(false, false, true);
|
|
340
354
|
//remove this function from the lists because it's not a callable
|
|
341
355
|
const functionStatement = this._references.functionStatements.pop();
|
|
342
356
|
//if we have an overrides keyword AND this method is called 'new', that's not allowed
|
|
@@ -375,7 +389,10 @@ class Parser {
|
|
|
375
389
|
if (endingKeyword.kind !== lexer_1.TokenKind.EndClass) {
|
|
376
390
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
|
|
377
391
|
}
|
|
378
|
-
const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName);
|
|
392
|
+
const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName, this.currentNamespaceName, this.currentSymbolTable);
|
|
393
|
+
if (className) {
|
|
394
|
+
this.currentSymbolTable.addSymbol(className.text, className.range, result.getConstructorFunctionType());
|
|
395
|
+
}
|
|
379
396
|
this._references.classStatements.push(result);
|
|
380
397
|
this.exitAnnotationBlock(parentAnnotations);
|
|
381
398
|
return result;
|
|
@@ -389,7 +406,7 @@ class Parser {
|
|
|
389
406
|
asToken = this.advance();
|
|
390
407
|
fieldType = this.typeToken();
|
|
391
408
|
//no field type specified
|
|
392
|
-
if (!util_1.util.tokenToBscType(fieldType)) {
|
|
409
|
+
if (!util_1.util.tokenToBscType(fieldType, true, this.currentNamespaceName)) {
|
|
393
410
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedValidTypeToFollowAsKeyword()), { range: this.peek().range }));
|
|
394
411
|
}
|
|
395
412
|
}
|
|
@@ -400,10 +417,10 @@ class Parser {
|
|
|
400
417
|
equal = this.advance();
|
|
401
418
|
initialValue = this.expression();
|
|
402
419
|
}
|
|
403
|
-
return new Statement_1.ClassFieldStatement(accessModifier, name, asToken, fieldType, equal, initialValue);
|
|
420
|
+
return new Statement_1.ClassFieldStatement(accessModifier, name, asToken, fieldType, equal, initialValue, this.currentNamespaceName);
|
|
404
421
|
}
|
|
405
|
-
functionDeclaration(isAnonymous, checkIdentifier = true) {
|
|
406
|
-
var _a;
|
|
422
|
+
functionDeclaration(isAnonymous, checkIdentifier = true, forClassMethod = false) {
|
|
423
|
+
var _a, _b, _c, _d;
|
|
407
424
|
let previousCallExpressions = this.callExpressions;
|
|
408
425
|
this.callExpressions = [];
|
|
409
426
|
try {
|
|
@@ -463,7 +480,7 @@ class Parser {
|
|
|
463
480
|
if (this.check(lexer_1.TokenKind.As)) {
|
|
464
481
|
asToken = this.advance();
|
|
465
482
|
typeToken = this.typeToken();
|
|
466
|
-
if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript)) {
|
|
483
|
+
if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
|
|
467
484
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType((_a = typeToken.text) !== null && _a !== void 0 ? _a : '')), { range: typeToken.range }));
|
|
468
485
|
}
|
|
469
486
|
}
|
|
@@ -476,11 +493,25 @@ class Parser {
|
|
|
476
493
|
this.consumeStatementSeparators(true);
|
|
477
494
|
let func = new Expression_1.FunctionExpression(params, undefined, //body
|
|
478
495
|
functionType, undefined, //ending keyword
|
|
479
|
-
leftParen, rightParen, asToken, typeToken,
|
|
496
|
+
leftParen, rightParen, asToken, typeToken, //return type
|
|
497
|
+
this.currentFunctionExpression, this.currentNamespaceName, (_c = (_b = this.currentNamespace) === null || _b === void 0 ? void 0 : _b.symbolTable) !== null && _c !== void 0 ? _c : this.symbolTable);
|
|
480
498
|
//if there is a parent function, register this function with the parent
|
|
481
499
|
if (this.currentFunctionExpression) {
|
|
482
500
|
this.currentFunctionExpression.childFunctionExpressions.push(func);
|
|
483
501
|
}
|
|
502
|
+
// add the function to the relevant symbol tables
|
|
503
|
+
if (!isAnonymous && !forClassMethod) {
|
|
504
|
+
const funcType = func.getFunctionType();
|
|
505
|
+
funcType.setName(name.text);
|
|
506
|
+
// add the function as declared to the current namespace's table
|
|
507
|
+
(_d = this.currentNamespace) === null || _d === void 0 ? void 0 : _d.symbolTable.addSymbol(name.text, name.range, funcType);
|
|
508
|
+
let fullyQualifiedName = name.text;
|
|
509
|
+
if (this.currentNamespaceName) {
|
|
510
|
+
// add the "namespaced" name of this function to the parent symbol table
|
|
511
|
+
fullyQualifiedName = this.currentNamespaceName.getName(ParseMode.BrighterScript) + '.' + name.text;
|
|
512
|
+
}
|
|
513
|
+
this.currentSymbolTable.addSymbol(fullyQualifiedName, name.range, funcType);
|
|
514
|
+
}
|
|
484
515
|
this._references.functionExpressions.push(func);
|
|
485
516
|
let previousFunctionExpression = this.currentFunctionExpression;
|
|
486
517
|
this.currentFunctionExpression = func;
|
|
@@ -526,13 +557,13 @@ class Parser {
|
|
|
526
557
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
|
|
527
558
|
throw this.lastDiagnosticAsError();
|
|
528
559
|
}
|
|
529
|
-
|
|
530
|
-
// force the name into an identifier so the AST makes some sense
|
|
531
|
-
name.kind = lexer_1.TokenKind.Identifier;
|
|
560
|
+
const name = this.identifier(...lexer_1.AllowedLocalIdentifiers);
|
|
532
561
|
let typeToken;
|
|
533
562
|
let defaultValue;
|
|
563
|
+
let equalsToken;
|
|
534
564
|
// parse argument default value
|
|
535
565
|
if (this.match(lexer_1.TokenKind.Equal)) {
|
|
566
|
+
equalsToken = this.previous();
|
|
536
567
|
// it seems any expression is allowed here -- including ones that operate on other arguments!
|
|
537
568
|
defaultValue = this.expression();
|
|
538
569
|
}
|
|
@@ -540,15 +571,28 @@ class Parser {
|
|
|
540
571
|
if (this.check(lexer_1.TokenKind.As)) {
|
|
541
572
|
asToken = this.advance();
|
|
542
573
|
typeToken = this.typeToken();
|
|
543
|
-
if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript)) {
|
|
574
|
+
if (!util_1.util.tokenToBscType(typeToken, this.options.mode === ParseMode.BrighterScript, this.currentNamespaceName)) {
|
|
544
575
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeToken.text)), { range: typeToken.range }));
|
|
545
576
|
throw this.lastDiagnosticAsError();
|
|
546
577
|
}
|
|
547
578
|
}
|
|
548
|
-
|
|
579
|
+
let type;
|
|
580
|
+
if (typeToken) {
|
|
581
|
+
type = util_1.util.tokenToBscType(typeToken, true, this.currentNamespaceName);
|
|
582
|
+
}
|
|
583
|
+
else if (defaultValue) {
|
|
584
|
+
type = getBscTypeFromExpression(defaultValue, this.currentFunctionExpression);
|
|
585
|
+
if ((0, reflection_1.isInvalidType)(type)) {
|
|
586
|
+
type = new DynamicType_1.DynamicType();
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
type = new DynamicType_1.DynamicType();
|
|
591
|
+
}
|
|
592
|
+
return new Expression_1.FunctionParameterExpression(name, type, equalsToken, defaultValue, asToken, typeToken, this.currentNamespaceName);
|
|
549
593
|
}
|
|
550
594
|
assignment() {
|
|
551
|
-
let name = this.
|
|
595
|
+
let name = this.identifier(...this.allowedLocalIdentifiers);
|
|
552
596
|
//add diagnostic if name is a reserved word that cannot be used as an identifier
|
|
553
597
|
if (lexer_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
|
|
554
598
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
@@ -557,12 +601,14 @@ class Parser {
|
|
|
557
601
|
let value = this.expression();
|
|
558
602
|
let result;
|
|
559
603
|
if (operator.kind === lexer_1.TokenKind.Equal) {
|
|
560
|
-
result = new Statement_1.AssignmentStatement(
|
|
604
|
+
result = new Statement_1.AssignmentStatement(name, operator, value, this.currentFunctionExpression);
|
|
561
605
|
}
|
|
562
606
|
else {
|
|
563
|
-
result = new Statement_1.AssignmentStatement(
|
|
607
|
+
result = new Statement_1.AssignmentStatement(name, operator, new Expression_1.BinaryExpression(new Expression_1.VariableExpression(name, this.currentNamespaceName), operator, value), this.currentFunctionExpression);
|
|
564
608
|
}
|
|
565
609
|
this._references.assignmentStatements.push(result);
|
|
610
|
+
const assignmentType = getBscTypeFromExpression(result.value, this.currentFunctionExpression);
|
|
611
|
+
this.currentSymbolTable.addSymbol(name.text, name.range, assignmentType);
|
|
566
612
|
return result;
|
|
567
613
|
}
|
|
568
614
|
checkLibrary() {
|
|
@@ -717,7 +763,7 @@ class Parser {
|
|
|
717
763
|
}
|
|
718
764
|
forEachStatement() {
|
|
719
765
|
let forEach = this.advance();
|
|
720
|
-
let name = this.
|
|
766
|
+
let name = this.identifier(...this.allowedLocalIdentifiers);
|
|
721
767
|
let maybeIn = this.peek();
|
|
722
768
|
if (this.check(lexer_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
|
|
723
769
|
this.advance();
|
|
@@ -738,11 +784,10 @@ class Parser {
|
|
|
738
784
|
throw this.lastDiagnosticAsError();
|
|
739
785
|
}
|
|
740
786
|
let endFor = this.advance();
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
}, name, target, body);
|
|
787
|
+
//TODO TYPES infer type from `target`
|
|
788
|
+
const itemType = new DynamicType_1.DynamicType();
|
|
789
|
+
this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
|
|
790
|
+
return new Statement_1.ForEachStatement(forEach, name, maybeIn, target, body, endFor);
|
|
746
791
|
}
|
|
747
792
|
exitFor() {
|
|
748
793
|
let keyword = this.advance();
|
|
@@ -773,12 +818,13 @@ class Parser {
|
|
|
773
818
|
this.namespaceAndFunctionDepth++;
|
|
774
819
|
let name = this.getNamespacedVariableNameExpression();
|
|
775
820
|
//set the current namespace name
|
|
776
|
-
|
|
821
|
+
let result = new Statement_1.NamespaceStatement(keyword, name, null, null, this.currentSymbolTable);
|
|
822
|
+
this.currentNamespace = result;
|
|
777
823
|
this.globalTerminators.push([lexer_1.TokenKind.EndNamespace]);
|
|
778
824
|
let body = this.body();
|
|
779
825
|
this.globalTerminators.pop();
|
|
780
826
|
//unset the current namespace name
|
|
781
|
-
this.
|
|
827
|
+
this.currentNamespace = undefined;
|
|
782
828
|
let endKeyword;
|
|
783
829
|
if (this.check(lexer_1.TokenKind.EndNamespace)) {
|
|
784
830
|
endKeyword = this.advance();
|
|
@@ -788,7 +834,8 @@ class Parser {
|
|
|
788
834
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('namespace')), { range: keyword.range }));
|
|
789
835
|
}
|
|
790
836
|
this.namespaceAndFunctionDepth--;
|
|
791
|
-
|
|
837
|
+
result.body = body;
|
|
838
|
+
result.endKeyword = endKeyword;
|
|
792
839
|
this._references.namespaceStatements.push(result);
|
|
793
840
|
return result;
|
|
794
841
|
}
|
|
@@ -1276,9 +1323,11 @@ class Parser {
|
|
|
1276
1323
|
: new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
|
|
1277
1324
|
}
|
|
1278
1325
|
else if ((0, reflection_1.isDottedGetExpression)(left)) {
|
|
1279
|
-
|
|
1326
|
+
const dottedSetStmt = new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === lexer_1.TokenKind.Equal
|
|
1280
1327
|
? right
|
|
1281
1328
|
: new Expression_1.BinaryExpression(left, operator, right));
|
|
1329
|
+
this._references.dottedSetStatements.push(dottedSetStmt);
|
|
1330
|
+
return dottedSetStmt;
|
|
1282
1331
|
}
|
|
1283
1332
|
}
|
|
1284
1333
|
return this.expressionStatement(expr);
|
|
@@ -1338,7 +1387,9 @@ class Parser {
|
|
|
1338
1387
|
this.current -= 2;
|
|
1339
1388
|
throw new CancelStatementError();
|
|
1340
1389
|
}
|
|
1341
|
-
|
|
1390
|
+
const stmt = new Statement_1.LabelStatement(tokens);
|
|
1391
|
+
this.currentFunctionExpression.labelStatements.push(stmt);
|
|
1392
|
+
return stmt;
|
|
1342
1393
|
}
|
|
1343
1394
|
/**
|
|
1344
1395
|
* Parses a `goto` statement
|
|
@@ -1735,7 +1786,7 @@ class Parser {
|
|
|
1735
1786
|
else {
|
|
1736
1787
|
let k = key();
|
|
1737
1788
|
let expr = this.expression();
|
|
1738
|
-
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
|
|
1789
|
+
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
|
|
1739
1790
|
members.push(lastAAMember);
|
|
1740
1791
|
}
|
|
1741
1792
|
while (this.matchAny(lexer_1.TokenKind.Comma, lexer_1.TokenKind.Newline, lexer_1.TokenKind.Colon, lexer_1.TokenKind.Comment)) {
|
|
@@ -1762,14 +1813,15 @@ class Parser {
|
|
|
1762
1813
|
}
|
|
1763
1814
|
let k = key();
|
|
1764
1815
|
let expr = this.expression();
|
|
1765
|
-
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
|
|
1816
|
+
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
|
|
1766
1817
|
members.push(lastAAMember);
|
|
1767
1818
|
}
|
|
1768
1819
|
}
|
|
1769
1820
|
this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), lexer_1.TokenKind.RightCurlyBrace);
|
|
1770
1821
|
}
|
|
1771
1822
|
let closingBrace = this.previous();
|
|
1772
|
-
const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace);
|
|
1823
|
+
const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace, this.currentFunctionExpression);
|
|
1824
|
+
this._references.aaLiterals.push(aaExpr);
|
|
1773
1825
|
this.addPropertyHints(aaExpr);
|
|
1774
1826
|
return aaExpr;
|
|
1775
1827
|
case this.matchAny(lexer_1.TokenKind.Pos, lexer_1.TokenKind.Tab):
|
|
@@ -1945,6 +1997,235 @@ class Parser {
|
|
|
1945
1997
|
this.advance();
|
|
1946
1998
|
}
|
|
1947
1999
|
}
|
|
2000
|
+
/**
|
|
2001
|
+
* Get the token at the specified position
|
|
2002
|
+
* @param position
|
|
2003
|
+
*/
|
|
2004
|
+
getTokenAt(position) {
|
|
2005
|
+
for (let token of this.tokens) {
|
|
2006
|
+
if (util_1.util.rangeContains(token.range, position)) {
|
|
2007
|
+
return token;
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
/**
|
|
2012
|
+
* Get the token closest to the position. if no token is found, the previous token is returned
|
|
2013
|
+
* @param position
|
|
2014
|
+
* @param tokens
|
|
2015
|
+
*/
|
|
2016
|
+
getClosestToken(position) {
|
|
2017
|
+
let tokens = this.tokens;
|
|
2018
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
2019
|
+
let token = tokens[i];
|
|
2020
|
+
if (util_1.util.rangeContains(token.range, position)) {
|
|
2021
|
+
return token;
|
|
2022
|
+
}
|
|
2023
|
+
//if the position less than this token range, then this position touches no token,
|
|
2024
|
+
if (util_1.util.positionIsGreaterThanRange(position, token.range) === false) {
|
|
2025
|
+
let t = tokens[i - 1];
|
|
2026
|
+
//return the token or the first token
|
|
2027
|
+
return t ? t : tokens[0];
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
//return the last token
|
|
2031
|
+
return tokens[tokens.length - 1];
|
|
2032
|
+
}
|
|
2033
|
+
isPositionNextToTokenKind(position, tokenKind) {
|
|
2034
|
+
const closestToken = this.getClosestToken(position);
|
|
2035
|
+
const previousToken = this.getPreviousToken(closestToken);
|
|
2036
|
+
const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
|
|
2037
|
+
//next to matched token
|
|
2038
|
+
if (!closestToken || closestToken.kind === lexer_1.TokenKind.Eof) {
|
|
2039
|
+
return false;
|
|
2040
|
+
}
|
|
2041
|
+
else if (closestToken.kind === tokenKind) {
|
|
2042
|
+
return true;
|
|
2043
|
+
}
|
|
2044
|
+
else if (closestToken.kind === lexer_1.TokenKind.Newline || previousTokenKind === lexer_1.TokenKind.Newline) {
|
|
2045
|
+
return false;
|
|
2046
|
+
//next to an identifier, which is next to token kind
|
|
2047
|
+
}
|
|
2048
|
+
else if (closestToken.kind === lexer_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
|
|
2049
|
+
return true;
|
|
2050
|
+
}
|
|
2051
|
+
else {
|
|
2052
|
+
return false;
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
getTokenBefore(currentToken, tokenKind) {
|
|
2056
|
+
const index = this.tokens.indexOf(currentToken);
|
|
2057
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
2058
|
+
currentToken = this.tokens[i];
|
|
2059
|
+
if (currentToken.kind === lexer_1.TokenKind.Newline) {
|
|
2060
|
+
break;
|
|
2061
|
+
}
|
|
2062
|
+
else if (currentToken.kind === tokenKind) {
|
|
2063
|
+
return currentToken;
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
return undefined;
|
|
2067
|
+
}
|
|
2068
|
+
tokenFollows(currentToken, tokenKind) {
|
|
2069
|
+
const index = this.tokens.indexOf(currentToken);
|
|
2070
|
+
if (index > 0) {
|
|
2071
|
+
return this.tokens[index - 1].kind === tokenKind;
|
|
2072
|
+
}
|
|
2073
|
+
return false;
|
|
2074
|
+
}
|
|
2075
|
+
getTokensUntil(currentToken, tokenKind, direction = -1) {
|
|
2076
|
+
let tokens = [];
|
|
2077
|
+
for (let i = this.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.tokens.length; i += direction) {
|
|
2078
|
+
currentToken = this.tokens[i];
|
|
2079
|
+
if (currentToken.kind === lexer_1.TokenKind.Newline || currentToken.kind === tokenKind) {
|
|
2080
|
+
break;
|
|
2081
|
+
}
|
|
2082
|
+
tokens.push(currentToken);
|
|
2083
|
+
}
|
|
2084
|
+
return tokens;
|
|
2085
|
+
}
|
|
2086
|
+
getPreviousToken(token) {
|
|
2087
|
+
let idx = this.tokens.indexOf(token);
|
|
2088
|
+
return this.tokens[idx - 1];
|
|
2089
|
+
}
|
|
2090
|
+
getPreviousTokenFromIndex(idx) {
|
|
2091
|
+
return { token: this.tokens[idx - 1], index: idx - 1 };
|
|
2092
|
+
}
|
|
2093
|
+
getPreviousTokenIgnoreNests(currentTokenIndex, leftBracketType, rightBracketType) {
|
|
2094
|
+
let currentToken = this.tokens[currentTokenIndex];
|
|
2095
|
+
let previousTokenResult;
|
|
2096
|
+
function isRightBracket(token) {
|
|
2097
|
+
return (token === null || token === void 0 ? void 0 : token.kind) === rightBracketType;
|
|
2098
|
+
}
|
|
2099
|
+
function isLeftBracket(token) {
|
|
2100
|
+
return (token === null || token === void 0 ? void 0 : token.kind) === leftBracketType;
|
|
2101
|
+
}
|
|
2102
|
+
let lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2103
|
+
let lastTokenWasLeftBracket = false;
|
|
2104
|
+
let bracketNestCount = 0;
|
|
2105
|
+
let hasBrackets = false;
|
|
2106
|
+
// check for nested function call
|
|
2107
|
+
if (isRightBracket(currentToken)) {
|
|
2108
|
+
bracketNestCount++;
|
|
2109
|
+
hasBrackets = true;
|
|
2110
|
+
}
|
|
2111
|
+
while (currentToken && bracketNestCount > 0) {
|
|
2112
|
+
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2113
|
+
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2114
|
+
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2115
|
+
lastTokenWasLeftBracket = false;
|
|
2116
|
+
if (isRightBracket(currentToken)) {
|
|
2117
|
+
bracketNestCount++;
|
|
2118
|
+
}
|
|
2119
|
+
while (isLeftBracket(currentToken)) {
|
|
2120
|
+
bracketNestCount--;
|
|
2121
|
+
lastTokenWasLeftBracket = true;
|
|
2122
|
+
lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2123
|
+
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2124
|
+
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2125
|
+
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
// We will not be able to decipher the token type if it was in brackets
|
|
2129
|
+
// e.g (someVar+otherVar).toStr() -- we don't bother trying to decipher what "(someVar+otherVar)" is
|
|
2130
|
+
let isUnknown = (lastTokenWasLeftBracket && (lastTokenHadLeadingWhitespace || !this.isAcceptableChainToken(currentToken)));
|
|
2131
|
+
const tokenWithIndex = { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: isUnknown, hasBrackets: hasBrackets };
|
|
2132
|
+
return tokenWithIndex;
|
|
2133
|
+
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Finds the previous token in a chain (e.g. 'm.obj.func(someFunc()).value'), skipping over any arguments of function calls
|
|
2136
|
+
* If this function was called with the token at 'value' above, the previous identifier in the chain is 'func'
|
|
2137
|
+
* @param currentTokenIndex token index to start from
|
|
2138
|
+
* @param allowCurrent can the current token be the token that's the identifier?
|
|
2139
|
+
* @returns the previous identifer
|
|
2140
|
+
*/
|
|
2141
|
+
getPreviousTokenInChain(currentTokenIndex, allowCurrent = false) {
|
|
2142
|
+
let currentToken = this.tokens[currentTokenIndex];
|
|
2143
|
+
let previousTokenResult;
|
|
2144
|
+
let usage = TokenUsage.Direct;
|
|
2145
|
+
if (!allowCurrent) {
|
|
2146
|
+
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2147
|
+
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2148
|
+
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2149
|
+
}
|
|
2150
|
+
if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === lexer_1.TokenKind.Dot) {
|
|
2151
|
+
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2152
|
+
currentToken = previousTokenResult.token;
|
|
2153
|
+
currentTokenIndex = previousTokenResult.index;
|
|
2154
|
+
}
|
|
2155
|
+
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, lexer_1.TokenKind.LeftParen, lexer_1.TokenKind.RightParen);
|
|
2156
|
+
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2157
|
+
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2158
|
+
if (previousTokenResult.hasBrackets) {
|
|
2159
|
+
usage = TokenUsage.Call;
|
|
2160
|
+
}
|
|
2161
|
+
let tokenTypeIsNotKnowable = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable;
|
|
2162
|
+
if (currentTokenIndex) {
|
|
2163
|
+
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, lexer_1.TokenKind.LeftSquareBracket, lexer_1.TokenKind.RightSquareBracket);
|
|
2164
|
+
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2165
|
+
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2166
|
+
if (previousTokenResult.hasBrackets) {
|
|
2167
|
+
usage = TokenUsage.ArrayReference;
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
tokenTypeIsNotKnowable = tokenTypeIsNotKnowable || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
|
|
2171
|
+
if (tokenTypeIsNotKnowable || this.isAcceptableChainToken(currentToken)) {
|
|
2172
|
+
// either we have a valid chain token, or we can't know what the token type is
|
|
2173
|
+
return { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: tokenTypeIsNotKnowable, usage: usage };
|
|
2174
|
+
}
|
|
2175
|
+
return undefined;
|
|
2176
|
+
}
|
|
2177
|
+
isAcceptableChainToken(currentToken, lastTokenHasWhitespace = false) {
|
|
2178
|
+
if (!currentToken || lastTokenHasWhitespace) {
|
|
2179
|
+
return false;
|
|
2180
|
+
}
|
|
2181
|
+
if (currentToken.kind === lexer_1.TokenKind.Identifier) {
|
|
2182
|
+
return true;
|
|
2183
|
+
}
|
|
2184
|
+
if (currentToken.leadingWhitespace.length === 0) {
|
|
2185
|
+
// start of the chain
|
|
2186
|
+
return lexer_1.AllowedLocalIdentifiers.includes(currentToken.kind);
|
|
2187
|
+
}
|
|
2188
|
+
// not the start of the chain
|
|
2189
|
+
return lexer_1.AllowedProperties.includes(currentToken.kind);
|
|
2190
|
+
}
|
|
2191
|
+
/**
|
|
2192
|
+
* Builds up a chain of tokens, starting with the first in the chain, and ending with currentToken
|
|
2193
|
+
* e.g. m.prop.method().field (with 'field' as currentToken) -> ["m", "prop", "method", "field"], with each element as a token
|
|
2194
|
+
* @param currentToken the token that is the end of the chain
|
|
2195
|
+
* @returns array of tokens
|
|
2196
|
+
*/
|
|
2197
|
+
getTokenChain(currentToken) {
|
|
2198
|
+
const tokenChain = [];
|
|
2199
|
+
let currentTokenIndex = this.tokens.indexOf(currentToken);
|
|
2200
|
+
let previousTokenResult;
|
|
2201
|
+
let lastTokenHasWhitespace = false;
|
|
2202
|
+
let includesUnknown = false;
|
|
2203
|
+
previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex, true);
|
|
2204
|
+
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2205
|
+
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2206
|
+
if (this.isAcceptableChainToken(currentToken)) {
|
|
2207
|
+
tokenChain.push(previousTokenResult);
|
|
2208
|
+
lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2209
|
+
}
|
|
2210
|
+
if (!lastTokenHasWhitespace) {
|
|
2211
|
+
previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
|
|
2212
|
+
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2213
|
+
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2214
|
+
includesUnknown = !!(previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
|
|
2215
|
+
while (!includesUnknown && this.isAcceptableChainToken(currentToken, lastTokenHasWhitespace)) {
|
|
2216
|
+
tokenChain.push(previousTokenResult);
|
|
2217
|
+
lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2218
|
+
if (!lastTokenHasWhitespace) {
|
|
2219
|
+
previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
|
|
2220
|
+
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2221
|
+
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2222
|
+
includesUnknown = includesUnknown || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
tokenChain.reverse();
|
|
2227
|
+
return { chain: tokenChain, includesUnknowableTokenType: !!includesUnknown };
|
|
2228
|
+
}
|
|
1948
2229
|
/**
|
|
1949
2230
|
* References are found during the initial parse.
|
|
1950
2231
|
* However, sometimes plugins can modify the AST, requiring a full walk to re-compute all references.
|
|
@@ -1952,10 +2233,8 @@ class Parser {
|
|
|
1952
2233
|
*/
|
|
1953
2234
|
findReferences() {
|
|
1954
2235
|
this._references = new References();
|
|
2236
|
+
//gather up all the top-level statements
|
|
1955
2237
|
this.ast.walk((0, visitors_1.createVisitor)({
|
|
1956
|
-
AssignmentStatement: s => {
|
|
1957
|
-
this._references.assignmentStatements.push(s);
|
|
1958
|
-
},
|
|
1959
2238
|
ClassStatement: s => {
|
|
1960
2239
|
this._references.classStatements.push(s);
|
|
1961
2240
|
},
|
|
@@ -1964,12 +2243,22 @@ class Parser {
|
|
|
1964
2243
|
},
|
|
1965
2244
|
FunctionStatement: s => {
|
|
1966
2245
|
this._references.functionStatements.push(s);
|
|
2246
|
+
//add the initial set of function expressions for function statements
|
|
2247
|
+
this._references.functionExpressions.push(s.func);
|
|
1967
2248
|
},
|
|
1968
2249
|
ImportStatement: s => {
|
|
1969
2250
|
this._references.importStatements.push(s);
|
|
1970
2251
|
},
|
|
1971
2252
|
LibraryStatement: s => {
|
|
1972
2253
|
this._references.libraryStatements.push(s);
|
|
2254
|
+
}
|
|
2255
|
+
}), {
|
|
2256
|
+
walkMode: visitors_1.WalkMode.visitStatements
|
|
2257
|
+
});
|
|
2258
|
+
let func;
|
|
2259
|
+
let visitor = (0, visitors_1.createVisitor)({
|
|
2260
|
+
AssignmentStatement: s => {
|
|
2261
|
+
this._references.assignmentStatements.push(s);
|
|
1973
2262
|
},
|
|
1974
2263
|
FunctionExpression: (expression, parent) => {
|
|
1975
2264
|
if (!(0, reflection_1.isClassMethodStatement)(parent)) {
|
|
@@ -1988,9 +2277,27 @@ class Parser {
|
|
|
1988
2277
|
DottedSetStatement: e => {
|
|
1989
2278
|
this.addPropertyHints(e.name);
|
|
1990
2279
|
}
|
|
1991
|
-
}), {
|
|
1992
|
-
walkMode: visitors_1.WalkMode.visitAllRecursive
|
|
1993
2280
|
});
|
|
2281
|
+
//walk all function expressions (we'll add new ones as we move along too)
|
|
2282
|
+
for (let i = 0; i < this._references.functionExpressions.length; i++) {
|
|
2283
|
+
func = this._references.functionExpressions[i];
|
|
2284
|
+
//walk this function expression
|
|
2285
|
+
func.body.walk(visitor, {
|
|
2286
|
+
walkMode: visitors_1.WalkMode.visitAll
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
getContainingClass(currentToken) {
|
|
2291
|
+
return this.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
|
|
2292
|
+
}
|
|
2293
|
+
getContainingAA(currentToken) {
|
|
2294
|
+
return this.references.aaLiterals.find((aa) => util_1.util.rangeContains(aa.range, currentToken.range.start));
|
|
2295
|
+
}
|
|
2296
|
+
getContainingNamespace(currentToken) {
|
|
2297
|
+
return this.references.namespaceStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
|
|
2298
|
+
}
|
|
2299
|
+
getContainingFunctionExpression(currentToken) {
|
|
2300
|
+
return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, currentToken.range.start));
|
|
1994
2301
|
}
|
|
1995
2302
|
dispose() {
|
|
1996
2303
|
}
|
|
@@ -2005,6 +2312,8 @@ class References {
|
|
|
2005
2312
|
constructor() {
|
|
2006
2313
|
this.assignmentStatements = [];
|
|
2007
2314
|
this.classStatements = [];
|
|
2315
|
+
this.dottedSetStatements = [];
|
|
2316
|
+
this.aaLiterals = [];
|
|
2008
2317
|
this.functionExpressions = [];
|
|
2009
2318
|
this.functionStatements = [];
|
|
2010
2319
|
this.interfaceStatements = [];
|
|
@@ -2046,9 +2355,61 @@ class References {
|
|
|
2046
2355
|
}
|
|
2047
2356
|
}
|
|
2048
2357
|
exports.References = References;
|
|
2358
|
+
var TokenUsage;
|
|
2359
|
+
(function (TokenUsage) {
|
|
2360
|
+
TokenUsage[TokenUsage["Direct"] = 1] = "Direct";
|
|
2361
|
+
TokenUsage[TokenUsage["Call"] = 2] = "Call";
|
|
2362
|
+
TokenUsage[TokenUsage["ArrayReference"] = 3] = "ArrayReference";
|
|
2363
|
+
})(TokenUsage = exports.TokenUsage || (exports.TokenUsage = {}));
|
|
2049
2364
|
class CancelStatementError extends Error {
|
|
2050
2365
|
constructor() {
|
|
2051
2366
|
super('CancelStatement');
|
|
2052
2367
|
}
|
|
2053
2368
|
}
|
|
2369
|
+
/**
|
|
2370
|
+
* Gets the type of an expression. If it can not be processed, will return DynamicType
|
|
2371
|
+
*
|
|
2372
|
+
* @param expression the Expression to process
|
|
2373
|
+
* @param functionExpression the wrapping function expression
|
|
2374
|
+
* @return the best guess type of that expression
|
|
2375
|
+
*/
|
|
2376
|
+
function getBscTypeFromExpression(expression, functionExpression) {
|
|
2377
|
+
try {
|
|
2378
|
+
if ((0, reflection_1.isFunctionExpression)(expression)) {
|
|
2379
|
+
return expression.getFunctionType();
|
|
2380
|
+
//literal
|
|
2381
|
+
}
|
|
2382
|
+
else if ((0, reflection_1.isLiteralExpression)(expression)) {
|
|
2383
|
+
return expression.type;
|
|
2384
|
+
//Associative array literal
|
|
2385
|
+
}
|
|
2386
|
+
else if ((0, reflection_1.isAALiteralExpression)(expression)) {
|
|
2387
|
+
return new ObjectType_1.ObjectType(expression.memberTable);
|
|
2388
|
+
//Array literal
|
|
2389
|
+
}
|
|
2390
|
+
else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {
|
|
2391
|
+
return new ArrayType_1.ArrayType();
|
|
2392
|
+
//function call
|
|
2393
|
+
}
|
|
2394
|
+
else if ((0, reflection_1.isNewExpression)(expression)) {
|
|
2395
|
+
return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression); // new CustomType(expression.className.getName(ParseMode.BrighterScript));
|
|
2396
|
+
//Function call
|
|
2397
|
+
}
|
|
2398
|
+
else if ((0, reflection_1.isCallExpression)(expression)) {
|
|
2399
|
+
return (0, helpers_1.getTypeFromCallExpression)(expression, functionExpression);
|
|
2400
|
+
}
|
|
2401
|
+
else if ((0, reflection_1.isVariableExpression)(expression)) {
|
|
2402
|
+
return (0, helpers_1.getTypeFromVariableExpression)(expression, functionExpression);
|
|
2403
|
+
}
|
|
2404
|
+
else if ((0, reflection_1.isDottedGetExpression)(expression)) {
|
|
2405
|
+
return (0, helpers_1.getTypeFromDottedGetExpression)(expression, functionExpression);
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
catch (e) {
|
|
2409
|
+
//do nothing. Just return dynamic
|
|
2410
|
+
}
|
|
2411
|
+
//fallback to dynamic
|
|
2412
|
+
return new DynamicType_1.DynamicType();
|
|
2413
|
+
}
|
|
2414
|
+
exports.getBscTypeFromExpression = getBscTypeFromExpression;
|
|
2054
2415
|
//# sourceMappingURL=Parser.js.map
|