UNPKG

pi-lens

Version:

Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo

90 lines (89 loc) • 3.67 kB
import * as path from "node:path"; import { safeSpawnAsync } from "../../safe-spawn.js"; import { createAvailabilityChecker } from "./utils/runner-helpers.js"; import { PRIORITY } from "../priorities.js"; // zig rejects `--version`; the version subcommand is `zig version`. Using the // default probe would make this runner skip on every machine. const zig = createAvailabilityChecker("zig", ".exe", ["version"]); function parseZigOutput(raw, filePath) { const diagnostics = []; for (const line of raw.split(/\r?\n/)) { const match = line.match(/^(.*?):(\d+):(\d+):\s*(error|warning|note):\s*(.+)$/); if (!match) continue; const [, rawFile, lineStr, colStr, level, message] = match; const resolvedSource = path.resolve(rawFile.trim()); const resolvedTarget = path.resolve(filePath); if (resolvedSource !== resolvedTarget) continue; const severity = level === "error" ? "error" : "warning"; diagnostics.push({ id: `zig-${level}-${lineStr}-${colStr}`, message, filePath, line: Number.parseInt(lineStr, 10) || 1, column: Number.parseInt(colStr, 10) || 1, severity, semantic: severity === "error" ? "blocking" : "warning", tool: "zig", rule: `zig-${level}`, fixable: false, }); } return diagnostics; } function firstOutputLine(result) { return `${result.stderr || ""}\n${result.stdout || ""}` .trim() .split(/\r?\n/, 1)[0] .slice(0, 200); } const zigCheckRunner = { id: "zig-check", appliesTo: ["zig"], priority: PRIORITY.GENERAL_ANALYSIS, enabledByDefault: true, skipTestFiles: false, async run(ctx) { const cwd = ctx.cwd || process.cwd(); if (!(await (zig.isAvailableAsync(cwd)))) { return { status: "skipped", diagnostics: [], semantic: "none" }; } const cmd = zig.getCommand(cwd); const absPath = path.resolve(cwd, ctx.filePath); const result = await safeSpawnAsync(cmd, ["build-exe", absPath, "-fno-emit-bin"], { cwd, timeout: 30000 }); if (result.error && !result.stdout && !result.stderr) { return { status: "skipped", diagnostics: [], semantic: "none" }; } const diagnostics = parseZigOutput(`${result.stderr || ""}\n${result.stdout || ""}`, ctx.filePath); if (diagnostics.length === 0) { if (result.status && result.status !== 0) { return { status: "failed", diagnostics: [ { id: "zig-check-nonzero-no-diagnostics", message: firstOutputLine(result) || "zig build-exe exited non-zero without structured diagnostics", filePath: ctx.filePath, severity: "warning", semantic: "warning", tool: "zig", rule: "zig-check", fixable: false, }, ], semantic: "warning", }; } return { status: "succeeded", diagnostics: [], semantic: "none" }; } const hasErrors = diagnostics.some((d) => d.severity === "error"); return { status: hasErrors ? "failed" : "succeeded", diagnostics, semantic: hasErrors ? "blocking" : "warning", }; }, }; export default zigCheckRunner;