aboutsummaryrefslogtreecommitdiff
path: root/tests/drivers/ext_cache_test.js
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-15 10:11:56 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-15 10:11:56 +0330
commite1e0a265e931637f452ac05bb7d912e07bcee574 (patch)
tree60289bb1fc3d812dfc576f01e0f8a83091a495c1 /tests/drivers/ext_cache_test.js
parentanalyzer: check borrow returns of forward-called functions at the unit's end;... (diff)
lsp: borrow errors ranged on the use, with related information for where the owner ended and was declared; vscode client passes relatedInformation through
Diffstat (limited to 'tests/drivers/ext_cache_test.js')
-rw-r--r--tests/drivers/ext_cache_test.js13
1 files changed, 13 insertions, 0 deletions
diff --git a/tests/drivers/ext_cache_test.js b/tests/drivers/ext_cache_test.js
index 93caf94..9bd3e3a 100644
--- a/tests/drivers/ext_cache_test.js
+++ b/tests/drivers/ext_cache_test.js
@@ -31,6 +31,8 @@ const stub = {
EventEmitter: class { constructor() { this.event = () => ({ dispose() {} }); } fire() {} },
Diagnostic: class { constructor(range, message, severity) { Object.assign(this, { range, message, severity }); } },
Range: class { constructor(a, b, c, d) { Object.assign(this, { start: { line: a, character: b }, end: { line: c, character: d } }); } },
+ Location: class { constructor(uri, range) { Object.assign(this, { uri, range }); } },
+ DiagnosticRelatedInformation: class { constructor(location, message) { Object.assign(this, { location, message }); } },
DiagnosticSeverity: { Error: 0, Warning: 1, Information: 2, Hint: 3 },
SemanticTokensLegend: class { constructor(t, m) { this.tokenTypes = t; this.tokenModifiers = m; } },
SemanticTokensBuilder: class { constructor() {} push() {} build() { return null; } },
@@ -177,6 +179,17 @@ const mainUri = 'file://' + main;
const expiredList = await world.completion.provideCompletionItems(expiredDoc, { line: 3, character: 1 }, { isCancellationRequested: false });
const expiredItem = expiredList && expiredList.items.find(c => c.label === 'used');
check('completion maps consumed lifetimes to the editor strikethrough tag', expiredItem && expiredItem.tags?.[0] === stub.CompletionItemTag.Deprecated && /lifetime ended/.test(expiredItem.documentation?.value));
+ // a borrow error keeps the server's related information: where the owner ended and where it was declared
+ const borrowPath = path.join(root, 'borrow.zc');
+ const borrowDoc = doc(borrowPath, 'include rt;\nfn main() {\n\tchar* t = rt.new(4); t[0] = 65;\n\tchar* r = t + 1;\n\trt.free(t);\n\treturn r[0];\n}\n');
+ fs.writeFileSync(borrowPath, borrowDoc.text);
+ world.textDocuments.push(borrowDoc);
+ if (world.listeners.onDidOpenTextDocument) world.listeners.onDidOpenTextDocument(borrowDoc);
+ await until(() => world.sets.some(s => s.uri === 'file://' + borrowPath && s.list.length));
+ const borrowSet = world.sets.filter(s => s.uri === 'file://' + borrowPath).pop();
+ const borrowDiag = borrowSet && borrowSet.list.find(d => /r borrows t/.test(d.message));
+ const related = borrowDiag && borrowDiag.relatedInformation;
+ check('borrow diagnostics pass related information through to the editor', related && related.length === 2 && related[0] instanceof stub.DiagnosticRelatedInformation && related[0].message === 'owner t was freed here' && related[0].location.range.start.line === 4 && related[1].message === 'owner t is declared here', JSON.stringify(borrowSet && borrowSet.list));
const actionDoc = doc(path.join(root, 'imports.zc'), 'fn main() { rt.put_n(7); }');
const actions = await world.actions.provideCodeActions(actionDoc, new stub.Range(0, 15, 0, 15), {}, { isCancellationRequested: false });
check('quick fixes reach the editor as workspace edits', actions.some(a => a.kind === 'quickfix' && a.edit.edits.some(e => e.newText === 'include rt;\n')));