diff options
| author | 2026-10-12 08:46:23 +0330 | |
|---|---|---|
| committer | 2026-10-12 08:46:23 +0330 | |
| commit | ecc350ca5c2eb50be8309c5f14f8bf0d87db9a02 (patch) | |
| tree | 70e0af76a1b13affff7c6cc8aac7b3e6ef960478 /tests/drivers/core_lsp_test.js | |
a
Diffstat (limited to 'tests/drivers/core_lsp_test.js')
| -rw-r--r-- | tests/drivers/core_lsp_test.js | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/tests/drivers/core_lsp_test.js b/tests/drivers/core_lsp_test.js new file mode 100644 index 0000000..41d0095 --- /dev/null +++ b/tests/drivers/core_lsp_test.js @@ -0,0 +1,43 @@ +// check maintained zc sources through the editor document protocol, one file at a time. +const assert = require('assert'); +const fs = require('fs'); +const cp = require('child_process'); +const path = require('path'); +const target = process.argv[2]; +const files = ['src/runtime/rt.zc', 'src/compiler/compiler.zc', 'src/runtime/run.zc', 'src/lib/std.zc', 'src/lsp/server.zc', 'src/tools/build.zc']; +const frame = message => { + const body = Buffer.from(JSON.stringify(message)); + return Buffer.concat([Buffer.from('Content-Length: ' + body.length + '\r\n\r\n'), body]); +}; +for (const file of files) { + const uri = 'file://' + path.resolve(file); + const text = fs.readFileSync(file, 'utf8'); + const messages = [ + { jsonrpc: '2.0', id: 1, method: 'initialize', params: {} }, + { jsonrpc: '2.0', method: 'initialized', params: {} }, + { jsonrpc: '2.0', method: 'textDocument/didOpen', params: { textDocument: { uri, version: 1, languageId: 'zc', text } } }, + { jsonrpc: '2.0', id: 2, method: 'textDocument/semanticTokens/full', params: { textDocument: { uri } } }, + { jsonrpc: '2.0', method: 'textDocument/didChange', params: { textDocument: { uri, version: 2 }, contentChanges: [{ text: text + '\n' }] } }, + { jsonrpc: '2.0', method: 'textDocument/didClose', params: { textDocument: { uri } } }, + { jsonrpc: '2.0', id: 3, method: 'shutdown', params: null }, + { jsonrpc: '2.0', method: 'exit' }, + ]; + const result = cp.spawnSync(target, [], { input: Buffer.concat(messages.map(frame)), timeout: 30000, maxBuffer: 32 << 20 }); + assert.strictEqual(result.status, 0, file + ': ' + result.stderr); + let data = result.stdout; + const replies = []; + while (data.length) { + const end = data.indexOf('\r\n\r\n'); + assert.ok(end >= 0, 'complete protocol header'); + const length = Number(/Content-Length:\s*(\d+)/i.exec(data.subarray(0, end).toString())[1]); + replies.push(JSON.parse(data.subarray(end + 4, end + 4 + length))); + data = data.subarray(end + 4 + length); + } + const diagnostics = replies.filter(m => m.method === 'textDocument/publishDiagnostics'); + assert.strictEqual(diagnostics.length, 3, file + ': open, change, and close publish diagnostics'); + const errors = diagnostics.flatMap(m => m.params.diagnostics).filter(d => d.severity === 1); + assert.deepStrictEqual(errors, [], file + ': ' + errors.map(d => (d.range.start.line + 1) + ': ' + d.message).join('\n')); + assert.ok(replies.find(m => m.id === 2).result.data.length, file + ': semantic tokens are available'); + assert.deepStrictEqual(diagnostics[2].params.diagnostics, [], 'close clears diagnostics'); + console.log('ok editor open, highlight, change, and close: ' + file); +} |
