brighterscript 1.0.0-alpha.16 → 1.0.0-alpha.19
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 +72 -1
- package/README.md +30 -9
- package/dist/BsConfig.d.ts +4 -0
- package/dist/DiagnosticMessages.d.ts +16 -1
- package/dist/DiagnosticMessages.js +15 -0
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/Logger.js +5 -5
- package/dist/Logger.js.map +1 -1
- package/dist/Program.d.ts +2 -2
- package/dist/Program.js +3 -3
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +4 -0
- package/dist/ProgramBuilder.js +14 -4
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +58 -8
- package/dist/Scope.js +141 -25
- package/dist/Scope.js.map +1 -1
- package/dist/XmlScope.js +1 -1
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/creators.d.ts +3 -3
- package/dist/astUtils/creators.js +8 -8
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/creators.spec.js +10 -0
- package/dist/astUtils/creators.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +8 -5
- package/dist/astUtils/reflection.js +18 -6
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +10 -0
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +4 -1
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +2 -0
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +2 -2
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +7 -3
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -1
- package/dist/{types/FunctionType.spec.d.ts → bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.d.ts} +0 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +32 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +1 -0
- package/dist/cli.js +9 -2
- package/dist/cli.js.map +1 -1
- package/dist/examples/plugins/removePrint.js +12 -14
- package/dist/examples/plugins/removePrint.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +3 -3
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +2 -2
- package/dist/files/BrsFile.js +89 -59
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +187 -67
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/globalCallables.js +79 -79
- package/dist/globalCallables.js.map +1 -1
- package/dist/interfaces.d.ts +43 -4
- package/dist/parser/Expression.d.ts +75 -8
- package/dist/parser/Expression.js +147 -22
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +6 -6
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +3 -6
- package/dist/parser/Parser.js +145 -142
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +61 -6
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGTypes.d.ts +2 -2
- package/dist/parser/SGTypes.js +2 -2
- package/dist/parser/SGTypes.js.map +1 -1
- package/dist/parser/Statement.d.ts +63 -43
- package/dist/parser/Statement.js +135 -92
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +181 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/TryCatch.spec.js +7 -5
- package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
- package/dist/types/ArrayType.js +4 -1
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +3 -1
- package/dist/types/ArrayType.spec.js.map +1 -1
- package/dist/types/BooleanType.d.ts +4 -2
- package/dist/types/BooleanType.js +7 -2
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BooleanType.spec.js +3 -1
- package/dist/types/BooleanType.spec.js.map +1 -1
- package/dist/types/BscType.d.ts +1 -0
- package/dist/types/BscType.js +16 -1
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/CustomType.js +10 -0
- package/dist/types/CustomType.js.map +1 -1
- package/dist/types/DoubleType.d.ts +2 -0
- package/dist/types/DoubleType.js +7 -2
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DoubleType.spec.js +3 -1
- package/dist/types/DoubleType.spec.js.map +1 -1
- package/dist/types/DynamicType.d.ts +2 -0
- package/dist/types/DynamicType.js +5 -1
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/FloatType.d.ts +3 -1
- package/dist/types/FloatType.js +7 -2
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FloatType.spec.js +2 -0
- package/dist/types/FloatType.spec.js.map +1 -1
- package/dist/types/FunctionType.d.ts +3 -22
- package/dist/types/FunctionType.js +8 -68
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/IntegerType.d.ts +3 -1
- package/dist/types/IntegerType.js +7 -2
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/IntegerType.spec.js +3 -1
- package/dist/types/IntegerType.spec.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +13 -10
- package/dist/types/InterfaceType.js +33 -29
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.js +36 -16
- package/dist/types/InterfaceType.spec.js.map +1 -1
- package/dist/types/InvalidType.d.ts +4 -2
- package/dist/types/InvalidType.js +7 -2
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/InvalidType.spec.js +2 -0
- package/dist/types/InvalidType.spec.js.map +1 -1
- package/dist/types/LazyType.js +4 -0
- package/dist/types/LazyType.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +3 -1
- package/dist/types/LongIntegerType.js +7 -2
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/LongIntegerType.spec.js +2 -0
- package/dist/types/LongIntegerType.spec.js.map +1 -1
- package/dist/types/ObjectType.d.ts +2 -1
- package/dist/types/ObjectType.js +4 -2
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/StringType.d.ts +4 -2
- package/dist/types/StringType.js +7 -2
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/StringType.spec.js +2 -0
- package/dist/types/StringType.spec.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +28 -0
- package/dist/types/TypedFunctionType.js +88 -0
- package/dist/types/TypedFunctionType.js.map +1 -0
- package/dist/types/TypedFunctionType.spec.d.ts +1 -0
- package/dist/types/TypedFunctionType.spec.js +37 -0
- package/dist/types/TypedFunctionType.spec.js.map +1 -0
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/VoidType.d.ts +4 -2
- package/dist/types/VoidType.js +5 -1
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/helpers.js +7 -2
- package/dist/types/helpers.js.map +1 -1
- package/dist/util.d.ts +6 -7
- package/dist/util.js +43 -55
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +14 -1
- package/dist/validators/ClassValidator.js +129 -82
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +3 -2
- package/dist/types/FunctionType.spec.js +0 -35
- package/dist/types/FunctionType.spec.js.map +0 -1
- package/dist/types/UniversalFunctionType.d.ts +0 -9
- package/dist/types/UniversalFunctionType.js +0 -25
- package/dist/types/UniversalFunctionType.js.map +0 -1
package/dist/parser/Parser.js
CHANGED
|
@@ -187,7 +187,7 @@ class Parser {
|
|
|
187
187
|
declaration() {
|
|
188
188
|
try {
|
|
189
189
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
190
|
-
return this.
|
|
190
|
+
return this.functionStatement({ hasName: true, hasBody: true, hasEnd: true });
|
|
191
191
|
}
|
|
192
192
|
if (this.checkLibrary()) {
|
|
193
193
|
return this.libraryStatement();
|
|
@@ -241,46 +241,29 @@ class Parser {
|
|
|
241
241
|
return new Statement_1.EnumMemberStatement(tokens, value);
|
|
242
242
|
}
|
|
243
243
|
/**
|
|
244
|
-
* Create a new
|
|
244
|
+
* Create a new InterfaceFieldStatement. This should only be called from within `interfaceDeclaration`
|
|
245
245
|
*/
|
|
246
246
|
interfaceFieldStatement() {
|
|
247
247
|
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
248
|
-
let asToken
|
|
249
|
-
let
|
|
250
|
-
|
|
251
|
-
if (!type) {
|
|
252
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeToken.text)), { range: typeToken.range }));
|
|
253
|
-
throw this.lastDiagnosticAsError();
|
|
254
|
-
}
|
|
255
|
-
return new Statement_1.InterfaceFieldStatement(name, asToken, typeToken, type);
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration()`
|
|
259
|
-
*/
|
|
260
|
-
interfaceMethodStatement() {
|
|
261
|
-
const functionType = this.advance();
|
|
262
|
-
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
263
|
-
const leftParen = this.consumeToken(TokenKind_1.TokenKind.LeftParen);
|
|
264
|
-
const params = [];
|
|
265
|
-
const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
|
|
266
|
-
let asToken = null;
|
|
267
|
-
let returnTypeToken = null;
|
|
248
|
+
let asToken;
|
|
249
|
+
let typeExpr;
|
|
250
|
+
//look for `as SOME_TYPE`
|
|
268
251
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
269
|
-
asToken = this.
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if (!
|
|
273
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text,
|
|
274
|
-
throw this.lastDiagnosticAsError();
|
|
252
|
+
asToken = this.consumeToken(TokenKind_1.TokenKind.As);
|
|
253
|
+
typeExpr = this.typeExpression();
|
|
254
|
+
//no field type specified
|
|
255
|
+
if (!typeExpr.isValidType()) {
|
|
256
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
|
|
275
257
|
}
|
|
276
258
|
}
|
|
277
|
-
return new Statement_1.
|
|
259
|
+
return new Statement_1.InterfaceFieldStatement(name, asToken, typeExpr, this.currentNamespaceName);
|
|
278
260
|
}
|
|
279
261
|
interfaceDeclaration() {
|
|
280
262
|
this.warnIfNotBrighterScriptMode('interface declarations');
|
|
281
263
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
282
264
|
const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
|
|
283
|
-
|
|
265
|
+
//get the interface name
|
|
266
|
+
let nameToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('interface'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
284
267
|
let extendsToken;
|
|
285
268
|
let parentInterfaceName;
|
|
286
269
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
@@ -292,6 +275,10 @@ class Parser {
|
|
|
292
275
|
let body = [];
|
|
293
276
|
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
294
277
|
try {
|
|
278
|
+
//break out of this loop if we encountered the `EndInterface` token not followed by `as`
|
|
279
|
+
if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
295
282
|
let decl;
|
|
296
283
|
//collect leading annotations
|
|
297
284
|
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
@@ -303,7 +290,15 @@ class Parser {
|
|
|
303
290
|
//methods (function/sub keyword followed by opening paren)
|
|
304
291
|
}
|
|
305
292
|
else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
306
|
-
|
|
293
|
+
const functionStatement = this.functionStatement({
|
|
294
|
+
hasName: true,
|
|
295
|
+
hasBody: false,
|
|
296
|
+
hasEnd: false,
|
|
297
|
+
onlyCallableAsMember: true
|
|
298
|
+
});
|
|
299
|
+
decl = new Statement_1.InterfaceMethodStatement(functionStatement.name, functionStatement.func);
|
|
300
|
+
//refer to this statement as parent of the expression
|
|
301
|
+
functionStatement.func.functionStatement = decl;
|
|
307
302
|
//comments
|
|
308
303
|
}
|
|
309
304
|
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
@@ -313,10 +308,6 @@ class Parser {
|
|
|
313
308
|
this.consumePendingAnnotations(decl);
|
|
314
309
|
body.push(decl);
|
|
315
310
|
}
|
|
316
|
-
else {
|
|
317
|
-
//we didn't find a declaration...flag tokens until next line
|
|
318
|
-
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
319
|
-
}
|
|
320
311
|
}
|
|
321
312
|
catch (e) {
|
|
322
313
|
//throw out any failed members and move on to the next line
|
|
@@ -324,14 +315,13 @@ class Parser {
|
|
|
324
315
|
}
|
|
325
316
|
//ensure statement separator
|
|
326
317
|
this.consumeStatementSeparators();
|
|
327
|
-
//break out of this loop if we encountered the `EndInterface` token not followed by `as`
|
|
328
|
-
if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
329
|
-
break;
|
|
330
|
-
}
|
|
331
318
|
}
|
|
332
319
|
//consume the final `end interface` token
|
|
333
|
-
|
|
334
|
-
|
|
320
|
+
let endingKeyword = this.advance();
|
|
321
|
+
if (endingKeyword.kind !== TokenKind_1.TokenKind.EndInterface) {
|
|
322
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('interface')), { range: endingKeyword.range }));
|
|
323
|
+
}
|
|
324
|
+
const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endingKeyword, this.currentNamespaceName);
|
|
335
325
|
this._references.interfaceStatements.push(statement);
|
|
336
326
|
this.exitAnnotationBlock(parentAnnotations);
|
|
337
327
|
return statement;
|
|
@@ -424,14 +414,12 @@ class Parser {
|
|
|
424
414
|
}
|
|
425
415
|
//methods (function/sub keyword OR identifier followed by opening paren)
|
|
426
416
|
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))) {
|
|
427
|
-
const
|
|
428
|
-
//remove this function from the lists because it's not a callable
|
|
429
|
-
const functionStatement = this._references.functionStatements.pop();
|
|
417
|
+
const functionStatement = this.functionStatement({ hasName: true, hasBody: true, hasEnd: true, onlyCallableAsMember: true });
|
|
430
418
|
//if we have an overrides keyword AND this method is called 'new', that's not allowed
|
|
431
|
-
if (overrideKeyword &&
|
|
419
|
+
if (overrideKeyword && functionStatement.name.text.toLowerCase() === 'new') {
|
|
432
420
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseOverrideKeywordOnConstructorFunction()), { range: overrideKeyword.range }));
|
|
433
421
|
}
|
|
434
|
-
decl = new Statement_1.ClassMethodStatement(accessModifier,
|
|
422
|
+
decl = new Statement_1.ClassMethodStatement(accessModifier, functionStatement.name, functionStatement.func, overrideKeyword);
|
|
435
423
|
//refer to this statement as parent of the expression
|
|
436
424
|
functionStatement.func.functionStatement = decl;
|
|
437
425
|
//cache the range property so that plugins can't affect it
|
|
@@ -476,13 +464,13 @@ class Parser {
|
|
|
476
464
|
classFieldDeclaration(accessModifier) {
|
|
477
465
|
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
478
466
|
let asToken;
|
|
479
|
-
let
|
|
467
|
+
let fieldTypeExpr;
|
|
480
468
|
//look for `as SOME_TYPE`
|
|
481
469
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
482
470
|
asToken = this.advance();
|
|
483
|
-
|
|
471
|
+
fieldTypeExpr = this.typeExpression();
|
|
484
472
|
//no field type specified
|
|
485
|
-
if (!
|
|
473
|
+
if (!fieldTypeExpr.isValidType(this.options.mode)) {
|
|
486
474
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedValidTypeToFollowAsKeyword()), { range: this.peek().range }));
|
|
487
475
|
}
|
|
488
476
|
}
|
|
@@ -493,22 +481,34 @@ class Parser {
|
|
|
493
481
|
equal = this.advance();
|
|
494
482
|
initialValue = this.expression();
|
|
495
483
|
}
|
|
496
|
-
return new Statement_1.ClassFieldStatement(accessModifier, name, asToken,
|
|
484
|
+
return new Statement_1.ClassFieldStatement(accessModifier, name, asToken, fieldTypeExpr, equal, initialValue, this.currentNamespaceName);
|
|
485
|
+
}
|
|
486
|
+
functionStatement(options) {
|
|
487
|
+
options.hasName = true;
|
|
488
|
+
const funcResult = this.functionDeclaration(options);
|
|
489
|
+
if (funcResult) {
|
|
490
|
+
let result = new Statement_1.FunctionStatement(funcResult.name, funcResult.functionExpression, this.currentNamespaceName);
|
|
491
|
+
funcResult.functionExpression.functionStatement = result;
|
|
492
|
+
if (!options.onlyCallableAsMember) {
|
|
493
|
+
this._references.functionStatements.push(result);
|
|
494
|
+
}
|
|
495
|
+
return result;
|
|
496
|
+
}
|
|
497
497
|
}
|
|
498
|
-
functionDeclaration(
|
|
498
|
+
functionDeclaration(options = {}) {
|
|
499
499
|
var _a, _b, _c, _d;
|
|
500
500
|
let previousCallExpressions = this.callExpressions;
|
|
501
501
|
this.callExpressions = [];
|
|
502
502
|
try {
|
|
503
503
|
//track depth to help certain statements need to know if they are contained within a function body
|
|
504
504
|
this.namespaceAndFunctionDepth++;
|
|
505
|
-
let
|
|
505
|
+
let functionKeyword;
|
|
506
506
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
507
|
-
|
|
507
|
+
functionKeyword = this.advance();
|
|
508
508
|
}
|
|
509
509
|
else {
|
|
510
510
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
|
|
511
|
-
|
|
511
|
+
functionKeyword = {
|
|
512
512
|
isReserved: true,
|
|
513
513
|
kind: TokenKind_1.TokenKind.Function,
|
|
514
514
|
text: 'function',
|
|
@@ -520,30 +520,30 @@ class Parser {
|
|
|
520
520
|
leadingWhitespace: ''
|
|
521
521
|
};
|
|
522
522
|
}
|
|
523
|
-
let isSub = (
|
|
524
|
-
let
|
|
523
|
+
let isSub = (functionKeyword === null || functionKeyword === void 0 ? void 0 : functionKeyword.kind) === TokenKind_1.TokenKind.Sub;
|
|
524
|
+
let functionKeywordText = isSub ? 'sub' : 'function';
|
|
525
525
|
let name;
|
|
526
526
|
let leftParen;
|
|
527
|
-
if (
|
|
528
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(
|
|
527
|
+
if (!options.hasName) {
|
|
528
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionKeywordText), TokenKind_1.TokenKind.LeftParen);
|
|
529
529
|
}
|
|
530
530
|
else {
|
|
531
|
-
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(
|
|
532
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(
|
|
531
|
+
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionKeywordText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
532
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionKeywordText), TokenKind_1.TokenKind.LeftParen);
|
|
533
533
|
//prevent functions from ending with type designators
|
|
534
534
|
let lastChar = name.text[name.text.length - 1];
|
|
535
535
|
if (['$', '%', '!', '#', '&'].includes(lastChar)) {
|
|
536
536
|
//don't throw this error; let the parser continue
|
|
537
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(
|
|
537
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionKeywordText, name.text, lastChar)), { range: name.range }));
|
|
538
538
|
}
|
|
539
|
-
//flag functions with keywords for names (only for standard functions)
|
|
540
|
-
if (
|
|
539
|
+
//flag functions with keywords for names (only for standard functions - not for class methods)
|
|
540
|
+
if (!options.onlyCallableAsMember && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
|
|
541
541
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
542
542
|
}
|
|
543
543
|
}
|
|
544
544
|
let params = [];
|
|
545
545
|
let asToken;
|
|
546
|
-
let
|
|
546
|
+
let typeExpr;
|
|
547
547
|
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
548
548
|
do {
|
|
549
549
|
if (params.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
@@ -555,9 +555,9 @@ class Parser {
|
|
|
555
555
|
let rightParen = this.advance();
|
|
556
556
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
557
557
|
asToken = this.advance();
|
|
558
|
-
|
|
559
|
-
if (!
|
|
560
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType((_a =
|
|
558
|
+
typeExpr = this.typeExpression();
|
|
559
|
+
if (!typeExpr.isValidType(this.options.mode)) {
|
|
560
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType((_a = typeExpr.getText()) !== null && _a !== void 0 ? _a : '')), { range: typeExpr.range }));
|
|
561
561
|
}
|
|
562
562
|
}
|
|
563
563
|
params.reduce((haveFoundOptional, param) => {
|
|
@@ -566,17 +566,20 @@ class Parser {
|
|
|
566
566
|
}
|
|
567
567
|
return haveFoundOptional || !!param.defaultValue;
|
|
568
568
|
}, false);
|
|
569
|
-
|
|
569
|
+
if (options.hasEnd && options.hasBody) {
|
|
570
|
+
// do not go to next statement - we don't care about any other statement
|
|
571
|
+
this.consumeStatementSeparators(true);
|
|
572
|
+
}
|
|
570
573
|
let func = new Expression_1.FunctionExpression(params, undefined, //body
|
|
571
|
-
|
|
572
|
-
leftParen, rightParen, asToken,
|
|
574
|
+
functionKeyword, undefined, //ending keyword
|
|
575
|
+
leftParen, rightParen, asToken, typeExpr, //return type
|
|
573
576
|
this.currentFunctionExpression, this.currentNamespaceName, (_c = (_b = this.currentNamespace) === null || _b === void 0 ? void 0 : _b.symbolTable) !== null && _c !== void 0 ? _c : this.symbolTable);
|
|
574
577
|
//if there is a parent function, register this function with the parent
|
|
575
578
|
if (this.currentFunctionExpression) {
|
|
576
579
|
this.currentFunctionExpression.childFunctionExpressions.push(func);
|
|
577
580
|
}
|
|
578
581
|
// add the function to the relevant symbol tables
|
|
579
|
-
if (!
|
|
582
|
+
if (!options.onlyCallableAsMember && name) {
|
|
580
583
|
const funcType = func.getFunctionType();
|
|
581
584
|
funcType.setName(name.text);
|
|
582
585
|
// add the function as declared to the current namespace's table
|
|
@@ -589,42 +592,35 @@ class Parser {
|
|
|
589
592
|
this.currentSymbolTable.addSymbol(fullyQualifiedName, name.range, funcType);
|
|
590
593
|
}
|
|
591
594
|
this._references.functionExpressions.push(func);
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
595
|
+
if (options.hasBody) {
|
|
596
|
+
let previousFunctionExpression = this.currentFunctionExpression;
|
|
597
|
+
this.currentFunctionExpression = func;
|
|
598
|
+
//make sure to restore the currentFunctionExpression even if the body block fails to parse
|
|
599
|
+
try {
|
|
600
|
+
//support ending the function with `end sub` OR `end function`
|
|
601
|
+
func.body = this.block();
|
|
602
|
+
}
|
|
603
|
+
finally {
|
|
604
|
+
this.currentFunctionExpression = previousFunctionExpression;
|
|
605
|
+
}
|
|
606
|
+
if (!func.body) {
|
|
607
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callableBlockMissingEndKeyword(functionKeywordText)), { range: this.peek().range }));
|
|
608
|
+
throw this.lastDiagnosticAsError();
|
|
609
|
+
}
|
|
605
610
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
611
|
+
if (options.hasEnd) {
|
|
612
|
+
// consume 'end sub' or 'end function'
|
|
613
|
+
func.end = this.advance();
|
|
614
|
+
let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
|
|
615
|
+
//if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
|
|
616
|
+
//add an error but don't hard-fail so the AST can continue more gracefully
|
|
617
|
+
if (func.end.kind !== expectedEndKind) {
|
|
618
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionKeywordText, func.end.text)), { range: this.peek().range }));
|
|
619
|
+
}
|
|
613
620
|
}
|
|
614
621
|
func.callExpressions = this.callExpressions;
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
func.cacheRange();
|
|
618
|
-
return func;
|
|
619
|
-
}
|
|
620
|
-
else {
|
|
621
|
-
let result = new Statement_1.FunctionStatement(name, func, this.currentNamespaceName);
|
|
622
|
-
func.functionStatement = result;
|
|
623
|
-
this._references.functionStatements.push(result);
|
|
624
|
-
//cache the range property so that plugins can't affect it
|
|
625
|
-
result.cacheRange();
|
|
626
|
-
return result;
|
|
627
|
-
}
|
|
622
|
+
func.cacheRange();
|
|
623
|
+
return { name: name, functionExpression: func };
|
|
628
624
|
}
|
|
629
625
|
finally {
|
|
630
626
|
this.namespaceAndFunctionDepth--;
|
|
@@ -638,7 +634,7 @@ class Parser {
|
|
|
638
634
|
throw this.lastDiagnosticAsError();
|
|
639
635
|
}
|
|
640
636
|
const name = this.identifier(...TokenKind_1.AllowedLocalIdentifiers);
|
|
641
|
-
let
|
|
637
|
+
let typeExpr;
|
|
642
638
|
let defaultValue;
|
|
643
639
|
let equalsToken;
|
|
644
640
|
// parse argument default value
|
|
@@ -650,26 +646,26 @@ class Parser {
|
|
|
650
646
|
let asToken = null;
|
|
651
647
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
652
648
|
asToken = this.advance();
|
|
653
|
-
|
|
654
|
-
if (!
|
|
655
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text,
|
|
649
|
+
typeExpr = this.typeExpression();
|
|
650
|
+
if (!typeExpr.isValidType(this.options.mode)) {
|
|
651
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
|
|
656
652
|
throw this.lastDiagnosticAsError();
|
|
657
653
|
}
|
|
658
654
|
}
|
|
659
|
-
let
|
|
660
|
-
if (
|
|
661
|
-
|
|
655
|
+
let typeInContext;
|
|
656
|
+
if (typeExpr) {
|
|
657
|
+
typeInContext = typeExpr.type;
|
|
662
658
|
}
|
|
663
659
|
else if (defaultValue) {
|
|
664
|
-
|
|
665
|
-
if ((0, reflection_1.isInvalidType)(
|
|
666
|
-
|
|
660
|
+
typeInContext = getBscTypeFromExpression(defaultValue, this.currentFunctionExpression);
|
|
661
|
+
if ((0, reflection_1.isInvalidType)(typeInContext)) {
|
|
662
|
+
typeInContext = new DynamicType_1.DynamicType();
|
|
667
663
|
}
|
|
668
664
|
}
|
|
669
665
|
else {
|
|
670
|
-
|
|
666
|
+
typeInContext = new DynamicType_1.DynamicType();
|
|
671
667
|
}
|
|
672
|
-
return new Expression_1.FunctionParameterExpression(name,
|
|
668
|
+
return new Expression_1.FunctionParameterExpression(name, typeInContext, equalsToken, defaultValue, asToken, typeExpr, this.currentNamespaceName);
|
|
673
669
|
}
|
|
674
670
|
assignment() {
|
|
675
671
|
let name = this.identifier(...this.allowedLocalIdentifiers);
|
|
@@ -863,6 +859,12 @@ class Parser {
|
|
|
863
859
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedExpressionAfterForEachIn()), { range: this.peek().range }));
|
|
864
860
|
throw this.lastDiagnosticAsError();
|
|
865
861
|
}
|
|
862
|
+
let itemType = new DynamicType_1.DynamicType();
|
|
863
|
+
const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
|
|
864
|
+
if ((0, reflection_1.isArrayType)(targetType)) {
|
|
865
|
+
itemType = targetType.getDefaultType();
|
|
866
|
+
}
|
|
867
|
+
this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
|
|
866
868
|
this.consumeStatementSeparators();
|
|
867
869
|
let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
|
|
868
870
|
if (!body) {
|
|
@@ -870,12 +872,6 @@ class Parser {
|
|
|
870
872
|
throw this.lastDiagnosticAsError();
|
|
871
873
|
}
|
|
872
874
|
let endFor = this.advance();
|
|
873
|
-
let itemType = new DynamicType_1.DynamicType();
|
|
874
|
-
const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
|
|
875
|
-
if ((0, reflection_1.isArrayType)(targetType)) {
|
|
876
|
-
itemType = targetType.getDefaultType();
|
|
877
|
-
}
|
|
878
|
-
this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
|
|
879
875
|
return new Statement_1.ForEachStatement(forEach, name, maybeIn, target, body, endFor);
|
|
880
876
|
}
|
|
881
877
|
exitFor() {
|
|
@@ -1120,7 +1116,7 @@ class Parser {
|
|
|
1120
1116
|
}
|
|
1121
1117
|
tryCatchStatement() {
|
|
1122
1118
|
const tryToken = this.advance();
|
|
1123
|
-
const statement = new Statement_1.TryCatchStatement(tryToken);
|
|
1119
|
+
const statement = new Statement_1.TryCatchStatement({ try: tryToken });
|
|
1124
1120
|
//ensure statement separator
|
|
1125
1121
|
this.consumeStatementSeparators();
|
|
1126
1122
|
statement.tryBranch = this.block(TokenKind_1.TokenKind.Catch, TokenKind_1.TokenKind.EndTry);
|
|
@@ -1129,27 +1125,26 @@ class Parser {
|
|
|
1129
1125
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedCatchBlockInTryCatch()), { range: this.peek().range }));
|
|
1130
1126
|
//gracefully handle end-try
|
|
1131
1127
|
if (peek.kind === TokenKind_1.TokenKind.EndTry) {
|
|
1132
|
-
statement.
|
|
1128
|
+
statement.tokens.endTry = this.advance();
|
|
1133
1129
|
}
|
|
1134
1130
|
return statement;
|
|
1135
1131
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
}
|
|
1132
|
+
const catchStmt = new Statement_1.CatchStatement({ catch: this.advance() });
|
|
1133
|
+
statement.catchStatement = catchStmt;
|
|
1139
1134
|
const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
1140
1135
|
if (exceptionVarToken) {
|
|
1141
1136
|
// force it into an identifier so the AST makes some sense
|
|
1142
1137
|
exceptionVarToken.kind = TokenKind_1.TokenKind.Identifier;
|
|
1143
|
-
|
|
1138
|
+
catchStmt.exceptionVariable = exceptionVarToken;
|
|
1144
1139
|
}
|
|
1145
1140
|
//ensure statement sepatator
|
|
1146
1141
|
this.consumeStatementSeparators();
|
|
1147
|
-
|
|
1142
|
+
catchStmt.catchBranch = this.block(TokenKind_1.TokenKind.EndTry);
|
|
1148
1143
|
if (this.peek().kind !== TokenKind_1.TokenKind.EndTry) {
|
|
1149
1144
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndTryToTerminateTryCatch()), { range: this.peek().range }));
|
|
1150
1145
|
}
|
|
1151
1146
|
else {
|
|
1152
|
-
statement.
|
|
1147
|
+
statement.tokens.endTry = this.advance();
|
|
1153
1148
|
}
|
|
1154
1149
|
return statement;
|
|
1155
1150
|
}
|
|
@@ -1595,7 +1590,7 @@ class Parser {
|
|
|
1595
1590
|
}
|
|
1596
1591
|
anonymousFunction() {
|
|
1597
1592
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
1598
|
-
const func = this.functionDeclaration(true);
|
|
1593
|
+
const func = this.functionDeclaration({ hasName: false, hasBody: true, hasEnd: true }).functionExpression;
|
|
1599
1594
|
//if there's an open paren after this, this is an IIFE
|
|
1600
1595
|
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
1601
1596
|
return this.finishCall(this.advance(), func);
|
|
@@ -1784,7 +1779,7 @@ class Parser {
|
|
|
1784
1779
|
* Allows for built-in types (double, string, etc.) or namespaced custom types in Brighterscript mode
|
|
1785
1780
|
* Will return a token of whatever is next to be parsed (unless `advanceIfUnknown` is false, in which case undefined will be returned instead
|
|
1786
1781
|
*/
|
|
1787
|
-
|
|
1782
|
+
typeExpression() {
|
|
1788
1783
|
let typeToken;
|
|
1789
1784
|
if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
|
|
1790
1785
|
// Token is a built in type
|
|
@@ -1805,18 +1800,23 @@ class Parser {
|
|
|
1805
1800
|
// just get whatever's next
|
|
1806
1801
|
typeToken = this.advance();
|
|
1807
1802
|
}
|
|
1808
|
-
|
|
1803
|
+
//TODO: to support InterfaceTypeLiterals - (eg. `{name as string; age as integer}`), check if "typeToken" is a curly bracket, and do something else
|
|
1804
|
+
let typeExpr = new Expression_1.TypeExpression({ type: typeToken }, this.currentNamespaceName);
|
|
1805
|
+
if (this.options.mode === ParseMode.BrighterScript) {
|
|
1809
1806
|
// Check if it is an array - that is, if it has `[]` after the type
|
|
1810
|
-
// eg. `string[]` or `SomeKlass[]`
|
|
1811
|
-
|
|
1812
|
-
this.advance();
|
|
1807
|
+
// eg. `string[]` or `SomeKlass[]` or `float[][][]`
|
|
1808
|
+
while (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1809
|
+
const leftBracket = this.advance();
|
|
1813
1810
|
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1814
1811
|
const rightBracket = this.advance();
|
|
1815
|
-
|
|
1812
|
+
typeExpr = new Expression_1.ArrayTypeExpression([typeExpr], { leftBracket: leftBracket, rightBracket: rightBracket }, this.currentNamespaceName);
|
|
1813
|
+
}
|
|
1814
|
+
else {
|
|
1815
|
+
break;
|
|
1816
1816
|
}
|
|
1817
1817
|
}
|
|
1818
1818
|
}
|
|
1819
|
-
return
|
|
1819
|
+
return typeExpr;
|
|
1820
1820
|
}
|
|
1821
1821
|
primary() {
|
|
1822
1822
|
switch (true) {
|
|
@@ -2397,6 +2397,9 @@ class Parser {
|
|
|
2397
2397
|
this._references.expressions.add(s.initialValue);
|
|
2398
2398
|
}
|
|
2399
2399
|
},
|
|
2400
|
+
InterfaceStatement: s => {
|
|
2401
|
+
this._references.interfaceStatements.push(s);
|
|
2402
|
+
},
|
|
2400
2403
|
NamespaceStatement: s => {
|
|
2401
2404
|
this._references.namespaceStatements.push(s);
|
|
2402
2405
|
},
|
|
@@ -2410,7 +2413,7 @@ class Parser {
|
|
|
2410
2413
|
this._references.libraryStatements.push(s);
|
|
2411
2414
|
},
|
|
2412
2415
|
FunctionExpression: (expression, parent) => {
|
|
2413
|
-
if (!(0, reflection_1.isClassMethodStatement)(parent)) {
|
|
2416
|
+
if (!(0, reflection_1.isClassMethodStatement)(parent) && !(0, reflection_1.isInterfaceMethodStatement)(parent)) {
|
|
2414
2417
|
this._references.functionExpressions.push(expression);
|
|
2415
2418
|
}
|
|
2416
2419
|
},
|
|
@@ -2542,7 +2545,7 @@ class References {
|
|
|
2542
2545
|
if (!this._interfaceStatementLookup) {
|
|
2543
2546
|
this._interfaceStatementLookup = new Map();
|
|
2544
2547
|
for (const stmt of this.interfaceStatements) {
|
|
2545
|
-
this._interfaceStatementLookup.set(stmt.
|
|
2548
|
+
this._interfaceStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
|
|
2546
2549
|
}
|
|
2547
2550
|
}
|
|
2548
2551
|
return this._interfaceStatementLookup;
|
|
@@ -2587,7 +2590,7 @@ function getBscTypeFromExpression(expression, functionExpression) {
|
|
|
2587
2590
|
//Associative array literal
|
|
2588
2591
|
}
|
|
2589
2592
|
else if ((0, reflection_1.isAALiteralExpression)(expression)) {
|
|
2590
|
-
return new ObjectType_1.ObjectType(expression.memberTable);
|
|
2593
|
+
return new ObjectType_1.ObjectType('object', expression.memberTable);
|
|
2591
2594
|
//Array literal
|
|
2592
2595
|
}
|
|
2593
2596
|
else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {
|
|
@@ -2598,7 +2601,7 @@ function getBscTypeFromExpression(expression, functionExpression) {
|
|
|
2598
2601
|
//function call
|
|
2599
2602
|
}
|
|
2600
2603
|
else if ((0, reflection_1.isNewExpression)(expression)) {
|
|
2601
|
-
return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression);
|
|
2604
|
+
return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression);
|
|
2602
2605
|
//Function call
|
|
2603
2606
|
}
|
|
2604
2607
|
else if ((0, reflection_1.isCallExpression)(expression)) {
|