fix unclosed block detection

add parser tests (codex)
This commit is contained in:
2026-08-18 12:49:31 +02:00
parent c34d2864aa
commit 15422cca1f
4 changed files with 51 additions and 3 deletions
-2
View File
@@ -303,7 +303,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -489,7 +488,6 @@
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
+1
View File
@@ -57,6 +57,7 @@
"scripts": { "scripts": {
"vscode:prepublish": "npm run compile", "vscode:prepublish": "npm run compile",
"compile": "tsc -p ./", "compile": "tsc -p ./",
"test": "npm run compile && node --test test/*.test.js",
"watch": "tsc -watch -p ./", "watch": "tsc -watch -p ./",
"lint": "eslint src --ext ts" "lint": "eslint src --ext ts"
}, },
+2 -1
View File
@@ -41,8 +41,9 @@ export class EftlParser {
// Check for unclosed blocks // Check for unclosed blocks
for (const block of this.blockStack) { for (const block of this.blockStack) {
const expectedClose = this.getMatchingClose(block.type);
this.errors.push({ this.errors.push({
message: `Unclosed block: ${block.token.value}`, message: `Unclosed tag: ${block.token.value} (expected ${expectedClose})`,
line: block.token.line, line: block.token.line,
column: block.token.column, column: block.token.column,
length: block.token.length length: block.token.length
+48
View File
@@ -0,0 +1,48 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const { EftlParser } = require('../out/parser');
const { EftlTokenizer } = require('../out/tokenizer');
function parse(source) {
const { tokens, errors: tokenizerErrors } = new EftlTokenizer(source).tokenize();
assert.deepEqual(tokenizerErrors, []);
return new EftlParser(tokens).parse().errors;
}
test('accepts a correctly closed VAR tag', () => {
assert.deepEqual(parse('[VAR][/VAR]'), []);
});
test('reports a VAR tag without its closing tag', () => {
assert.deepEqual(parse('[VAR]'), [{
message: 'Unclosed tag: [VAR] (expected [/VAR])',
line: 1,
column: 1,
length: 5
}]);
});
test('reports an unexpected closing tag', () => {
const errors = parse('[/VAR]');
assert.equal(errors.length, 1);
assert.match(errors[0].message, /Unexpected closing tag/);
});
test('reports every unclosed nested tag at its opening token', () => {
assert.deepEqual(parse('[EFTL]\n[VAR]'), [
{
message: 'Unclosed tag: [EFTL] (expected [/EFTL])',
line: 1,
column: 1,
length: 6
},
{
message: 'Unclosed tag: [VAR] (expected [/VAR])',
line: 2,
column: 1,
length: 5
}
]);
});