Format authored monorepo code with pinned language formatters

This commit is contained in:
Timothy J. Aveni
2026-09-15 15:23:24 -07:00
parent a174faea5c
commit 00fc2b9ff1
69 changed files with 5135 additions and 3306 deletions
+46 -18
View File
@@ -17,20 +17,26 @@ export const parseQx = (source: string, fileName = "<memory>") => {
kind: QuixosCapabilityParser.ruleNames[context.ruleIndex]!,
start: offset(context.start?.start ?? 0),
end: offset((context.stop?.stop ?? -1) + 1),
children: context.children.flatMap((child) => child instanceof ParserRuleContext ? [node(child)] : []),
children: context.children.flatMap((child) => (child instanceof ParserRuleContext ? [node(child)] : [])),
});
return {
source, fileName,
source,
fileName,
root: node(parsed.tree),
diagnostics: parsed.diagnostics.map((diagnostic) => {
const line = source.split("\n")[diagnostic.line - 1] ?? "";
return { ...diagnostic, column: [...line].slice(0, diagnostic.column).join("").length };
}),
tokens: parsed.tokens.getTokens().filter((token) => token.type !== -1).map((token) => ({
kind: QuixosCapabilityParser.symbolicNames[token.type] ?? "token",
start: offset(token.start), end: offset(token.stop + 1),
text: token.text ?? "", trivia: token.channel !== 0,
})),
tokens: parsed.tokens
.getTokens()
.filter((token) => token.type !== -1)
.map((token) => ({
kind: QuixosCapabilityParser.symbolicNames[token.type] ?? "token",
start: offset(token.start),
end: offset(token.stop + 1),
text: token.text ?? "",
trivia: token.channel !== 0,
})),
};
};
@@ -41,8 +47,14 @@ export const applySourceEdits = (source: string, edits: readonly SourceEdit[]) =
let previousStart = -1;
let result = "";
for (const edit of sorted) {
if (!Number.isInteger(edit.start) || !Number.isInteger(edit.end) ||
edit.start < end || edit.start === previousStart || edit.end < edit.start || edit.end > source.length) {
if (
!Number.isInteger(edit.start) ||
!Number.isInteger(edit.end) ||
edit.start < end ||
edit.start === previousStart ||
edit.end < edit.start ||
edit.end > source.length
) {
throw new Error("Invalid or overlapping source edits");
}
result += source.slice(end, edit.start) + edit.text;
@@ -68,14 +80,27 @@ export const lintQx = (source: string, fileName = "<memory>") => {
const importPath: string = JSON.parse(source.slice(literal.start, literal.end));
let message: string | undefined;
let code = "invalid-source-import";
try { validateQxImportPath(importPath); } catch (error) { message = (error as Error).message; }
if (!message && seen.has(importPath)) { code = "duplicate-source-import"; message = `Repeated local import ${importPath}`; }
try {
validateQxImportPath(importPath);
} catch (error) {
message = (error as Error).message;
}
if (!message && seen.has(importPath)) {
code = "duplicate-source-import";
message = `Repeated local import ${importPath}`;
}
seen.add(importPath);
if (message) {
const prefix = source.slice(0, node.start);
diagnostics.push({ phase: "syntax", code, message, fileName,
line: prefix.split("\n").length, column: prefix.length - prefix.lastIndexOf("\n") - 1,
severity: code === "duplicate-source-import" ? "warning" : "error" });
diagnostics.push({
phase: "syntax",
code,
message,
fileName,
line: prefix.split("\n").length,
column: prefix.length - prefix.lastIndexOf("\n") - 1,
severity: code === "duplicate-source-import" ? "warning" : "error",
});
}
}
return diagnostics;
@@ -117,12 +142,15 @@ export const addWorkspaceImport = (source: string, importPath: string) => {
}
const brace = syntax.tokens.find((token) => token.kind === "LBRACE")!;
const newline = source.includes("\r\n") ? "\r\n" : "\n";
return applySourceEdits(source, [{ start: brace.end, end: brace.end,
text: `${newline} import ${JSON.stringify(importPath)};` }]);
return applySourceEdits(source, [
{ start: brace.end, end: brace.end, text: `${newline} import ${JSON.stringify(importPath)};` },
]);
};
export const validateQxImportPath = (value: string) => {
if (!/^(?:[A-Za-z0-9_-][A-Za-z0-9_.-]*\/)*[A-Za-z0-9_-][A-Za-z0-9_.-]*\.qx$/.test(value) ||
value.split("/").some((part) => part === "." || part === ".."))
if (
!/^(?:[A-Za-z0-9_-][A-Za-z0-9_.-]*\/)*[A-Za-z0-9_-][A-Za-z0-9_.-]*\.qx$/.test(value) ||
value.split("/").some((part) => part === "." || part === "..")
)
throw new Error(`Invalid repository-relative QX import path: ${value}`);
};