170 lines
4.6 KiB
TypeScript
170 lines
4.6 KiB
TypeScript
import { describe, it, before, after } from "node:test";
|
|
import * as assert from "node:assert/strict";
|
|
import * as fs from "node:fs";
|
|
import * as os from "node:os";
|
|
import * as path from "node:path";
|
|
import {
|
|
setTestSocket,
|
|
stopTestDaemon,
|
|
runCliJson,
|
|
requireServer,
|
|
} from "../helpers.ts";
|
|
|
|
const skip = requireServer("gopls");
|
|
|
|
async function pollUntil<T>(
|
|
fn: () => Promise<T>,
|
|
predicate: (v: T) => boolean,
|
|
timeoutMs: number,
|
|
intervalMs = 250,
|
|
): Promise<T> {
|
|
const deadline = Date.now() + timeoutMs;
|
|
let last: T = await fn();
|
|
while (Date.now() < deadline) {
|
|
if (predicate(last)) return last;
|
|
await new Promise((r) => setTimeout(r, intervalMs));
|
|
last = await fn();
|
|
}
|
|
return last;
|
|
}
|
|
|
|
interface DiagResult {
|
|
[serverId: string]: { diagnostics?: { message: string }[] };
|
|
}
|
|
|
|
describe("watcher: gopls picks up external file changes", { skip: skip ?? undefined }, () => {
|
|
let tmpDir: string;
|
|
let mainFile: string;
|
|
let helperFile: string;
|
|
const env = { ...process.env };
|
|
let cleanup: () => void;
|
|
|
|
before(async () => {
|
|
cleanup = setTestSocket(env);
|
|
await stopTestDaemon(env);
|
|
|
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-lsp-gopls-watch-"));
|
|
fs.writeFileSync(path.join(tmpDir, "go.mod"), "module example.com/wtest\n\ngo 1.21\n");
|
|
mainFile = path.join(tmpDir, "main.go");
|
|
helperFile = path.join(tmpDir, "helper.go");
|
|
fs.writeFileSync(
|
|
mainFile,
|
|
"package main\n\nfunc main() {\n\tHelper()\n}\n",
|
|
);
|
|
});
|
|
|
|
after(async () => {
|
|
await stopTestDaemon(env);
|
|
cleanup();
|
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it("initially reports undefined symbol", async () => {
|
|
const result = await pollUntil(
|
|
async () =>
|
|
(await runCliJson(
|
|
[mainFile, "diagnostics", '{"timeoutMs":3000}'],
|
|
env,
|
|
)) as DiagResult,
|
|
(r) => {
|
|
const diags = r["gopls"]?.diagnostics ?? [];
|
|
return diags.some(
|
|
(d) =>
|
|
d.message.toLowerCase().includes("undefined") ||
|
|
d.message.includes("Helper"),
|
|
);
|
|
},
|
|
15000,
|
|
500,
|
|
);
|
|
const diags = result["gopls"]?.diagnostics ?? [];
|
|
const hasUndefined = diags.some((d) =>
|
|
d.message.toLowerCase().includes("undefined") || d.message.includes("Helper"),
|
|
);
|
|
assert.ok(
|
|
hasUndefined,
|
|
`Expected undefined-symbol diagnostic, got: ${JSON.stringify(diags)}`,
|
|
);
|
|
});
|
|
|
|
it("clears the diagnostic after helper.go is created externally", async () => {
|
|
fs.writeFileSync(
|
|
helperFile,
|
|
"package main\n\nfunc Helper() {}\n",
|
|
);
|
|
|
|
const result = await pollUntil(
|
|
async () =>
|
|
(await runCliJson(
|
|
[mainFile, "diagnostics", '{"timeoutMs":3000}'],
|
|
env,
|
|
)) as DiagResult,
|
|
(r) => {
|
|
const diags = r["gopls"]?.diagnostics ?? [];
|
|
return !diags.some(
|
|
(d) =>
|
|
d.message.toLowerCase().includes("undefined") ||
|
|
d.message.includes("Helper"),
|
|
);
|
|
},
|
|
15000,
|
|
500,
|
|
);
|
|
|
|
const finalDiags = result["gopls"]?.diagnostics ?? [];
|
|
const stillUndefined = finalDiags.some(
|
|
(d) =>
|
|
d.message.toLowerCase().includes("undefined") ||
|
|
d.message.includes("Helper"),
|
|
);
|
|
assert.ok(
|
|
!stillUndefined,
|
|
`Expected diagnostic to clear after creating helper.go, still got: ${JSON.stringify(finalDiags)}`,
|
|
);
|
|
});
|
|
|
|
it("closes an opened file when it is deleted externally", async () => {
|
|
fs.writeFileSync(
|
|
helperFile,
|
|
"package main\n\nfunc Helper(x int) {}\n",
|
|
);
|
|
await runCliJson([helperFile, "diagnostics", '{"timeoutMs":3000}'], env);
|
|
|
|
await pollUntil(
|
|
async () =>
|
|
(await runCliJson(
|
|
[mainFile, "diagnostics", '{"timeoutMs":3000}'],
|
|
env,
|
|
)) as DiagResult,
|
|
(r) => {
|
|
const diags = r["gopls"]?.diagnostics ?? [];
|
|
return diags.some((d) => d.message.includes("not enough arguments"));
|
|
},
|
|
15000,
|
|
500,
|
|
);
|
|
|
|
fs.rmSync(helperFile);
|
|
|
|
const result = await pollUntil(
|
|
async () =>
|
|
(await runCliJson(
|
|
[mainFile, "diagnostics", '{"timeoutMs":3000}'],
|
|
env,
|
|
)) as DiagResult,
|
|
(r) => {
|
|
const diags = r["gopls"]?.diagnostics ?? [];
|
|
return diags.some((d) => d.message.toLowerCase().includes("undefined"));
|
|
},
|
|
15000,
|
|
500,
|
|
);
|
|
|
|
const finalDiags = result["gopls"]?.diagnostics ?? [];
|
|
assert.ok(
|
|
finalDiags.some((d) => d.message.toLowerCase().includes("undefined")),
|
|
`Expected undefined-symbol diagnostic after deleting opened helper.go, got: ${JSON.stringify(finalDiags)}`,
|
|
);
|
|
});
|
|
});
|