diff --git a/dev/configs/.changeset/pretty-dogs-film.md b/dev/configs/.changeset/pretty-dogs-film.md new file mode 100644 index 0000000000..3afd2054b1 --- /dev/null +++ b/dev/configs/.changeset/pretty-dogs-film.md @@ -0,0 +1,7 @@ +--- +"arktype": patch +--- + +Improve static parse error contextual summaries + +Thanks @Hsiwe! https://github.com/arktypeio/arktype/pull/873 diff --git a/dev/test/astUtils.test.ts b/dev/test/astUtils.test.ts new file mode 100644 index 0000000000..05e73f7b63 --- /dev/null +++ b/dev/test/astUtils.test.ts @@ -0,0 +1,20 @@ +import { describe, it } from "mocha" +import type { astToString } from "../../src/parse/ast/utils.js" +import { attest } from "../attest/main.js" + +describe("astToString", () => { + it("no parentheses if nested ast is an array", () => { + const t = {} as unknown as astToString< + [["number", "[]"], "|", "number"] + > + attest(t).typed as "'number[]|number'" + }) + it("parentheses if nested ast is an infix expression", () => { + const t = {} as unknown as astToString<[["0", "|", "1"], "|", "string"]> + attest(t).typed as "'(0|1)|string'" + }) + it('defaults to "..." if input is bad', () => { + const t = {} as unknown as astToString<["0", "///", "1"]> + attest(t).typed as "'...'" + }) +}) diff --git a/src/parse/ast/utils.ts b/src/parse/ast/utils.ts index fd6a093522..5c13501484 100644 --- a/src/parse/ast/utils.ts +++ b/src/parse/ast/utils.ts @@ -1,12 +1,26 @@ -import type { Literalable } from "../../utils/generics.js" +import type { List, Literalable } from "../../utils/generics.js" +import type { Scanner } from "../string/shift/scanner.js" +import type { InfixExpression, PostfixExpression } from "./ast.js" -export type astToString = `'${astToStringRecurse}'` +export type astToString = `'${astToStringRecurse}'` -type astToStringRecurse = ast extends [ - infer head, - ...infer tail -] - ? astToStringRecurse}`> +type astToStringRecurse = ast extends PostfixExpression< + infer operator, + infer operand +> + ? operator extends "[]" + ? `${groupAst}[]` + : never + : ast extends InfixExpression + ? operator extends "&" | "|" | "%" | Scanner.Comparator + ? `${groupAst}${operator}${groupAst}` + : never : ast extends Literalable - ? `${result}${ast extends bigint ? `${ast}n` : ast}` + ? `${ast extends bigint ? `${ast}n` : ast}` : "..." + +type groupAst = ast extends List + ? ast[1] extends "[]" + ? astToStringRecurse + : `(${astToStringRecurse})` + : astToStringRecurse