дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-08 19:02:17 +02:00
feat: add oxfmt/oxlint support for JS and TS projects (#717)
Below an oxfmt configuration (.oxfmtrc.json/.jsonc, oxfmt.config.ts/.mts) Reformat Code runs oxfmt instead of Prettier, with the same external-formatter settings; oxfmt formats whole files, so a selection formats the file with a notice. oxlint --lsp serves JS/TS/React/Vue/Svelte files below an oxlint config. Both are managed npm tools; a missing oxfmt gets the same Install prompt and error handling as Prettier, and formatter messages are translated for either tool. Co-authored-by: d0whc3r <[email protected]>
Цей коміт міститься в:
1 джерело
e2f8e8d5bc
коміт
44c603f7db
14 files changed
+246
-75
No files matched your search
@@ -118,19 +118,22 @@ async function format(
|
||||
try {
|
||||
edits = await lspRequest(() => commands.lspFormat(doc.doc, range, { ...options, onSave: opts.onSave }));
|
||||
} catch (e) {
|
||||
if (e instanceof IpcError && e.data?.type === "tool" && e.data.tool === "prettier") {
|
||||
if (e instanceof IpcError && e.data?.type === "tool" && (e.data.tool === "prettier" || e.data.tool === "oxfmt")) {
|
||||
const tool = e.data.tool;
|
||||
if (e.kind === "notFound" && e.data.missing) {
|
||||
await executeAction("tools.promptInstall", { name: "prettier", sticky: !opts.onSave });
|
||||
await executeAction("tools.promptInstall", { name: tool, sticky: !opts.onSave });
|
||||
} else if (e.kind !== "cancelled") {
|
||||
notifications().notify({
|
||||
group: "tools",
|
||||
level: "error",
|
||||
title: tx("Prettier formatting failed"),
|
||||
title: tool === "oxfmt" ? tx("oxfmt formatting failed") : tx("Prettier formatting failed"),
|
||||
body:
|
||||
e.kind === "timedOut"
|
||||
? tx("Prettier formatting timed out")
|
||||
? tool === "oxfmt"
|
||||
? tx("oxfmt formatting timed out")
|
||||
: tx("Prettier formatting timed out")
|
||||
: createElement("span", { className: styles.diagnostics }, e.message),
|
||||
key: `prettier-format-error:${doc.path}`,
|
||||
key: `${tool}-format-error:${doc.path}`,
|
||||
sticky: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
import { formatDocument } from "./format";
|
||||
import * as lsp from "./lsp";
|
||||
|
||||
const tool = { type: "tool", tool: "prettier", missing: false } as const;
|
||||
const views: EditorView[] = [];
|
||||
const viewFor = (path = "/project/file.css") => {
|
||||
const view = new EditorView({
|
||||
@@ -43,7 +42,9 @@ afterEach(() => {
|
||||
_resetI18nForTests();
|
||||
});
|
||||
|
||||
describe("external formatter errors", () => {
|
||||
describe.each(["prettier", "oxfmt"])("%s formatter errors", (name) => {
|
||||
const tool = { type: "tool", tool: name, missing: false } as const;
|
||||
const display = name === "prettier" ? "Prettier" : name;
|
||||
it("uses structured missing-tool information to request the shared install prompt", async () => {
|
||||
const prompt = vi.fn();
|
||||
const dispose = registerAction({
|
||||
@@ -54,9 +55,9 @@ describe("external formatter errors", () => {
|
||||
try {
|
||||
failWith({ kind: "notFound", message: "unrelated diagnostic", data: { ...tool, missing: true } });
|
||||
await formatDocument(viewFor());
|
||||
expect(prompt).toHaveBeenCalledWith({ name: "prettier", sticky: true });
|
||||
expect(prompt).toHaveBeenCalledWith({ name, sticky: true });
|
||||
await formatDocument(viewFor(), { explicit: false, onSave: true });
|
||||
expect(prompt).toHaveBeenLastCalledWith({ name: "prettier", sticky: false });
|
||||
expect(prompt).toHaveBeenLastCalledWith({ name, sticky: false });
|
||||
expect(useNotifications.getState().items).toHaveLength(0);
|
||||
} finally {
|
||||
dispose();
|
||||
@@ -95,7 +96,7 @@ describe("external formatter errors", () => {
|
||||
for (let i = 0; i < 3; i++) await formatDocument(view, { explicit: false, onSave: true });
|
||||
const notes = useNotifications.getState().items;
|
||||
expect(notes).toHaveLength(1);
|
||||
expect(notes[0]).toMatchObject({ sticky: false, title: "Prettier 格式化失败" });
|
||||
expect(notes[0]).toMatchObject({ sticky: false, title: `${display} 格式化失败` });
|
||||
expect(balloonTimeout(notes[0]!)).toBe(10000);
|
||||
render(<Balloons />);
|
||||
expect(screen.getByRole("alert")).toHaveTextContent(stderr);
|
||||
@@ -115,7 +116,7 @@ describe("external formatter errors", () => {
|
||||
const request = failWith({ kind: "timedOut", message: "arbitrary backend text", data: tool });
|
||||
const view = viewFor();
|
||||
await formatDocument(view);
|
||||
expect(useNotifications.getState().items[0]).toMatchObject({ body: "Prettier 格式化超时", sticky: false });
|
||||
expect(useNotifications.getState().items[0]).toMatchObject({ body: `${display} 格式化超时`, sticky: false });
|
||||
clearNotifications();
|
||||
request.mockRejectedValue(new IpcError({ kind: "cancelled", message: "cancelled", data: tool }));
|
||||
await formatDocument(view);
|
||||
|
||||
@@ -1614,16 +1614,18 @@
|
||||
"Install Missing Tool": "安装缺失的工具",
|
||||
"Prettier formatting failed": "Prettier 格式化失败",
|
||||
"Prettier formatting timed out": "Prettier 格式化超时",
|
||||
"Prettier does not support selection formatting for this language; formatted the whole file": "Prettier 不支持此语言的选区格式化,已格式化整个文件",
|
||||
"oxfmt formatting failed": "oxfmt 格式化失败",
|
||||
"oxfmt formatting timed out": "oxfmt 格式化超时",
|
||||
"{name} does not support selection formatting for this language; formatted the whole file": "{name} 不支持此语言的选区格式化,已格式化整个文件",
|
||||
"Formatting timed out": "格式化超时",
|
||||
"Prettier: Node.js is required": "Prettier:需要 Node.js",
|
||||
"{name}: Node.js is required": "{name}:需要 Node.js",
|
||||
"Formatter": "格式化工具",
|
||||
"JSON with Comments": "带注释的 JSON",
|
||||
"Unknown external formatter: {tool}": "未知的外部格式化工具:{tool}",
|
||||
"Prettier: package has no CLI entry point": "Prettier:软件包未提供命令行入口",
|
||||
"Prettier: CLI does not exist: {path}": "Prettier:命令行程序不存在:{path}",
|
||||
"Prettier: file has no directory": "Prettier:文件路径不含目录",
|
||||
"Prettier: {error}": "Prettier:{error}",
|
||||
"{name}: package has no CLI entry point": "{name}:软件包未提供命令行入口",
|
||||
"{name}: CLI does not exist: {path}": "{name}:命令行程序不存在:{path}",
|
||||
"{name}: file has no directory": "{name}:文件路径不含目录",
|
||||
"{name}: {error}": "{name}:{error}",
|
||||
"Reformat File": "重新格式化文件",
|
||||
"Reformat code": "重新格式化代码",
|
||||
"Reformat code on save": "保存时重新格式化代码",
|
||||
|
||||
Reference in new issue
Заблокувати користувача