From 6d03f91958d7abe4e33ce9332ee89a2e1426ef0d Mon Sep 17 00:00:00 2001 From: Bronley Plumb Date: Tue, 21 Feb 2023 11:35:41 -0500 Subject: [PATCH] Fix crash when func has no block --- src/parser/Parser.ts | 13 +++++++------ src/parser/tests/statement/Function.spec.ts | 12 +++++++++++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/parser/Parser.ts b/src/parser/Parser.ts index c44d0fd2f..aba004152 100644 --- a/src/parser/Parser.ts +++ b/src/parser/Parser.ts @@ -887,12 +887,13 @@ export class Parser { this._references.functionExpressions.push(func); - //make sure to restore the currentFunctionExpression even if the body block fails to parse - try { - //support ending the function with `end sub` OR `end function` - func.body = this.block(); - func.body.symbolTable = new SymbolTable(`Block: Function '${name?.text ?? ''}'`, () => func.getSymbolTable()); - } finally { } + //support ending the function with `end sub` OR `end function` + func.body = this.block(); + //if the parser was unable to produce a block, make an empty one so the AST makes some sense... + if (!func.body) { + func.body = new Block([], util.createRangeFromPositions(func.range.start, func.range.start)); + } + func.body.symbolTable = new SymbolTable(`Block: Function '${name?.text ?? ''}'`, () => func.getSymbolTable()); if (!func.body) { this.diagnostics.push({ diff --git a/src/parser/tests/statement/Function.spec.ts b/src/parser/tests/statement/Function.spec.ts index 1208229b6..d2fd5c121 100644 --- a/src/parser/tests/statement/Function.spec.ts +++ b/src/parser/tests/statement/Function.spec.ts @@ -1,13 +1,23 @@ import { expect } from '../../../chai-config.spec'; - import { Parser } from '../../Parser'; import { Lexer } from '../../../lexer/Lexer'; import { TokenKind } from '../../../lexer/TokenKind'; import { EOF, identifier, token } from '../Parser.spec'; +import { isFunctionStatement } from '../../../astUtils/reflection'; +import type { FunctionStatement } from '../../Statement'; describe('parser', () => { describe('function declarations', () => { + it('still provides a body when end keyword is mangled/missing', () => { + const parser = Parser.parse(` + sub test() + end su + `); + const func = parser.ast.findChild(isFunctionStatement); + expect(func.func.body).to.exist; + }); + it('recovers when using `end sub` instead of `end function`', () => { const { tokens } = Lexer.scan(` function Main()