Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
Pretty: use formatActual as default formatter (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti authored Mar 5, 2023
1 parent 3f70820 commit d07b0f1
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 29 deletions.
5 changes: 5 additions & 0 deletions .changeset/lemon-dolphins-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/schema": patch
---

Pretty: use formatActual as default formatter
2 changes: 1 addition & 1 deletion src/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ const parserFor = <A>(
const searchTree = _getSearchTree(types, as)
const ownKeys = Reflect.ownKeys(searchTree.keys)
const len = ownKeys.length
const otherwise = searchTree.otherwise
return make(I.makeSchema(ast), (input, options) => {
const es: Array<PR.ParseError> = []

Expand Down Expand Up @@ -455,7 +456,6 @@ const parserFor = <A>(
}
// if none of the schemas with at least one property with a literal value succeeded,
// proceed with those that have no literal at all
const otherwise = searchTree.otherwise
for (let i = 0; i < otherwise.length; i++) {
const t = otherwise[i].parse(input, options)
if (PR.isSuccess(t)) {
Expand Down
55 changes: 30 additions & 25 deletions src/Pretty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as O from "@effect/data/Option"
import * as RA from "@effect/data/ReadonlyArray"
import * as H from "@effect/schema/annotation/Hook"
import * as AST from "@effect/schema/AST"
import { formatActual } from "@effect/schema/formatter/Tree"
import * as I from "@effect/schema/internal/common"
import * as P from "@effect/schema/Parser"
import type { Schema } from "@effect/schema/Schema"
Expand All @@ -28,6 +29,12 @@ const getHook = AST.getAnnotation<H.Hook<Pretty<any>>>(
H.PrettyHookId
)

const toString = (ast: AST.AST) => make(I.makeSchema(ast), (a) => String(a))

const stringify = (ast: AST.AST) => make(I.makeSchema(ast), (a) => JSON.stringify(a))

const format = (ast: AST.AST) => make(I.makeSchema(ast), formatActual)

/**
* @since 1.0.0
*/
Expand All @@ -40,34 +47,31 @@ export const match: AST.Match<Pretty<any>> = {
({ handler }) => handler(...ast.typeParameters.map(go))
)
),
"Literal": (ast) =>
make(
I.makeSchema(ast),
(literal: AST.LiteralValue): string =>
typeof literal === "bigint" ?
`${literal.toString()}n` :
JSON.stringify(literal)
),
"SymbolKeyword": (ast) => make(I.makeSchema(ast), (s) => String(s)),
"BooleanKeyword": (ast) => make(I.makeSchema(ast), (s) => String(s)),
"UniqueSymbol": (ast) => make(I.makeSchema(ast), (s) => String(s)),
"TemplateLiteral": (ast) => make(I.makeSchema(ast), (s) => String(s)),
"UndefinedKeyword": (ast) => make(I.makeSchema(ast), () => "undefined"),
"VoidKeyword": (ast) => make(I.makeSchema(ast), () => "void(0)"),
"NeverKeyword": (ast) =>
make(I.makeSchema(ast), () => {
throw new Error("cannot pretty print a `never` value")
}) as any,
"UnknownKeyword": (ast) => make(I.makeSchema(ast), (a) => JSON.stringify(a, null, 2)),
"AnyKeyword": (ast) => make(I.makeSchema(ast), (a) => JSON.stringify(a, null, 2)),
"ObjectKeyword": (ast) => make(I.makeSchema(ast), (a) => JSON.stringify(a, null, 2)),
"StringKeyword": (ast) => make(I.makeSchema(ast), (s) => JSON.stringify(s)),
"NumberKeyword": (ast) =>
}),
"Literal": (ast) =>
make(
I.makeSchema(ast),
(n) => Number.isNaN(n) ? "NaN" : String(n)
(literal: AST.LiteralValue): string =>
typeof literal === "bigint" ?
`${String(literal)}n` :
JSON.stringify(literal)
),
"BigIntKeyword": (ast) => make(I.makeSchema(ast), (bi) => `${bi.toString()}n`),
"SymbolKeyword": toString,
"UniqueSymbol": toString,
"TemplateLiteral": stringify,
"UndefinedKeyword": toString,
"UnknownKeyword": format,
"AnyKeyword": format,
"ObjectKeyword": format,
"StringKeyword": stringify,
"NumberKeyword": toString,
"BooleanKeyword": toString,
"BigIntKeyword": (ast: AST.AST) => make(I.makeSchema(ast), (a) => `${String(a)}n`),
"Enums": stringify,
"Tuple": (ast, go) => {
const elements = ast.elements.map((e) => go(e.type))
const rest = pipe(ast.rest, O.map(RA.mapNonEmpty(go)))
Expand Down Expand Up @@ -127,7 +131,9 @@ export const match: AST.Match<Pretty<any>> = {
if (ps.isOptional && !Object.prototype.hasOwnProperty.call(input, name)) {
continue
}
output.push(`${prettyName(name)}: ${propertySignaturesTypes[i].pretty(input[name])}`)
output.push(
`${getPrettyPropertyKey(name)}: ${propertySignaturesTypes[i].pretty(input[name])}`
)
expectedKeys[name] = null
}
// ---------------------------------------------
Expand All @@ -141,7 +147,7 @@ export const match: AST.Match<Pretty<any>> = {
if (Object.prototype.hasOwnProperty.call(expectedKeys, key)) {
continue
}
output.push(`${prettyName(key)}: ${type.pretty(input[key])}`)
output.push(`${getPrettyPropertyKey(key)}: ${type.pretty(input[key])}`)
}
}
}
Expand All @@ -163,7 +169,6 @@ export const match: AST.Match<Pretty<any>> = {
const schema = I.lazy(f)
return make(schema, (a) => get().pretty(a))
},
"Enums": (ast) => make(I.makeSchema(ast), (sn) => JSON.stringify(sn)),
"Refinement": (ast, go) => go(ast.from),
"Transform": (ast, go) => go(ast.to)
}
Expand All @@ -176,5 +181,5 @@ const compile = AST.getCompiler(match)
*/
export const pretty = <A>(schema: Schema<A>) => (a: A): string => compile(schema.ast).pretty(a)

const prettyName = (name: PropertyKey): string =>
const getPrettyPropertyKey = (name: PropertyKey): string =>
typeof name === "string" ? JSON.stringify(name) : String(name)
2 changes: 1 addition & 1 deletion src/formatter/Tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const formatActual = (actual: unknown): string => {
return "null"
}
if (typeof actual === "number") {
return Number.isNaN(actual) ? "NaN" : String(actual)
return String(actual)
}
if (typeof actual === "bigint") {
return String(actual) + "n"
Expand Down
25 changes: 23 additions & 2 deletions test/Pretty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe.concurrent("Pretty", () => {
it("templateLiteral. a${string}b", () => {
const schema = S.templateLiteral(S.literal("a"), S.string, S.literal("b"))
const pretty = P.pretty(schema)
expect(pretty("acb")).toEqual("acb")
expect(pretty("acb")).toEqual(`"acb"`)
})

it("never", () => {
Expand All @@ -24,6 +24,13 @@ describe.concurrent("Pretty", () => {
)
})

it("unknown", () => {
const schema = S.unknown
const pretty = P.pretty(schema)
expect(pretty("a")).toEqual(`"a"`)
expect(pretty(1n)).toEqual(`1n`)
})

it("string", () => {
const schema = S.string
const pretty = P.pretty(schema)
Expand Down Expand Up @@ -324,7 +331,7 @@ describe.concurrent("Pretty", () => {
expect(pretty(["a", 1, true])).toEqual(`["a", 1, true]`)
})

it("union", () => {
it("union/ primitives", () => {
const schema = S.union(S.string, S.number)
const pretty = P.pretty(schema)
expect(pretty("a")).toEqual(
Expand All @@ -335,6 +342,20 @@ describe.concurrent("Pretty", () => {
)
})

it("union/ discriminated", () => {
const schema = S.union(
S.struct({ tag: S.literal("a"), a: S.string }),
S.struct({ tag: S.literal("b"), b: S.number })
)
const pretty = P.pretty(schema)
expect(pretty({ tag: "a", a: "-" })).toEqual(
`{ "tag": "a", "a": "-" }`
)
expect(pretty({ tag: "b", b: 1 })).toEqual(
`{ "tag": "b", "b": 1 }`
)
})

it("lazy", () => {
interface A {
readonly a: string
Expand Down

0 comments on commit d07b0f1

Please sign in to comment.