@zgeoff/format-codemod 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/cli/apply-diff-mode.d.ts +0 -5
- package/dist/cli/build-unified-diff.d.ts +0 -5
- package/dist/cli/expand-inputs.d.ts +0 -6
- package/dist/cli/load-format-ignore.d.ts +0 -7
- package/dist/cli/parse-cli-args.d.ts +0 -6
- package/dist/cli/print-report.d.ts +0 -5
- package/dist/cli/read-package-version.d.ts +0 -5
- package/dist/cli/try-check-file.d.ts +0 -5
- package/dist/cli/types.d.ts +0 -5
- package/dist/cli.js +10 -1
- package/dist/index.js +10 -1
- package/dist/transform/apply-edits.d.ts +0 -5
- package/dist/transform/build-edits-from-ast.d.ts +0 -3
- package/dist/transform/collect-ast-nodes.d.ts +0 -4
- package/dist/transform/collect-child-nodes.d.ts +0 -4
- package/dist/transform/collect-head-chain.d.ts +0 -7
- package/dist/transform/needs-blank-line.d.ts +0 -11
- package/dist/transform/parse-source.d.ts +0 -8
- package/dist/transform/plan-gap-edit.d.ts +0 -12
- package/dist/transform.d.ts +0 -8
- package/dist/types.d.ts +0 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,8 +38,11 @@ between two kinds takes a blank line:
|
|
|
38
38
|
- `const`/`let`/`var` declarations
|
|
39
39
|
- `using`/`await using` declarations
|
|
40
40
|
- bare calls and method calls — two distinct kinds, split by the first call in reading order:
|
|
41
|
-
`
|
|
41
|
+
`use(x).report()` opens with a bare function, `fs.writeFileSync(…)` opens with a member, and a
|
|
42
42
|
member call chained onto a bare call's result is still a bare call
|
|
43
|
+
- `expect` assertions — a statement whose first call in reading order is `expect` or an `expect.*`
|
|
44
|
+
helper (`expect(x).toBe(y)`, `expect.assertions(1)`) is its own kind, so a run of assertions stays
|
|
45
|
+
glued while the boundary with any acting statement is padded
|
|
43
46
|
- assignments and increments
|
|
44
47
|
|
|
45
48
|
Two axes overlay the kinds and pad their own boundaries:
|
|
@@ -3,9 +3,4 @@ export interface DiffOutput {
|
|
|
3
3
|
readonly message: string | null;
|
|
4
4
|
readonly stdout: string | null;
|
|
5
5
|
}
|
|
6
|
-
/**
|
|
7
|
-
* Reached only when the file needs edits. Write mode saves the file here — the
|
|
8
|
-
* one file-system effect below the entry; what to print is returned, never
|
|
9
|
-
* printed, because the entry owns the output streams.
|
|
10
|
-
*/
|
|
11
6
|
export declare function applyDiffMode(edit: FileEdit, mode: CLIMode): DiffOutput;
|
|
@@ -1,6 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A real unified diff — @@ hunk headers with context — so --dry output can be
|
|
3
|
-
* applied with patch(1). Inputs are expected to end with a newline, which
|
|
4
|
-
* TypeScript sources do and the transform preserves.
|
|
5
|
-
*/
|
|
6
1
|
export declare function buildUnifiedDiff(before: string, after: string, label: string): string;
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deduped: overlapping patterns (a `src/**` glob plus a file inside src/) must
|
|
3
|
-
* not process — or report — the same file twice. Ignore globs filter the final
|
|
4
|
-
* list uniformly, so a file is skipped whether it arrived via a directory,
|
|
5
|
-
* a glob, or an explicit path argument.
|
|
6
|
-
*/
|
|
7
1
|
export declare function expandInputs(patterns: readonly string[], ignore?: readonly string[]): Promise<string[]>;
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reads `.formatignore` from the given directory: one glob per line, blank
|
|
3
|
-
* lines and `#`-prefixed comment lines skipped. Lines share --ignore's glob
|
|
4
|
-
* semantics — this is not a gitignore dialect, so `!` negation and directory
|
|
5
|
-
* anchoring don't apply. A missing file yields an empty list, so callers
|
|
6
|
-
* merge unconditionally.
|
|
7
|
-
*/
|
|
8
1
|
export declare function loadFormatIgnore(dir: string): readonly string[];
|
|
@@ -8,10 +8,4 @@ export interface CLIArgs {
|
|
|
8
8
|
readonly ignore: readonly string[];
|
|
9
9
|
readonly inputs: readonly string[];
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* Strict parsing: an unknown flag is a usage error, not a silent no-op. That
|
|
13
|
-
* matters because the default mode writes files — a typo'd --check must never
|
|
14
|
-
* fall through to an in-place rewrite. CLIArgs is always an object, so the
|
|
15
|
-
* string (error message) return is unambiguous.
|
|
16
|
-
*/
|
|
17
11
|
export declare function parseCLIArgs(argv: readonly string[]): CLIArgs | string;
|
|
@@ -1,7 +1,2 @@
|
|
|
1
1
|
import type { FileReport } from './types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* Prints one file's outcome: the stdout payload (--dry diffs) to stdout,
|
|
4
|
-
* messages and per-file progress to stderr. Quiet drops the OK/SKIP noise but
|
|
5
|
-
* never the messages.
|
|
6
|
-
*/
|
|
7
2
|
export declare function printReport(file: string, report: FileReport, quiet: boolean): void;
|
|
@@ -1,7 +1,2 @@
|
|
|
1
1
|
import type { CLIMode, FileReport } from './types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* A failed file must fail the batch: --check would otherwise exit 0 having
|
|
4
|
-
* validated nothing, and a throw would kill the process mid-batch with the
|
|
5
|
-
* remaining files silently skipped.
|
|
6
|
-
*/
|
|
7
2
|
export declare function tryCheckFile(file: string, mode: CLIMode): FileReport;
|
package/dist/cli/types.d.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import type { TransformResult } from '../types.ts';
|
|
2
2
|
export type CLIMode = 'write' | 'check' | 'dry';
|
|
3
3
|
export type FileOutcome = 'ok' | 'changed' | 'failed' | 'skipped';
|
|
4
|
-
/**
|
|
5
|
-
* Everything the entry needs to report one file: the outcome for exit-code
|
|
6
|
-
* logic, sizes for --bench, and the text to print — modules below the entry
|
|
7
|
-
* never write to stdout/stderr themselves.
|
|
8
|
-
*/
|
|
9
4
|
export interface FileReport {
|
|
10
5
|
readonly outcome: FileOutcome;
|
|
11
6
|
readonly bytes: number;
|
package/dist/cli.js
CHANGED
|
@@ -302,10 +302,19 @@ function getStatementKind(node) {
|
|
|
302
302
|
return "declaration";
|
|
303
303
|
}
|
|
304
304
|
if (isExpressionStatementOf(node, CALL_TYPES)) {
|
|
305
|
-
return pickCallKind(node);
|
|
305
|
+
return isExpectHeaded(node) ? "expect" : pickCallKind(node);
|
|
306
306
|
}
|
|
307
307
|
return isExpressionStatementOf(node, MUTATION_TYPES) ? "mutation" : null;
|
|
308
308
|
}
|
|
309
|
+
function isExpectHeaded(node) {
|
|
310
|
+
const expression = node["expression"];
|
|
311
|
+
const callee = isASTNode(expression) ? findDeepestCallee(expression) : null;
|
|
312
|
+
if (callee === null) {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
const head = collectHeadChain(callee).at(-1);
|
|
316
|
+
return head?.type === "Identifier" && head["name"] === "expect";
|
|
317
|
+
}
|
|
309
318
|
function pickCallKind(node) {
|
|
310
319
|
const expression = node["expression"];
|
|
311
320
|
const callee = isASTNode(expression) ? findDeepestCallee(expression) : null;
|
package/dist/index.js
CHANGED
|
@@ -135,10 +135,19 @@ function getStatementKind(node) {
|
|
|
135
135
|
return "declaration";
|
|
136
136
|
}
|
|
137
137
|
if (isExpressionStatementOf(node, CALL_TYPES)) {
|
|
138
|
-
return pickCallKind(node);
|
|
138
|
+
return isExpectHeaded(node) ? "expect" : pickCallKind(node);
|
|
139
139
|
}
|
|
140
140
|
return isExpressionStatementOf(node, MUTATION_TYPES) ? "mutation" : null;
|
|
141
141
|
}
|
|
142
|
+
function isExpectHeaded(node) {
|
|
143
|
+
const expression = node["expression"];
|
|
144
|
+
const callee = isASTNode(expression) ? findDeepestCallee(expression) : null;
|
|
145
|
+
if (callee === null) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
const head = collectHeadChain(callee).at(-1);
|
|
149
|
+
return head?.type === "Identifier" && head["name"] === "expect";
|
|
150
|
+
}
|
|
142
151
|
function pickCallKind(node) {
|
|
143
152
|
const expression = node["expression"];
|
|
144
153
|
const callee = isASTNode(expression) ? findDeepestCallee(expression) : null;
|
|
@@ -1,7 +1,2 @@
|
|
|
1
1
|
import type { Edit } from '../types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* Callers must pass edits sorted last-to-first, so each splice's offsets stay
|
|
4
|
-
* valid without adjustment. Segments are collected and joined once instead of
|
|
5
|
-
* re-copying the whole string per edit.
|
|
6
|
-
*/
|
|
7
2
|
export declare function applyEdits(src: string, edits: readonly Edit[]): string;
|
|
@@ -1,9 +1,2 @@
|
|
|
1
1
|
import type { ASTNode } from '../types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* The nodes on the walk from an expression to its head, outermost first and
|
|
4
|
-
* ending at the head itself — `(await f()).prop` yields the member access,
|
|
5
|
-
* the parenthesis, the await, the call, and finally `f`. Nodes outside the
|
|
6
|
-
* walk (call arguments, ternary branches) never appear, so a scan of the
|
|
7
|
-
* chain sees only what a reader meets before the expression's first token.
|
|
8
|
-
*/
|
|
9
2
|
export declare function collectHeadChain(expression: ASTNode): ASTNode[];
|
|
@@ -1,13 +1,2 @@
|
|
|
1
1
|
import type { ASTNode } from '../types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* The "always" rules: a blank line between class members, after a var or
|
|
4
|
-
* using block before a statement of any other kind, after a directive
|
|
5
|
-
* prologue, after the last import of a block, before a return, after a
|
|
6
|
-
* function/class declaration, on both sides of a type alias or interface
|
|
7
|
-
* declaration, on both sides of a control-flow block — its closing brace
|
|
8
|
-
* ends a visual unit just like its opening keyword starts one —
|
|
9
|
-
* and at the boundary between statement kinds: bare call vs method call vs
|
|
10
|
-
* mutation, instantiation vs anything else, and awaited vs non-awaited. Any
|
|
11
|
-
* match means exactly one blank line; a pair matching no rule sits flush.
|
|
12
|
-
*/
|
|
13
2
|
export declare function needsBlankLine(container: ASTNode, prev: ASTNode, next: ASTNode): boolean;
|
|
@@ -1,10 +1,2 @@
|
|
|
1
1
|
import type { ParsedSource } from '../types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* The filename picks the dialect — `.tsx` enables JSX, anything else parses as
|
|
4
|
-
* plain TypeScript, so `.ts`-only syntax like `<string>value` assertions and
|
|
5
|
-
* un-comma'd generic arrows parse correctly. oxc reports syntax errors as a
|
|
6
|
-
* list instead of throwing; any error means node offsets can't be trusted for
|
|
7
|
-
* splicing, so the first message is returned and the caller skips the file.
|
|
8
|
-
* ParsedSource is always an object, so the string return is unambiguous.
|
|
9
|
-
*/
|
|
10
2
|
export declare function parseSource(src: string, filename: string): ParsedSource | string;
|
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
import type { ASTNode, Edit, SourceFile } from '../types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* A pair of adjacent statements in a file and the gap shape they take: one
|
|
4
|
-
* blank line between them when `pad` is set, none otherwise.
|
|
5
|
-
*/
|
|
6
2
|
export interface GapEditInput {
|
|
7
3
|
readonly file: SourceFile;
|
|
8
4
|
readonly prev: ASTNode;
|
|
9
5
|
readonly next: ASTNode;
|
|
10
6
|
readonly pad: boolean;
|
|
11
7
|
}
|
|
12
|
-
/**
|
|
13
|
-
* Plans the single whitespace splice that gives the gap between two statements
|
|
14
|
-
* its target shape, or null when the gap is already compliant or unsafe to
|
|
15
|
-
* touch. Collapsing never crosses a comment: prose between statements marks
|
|
16
|
-
* grouping the padding rules can't see, so a comment-bearing gap only ever
|
|
17
|
-
* grows. Comment positions come from the parser rather than lexical scanning,
|
|
18
|
-
* so comment-lookalike text can't mislead the classification.
|
|
19
|
-
*/
|
|
20
8
|
export declare function planGapEdit(input: GapEditInput): Edit | null;
|
package/dist/transform.d.ts
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import type { TransformResult } from './types.ts';
|
|
2
2
|
export interface TransformOptions {
|
|
3
|
-
/**
|
|
4
|
-
* Picks the parse dialect: `.tsx` enables JSX, anything else is plain
|
|
5
|
-
* TypeScript. Defaults to 'source.ts' — JSX callers must say so.
|
|
6
|
-
*/
|
|
7
3
|
readonly filename?: string;
|
|
8
4
|
}
|
|
9
|
-
/**
|
|
10
|
-
* Pure transform: source string in, edited source string out, no I/O. On a
|
|
11
|
-
* parse error the input is returned untouched alongside the error message.
|
|
12
|
-
*/
|
|
13
5
|
export declare function transform(src: string, options?: TransformOptions): TransformResult;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The fields of the oxc AST this transform reads; the index signature carries
|
|
3
|
-
* every other node property so the generic child walk can recurse untyped. The
|
|
4
|
-
* codemod never mutates the tree, so everything is readonly.
|
|
5
|
-
*/
|
|
6
1
|
export interface ASTNode {
|
|
7
2
|
readonly type: string;
|
|
8
3
|
readonly kind?: string;
|
|
@@ -21,10 +16,6 @@ export interface ParsedSource {
|
|
|
21
16
|
readonly program: ASTNode;
|
|
22
17
|
readonly comments: readonly CommentSpan[];
|
|
23
18
|
}
|
|
24
|
-
/**
|
|
25
|
-
* The raw text and its comment spans together — what gap planning needs to
|
|
26
|
-
* classify inter-statement trivia without re-lexing.
|
|
27
|
-
*/
|
|
28
19
|
export interface SourceFile {
|
|
29
20
|
readonly src: string;
|
|
30
21
|
readonly comments: readonly CommentSpan[];
|