UNPKG

pi-lens

Version:

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

263 lines (260 loc) • 8.94 kB
import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url); import { rootMarkersForFile } from "./chunk-22AVIGXS.js"; import { createGenerationMap, createGenerationSource } from "./chunk-VN2AXLEX.js"; import { getDegradationLedgerGeneration, recordDegradationOnce } from "./chunk-N3YQJI6O.js"; import { logExtension } from "./chunk-O6TQT6RI.js"; import { isAtOrAboveHomeDir, isRealGitMarker, isUnderDir, isWindowsPath, nameMatchesMarkerGlob, normalizeEphemeralMapKey } from "./chunk-Q5U6FMDI.js"; // dist/clients/tool-cwd.js import * as os from "node:os"; import { existsSync, readdirSync } from "node:fs"; import * as path from "node:path"; var FORMATTER_MARKERS = { biome: ["biome.json", "biome.jsonc", "package.json", ".gitignore"], prettier: [ ".prettierrc", ".prettierrc.json", ".prettierrc.yaml", ".prettierrc.yml", ".prettierrc.js", ".prettierrc.cjs", ".prettierrc.mjs", "prettier.config.js", "prettier.config.cjs", "prettier.config.mjs", ".prettierignore", "package.json", ".gitignore" ], ruff: ["pyproject.toml", "ruff.toml", ".ruff.toml", ".gitignore"], black: ["pyproject.toml", "black.toml", ".black", ".gitignore"], "php-cs-fixer": [".php-cs-fixer.php", ".php-cs-fixer.dist.php", ".gitignore"], sqlfluff: [".sqlfluff", "pyproject.toml", "setup.cfg", ".gitignore"], oxfmt: [ "oxfmt.toml", ".oxfmtrc.json", "vite-plus.json", "package.json", ".gitignore" ], rustfmt: ["rustfmt.toml", ".rustfmt.toml", "Cargo.toml", ".gitignore"], rubocop: [".rubocop.yml", ".rubocop.yaml", ".gitignore"], standardrb: [".standard.yml", ".standard.yaml", ".gitignore"], "clang-format": [".clang-format", "_clang-format", ".gitignore"], stylua: ["stylua.toml", ".stylua.toml", ".gitignore"], ocamlformat: [".ocamlformat", ".gitignore"], "google-java-format": [".google-java-format", ".editorconfig", ".gitignore"], cljfmt: [".cljfmt.edn", "cljfmt.edn", ".cljfmt", ".gitignore"], "cmake-format": [ ".cmake-format", ".cmake-format.yaml", ".cmake-format.yml", ".cmake-format.json", ".cmake-format.py", "cmake-format.yaml", "cmake-format.yml", ".editorconfig", ".gitignore" ], "psscriptanalyzer-format": [ "PSScriptAnalyzerSettings.psd1", "ScriptAnalyzerSettings.psd1", ".gitignore" ], csharpier: [ ".csharpierrc", ".csharpierrc.json", ".csharpierrc.yaml", ".csharpierrc.yml", ".gitignore" ], ormolu: [".ormolu", ".gitignore"], taplo: ["taplo.toml", ".taplo.toml", ".gitignore"], terraform: [".terraform.lock.hcl", ".gitignore"], swiftformat: [".swiftformat", ".gitignore"], fantomas: [".fantomasignore", ".editorconfig", ".gitignore"], mix: [".formatter.exs", ".gitignore"], shfmt: [".editorconfig", ".gitignore"], ktlint: [".editorconfig", ".gitignore"], ktfmt: [ ".editorconfig", ".ktfmt", ".ktfmt.kts", "build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts", ".gitignore" ], typstyle: [".gitignore"] }; var toolCwdGeneration = createGenerationSource("tool-cwd"); var logged = createGenerationMap("tool-cwd-resolution-log"); function _toolCwdEphemeralKey(parts) { return parts.map(normalizeEphemeralMapKey).join("\0"); } function syncGeneration() { if (toolCwdGeneration.current() === getDegradationLedgerGeneration()) return; logged.clear(); while (toolCwdGeneration.current() < getDegradationLedgerGeneration()) { toolCwdGeneration.bump(); } } function walkMarkerRoot(startDir, markers, homeDir) { let current = path.resolve(startDir); for (let depth = 0; depth < 64; depth++) { if (isAtOrAboveHomeDir(current, homeDir)) break; for (const marker of markers) { const slash = marker.replace(/\\/g, "/").lastIndexOf("/"); const parent = slash >= 0 ? marker.slice(0, slash) : ""; const basename = slash >= 0 ? marker.slice(slash + 1) : marker; const target = parent ? path.join(current, ...parent.split("/").filter(Boolean)) : current; let found = false; if (basename.includes("*")) { try { found = readdirSync(target, { withFileTypes: true }).some((entry) => (entry.isFile() || entry.isSymbolicLink()) && nameMatchesMarkerGlob(entry.name, basename)); } catch { found = false; } } else { found = existsSync(path.join(target, basename)); } if (found) return { root: current, marker }; } const parentDir = path.dirname(current); if (parentDir === current) break; current = parentDir; } return { root: null }; } function findMarkerRoot(startDir, markers, homeDir) { syncGeneration(); return walkMarkerRoot(startDir, markers, homeDir); } function markersFor(kind, tool, file, ctx) { if (kind === "lsp") return ctx.rootMarkers ?? []; if (kind === "runner") return ctx.rootMarkers ?? rootMarkersForFile(file, tool); return FORMATTER_MARKERS[tool] ?? [".gitignore"]; } function emitResolution(kind, tool, cwd, reason) { syncGeneration(); const key = _toolCwdEphemeralKey([kind, tool, cwd, reason]); if (logged.current(key) !== 0) return; logged.bump(key); logExtension({ subsystem: "tool-cwd", level: "debug", message: `cwd ${kind} ${tool} cwd=${cwd} reason=${reason}` }); } function logRunnerAdvisoryOnce(ctx, tool, root, message) { syncGeneration(); const key = _toolCwdEphemeralKey(["runner-advisory", tool, root]); if (logged.current(key) !== 0) return; logged.bump(key); ctx.log(message, "debug"); } function resolveToolCwd(kind, tool, file, ctx) { const dispatchRoot = path.resolve(ctx.cwd ?? process.cwd()); const absoluteFile = path.resolve(file); const fileDir = path.dirname(absoluteFile); const homeDir = ctx.homeDir ?? os.homedir(); const insideDispatch = isUnderDir(absoluteFile, dispatchRoot); if (ctx.serverRoot) { const rootPath = isWindowsPath(ctx.serverRoot) ? path.win32 : path; const serverRoot = rootPath.resolve(ctx.serverRoot); if (!ctx.suppressTelemetry) emitResolution(kind, tool, serverRoot, "server-root"); return { cwd: serverRoot }; } const markers = markersFor(kind, tool, absoluteFile, ctx); const markerResult = markers.length ? findMarkerRoot(fileDir, markers, ctx.allowHomeMarker ? path.parse(homeDir).root : homeDir) : { root: null }; const markerRoot = markerResult.root; if (markerRoot && (insideDispatch ? isUnderDir(markerRoot, dispatchRoot) : true)) { const finalReason = `marker:${markerResult.marker ?? markers[0]}`; if (!ctx.suppressTelemetry) emitResolution(kind, tool, markerRoot, finalReason); return { cwd: markerRoot, ...markerResult.marker !== void 0 ? { marker: markerResult.marker } : {} }; } const memo = ctx.toolCwdMemo; if (memo && memo.gitRoot === void 0) { const gitResult = findMarkerRoot(fileDir, [".git"], homeDir); memo.gitRoot = gitResult.root && isRealGitMarker(path.join(gitResult.root, ".git")) ? gitResult.root : null; } const gitRoot = memo && memo.gitRoot !== void 0 ? memo.gitRoot : (() => { const gitResult = findMarkerRoot(fileDir, [".git"], homeDir); return gitResult.root && isRealGitMarker(path.join(gitResult.root, ".git")) ? gitResult.root : null; })(); if (gitRoot && (insideDispatch ? isUnderDir(gitRoot, dispatchRoot) : true)) { if (!ctx.suppressTelemetry) emitResolution(kind, tool, gitRoot, "git-root"); return { cwd: gitRoot, marker: ".git" }; } if (insideDispatch) { if (kind === "formatter") { if (!ctx.suppressTelemetry) emitResolution(kind, tool, fileDir, "file-dir-fallback"); if (!ctx.suppressTelemetry && !isUnderDir(fileDir, homeDir)) { recordDegradationOnce({ kind: "tool-cwd-resolution", subject: tool, reason: `${kind}:home-cap:${absoluteFile}` }); } return { cwd: fileDir }; } if (!ctx.suppressTelemetry) emitResolution(kind, tool, dispatchRoot, "dispatch-root"); return { cwd: dispatchRoot }; } const reason = isUnderDir(fileDir, homeDir) ? "file-dir-fallback" : "home-cap"; const fallback = isUnderDir(fileDir, homeDir) ? fileDir : homeDir; if (!ctx.suppressTelemetry) recordDegradationOnce({ kind: "tool-cwd-resolution", subject: tool, reason: `${kind}:${reason}:${absoluteFile}` }); if (!ctx.suppressTelemetry) emitResolution(kind, tool, fallback, reason); return { cwd: fallback }; } function resolveRunnerCwd(ctx, tool) { return resolveToolCwd("runner", tool, ctx.filePath, ctx).cwd; } function resolveRunnerCwdWithReason(ctx, tool) { return resolveToolCwd("runner", tool, ctx.filePath, ctx); } export { logRunnerAdvisoryOnce, resolveToolCwd, resolveRunnerCwd, resolveRunnerCwdWithReason };