pi-lens
Version:
Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo
71 lines (70 loc) • 2.82 kB
JavaScript
import { safeSpawnAsync } from "../../safe-spawn.js";
import { getLinterPolicyForCwd, hasYamllintConfig } from "../../tool-policy.js";
import { PRIORITY } from "../priorities.js";
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
const yamllint = createAvailabilityChecker("yamllint", ".exe");
export { hasYamllintConfig };
function parseYamllintParsable(raw, filePath) {
const diagnostics = [];
for (const line of raw.split(/\r?\n/)) {
if (!line.trim())
continue;
const match = line.match(/^(.*?):(\d+):(\d+):\s*\[(error|warning)\]\s*(.*?)\s*\(([^)]+)\)\s*$/i);
if (!match)
continue;
const severity = match[4].toLowerCase() === "error" ? "error" : "warning";
diagnostics.push({
id: `yamllint-${match[2]}-${match[3]}-${match[6]}`,
message: `[${match[6]}] ${match[5]}`,
filePath,
line: Number(match[2]),
column: Number(match[3]),
severity,
semantic: severity === "error" ? "blocking" : "warning",
tool: "yamllint",
rule: match[6],
});
}
return diagnostics;
}
const yamllintRunner = {
id: "yamllint",
appliesTo: ["yaml"],
priority: PRIORITY.YAML_LINT,
enabledByDefault: true,
skipTestFiles: false,
async run(ctx) {
const cwd = ctx.cwd || process.cwd();
const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
if (policy && !policy.preferredRunners.includes("yamllint")) {
return { status: "skipped", diagnostics: [], semantic: "none" };
}
const hasConfig = hasYamllintConfig(cwd);
if (!hasConfig) {
ctx.log("yamllint: no config detected, running with default rules");
}
let cmd = null;
if (await (yamllint.isAvailableAsync(cwd))) {
cmd = yamllint.getCommand(cwd);
}
else {
cmd = await resolveToolCommandWithInstallFallback(cwd, "yamllint");
}
if (!cmd)
return { status: "skipped", diagnostics: [], semantic: "none" };
const result = await safeSpawnAsync(cmd, ["-f", "parsable", ctx.filePath], {
timeout: 15000,
});
const diagnostics = parseYamllintParsable(`${result.stdout ?? ""}${result.stderr ?? ""}`, ctx.filePath);
if (diagnostics.length === 0) {
return { status: "succeeded", diagnostics: [], semantic: "none" };
}
const hasBlocking = diagnostics.some((d) => d.semantic === "blocking");
return {
status: hasBlocking ? "failed" : "succeeded",
diagnostics,
semantic: hasBlocking ? "blocking" : "warning",
};
},
};
export default yamllintRunner;