brighterscript 1.0.0-alpha.17 → 1.0.0-alpha.18
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 +18 -0
- package/dist/DiagnosticMessages.d.ts +16 -1
- package/dist/DiagnosticMessages.js +15 -0
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/Scope.d.ts +58 -8
- package/dist/Scope.js +128 -16
- package/dist/Scope.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +6 -4
- package/dist/astUtils/reflection.js +14 -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/files/BrsFile.Class.spec.js +2 -2
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +1 -0
- package/dist/files/BrsFile.js +65 -39
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +16 -3
- 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 +8 -3
- package/dist/parser/Expression.js +15 -5
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +5 -5
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +2 -5
- package/dist/parser/Parser.js +105 -105
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +4 -4
- 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 +52 -36
- package/dist/parser/Statement.js +109 -76
- 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.js +2 -1
- 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.js +2 -1
- 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/FloatType.js +2 -1
- 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.js +2 -1
- 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.js +2 -1
- 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.js +2 -1
- 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/StringType.js +2 -1
- 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/{FunctionType.spec.d.ts → TypedFunctionType.spec.d.ts} +0 -0
- package/dist/types/TypedFunctionType.spec.js +37 -0
- package/dist/types/TypedFunctionType.spec.js.map +1 -0
- package/dist/types/helpers.js +7 -2
- package/dist/types/helpers.js.map +1 -1
- package/dist/util.d.ts +2 -2
- package/dist/util.js +5 -5
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +14 -1
- package/dist/validators/ClassValidator.js +127 -80
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +1 -1
- 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,44 +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 typeExpr
|
|
250
|
-
|
|
251
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
|
|
252
|
-
throw this.lastDiagnosticAsError();
|
|
253
|
-
}
|
|
254
|
-
return new Statement_1.InterfaceFieldStatement(name, asToken, typeExpr);
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration()`
|
|
258
|
-
*/
|
|
259
|
-
interfaceMethodStatement() {
|
|
260
|
-
const functionType = this.advance();
|
|
261
|
-
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
262
|
-
const leftParen = this.consumeToken(TokenKind_1.TokenKind.LeftParen);
|
|
263
|
-
const params = [];
|
|
264
|
-
const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
|
|
265
|
-
let asToken = null;
|
|
266
|
-
let returnTypeExpr;
|
|
248
|
+
let asToken;
|
|
249
|
+
let typeExpr;
|
|
250
|
+
//look for `as SOME_TYPE`
|
|
267
251
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
268
|
-
asToken = this.
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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 }));
|
|
273
257
|
}
|
|
274
258
|
}
|
|
275
|
-
return new Statement_1.
|
|
259
|
+
return new Statement_1.InterfaceFieldStatement(name, asToken, typeExpr, this.currentNamespaceName);
|
|
276
260
|
}
|
|
277
261
|
interfaceDeclaration() {
|
|
278
262
|
this.warnIfNotBrighterScriptMode('interface declarations');
|
|
279
263
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
280
264
|
const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
|
|
281
|
-
|
|
265
|
+
//get the interface name
|
|
266
|
+
let nameToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('interface'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
282
267
|
let extendsToken;
|
|
283
268
|
let parentInterfaceName;
|
|
284
269
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
@@ -290,6 +275,10 @@ class Parser {
|
|
|
290
275
|
let body = [];
|
|
291
276
|
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
292
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
|
+
}
|
|
293
282
|
let decl;
|
|
294
283
|
//collect leading annotations
|
|
295
284
|
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
@@ -301,7 +290,15 @@ class Parser {
|
|
|
301
290
|
//methods (function/sub keyword followed by opening paren)
|
|
302
291
|
}
|
|
303
292
|
else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
304
|
-
|
|
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;
|
|
305
302
|
//comments
|
|
306
303
|
}
|
|
307
304
|
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
@@ -311,10 +308,6 @@ class Parser {
|
|
|
311
308
|
this.consumePendingAnnotations(decl);
|
|
312
309
|
body.push(decl);
|
|
313
310
|
}
|
|
314
|
-
else {
|
|
315
|
-
//we didn't find a declaration...flag tokens until next line
|
|
316
|
-
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
317
|
-
}
|
|
318
311
|
}
|
|
319
312
|
catch (e) {
|
|
320
313
|
//throw out any failed members and move on to the next line
|
|
@@ -322,14 +315,13 @@ class Parser {
|
|
|
322
315
|
}
|
|
323
316
|
//ensure statement separator
|
|
324
317
|
this.consumeStatementSeparators();
|
|
325
|
-
//break out of this loop if we encountered the `EndInterface` token not followed by `as`
|
|
326
|
-
if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
327
|
-
break;
|
|
328
|
-
}
|
|
329
318
|
}
|
|
330
319
|
//consume the final `end interface` token
|
|
331
|
-
|
|
332
|
-
|
|
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);
|
|
333
325
|
this._references.interfaceStatements.push(statement);
|
|
334
326
|
this.exitAnnotationBlock(parentAnnotations);
|
|
335
327
|
return statement;
|
|
@@ -422,14 +414,12 @@ class Parser {
|
|
|
422
414
|
}
|
|
423
415
|
//methods (function/sub keyword OR identifier followed by opening paren)
|
|
424
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))) {
|
|
425
|
-
const
|
|
426
|
-
//remove this function from the lists because it's not a callable
|
|
427
|
-
const functionStatement = this._references.functionStatements.pop();
|
|
417
|
+
const functionStatement = this.functionStatement({ hasName: true, hasBody: true, hasEnd: true, onlyCallableAsMember: true });
|
|
428
418
|
//if we have an overrides keyword AND this method is called 'new', that's not allowed
|
|
429
|
-
if (overrideKeyword &&
|
|
419
|
+
if (overrideKeyword && functionStatement.name.text.toLowerCase() === 'new') {
|
|
430
420
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseOverrideKeywordOnConstructorFunction()), { range: overrideKeyword.range }));
|
|
431
421
|
}
|
|
432
|
-
decl = new Statement_1.ClassMethodStatement(accessModifier,
|
|
422
|
+
decl = new Statement_1.ClassMethodStatement(accessModifier, functionStatement.name, functionStatement.func, overrideKeyword);
|
|
433
423
|
//refer to this statement as parent of the expression
|
|
434
424
|
functionStatement.func.functionStatement = decl;
|
|
435
425
|
//cache the range property so that plugins can't affect it
|
|
@@ -493,20 +483,32 @@ class Parser {
|
|
|
493
483
|
}
|
|
494
484
|
return new Statement_1.ClassFieldStatement(accessModifier, name, asToken, fieldTypeExpr, equal, initialValue, this.currentNamespaceName);
|
|
495
485
|
}
|
|
496
|
-
|
|
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
|
+
}
|
|
498
|
+
functionDeclaration(options = {}) {
|
|
497
499
|
var _a, _b, _c, _d;
|
|
498
500
|
let previousCallExpressions = this.callExpressions;
|
|
499
501
|
this.callExpressions = [];
|
|
500
502
|
try {
|
|
501
503
|
//track depth to help certain statements need to know if they are contained within a function body
|
|
502
504
|
this.namespaceAndFunctionDepth++;
|
|
503
|
-
let
|
|
505
|
+
let functionKeyword;
|
|
504
506
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
505
|
-
|
|
507
|
+
functionKeyword = this.advance();
|
|
506
508
|
}
|
|
507
509
|
else {
|
|
508
510
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
|
|
509
|
-
|
|
511
|
+
functionKeyword = {
|
|
510
512
|
isReserved: true,
|
|
511
513
|
kind: TokenKind_1.TokenKind.Function,
|
|
512
514
|
text: 'function',
|
|
@@ -518,24 +520,24 @@ class Parser {
|
|
|
518
520
|
leadingWhitespace: ''
|
|
519
521
|
};
|
|
520
522
|
}
|
|
521
|
-
let isSub = (
|
|
522
|
-
let
|
|
523
|
+
let isSub = (functionKeyword === null || functionKeyword === void 0 ? void 0 : functionKeyword.kind) === TokenKind_1.TokenKind.Sub;
|
|
524
|
+
let functionKeywordText = isSub ? 'sub' : 'function';
|
|
523
525
|
let name;
|
|
524
526
|
let leftParen;
|
|
525
|
-
if (
|
|
526
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(
|
|
527
|
+
if (!options.hasName) {
|
|
528
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionKeywordText), TokenKind_1.TokenKind.LeftParen);
|
|
527
529
|
}
|
|
528
530
|
else {
|
|
529
|
-
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(
|
|
530
|
-
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);
|
|
531
533
|
//prevent functions from ending with type designators
|
|
532
534
|
let lastChar = name.text[name.text.length - 1];
|
|
533
535
|
if (['$', '%', '!', '#', '&'].includes(lastChar)) {
|
|
534
536
|
//don't throw this error; let the parser continue
|
|
535
|
-
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 }));
|
|
536
538
|
}
|
|
537
|
-
//flag functions with keywords for names (only for standard functions)
|
|
538
|
-
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())) {
|
|
539
541
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
540
542
|
}
|
|
541
543
|
}
|
|
@@ -564,9 +566,12 @@ class Parser {
|
|
|
564
566
|
}
|
|
565
567
|
return haveFoundOptional || !!param.defaultValue;
|
|
566
568
|
}, false);
|
|
567
|
-
|
|
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
|
+
}
|
|
568
573
|
let func = new Expression_1.FunctionExpression(params, undefined, //body
|
|
569
|
-
|
|
574
|
+
functionKeyword, undefined, //ending keyword
|
|
570
575
|
leftParen, rightParen, asToken, typeExpr, //return type
|
|
571
576
|
this.currentFunctionExpression, this.currentNamespaceName, (_c = (_b = this.currentNamespace) === null || _b === void 0 ? void 0 : _b.symbolTable) !== null && _c !== void 0 ? _c : this.symbolTable);
|
|
572
577
|
//if there is a parent function, register this function with the parent
|
|
@@ -574,7 +579,7 @@ class Parser {
|
|
|
574
579
|
this.currentFunctionExpression.childFunctionExpressions.push(func);
|
|
575
580
|
}
|
|
576
581
|
// add the function to the relevant symbol tables
|
|
577
|
-
if (!
|
|
582
|
+
if (!options.onlyCallableAsMember && name) {
|
|
578
583
|
const funcType = func.getFunctionType();
|
|
579
584
|
funcType.setName(name.text);
|
|
580
585
|
// add the function as declared to the current namespace's table
|
|
@@ -587,42 +592,35 @@ class Parser {
|
|
|
587
592
|
this.currentSymbolTable.addSymbol(fullyQualifiedName, name.range, funcType);
|
|
588
593
|
}
|
|
589
594
|
this._references.functionExpressions.push(func);
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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
|
+
}
|
|
603
610
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
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
|
+
}
|
|
611
620
|
}
|
|
612
621
|
func.callExpressions = this.callExpressions;
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
func.cacheRange();
|
|
616
|
-
return func;
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
let result = new Statement_1.FunctionStatement(name, func, this.currentNamespaceName);
|
|
620
|
-
func.functionStatement = result;
|
|
621
|
-
this._references.functionStatements.push(result);
|
|
622
|
-
//cache the range property so that plugins can't affect it
|
|
623
|
-
result.cacheRange();
|
|
624
|
-
return result;
|
|
625
|
-
}
|
|
622
|
+
func.cacheRange();
|
|
623
|
+
return { name: name, functionExpression: func };
|
|
626
624
|
}
|
|
627
625
|
finally {
|
|
628
626
|
this.namespaceAndFunctionDepth--;
|
|
@@ -1118,7 +1116,7 @@ class Parser {
|
|
|
1118
1116
|
}
|
|
1119
1117
|
tryCatchStatement() {
|
|
1120
1118
|
const tryToken = this.advance();
|
|
1121
|
-
const statement = new Statement_1.TryCatchStatement(tryToken);
|
|
1119
|
+
const statement = new Statement_1.TryCatchStatement({ try: tryToken });
|
|
1122
1120
|
//ensure statement separator
|
|
1123
1121
|
this.consumeStatementSeparators();
|
|
1124
1122
|
statement.tryBranch = this.block(TokenKind_1.TokenKind.Catch, TokenKind_1.TokenKind.EndTry);
|
|
@@ -1127,27 +1125,26 @@ class Parser {
|
|
|
1127
1125
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedCatchBlockInTryCatch()), { range: this.peek().range }));
|
|
1128
1126
|
//gracefully handle end-try
|
|
1129
1127
|
if (peek.kind === TokenKind_1.TokenKind.EndTry) {
|
|
1130
|
-
statement.
|
|
1128
|
+
statement.tokens.endTry = this.advance();
|
|
1131
1129
|
}
|
|
1132
1130
|
return statement;
|
|
1133
1131
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
}
|
|
1132
|
+
const catchStmt = new Statement_1.CatchStatement({ catch: this.advance() });
|
|
1133
|
+
statement.catchStatement = catchStmt;
|
|
1137
1134
|
const exceptionVarToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingExceptionVarToFollowCatch(), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
1138
1135
|
if (exceptionVarToken) {
|
|
1139
1136
|
// force it into an identifier so the AST makes some sense
|
|
1140
1137
|
exceptionVarToken.kind = TokenKind_1.TokenKind.Identifier;
|
|
1141
|
-
|
|
1138
|
+
catchStmt.exceptionVariable = exceptionVarToken;
|
|
1142
1139
|
}
|
|
1143
1140
|
//ensure statement sepatator
|
|
1144
1141
|
this.consumeStatementSeparators();
|
|
1145
|
-
|
|
1142
|
+
catchStmt.catchBranch = this.block(TokenKind_1.TokenKind.EndTry);
|
|
1146
1143
|
if (this.peek().kind !== TokenKind_1.TokenKind.EndTry) {
|
|
1147
1144
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedEndTryToTerminateTryCatch()), { range: this.peek().range }));
|
|
1148
1145
|
}
|
|
1149
1146
|
else {
|
|
1150
|
-
statement.
|
|
1147
|
+
statement.tokens.endTry = this.advance();
|
|
1151
1148
|
}
|
|
1152
1149
|
return statement;
|
|
1153
1150
|
}
|
|
@@ -1593,7 +1590,7 @@ class Parser {
|
|
|
1593
1590
|
}
|
|
1594
1591
|
anonymousFunction() {
|
|
1595
1592
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
1596
|
-
const func = this.functionDeclaration(true);
|
|
1593
|
+
const func = this.functionDeclaration({ hasName: false, hasBody: true, hasEnd: true }).functionExpression;
|
|
1597
1594
|
//if there's an open paren after this, this is an IIFE
|
|
1598
1595
|
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
1599
1596
|
return this.finishCall(this.advance(), func);
|
|
@@ -2400,6 +2397,9 @@ class Parser {
|
|
|
2400
2397
|
this._references.expressions.add(s.initialValue);
|
|
2401
2398
|
}
|
|
2402
2399
|
},
|
|
2400
|
+
InterfaceStatement: s => {
|
|
2401
|
+
this._references.interfaceStatements.push(s);
|
|
2402
|
+
},
|
|
2403
2403
|
NamespaceStatement: s => {
|
|
2404
2404
|
this._references.namespaceStatements.push(s);
|
|
2405
2405
|
},
|
|
@@ -2413,7 +2413,7 @@ class Parser {
|
|
|
2413
2413
|
this._references.libraryStatements.push(s);
|
|
2414
2414
|
},
|
|
2415
2415
|
FunctionExpression: (expression, parent) => {
|
|
2416
|
-
if (!(0, reflection_1.isClassMethodStatement)(parent)) {
|
|
2416
|
+
if (!(0, reflection_1.isClassMethodStatement)(parent) && !(0, reflection_1.isInterfaceMethodStatement)(parent)) {
|
|
2417
2417
|
this._references.functionExpressions.push(expression);
|
|
2418
2418
|
}
|
|
2419
2419
|
},
|
|
@@ -2545,7 +2545,7 @@ class References {
|
|
|
2545
2545
|
if (!this._interfaceStatementLookup) {
|
|
2546
2546
|
this._interfaceStatementLookup = new Map();
|
|
2547
2547
|
for (const stmt of this.interfaceStatements) {
|
|
2548
|
-
this._interfaceStatementLookup.set(stmt.
|
|
2548
|
+
this._interfaceStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
|
|
2549
2549
|
}
|
|
2550
2550
|
}
|
|
2551
2551
|
return this._interfaceStatementLookup;
|
|
@@ -2601,7 +2601,7 @@ function getBscTypeFromExpression(expression, functionExpression) {
|
|
|
2601
2601
|
//function call
|
|
2602
2602
|
}
|
|
2603
2603
|
else if ((0, reflection_1.isNewExpression)(expression)) {
|
|
2604
|
-
return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression);
|
|
2604
|
+
return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression);
|
|
2605
2605
|
//Function call
|
|
2606
2606
|
}
|
|
2607
2607
|
else if ((0, reflection_1.isCallExpression)(expression)) {
|