diff --git a/packages/core/src/formatter.ts b/packages/core/src/formatter.ts index 0ee56c10390..ab2474e68d2 100644 --- a/packages/core/src/formatter.ts +++ b/packages/core/src/formatter.ts @@ -1,6 +1,6 @@ export * as Formatter from "./formatter" -import { Context, Effect, Layer, Schema } from "effect" +import { Context, Effect, Layer } from "effect" import { ChildProcess } from "effect/unstable/process" import path from "path" import { makeLocationNode } from "@opencode-ai/util/effect/app-node" @@ -11,16 +11,7 @@ import { Config } from "./config" import { Location } from "./location" import { make, type Info } from "./formatter/builtins" -export const Status = Schema.Struct({ - name: Schema.String, - extensions: Schema.Array(Schema.String), - enabled: Schema.Boolean, -}).annotate({ identifier: "FormatterStatus" }) -export type Status = typeof Status.Type - export interface Interface { - readonly init: () => Effect.Effect - readonly status: () => Effect.Effect readonly file: (filepath: string) => Effect.Effect } @@ -84,23 +75,6 @@ const layer = Layer.effect( return result }) - const init = Effect.fn("Formatter.init")(function* () { - yield* load - }) - - const status = Effect.fn("Formatter.status")(function* () { - yield* load - return yield* Effect.forEach(formatters, (formatter) => - command(formatter).pipe( - Effect.map((enabled) => ({ - name: formatter.name, - extensions: [...formatter.extensions], - enabled: enabled !== false, - })), - ), - ) - }) - const file = Effect.fn("Formatter.file")(function* (filepath: string) { yield* load const matching = formatters.filter((formatter) => @@ -143,7 +117,7 @@ const layer = Layer.effect( return false }) - return Service.of({ init, status, file }) + return Service.of({ file }) }), ) diff --git a/packages/core/test/formatter.test.ts b/packages/core/test/formatter.test.ts index fbacfb971bd..2a837e6f0db 100644 --- a/packages/core/test/formatter.test.ts +++ b/packages/core/test/formatter.test.ts @@ -56,52 +56,22 @@ function withTemp(body: (directory: string) => Effect.Effect) } describe("Formatter", () => { - it.live("status() returns empty list when no formatters are configured", () => + it.live("does not run formatters marked as disabled in config", () => withTemp((directory) => - Formatter.Service.use((formatter) => formatter.status()).pipe(Effect.provide(formatterLayer(directory))), - ), - ) - - it.live("status() returns built-in formatters when formatter is true", () => - withTemp((directory) => - Formatter.Service.use((formatter) => - Effect.gen(function* () { - const statuses = yield* formatter.status() - const gofmt = statuses.find((item) => item.name === "gofmt") - expect(gofmt).toBeDefined() - expect(gofmt?.extensions).toContain(".go") - }), - ).pipe(Effect.provide(formatterLayer(directory, true))), - ), - ) - - it.live("status() keeps built-in formatters when config object is provided", () => - withTemp((directory) => - Formatter.Service.use((formatter) => - Effect.gen(function* () { - const statuses = yield* formatter.status() - expect(statuses.find((item) => item.name === "gofmt")?.extensions).toContain(".go") - expect(statuses.find((item) => item.name === "mix")).toBeDefined() - }), - ).pipe(Effect.provide(formatterLayer(directory, { gofmt: {} }))), - ), - ) - - it.live("status() excludes formatters marked as disabled in config", () => - withTemp((directory) => - Formatter.Service.use((formatter) => - Effect.gen(function* () { - const statuses = yield* formatter.status() - expect(statuses.find((item) => item.name === "gofmt")).toBeUndefined() - expect(statuses.find((item) => item.name === "mix")).toBeDefined() - }), - ).pipe(Effect.provide(formatterLayer(directory, { gofmt: { disabled: true } }))), - ), - ) - - it.live("service initializes without error", () => - withTemp((directory) => - Formatter.Service.use((formatter) => formatter.init()).pipe(Effect.provide(formatterLayer(directory))), + Effect.gen(function* () { + const file = path.join(directory, "test.disabled") + expect(yield* Formatter.Service.use((formatter) => formatter.file(file))).toBe(false) + }).pipe( + Effect.provide( + formatterLayer(directory, { + disabled: { + disabled: true, + command: [process.execPath, "-e", "process.exit(0)", "$FILE"], + extensions: [".disabled"], + }, + }), + ), + ), ), ) @@ -115,22 +85,29 @@ describe("Formatter", () => { ), ) - it.live("status() initializes formatter state per directory", () => - Effect.acquireUseRelease( - Effect.promise(() => Promise.all([tmpdir(), tmpdir()])), - ([off, on]) => + it.live("loads formatter state per directory", () => + withTemp((off) => + withTemp((on) => Effect.gen(function* () { - const disabled = yield* Formatter.Service.use((formatter) => formatter.status()).pipe( - Effect.provide(formatterLayer(off.path, false)), + const offFile = path.join(off, "test.isolated") + const onFile = path.join(on, "test.isolated") + const disabled = yield* Formatter.Service.use((formatter) => formatter.file(offFile)).pipe( + Effect.provide(formatterLayer(off, false)), ) - const enabled = yield* Formatter.Service.use((formatter) => formatter.status()).pipe( - Effect.provide(formatterLayer(on.path, true)), + const enabled = yield* Formatter.Service.use((formatter) => formatter.file(onFile)).pipe( + Effect.provide( + formatterLayer(on, { + isolated: { + command: [process.execPath, "-e", "process.exit(0)", "$FILE"], + extensions: [".isolated"], + }, + }), + ), ) - expect(disabled).toEqual([]) - expect(enabled.find((item) => item.name === "gofmt")).toBeDefined() + expect(disabled).toBe(false) + expect(enabled).toBe(true) }), - (directories) => - Effect.promise(() => Promise.all(directories.map((tmp) => tmp[Symbol.asyncDispose]())).then(() => undefined)), + ), ), )