Files
vscode-eftl-language/test/grammar.test.js
T
2026-08-19 14:12:48 +02:00

77 lines
3.1 KiB
JavaScript

const assert = require('node:assert/strict');
const fs = require('node:fs');
const test = require('node:test');
const oniguruma = require('vscode-oniguruma');
const textmate = require('vscode-textmate');
async function loadGrammar() {
await oniguruma.loadWASM(fs.readFileSync(require.resolve('vscode-oniguruma/release/onig.wasm')).buffer);
const registry = new textmate.Registry({
onigLib: Promise.resolve({
createOnigScanner: patterns => new oniguruma.OnigScanner(patterns),
createOnigString: value => new oniguruma.OnigString(value)
}),
loadGrammar: async scopeName => scopeName === 'source.eftl'
? textmate.parseRawGrammar(
fs.readFileSync('syntaxes/eftl.tmLanguage.json', 'utf8'),
'eftl.tmLanguage.json'
)
: null
});
return registry.loadGrammar('source.eftl');
}
test('highlights nested VAR blocks, self-closing functions, and WHILE attributes', async () => {
const grammar = await loadGrammar();
const source = [
'[EFTL]',
'[VAR name="count" type="number"][SIZE_OF varname="items" /][/VAR]',
'[WHILE threshold="99"][CONDITION][% count > 0 %][/CONDITION][DO]',
'[VAR name="current" type="string"][VALUE_OF varname="items" index="count" /][/VAR]',
'[/DO][/WHILE]',
'[IF][CONDITION][% count == 0 %][/CONDITION][THEN]',
'[VAR name="empty" type="boolean"][% empty = true; %][/VAR]',
'[/THEN][/IF]',
'[/EFTL]'
];
let ruleStack = textmate.INITIAL;
const variableTokens = [];
const selfClosingFunctionTokens = [];
const thresholdTokens = [];
const thresholdValueTokens = [];
const whileTokens = [];
for (const line of source) {
const result = grammar.tokenizeLine(line, ruleStack);
ruleStack = result.ruleStack;
for (const token of result.tokens) {
const text = line.slice(token.startIndex, token.endIndex);
if (text === 'VAR' && line[token.startIndex - 1] !== '/') variableTokens.push(token);
if (text === 'SIZE_OF' || text === 'VALUE_OF') selfClosingFunctionTokens.push(token);
if (text === 'threshold') thresholdTokens.push(token);
if (text === '"99"') thresholdValueTokens.push(token);
if (text === 'WHILE') whileTokens.push(token);
}
}
assert.equal(variableTokens.length, 3);
for (const token of variableTokens) {
assert.ok(token.scopes.includes('storage.type.variable.eftl'));
}
for (const token of selfClosingFunctionTokens) {
assert.ok(token.scopes.includes('meta.function.eftl'));
assert.ok(!token.scopes.includes('meta.function.block.eftl'));
}
assert.equal(thresholdTokens.length, 1);
assert.ok(thresholdTokens[0].scopes.includes('entity.other.attribute-name.eftl'));
assert.equal(thresholdValueTokens.length, 1);
assert.ok(thresholdValueTokens[0].scopes.includes('string.quoted.double.eftl'));
assert.equal(whileTokens.length, 1);
assert.ok(whileTokens[0].scopes.includes('keyword.control.loop.eftl'));
});