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
|
@@ -8,8 +8,18 @@ const Parser_1 = require("./Parser");
|
|
|
8
8
|
const Statement_1 = require("./Statement");
|
|
9
9
|
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
10
10
|
const DiagnosticMessages_1 = require("../DiagnosticMessages");
|
|
11
|
-
const
|
|
11
|
+
const reflection_1 = require("../astUtils/reflection");
|
|
12
12
|
const testHelpers_spec_1 = require("../testHelpers.spec");
|
|
13
|
+
const VoidType_1 = require("../types/VoidType");
|
|
14
|
+
const FunctionType_1 = require("../types/FunctionType");
|
|
15
|
+
const StringType_1 = require("../types/StringType");
|
|
16
|
+
const CustomType_1 = require("../types/CustomType");
|
|
17
|
+
const IntegerType_1 = require("../types/IntegerType");
|
|
18
|
+
const ObjectType_1 = require("../types/ObjectType");
|
|
19
|
+
const SymbolTable_1 = require("../SymbolTable");
|
|
20
|
+
const DynamicType_1 = require("../types/DynamicType");
|
|
21
|
+
const util_1 = require("../util");
|
|
22
|
+
const LazyType_1 = require("../types/LazyType");
|
|
13
23
|
describe('parser', () => {
|
|
14
24
|
it('emits empty object when empty token list is provided', () => {
|
|
15
25
|
(0, chai_1.expect)(Parser_1.Parser.parse([])).to.deep.include({
|
|
@@ -18,6 +28,56 @@ describe('parser', () => {
|
|
|
18
28
|
});
|
|
19
29
|
});
|
|
20
30
|
describe('findReferences', () => {
|
|
31
|
+
it('recomputes localVars', () => {
|
|
32
|
+
const parser = Parser_1.Parser.parse(`
|
|
33
|
+
sub main(herd)
|
|
34
|
+
for each zombie in herd
|
|
35
|
+
isAlive = false
|
|
36
|
+
end for
|
|
37
|
+
for i = 0 to 10 step 1
|
|
38
|
+
j = i
|
|
39
|
+
end for
|
|
40
|
+
humansAreAlive = false
|
|
41
|
+
end sub
|
|
42
|
+
`);
|
|
43
|
+
(0, chai_1.expect)(parser.references.functionExpressions[0].symbolTable.getOwnSymbols().map(x => x.name).sort()).to.eql([
|
|
44
|
+
'herd',
|
|
45
|
+
'humansAreAlive',
|
|
46
|
+
'i',
|
|
47
|
+
'isAlive',
|
|
48
|
+
'j',
|
|
49
|
+
'zombie'
|
|
50
|
+
]);
|
|
51
|
+
parser.invalidateReferences();
|
|
52
|
+
(0, chai_1.expect)(parser.references.functionExpressions[0].symbolTable.getOwnSymbols().map(x => x.name).sort()).to.eql([
|
|
53
|
+
'herd',
|
|
54
|
+
'humansAreAlive',
|
|
55
|
+
'i',
|
|
56
|
+
'isAlive',
|
|
57
|
+
'j',
|
|
58
|
+
'zombie'
|
|
59
|
+
]);
|
|
60
|
+
});
|
|
61
|
+
it('assigns localVars to correct function expression bucket', () => {
|
|
62
|
+
const parser = Parser_1.Parser.parse(`
|
|
63
|
+
sub main()
|
|
64
|
+
outerName = "bob"
|
|
65
|
+
speak = sub()
|
|
66
|
+
innerName = "innerBob"
|
|
67
|
+
end sub
|
|
68
|
+
age = 12
|
|
69
|
+
end sub
|
|
70
|
+
`);
|
|
71
|
+
parser.invalidateReferences();
|
|
72
|
+
(0, chai_1.expect)(parser.references.functionExpressions[0].symbolTable.getOwnSymbols().map(x => x.name)).to.eql([
|
|
73
|
+
'outerName',
|
|
74
|
+
'speak',
|
|
75
|
+
'age'
|
|
76
|
+
]);
|
|
77
|
+
(0, chai_1.expect)(parser.references.functionExpressions[1].symbolTable.getOwnSymbols().map(x => x.name)).to.eql([
|
|
78
|
+
'innerName'
|
|
79
|
+
]);
|
|
80
|
+
});
|
|
21
81
|
it('gets called if references are missing', () => {
|
|
22
82
|
const parser = Parser_1.Parser.parse(`
|
|
23
83
|
sub main()
|
|
@@ -197,6 +257,41 @@ describe('parser', () => {
|
|
|
197
257
|
`);
|
|
198
258
|
(0, chai_1.expect)((_a = parser.diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.equal(DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('namespace').message);
|
|
199
259
|
});
|
|
260
|
+
it('declares a symbol table for the namespace', () => {
|
|
261
|
+
let parser = parse(`
|
|
262
|
+
namespace Name.Space
|
|
263
|
+
function funcInt() as integer
|
|
264
|
+
return 3
|
|
265
|
+
end function
|
|
266
|
+
|
|
267
|
+
function funcStr() as string
|
|
268
|
+
return "hello"
|
|
269
|
+
end function
|
|
270
|
+
end namespace
|
|
271
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
272
|
+
(0, chai_1.expect)(parser.ast.statements[0]).to.be.instanceof(Statement_1.NamespaceStatement);
|
|
273
|
+
const namespaceStmt = parser.ast.statements[0];
|
|
274
|
+
(0, chai_1.expect)(namespaceStmt.symbolTable).to.be.instanceof(SymbolTable_1.SymbolTable);
|
|
275
|
+
(0, chai_1.expect)(namespaceStmt.symbolTable.getSymbolType('funcInt').toString()).to.equal('function funcInt() as integer');
|
|
276
|
+
(0, chai_1.expect)(namespaceStmt.symbolTable.getSymbolType('funcStr')).to.be.instanceof(FunctionType_1.FunctionType);
|
|
277
|
+
const strFunctionType = namespaceStmt.symbolTable.getSymbolType('funcStr');
|
|
278
|
+
(0, chai_1.expect)(strFunctionType.returnType.toString()).to.equal('string');
|
|
279
|
+
});
|
|
280
|
+
it('adds a fully qualified name of a function in a namespace to the parsers symbol table', () => {
|
|
281
|
+
let parser = parse(`
|
|
282
|
+
namespace Name.Space
|
|
283
|
+
function funcInt() as integer
|
|
284
|
+
return 3
|
|
285
|
+
end function
|
|
286
|
+
|
|
287
|
+
function funcStr() as string
|
|
288
|
+
return "hello"
|
|
289
|
+
end function
|
|
290
|
+
end namespace
|
|
291
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
292
|
+
(0, chai_1.expect)(parser.symbolTable.getSymbolType('Name.Space.funcInt')).to.be.instanceof(FunctionType_1.FunctionType);
|
|
293
|
+
(0, chai_1.expect)(parser.symbolTable.getSymbolType('Name.Space.funcStr')).to.be.instanceof(FunctionType_1.FunctionType);
|
|
294
|
+
});
|
|
200
295
|
});
|
|
201
296
|
it('supports << operator', () => {
|
|
202
297
|
var _a;
|
|
@@ -451,19 +546,19 @@ describe('parser', () => {
|
|
|
451
546
|
let { diagnostics, statements } = Parser_1.Parser.parse(tokens);
|
|
452
547
|
(0, chai_1.expect)(diagnostics).to.be.lengthOf(0, 'Should have zero diagnostics');
|
|
453
548
|
let fnSmt = statements[0];
|
|
454
|
-
if ((0,
|
|
549
|
+
if ((0, reflection_1.isFunctionStatement)(fnSmt)) {
|
|
455
550
|
let ifStmt = fnSmt.func.body.statements[0];
|
|
456
|
-
if ((0,
|
|
551
|
+
if ((0, reflection_1.isIfStatement)(ifStmt)) {
|
|
457
552
|
expectCommentWithText(ifStmt.thenBranch.statements[0], `'comment 1`);
|
|
458
553
|
expectCommentWithText(ifStmt.thenBranch.statements[1], `'comment 2`);
|
|
459
554
|
expectCommentWithText(ifStmt.thenBranch.statements[3], `'comment 3`);
|
|
460
555
|
let elseIfBranch = ifStmt.elseBranch;
|
|
461
|
-
if ((0,
|
|
556
|
+
if ((0, reflection_1.isIfStatement)(elseIfBranch)) {
|
|
462
557
|
expectCommentWithText(elseIfBranch.thenBranch.statements[0], `'comment 4`);
|
|
463
558
|
expectCommentWithText(elseIfBranch.thenBranch.statements[1], `'comment 5`);
|
|
464
559
|
expectCommentWithText(elseIfBranch.thenBranch.statements[3], `'comment 6`);
|
|
465
560
|
let elseBranch = elseIfBranch.elseBranch;
|
|
466
|
-
if ((0,
|
|
561
|
+
if ((0, reflection_1.isBlock)(elseBranch)) {
|
|
467
562
|
expectCommentWithText(elseBranch.statements[0], `'comment 7`);
|
|
468
563
|
expectCommentWithText(elseBranch.statements[1], `'comment 8`);
|
|
469
564
|
expectCommentWithText(elseBranch.statements[3], `'comment 9`);
|
|
@@ -605,7 +700,7 @@ describe('parser', () => {
|
|
|
605
700
|
(0, chai_1.expect)((_a = diagnostics[0]) === null || _a === void 0 ? void 0 : _a.message).to.eql(DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('import statements').message);
|
|
606
701
|
(0, chai_1.expect)(statements[0]).to.be.instanceof(Statement_1.ImportStatement);
|
|
607
702
|
});
|
|
608
|
-
it('
|
|
703
|
+
it('catches missing file path', () => {
|
|
609
704
|
var _a;
|
|
610
705
|
let { statements, diagnostics } = parse(`
|
|
611
706
|
import
|
|
@@ -949,6 +1044,308 @@ describe('parser', () => {
|
|
|
949
1044
|
(0, chai_1.expect)(fn.annotations[0].getArguments()).to.deep.equal([-100]);
|
|
950
1045
|
});
|
|
951
1046
|
});
|
|
1047
|
+
describe('getBscTypeFromExpression', () => {
|
|
1048
|
+
it('computes void type for sub with no return type', () => {
|
|
1049
|
+
const parser = parse(`
|
|
1050
|
+
sub main()
|
|
1051
|
+
getMessage = sub()
|
|
1052
|
+
print "hello"
|
|
1053
|
+
end sub
|
|
1054
|
+
end sub
|
|
1055
|
+
`);
|
|
1056
|
+
const func = parser.ast.statements[0].func;
|
|
1057
|
+
const type = (0, Parser_1.getBscTypeFromExpression)(func.body.statements[0].value, func);
|
|
1058
|
+
(0, chai_1.expect)(type.returnType).to.be.instanceof(VoidType_1.VoidType);
|
|
1059
|
+
});
|
|
1060
|
+
it('computes return type for sub with explicit return type', () => {
|
|
1061
|
+
const parser = parse(`
|
|
1062
|
+
sub main()
|
|
1063
|
+
getMessage = sub() as string
|
|
1064
|
+
return "hello"
|
|
1065
|
+
end sub
|
|
1066
|
+
end sub
|
|
1067
|
+
`);
|
|
1068
|
+
const func = parser.ast.statements[0].func;
|
|
1069
|
+
const type = (0, Parser_1.getBscTypeFromExpression)(func.body.statements[0].value, func);
|
|
1070
|
+
(0, chai_1.expect)(type.returnType).to.be.instanceof(StringType_1.StringType);
|
|
1071
|
+
});
|
|
1072
|
+
it('supports sub with custom return type', () => {
|
|
1073
|
+
const parser = parse(`
|
|
1074
|
+
sub main()
|
|
1075
|
+
getPerson = sub() as Person
|
|
1076
|
+
return new Person()
|
|
1077
|
+
end sub
|
|
1078
|
+
end sub
|
|
1079
|
+
|
|
1080
|
+
class Person
|
|
1081
|
+
end class
|
|
1082
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1083
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(parser.diagnostics);
|
|
1084
|
+
const func = parser.ast.statements[0].func;
|
|
1085
|
+
const type = (0, Parser_1.getBscTypeFromExpression)(func.body.statements[0].value, func);
|
|
1086
|
+
// Return type is LazyType, because "Person" is not fully known yet
|
|
1087
|
+
(0, chai_1.expect)(type.returnType).to.be.instanceof(LazyType_1.LazyType);
|
|
1088
|
+
});
|
|
1089
|
+
});
|
|
1090
|
+
describe('symbolTable', () => {
|
|
1091
|
+
it('stores the types', () => {
|
|
1092
|
+
const parser = parse(`
|
|
1093
|
+
sub main()
|
|
1094
|
+
someNum = 123
|
|
1095
|
+
someString = "hello world"
|
|
1096
|
+
someObj = {foo: "bar"}
|
|
1097
|
+
someCustom = new CustomKlass()
|
|
1098
|
+
end sub
|
|
1099
|
+
|
|
1100
|
+
class CustomKlass
|
|
1101
|
+
end class
|
|
1102
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1103
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(parser.diagnostics);
|
|
1104
|
+
const mainSymbolTable = parser.references.functionExpressions[0].symbolTable;
|
|
1105
|
+
(0, chai_1.expect)(mainSymbolTable.getSymbolType('someNum')).to.be.instanceof(IntegerType_1.IntegerType);
|
|
1106
|
+
(0, chai_1.expect)(mainSymbolTable.getSymbolType('someString')).to.be.instanceof(StringType_1.StringType);
|
|
1107
|
+
(0, chai_1.expect)(mainSymbolTable.getSymbolType('someObj')).to.be.instanceof(ObjectType_1.ObjectType);
|
|
1108
|
+
(0, chai_1.expect)(mainSymbolTable.getSymbolType('someCustom')).to.be.instanceof(CustomType_1.CustomType);
|
|
1109
|
+
});
|
|
1110
|
+
it('stores typed parameters in functions', () => {
|
|
1111
|
+
const parser = parse(`
|
|
1112
|
+
sub someFunc(param1 as string, param2 as integer)
|
|
1113
|
+
temp = param2
|
|
1114
|
+
end sub
|
|
1115
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1116
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(parser.diagnostics);
|
|
1117
|
+
const someFuncSymbolTable = parser.references.functionExpressions[0].symbolTable;
|
|
1118
|
+
(0, chai_1.expect)(someFuncSymbolTable.getSymbolType('param1')).to.be.instanceof(StringType_1.StringType);
|
|
1119
|
+
(0, chai_1.expect)(someFuncSymbolTable.getSymbolType('param2')).to.be.instanceof(IntegerType_1.IntegerType);
|
|
1120
|
+
(0, chai_1.expect)(someFuncSymbolTable.getSymbolType('temp')).to.be.instanceof(IntegerType_1.IntegerType);
|
|
1121
|
+
});
|
|
1122
|
+
it('properly defers typing lazy types', () => {
|
|
1123
|
+
const parser = parse(`
|
|
1124
|
+
sub someFunc()
|
|
1125
|
+
temp = foo()
|
|
1126
|
+
end sub
|
|
1127
|
+
|
|
1128
|
+
function foo() as string
|
|
1129
|
+
return "foo"
|
|
1130
|
+
end function
|
|
1131
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1132
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(parser.diagnostics);
|
|
1133
|
+
const someFuncSymbolTable = parser.references.functionExpressions[0].symbolTable;
|
|
1134
|
+
(0, chai_1.expect)((0, reflection_1.isLazyType)(someFuncSymbolTable.getSymbol('temp')[0].type)).to.be.true;
|
|
1135
|
+
(0, chai_1.expect)(someFuncSymbolTable.getSymbolType('temp').toTypeString()).to.eq('string');
|
|
1136
|
+
});
|
|
1137
|
+
it('does not know about symbols declared in parent functions', () => {
|
|
1138
|
+
const parser = parse(`
|
|
1139
|
+
sub main()
|
|
1140
|
+
count = 0
|
|
1141
|
+
addOne = sub()
|
|
1142
|
+
oldVal = count
|
|
1143
|
+
end sub
|
|
1144
|
+
end sub
|
|
1145
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1146
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(parser.diagnostics);
|
|
1147
|
+
const addOneSymbolTable = parser.references.functionExpressions[0].childFunctionExpressions[0].symbolTable;
|
|
1148
|
+
(0, chai_1.expect)((0, reflection_1.isUninitializedType)(addOneSymbolTable.getSymbolType('oldVal'))).to.be.true;
|
|
1149
|
+
});
|
|
1150
|
+
it('finds params', () => {
|
|
1151
|
+
const parser = parse(`
|
|
1152
|
+
sub alert(p1, p2 as string, p3 = 1)
|
|
1153
|
+
end sub
|
|
1154
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1155
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(parser.diagnostics);
|
|
1156
|
+
(0, testHelpers_spec_1.expectSymbolTableEquals)(parser.references.functionExpressions[0].symbolTable, [
|
|
1157
|
+
['p1', new DynamicType_1.DynamicType(), util_1.default.createRange(1, 26, 1, 28)],
|
|
1158
|
+
['p2', new StringType_1.StringType(), util_1.default.createRange(1, 30, 1, 32)],
|
|
1159
|
+
['p3', new IntegerType_1.IntegerType(), util_1.default.createRange(1, 44, 1, 46)]
|
|
1160
|
+
]);
|
|
1161
|
+
});
|
|
1162
|
+
describe('loops', () => {
|
|
1163
|
+
it('stores the loop variable in a for loop', () => {
|
|
1164
|
+
const parser = parse(`
|
|
1165
|
+
sub main()
|
|
1166
|
+
for i = 0 to 10 step 10
|
|
1167
|
+
print i
|
|
1168
|
+
end for
|
|
1169
|
+
end sub
|
|
1170
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1171
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(parser.diagnostics);
|
|
1172
|
+
const currentSymbolTable = parser.references.functionExpressions[0].symbolTable;
|
|
1173
|
+
(0, chai_1.expect)(currentSymbolTable.getSymbolType('i').toString()).to.eq('integer');
|
|
1174
|
+
});
|
|
1175
|
+
it('stores the loop variable in a for each loop', () => {
|
|
1176
|
+
const parser = parse(`
|
|
1177
|
+
sub doLoop(someData)
|
|
1178
|
+
for each datum in someData
|
|
1179
|
+
print datum
|
|
1180
|
+
end for
|
|
1181
|
+
end sub
|
|
1182
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1183
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(parser.diagnostics);
|
|
1184
|
+
const currentSymbolTable = parser.references.functionExpressions[0].symbolTable;
|
|
1185
|
+
(0, chai_1.expect)(currentSymbolTable.getSymbolType('datum').toString()).to.eq('dynamic');
|
|
1186
|
+
});
|
|
1187
|
+
});
|
|
1188
|
+
});
|
|
1189
|
+
describe('tokenChain', () => {
|
|
1190
|
+
it('can find a chain of tokens', () => {
|
|
1191
|
+
const parser = parse(`
|
|
1192
|
+
sub someFunc()
|
|
1193
|
+
print m.field.childField
|
|
1194
|
+
end sub
|
|
1195
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1196
|
+
const childFieldToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 38));
|
|
1197
|
+
const tokenChain = parser.getTokenChain(childFieldToken).chain;
|
|
1198
|
+
const tokenChainTokens = tokenChain.map(tcm => tcm.token);
|
|
1199
|
+
(0, chai_1.expect)(tokenChain.length).to.equal(3);
|
|
1200
|
+
(0, chai_1.expect)(tokenChainTokens.map(token => token.text)).to.eql(['m', 'field', 'childField']);
|
|
1201
|
+
(0, chai_1.expect)(tokenChain.map(tcm => tcm.usage)).to.eql([Parser_1.TokenUsage.Direct, Parser_1.TokenUsage.Direct, Parser_1.TokenUsage.Direct]);
|
|
1202
|
+
});
|
|
1203
|
+
it('can find a chain of tokens with function call with no args in the middle', () => {
|
|
1204
|
+
const parser = parse(`
|
|
1205
|
+
sub someFunc()
|
|
1206
|
+
print var.field.funcCall().childField
|
|
1207
|
+
end sub
|
|
1208
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1209
|
+
const childFieldToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 49));
|
|
1210
|
+
const tokenChain = parser.getTokenChain(childFieldToken).chain;
|
|
1211
|
+
const tokenChainTokens = tokenChain.map(tcm => tcm.token);
|
|
1212
|
+
(0, chai_1.expect)(tokenChain.length).to.equal(4);
|
|
1213
|
+
(0, chai_1.expect)(tokenChainTokens.map(token => token.text)).to.eql(['var', 'field', 'funcCall', 'childField']);
|
|
1214
|
+
(0, chai_1.expect)(tokenChain[2].usage).to.eql(Parser_1.TokenUsage.Call);
|
|
1215
|
+
});
|
|
1216
|
+
it('can find a chain of tokens with function call with multiple args in the middle', () => {
|
|
1217
|
+
const parser = parse(`
|
|
1218
|
+
sub someFunc()
|
|
1219
|
+
print var.field.funcCall(1, "string", {key: value}).childField
|
|
1220
|
+
end sub
|
|
1221
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1222
|
+
const childFieldToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 75));
|
|
1223
|
+
const tokenChain = parser.getTokenChain(childFieldToken).chain;
|
|
1224
|
+
const tokenChainTokens = tokenChain.map(tcm => tcm.token);
|
|
1225
|
+
(0, chai_1.expect)(tokenChain.length).to.equal(4);
|
|
1226
|
+
(0, chai_1.expect)(tokenChainTokens.map(token => token.text)).to.eql(['var', 'field', 'funcCall', 'childField']);
|
|
1227
|
+
(0, chai_1.expect)(tokenChain[2].usage).to.eql(Parser_1.TokenUsage.Call);
|
|
1228
|
+
});
|
|
1229
|
+
it('can find a chain of tokens with function call with function call inside', () => {
|
|
1230
|
+
const parser = parse(`
|
|
1231
|
+
sub someFunc()
|
|
1232
|
+
print var.field.funcCall(a(), b(), otherFunc2(c(), {d: func3(e)})).childField
|
|
1233
|
+
end sub
|
|
1234
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1235
|
+
const childFieldToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 90));
|
|
1236
|
+
const tokenChain = parser.getTokenChain(childFieldToken).chain;
|
|
1237
|
+
const tokenChainTokens = tokenChain.map(tcm => tcm.token);
|
|
1238
|
+
(0, chai_1.expect)(tokenChain.length).to.equal(4);
|
|
1239
|
+
(0, chai_1.expect)(tokenChainTokens.map(token => token.text)).to.eql(['var', 'field', 'funcCall', 'childField']);
|
|
1240
|
+
(0, chai_1.expect)(tokenChain[2].usage).to.eql(Parser_1.TokenUsage.Call);
|
|
1241
|
+
});
|
|
1242
|
+
it('can find a chain of tokens with array references inside', () => {
|
|
1243
|
+
const parser = parse(`
|
|
1244
|
+
sub someFunc()
|
|
1245
|
+
print var.field.myArray[0].childField
|
|
1246
|
+
end sub
|
|
1247
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1248
|
+
const childFieldToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 50));
|
|
1249
|
+
const tokenChain = parser.getTokenChain(childFieldToken).chain;
|
|
1250
|
+
const tokenChainTokens = tokenChain.map(tcm => tcm.token);
|
|
1251
|
+
(0, chai_1.expect)(tokenChain.length).to.equal(4);
|
|
1252
|
+
(0, chai_1.expect)(tokenChainTokens.map(token => token.text)).to.eql(['var', 'field', 'myArray', 'childField']);
|
|
1253
|
+
(0, chai_1.expect)(tokenChain[2].usage).to.eql(Parser_1.TokenUsage.ArrayReference);
|
|
1254
|
+
});
|
|
1255
|
+
it('includes unknown when an expression in brackets is part of the chain', () => {
|
|
1256
|
+
const parser = parse(`
|
|
1257
|
+
sub someFunc()
|
|
1258
|
+
print (1 + 1).toStr()
|
|
1259
|
+
end sub
|
|
1260
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1261
|
+
const toStrToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 34));
|
|
1262
|
+
const tokenChainResponse = parser.getTokenChain(toStrToken);
|
|
1263
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.true;
|
|
1264
|
+
});
|
|
1265
|
+
it('includes unknown when an expression in double brackets is part of the chain', () => {
|
|
1266
|
+
const parser = parse(`
|
|
1267
|
+
sub someFunc()
|
|
1268
|
+
print ((2 + 1)*3).toStr()
|
|
1269
|
+
end sub
|
|
1270
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1271
|
+
const toStrToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 38));
|
|
1272
|
+
const tokenChainResponse = parser.getTokenChain(toStrToken);
|
|
1273
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.true;
|
|
1274
|
+
});
|
|
1275
|
+
it('includes unknown when a complicated expression in brackets is part of the chain', () => {
|
|
1276
|
+
const parser = parse(`
|
|
1277
|
+
sub someFunc(currentDate, lastUpdate)
|
|
1278
|
+
print (INT((currentDate.asSeconds() - lastUpdate) / 86400)).toStr()
|
|
1279
|
+
end sub
|
|
1280
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1281
|
+
const toStrToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 81));
|
|
1282
|
+
const tokenChainResponse = parser.getTokenChain(toStrToken);
|
|
1283
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.true;
|
|
1284
|
+
});
|
|
1285
|
+
});
|
|
1286
|
+
it('includes unknown when property is referenced via brackets', () => {
|
|
1287
|
+
const parser = parse(`
|
|
1288
|
+
sub someFunc()
|
|
1289
|
+
complexObj = {prop: "hello", subObj: {prop: "foo", grandChildObj:{prop:"bar"}}}
|
|
1290
|
+
print complexObj.subObj.prop
|
|
1291
|
+
print complexObj["subObj"].prop
|
|
1292
|
+
print complexObj["subObj"]["grandChildObj"].prop
|
|
1293
|
+
end sub
|
|
1294
|
+
`, Parser_1.ParseMode.BrighterScript);
|
|
1295
|
+
const propAsChainToken = parser.getTokenAt(vscode_languageserver_1.Position.create(3, 44)); // complexObj.subObj.prop
|
|
1296
|
+
const propAsAsBracketToken = parser.getTokenAt(vscode_languageserver_1.Position.create(4, 47)); // complexObj["subObj"].prop
|
|
1297
|
+
const propAsAsDoubleBracketToken = parser.getTokenAt(vscode_languageserver_1.Position.create(5, 64)); // complexObj["subObj"]["grandChildObj"].prop
|
|
1298
|
+
let tokenChainResponse = parser.getTokenChain(propAsChainToken);
|
|
1299
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.false;
|
|
1300
|
+
(0, chai_1.expect)(tokenChainResponse.chain.map(tcm => tcm.token).map(token => token.text)).to.eql(['complexObj', 'subObj', 'prop']);
|
|
1301
|
+
tokenChainResponse = parser.getTokenChain(propAsAsBracketToken);
|
|
1302
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.false;
|
|
1303
|
+
(0, chai_1.expect)(tokenChainResponse.chain[0].usage).to.eql(Parser_1.TokenUsage.ArrayReference);
|
|
1304
|
+
tokenChainResponse = parser.getTokenChain(propAsAsDoubleBracketToken);
|
|
1305
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.true;
|
|
1306
|
+
});
|
|
1307
|
+
it('allows token kinds from AllowedLocalIdentifiers as start of a chain', () => {
|
|
1308
|
+
const parser = parse(`
|
|
1309
|
+
sub testLocalIdentifiers(override, string, float)
|
|
1310
|
+
override.someProp.someFunc()
|
|
1311
|
+
string.someProp.someFunc()
|
|
1312
|
+
float.someProp.someFunc()
|
|
1313
|
+
end sub
|
|
1314
|
+
`, Parser_1.ParseMode.BrightScript);
|
|
1315
|
+
const overrideFuncToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 40)); // override.someProp.someFunc()
|
|
1316
|
+
const stringFuncToken = parser.getTokenAt(vscode_languageserver_1.Position.create(3, 40)); // string.someProp.someFunc()
|
|
1317
|
+
const floatFuncToken = parser.getTokenAt(vscode_languageserver_1.Position.create(4, 38)); // float.someProp.someFunc()
|
|
1318
|
+
let tokenChainResponse = parser.getTokenChain(overrideFuncToken);
|
|
1319
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.false;
|
|
1320
|
+
(0, chai_1.expect)(tokenChainResponse.chain.map(tcm => tcm.token).map(token => token.text)).to.eql(['override', 'someProp', 'someFunc']);
|
|
1321
|
+
tokenChainResponse = parser.getTokenChain(stringFuncToken);
|
|
1322
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.false;
|
|
1323
|
+
(0, chai_1.expect)(tokenChainResponse.chain.map(tcm => tcm.token).map(token => token.text)).to.eql(['string', 'someProp', 'someFunc']);
|
|
1324
|
+
tokenChainResponse = parser.getTokenChain(floatFuncToken);
|
|
1325
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.false;
|
|
1326
|
+
(0, chai_1.expect)(tokenChainResponse.chain.map(tcm => tcm.token).map(token => token.text)).to.eql(['float', 'someProp', 'someFunc']);
|
|
1327
|
+
});
|
|
1328
|
+
it('allows token kinds from AllowedProperties in middle of a chain', () => {
|
|
1329
|
+
const parser = parse(`
|
|
1330
|
+
sub testAllowedProperties(someObj)
|
|
1331
|
+
someObj.override.someFunc()
|
|
1332
|
+
someObj.string.someFunc()
|
|
1333
|
+
someObj.float.someFunc()
|
|
1334
|
+
end sub
|
|
1335
|
+
`, Parser_1.ParseMode.BrightScript);
|
|
1336
|
+
const overrideFuncToken = parser.getTokenAt(vscode_languageserver_1.Position.create(2, 36)); // someObj.override.someFunc()
|
|
1337
|
+
const stringFuncToken = parser.getTokenAt(vscode_languageserver_1.Position.create(3, 36)); // someObj.string.someFunc()
|
|
1338
|
+
const floatFuncToken = parser.getTokenAt(vscode_languageserver_1.Position.create(4, 36)); // someObj.float.someFunc()
|
|
1339
|
+
let tokenChainResponse = parser.getTokenChain(overrideFuncToken);
|
|
1340
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.false;
|
|
1341
|
+
(0, chai_1.expect)(tokenChainResponse.chain.map(tcm => tcm.token).map(token => token.text)).to.eql(['someObj', 'override', 'someFunc']);
|
|
1342
|
+
tokenChainResponse = parser.getTokenChain(stringFuncToken);
|
|
1343
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.false;
|
|
1344
|
+
(0, chai_1.expect)(tokenChainResponse.chain.map(tcm => tcm.token).map(token => token.text)).to.eql(['someObj', 'string', 'someFunc']);
|
|
1345
|
+
tokenChainResponse = parser.getTokenChain(floatFuncToken);
|
|
1346
|
+
(0, chai_1.expect)(tokenChainResponse.includesUnknowableTokenType).to.be.false;
|
|
1347
|
+
(0, chai_1.expect)(tokenChainResponse.chain.map(tcm => tcm.token).map(token => token.text)).to.eql(['someObj', 'float', 'someFunc']);
|
|
1348
|
+
});
|
|
952
1349
|
});
|
|
953
1350
|
function parse(text, mode) {
|
|
954
1351
|
let { tokens } = lexer_1.Lexer.scan(text);
|
|
@@ -966,7 +1363,7 @@ function rangeToArray(range) {
|
|
|
966
1363
|
}
|
|
967
1364
|
exports.rangeToArray = rangeToArray;
|
|
968
1365
|
function expectCommentWithText(stat, text) {
|
|
969
|
-
if ((0,
|
|
1366
|
+
if ((0, reflection_1.isCommentStatement)(stat)) {
|
|
970
1367
|
(0, chai_1.expect)(stat.text).to.equal(text);
|
|
971
1368
|
}
|
|
972
1369
|
else {
|