aboutsummaryrefslogtreecommitdiff
path: root/plugin/test
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/test')
-rw-r--r--plugin/test/highlighting.test.js61
1 files changed, 61 insertions, 0 deletions
diff --git a/plugin/test/highlighting.test.js b/plugin/test/highlighting.test.js
new file mode 100644
index 0000000..df18f6a
--- /dev/null
+++ b/plugin/test/highlighting.test.js
@@ -0,0 +1,61 @@
+'use strict';
+
+const assert = require('node:assert/strict');
+const { test, before } = require('node:test');
+const fs = require('node:fs');
+const path = require('node:path');
+const { Registry } = require('vscode-textmate');
+const { loadWASM, OnigScanner, OnigString } = require('vscode-oniguruma');
+
+let grammar;
+before(async () => {
+ const wasm = fs.readFileSync(require.resolve('vscode-oniguruma/release/onig.wasm'));
+ await loadWASM(wasm.buffer.slice(wasm.byteOffset, wasm.byteOffset + wasm.byteLength));
+ const registry = new Registry({
+ onigLib: Promise.resolve({
+ createOnigScanner: patterns => new OnigScanner(patterns),
+ createOnigString: text => new OnigString(text)
+ }),
+ loadGrammar: async () => JSON.parse(fs.readFileSync(
+ path.join(__dirname, '../syntaxes/cie-pseudocode.tmLanguage.json'), 'utf8'))
+ });
+ grammar = await registry.loadGrammar('source.cie-pseudocode');
+});
+
+function scopesAt(text, word) {
+ const offset = text.indexOf(word);
+ return grammar.tokenizeLine(text).tokens.find(
+ token => token.startIndex <= offset && token.endIndex > offset).scopes;
+}
+
+test('C++ style scopes distinguish keywords, types, literals, operators and builtins', () => {
+ for (const [text, word, scope] of [
+ ['IF Ready THEN', 'IF', 'keyword.control'],
+ ['DECLARE X : INTEGER', 'DECLARE', 'storage.modifier'],
+ ['DECLARE X : INTEGER', 'INTEGER', 'storage.type'],
+ ['X <- TRUE', 'TRUE', 'constant.language'],
+ ['X <- 12.5', '12.5', 'constant.numeric'],
+ ['X <- 2 DIV 1', 'DIV', 'keyword.operator.word'],
+ ['X <- 1', '<-', 'keyword.operator'],
+ ['OUTPUT "text"', 'text', 'string.quoted.double'],
+ ["X <- 'A'", 'A', 'string.quoted.single']
+ ]) assert.ok(scopesAt(text, word).some(s => s.startsWith(scope)), text);
+ for (const name of ['LENGTH', 'MID', 'RIGHT', 'LEFT', 'LCASE', 'UCASE',
+ 'ASC', 'CHR', 'IS_NUM', 'NUM_TO_STR', 'STR_TO_NUM', 'EOF']) {
+ assert.ok(scopesAt(`${name}(X)`, name).includes('entity.name.function.cie-pseudocode'));
+ }
+});
+
+test('comments, strings, lowercase and keyword prefixes cannot become keywords', () => {
+ assert.ok(scopesAt('// IF [(', 'IF').some(s => s.startsWith('comment.')));
+ assert.ok(scopesAt('OUTPUT "IF // ["', 'IF').some(s => s.startsWith('string.')));
+ for (const text of ['if X then', 'IFValue <- 1', 'CASE OF X', 'CLASS Example']) {
+ assert.ok(!scopesAt(text, text.split(' ')[0]).some(
+ s => /^(keyword|storage)\./.test(s)), text);
+ }
+ // CIE has neither backslash escapes nor multiline string literals.
+ let state = grammar.tokenizeLine('OUTPUT "unfinished').ruleStack;
+ assert.ok(grammar.tokenizeLine('IF X THEN', state).tokens[0].scopes.includes(
+ 'keyword.control.cie-pseudocode'));
+ assert.ok(scopesAt('OUTPUT "x\\" + 1', '+').includes('keyword.operator.cie-pseudocode'));
+});