Reduce repeated compiler startup in monorepo QX formatting
This commit is contained in:
@@ -595,6 +595,30 @@ const main = async () => {
|
|||||||
process.stdout.write(`${JSON.stringify(plan, null, 2)}\n`);
|
process.stdout.write(`${JSON.stringify(plan, null, 2)}\n`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (command === "format" && (args[0] === "--check" || args[0] === "--write")) {
|
||||||
|
const check = args[0] === "--check",
|
||||||
|
files = args.slice(1);
|
||||||
|
if (!files.length || files.some((file) => file.startsWith("-")))
|
||||||
|
throw new Error("usage: quixos-qx format --check|--write FILE...");
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
const source = await readFile(file, "utf8"),
|
||||||
|
formatted = formatQx(source);
|
||||||
|
if (formatted === source) continue;
|
||||||
|
if (check) {
|
||||||
|
console.error(`Needs formatting: ${file}`);
|
||||||
|
process.exitCode = 1;
|
||||||
|
} else {
|
||||||
|
await writeFile(file, formatted);
|
||||||
|
console.log(`Formatted ${file}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`${file}: ${error instanceof Error ? error.message : error}`);
|
||||||
|
process.exitCode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
const [file, flag, ...rest] = args;
|
const [file, flag, ...rest] = args;
|
||||||
if (
|
if (
|
||||||
!file ||
|
!file ||
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { spawnSync } from "node:child_process";
|
||||||
|
import { mkdtempSync, readFileSync, writeFileSync, rmSync } from "node:fs";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
|
import { join, resolve } from "node:path";
|
||||||
|
import test from "node:test";
|
||||||
|
import { formatQx } from "../src/capability-language/source.js";
|
||||||
|
|
||||||
|
const cli = resolve(process.cwd(), "dist/src/capability-language/tool-cli.js");
|
||||||
|
const run = (...args: string[]) => spawnSync(process.execPath, [cli, "format", ...args], { encoding: "utf8" });
|
||||||
|
const source = `workspace Test id "w" revision "w@1" commit "${"1".repeat(40)}" {\n// 雪 🦊 comment preserved\n}\n`;
|
||||||
|
|
||||||
|
test("QX batch checks are read-only; writes match single-file formatting and remain idempotent", (t) => {
|
||||||
|
const root = mkdtempSync(join(tmpdir(), "qx-format-"));
|
||||||
|
t.after(() => rmSync(root, { recursive: true, force: true }));
|
||||||
|
const files = [join(root, "one.qx"), join(root, "two 雪.qx")];
|
||||||
|
for (const file of files) writeFileSync(file, source);
|
||||||
|
const check = run("--check", ...files);
|
||||||
|
assert.notEqual(check.status, 0, check.stderr);
|
||||||
|
for (const file of files) {
|
||||||
|
assert(check.stderr.includes(file));
|
||||||
|
assert.equal(readFileSync(file, "utf8"), source);
|
||||||
|
}
|
||||||
|
const single = run(files[0]!);
|
||||||
|
assert.equal(single.status, 0, single.stderr);
|
||||||
|
assert.equal(single.stdout, formatQx(source));
|
||||||
|
const write = run("--write", ...files);
|
||||||
|
assert.equal(write.status, 0, write.stderr);
|
||||||
|
for (const file of files) assert.equal(readFileSync(file, "utf8"), single.stdout);
|
||||||
|
assert.equal(run("--check", ...files).status, 0);
|
||||||
|
assert.equal(run("--write", ...files).stdout, "");
|
||||||
|
writeFileSync(files[0]!, source);
|
||||||
|
assert.equal(run(files[0]!, "--write").status, 0);
|
||||||
|
assert.equal(readFileSync(files[0]!, "utf8"), single.stdout);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("QX batch errors report every failure and do not truncate valid work", (t) => {
|
||||||
|
const root = mkdtempSync(join(tmpdir(), "qx-format-errors-"));
|
||||||
|
t.after(() => rmSync(root, { recursive: true, force: true }));
|
||||||
|
const broken = join(root, "broken.qx"),
|
||||||
|
missing = join(root, "missing.qx"),
|
||||||
|
valid = join(root, "valid.qx");
|
||||||
|
writeFileSync(broken, "workspace { invalid");
|
||||||
|
writeFileSync(valid, source);
|
||||||
|
const result = run("--write", broken, missing, valid);
|
||||||
|
assert.notEqual(result.status, 0);
|
||||||
|
assert(result.stderr.includes(broken));
|
||||||
|
assert(result.stderr.includes(missing));
|
||||||
|
assert.equal(readFileSync(broken, "utf8"), "workspace { invalid");
|
||||||
|
assert.equal(readFileSync(valid, "utf8"), formatQx(source));
|
||||||
|
writeFileSync(valid, source);
|
||||||
|
assert.notEqual(run("--write", valid, "--unknown").status, 0);
|
||||||
|
assert.equal(readFileSync(valid, "utf8"), source, "Validate arguments before writing any file");
|
||||||
|
assert.notEqual(run("--check").status, 0);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user