Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/rstack/src/fmt/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ const runFmtCLI = async (args: string[]): Promise<void> => {
const result = await runFmtFiles({
files,
mode,
cache: false,
maxWorkers,
});

Expand Down
49 changes: 0 additions & 49 deletions packages/rstack/src/fmt/format.ts

This file was deleted.

25 changes: 0 additions & 25 deletions packages/rstack/src/fmt/parser.ts

This file was deleted.

18 changes: 9 additions & 9 deletions packages/rstack/src/fmt/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import type {
FmtFileRequest,
FmtFileResult,
FmtRunResult,
FmtWorkerFileResult,
RunFmtFilesOptions,
} from './types.ts';
import type { FmtWorkerPool } from './workerPool.ts';

/** Formats one file and reports whether its contents differ. */
type FormatFile = (file: FmtFileRequest, shouldWrite: boolean) => Promise<FmtWorkerFileResult>;
type FormatFile = FmtWorkerPool['formatFile'];

/** Converts a formatter outcome into the shared per-file result. */
const runFmtFile = async (
Expand Down Expand Up @@ -39,22 +39,22 @@ const runFmtFile = async (
}
};

/** Processes files in workers while preserving input order. */
const runFmtFilesWithWorkers = async (
/** Processes files in a worker pool while preserving input order. */
const runFmtFilesInWorkerPool = async (
files: FmtFileRequest[],
shouldWrite: boolean,
maxWorkers?: number,
): Promise<FmtFileResult[]> => {
const { createFmtWorker } = await import('./parallel.ts');
const worker = await createFmtWorker(files.length, maxWorkers);
const { createFmtWorkerPool } = await import('./workerPool.ts');
const workerPool = await createFmtWorkerPool(files.length, maxWorkers);

try {
const results = await Promise.all(
files.map((file) => runFmtFile(file, shouldWrite, worker.formatFile)),
files.map((file) => runFmtFile(file, shouldWrite, workerPool.formatFile)),
);
return results.filter((result): result is FmtFileResult => result !== undefined);
} finally {
worker.terminate();
workerPool.terminate();
}
};

Expand Down Expand Up @@ -83,7 +83,7 @@ const runFmtFiles = async ({
const startTime = performance.now();
const shouldWrite = mode === 'write';
const results =
files.length === 0 ? [] : await runFmtFilesWithWorkers(files, shouldWrite, maxWorkers);
files.length === 0 ? [] : await runFmtFilesInWorkerPool(files, shouldWrite, maxWorkers);

return {
files: results,
Expand Down
28 changes: 0 additions & 28 deletions packages/rstack/src/fmt/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@ interface ResolvedFmtConfig {
ignorePatterns: string[];
}

interface FormatTextOptions {
/** File path used to resolve per-file options and infer the parser. */
filePath: string;
/** Cursor offset in the source to preserve across formatting. */
cursorOffset?: number;
/** Resolved project config used to derive per-file options. */
config: ResolvedFmtConfig;
}

interface DiscoverFmtFilesOptions {
/** Absolute directory used to resolve input paths. */
cwd: string;
Expand All @@ -70,7 +61,6 @@ interface FmtFileRequest {
options: ResolvedFmtOptions & Required<Pick<PrettierOptions, 'filepath'>>;
}

type FmtWorkerFileResult = 'changed' | 'unchanged' | 'unsupported';
type FmtMode = 'write' | 'check' | 'list-different';
type FmtExitCode = 0 | 1 | 2;

Expand All @@ -79,8 +69,6 @@ interface RunFmtFilesOptions {
files: FmtFileRequest[];
/** Whether to write changes or only report them. */
mode: FmtMode;
/** Persistent cache support is added in a later implementation step. */
cache: false;
/** Maximum number of formatting workers. */
maxWorkers?: number;
}
Expand All @@ -107,19 +95,6 @@ interface FmtRunResult {
durationMs: number;
}

interface FormattedTextResult {
status: 'formatted';
formatted: string;
cursorOffset?: number;
}

interface SkippedTextResult {
status: 'skipped';
reason: 'unsupported';
}

type FormatTextResult = FormattedTextResult | SkippedTextResult;

export type {
DiscoverFmtFilesOptions,
FmtConfig,
Expand All @@ -130,9 +105,6 @@ export type {
FmtMode,
FmtPluginSpecifier,
FmtRunResult,
FmtWorkerFileResult,
FormatTextOptions,
FormatTextResult,
ResolvedFmtConfig,
ResolvedFmtOptions,
RunFmtFilesOptions,
Expand Down
35 changes: 31 additions & 4 deletions packages/rstack/src/fmt/worker.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,37 @@
// Derived from @prettier/cli, see THIRD_PARTY_NOTICES.md

import { readFileSync, writeFileSync } from 'node:fs';
import { format } from 'prettier';
import { resolveFmtParser } from './parser.ts';
import {
format,
getFileInfo,
type FileInfoOptions,
type Options as PrettierOptions,
} from 'prettier';
import { getPrettierPlugins } from './prettierPlugins.ts';
import type { FmtFileRequest, FmtWorkerFileResult } from './types.ts';
import type { FmtFileRequest } from './types.ts';

type PrettierPlugins = NonNullable<PrettierOptions['plugins']>;
type FormatFileResult = 'changed' | 'unchanged' | 'unsupported';

const fileInfoOptions = {
ignorePath: [],
resolveConfig: false,
withNodeModules: true,
} satisfies FileInfoOptions;

/** Uses the configured parser or infers one without loading Prettier config. */
const resolveFmtParser = async (
filePath: string,
options: PrettierOptions,
plugins: PrettierPlugins,
): Promise<PrettierOptions['parser'] | null> =>
options.parser ??
(
await getFileInfo(filePath, {
...fileInfoOptions,
plugins,
})
).inferredParser;

/**
* Use synchronous direct I/O inside the dedicated worker to avoid libuv
Expand All @@ -13,7 +40,7 @@ import type { FmtFileRequest, FmtWorkerFileResult } from './types.ts';
const formatFile = async (
{ path, options }: FmtFileRequest,
shouldWrite: boolean,
): Promise<FmtWorkerFileResult> => {
): Promise<FormatFileResult> => {
const plugins = await getPrettierPlugins(options);
const parser = await resolveFmtParser(path, options, plugins);
if (!parser) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import WorkTank from 'worktank';

type FmtWorkerMethods = typeof import('./worker.ts');

interface FmtWorker {
interface FmtWorkerPool {
formatFile: FmtWorkerMethods['formatFile'];
terminate: () => void;
}
Expand All @@ -22,7 +22,10 @@ const getFmtWorkerUrl = (): URL => {
};

/** Creates and starts every worker before formatting can begin. */
const createFmtWorker = async (fileCount: number, maxWorkers?: number): Promise<FmtWorker> => {
const createFmtWorkerPool = async (
fileCount: number,
maxWorkers?: number,
): Promise<FmtWorkerPool> => {
const workerCount = getFmtWorkerCount(fileCount, maxWorkers);
const pool = new WorkTank<FmtWorkerMethods>({
pool: {
Expand Down Expand Up @@ -51,4 +54,5 @@ const createFmtWorker = async (fileCount: number, maxWorkers?: number): Promise<
};
};

export { createFmtWorker, getFmtWorkerCount };
export { createFmtWorkerPool, getFmtWorkerCount };
export type { FmtWorkerPool };
Loading