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

Commit

Permalink
replace UnionMember with Union
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti committed Dec 27, 2023
1 parent ef15330 commit b12f320
Show file tree
Hide file tree
Showing 24 changed files with 159 additions and 71 deletions.
1 change: 1 addition & 0 deletions .changeset/gentle-readers-call.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@

Refactor `ParseResult` module:

- replace `UnionMember` with `Union`
- rename `UnionMember` to `Member`
- ast `ast` field to `Member`
33 changes: 32 additions & 1 deletion docs/modules/ParseResult.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Added in v1.0.0
- [try](#try)
- [type](#type)
- [unexpected](#unexpected)
- [union](#union)
- [model](#model)
- [Forbidden (interface)](#forbidden-interface)
- [Index (interface)](#index-interface)
Expand All @@ -32,6 +33,7 @@ Added in v1.0.0
- [ParseIssue (type alias)](#parseissue-type-alias)
- [Type (interface)](#type-interface)
- [Unexpected (interface)](#unexpected-interface)
- [Union (interface)](#union-interface)
- [optimisation](#optimisation)
- [bimap](#bimap)
- [eitherOrUndefined](#eitherorundefined)
Expand Down Expand Up @@ -150,6 +152,19 @@ export declare const unexpected: (ast: Option.Option<AST.AST>) => Unexpected
Added in v1.0.0
## union
**Signature**
```ts
export declare const union: (
ast: AST.Union,
errors: readonly [Key | Type | Member, ...(Key | Type | Member)[]]
) => Union
```
Added in v1.0.0
# model
## Forbidden (interface)
Expand Down Expand Up @@ -246,7 +261,7 @@ export type ParseIssue =
// context
| Index
| Key
| Member
| Union
// primitives
| Type
| Missing
Expand Down Expand Up @@ -292,6 +307,22 @@ export interface Unexpected {

Added in v1.0.0

## Union (interface)

Error that occurs when a union has an error.

**Signature**

```ts
export interface Union {
readonly _tag: "Union"
readonly ast: AST.Union
readonly errors: ReadonlyArray.NonEmptyReadonlyArray<Member | Key | Type>
}
```

Added in v1.0.0

# optimisation

## bimap
Expand Down
12 changes: 10 additions & 2 deletions src/ArrayFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ const format = (self: ParseIssue, path: ReadonlyArray<PropertyKey> = []): Array<
return ReadonlyArray.flatMap(self.errors, (e) => format(e, [...path, self.key]))
case "Index":
return ReadonlyArray.flatMap(self.errors, (e) => format(e, [...path, self.index]))
case "Member":
return ReadonlyArray.flatMap(self.errors, (e) => format(e, path))
case "Missing":
return [{ _tag, path, message: "Missing key or index" }]
case "Forbidden":
Expand All @@ -38,6 +36,16 @@ const format = (self: ParseIssue, path: ReadonlyArray<PropertyKey> = []): Array<
message: "Unexpected" +
(Option.isSome(self.ast) ? `, expected ${formatExpected(self.ast.value)}` : "")
}]
case "Union":
return ReadonlyArray.flatMap(self.errors, (e) => {
switch (e._tag) {
case "Key":
case "Type":
return format(e, path)
case "Member":
return ReadonlyArray.flatMap(e.errors, (e) => format(e, path))
}
})
}
}

Expand Down
23 changes: 22 additions & 1 deletion src/ParseResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export type ParseIssue =
// context
| Index
| Key
| Member
| Union
// primitives
| Type
| Missing
Expand Down Expand Up @@ -195,6 +195,27 @@ export const unexpected = (
ast: Option.Option<AST.AST>
): Unexpected => ({ _tag: "Unexpected", ast })

/**
* Error that occurs when a union has an error.
*
* @category model
* @since 1.0.0
*/
export interface Union {
readonly _tag: "Union"
readonly ast: AST.Union
readonly errors: ReadonlyArray.NonEmptyReadonlyArray<Member | Key | Type>
}

/**
* @category constructors
* @since 1.0.0
*/
export const union = (
ast: AST.Union,
errors: ReadonlyArray.NonEmptyReadonlyArray<Member | Key | Type>
): Union => ({ _tag: "Union", ast, errors })

/**
* Error that occurs when a member in a union has an error.
*
Expand Down
4 changes: 2 additions & 2 deletions src/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser<any, any> => {
map.set(ast.types[i], goMemo(ast.types[i], isDecoding))
}
return (input, options) => {
const es: Array<[number, ParseResult.ParseIssue]> = []
const es: Array<[number, ParseResult.Member | ParseResult.Key | ParseResult.Type]> = []
let stepKey = 0
let candidates: Array<AST.AST> = []
if (len > 0) {
Expand Down Expand Up @@ -885,7 +885,7 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser<any, any> => {
// ---------------------------------------------
const computeResult = (es: State["es"]) =>
ReadonlyArray.isNonEmptyArray(es) ?
ParseResult.fail(sortByIndex(es)) :
ParseResult.fail(ParseResult.union(ast, sortByIndex(es))) :
// this should never happen
ParseResult.fail(ParseResult.type(AST.neverKeyword, input))

Expand Down
16 changes: 12 additions & 4 deletions src/TreeFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export const formatExpected = (ast: AST.AST): string => {
}

const isCollapsible = (es: Forest<string>, errors: NonEmptyReadonlyArray<ParseIssue>): boolean =>
es.length === 1 && es[0].forest.length !== 0 && errors[0]._tag !== "Member"
es.length === 1 && es[0].forest.length !== 0 && errors[0]._tag !== "Union"

/** @internal */
export const getMessage = (e: Type) =>
Expand Down Expand Up @@ -174,10 +174,18 @@ const go = (e: ParseIssue): Tree<string> => {
}
case "Missing":
return make("is missing")
case "Member":
case "Union":
return make(
`union member: ${formatExpected(e.ast)}`,
e.errors.map(go)
`Union (${e.ast.types.length} members): ` + formatExpected(e.ast),
e.errors.map((e) => {
switch (e._tag) {
case "Key":
case "Type":
return go(e)
case "Member":
return make(`Union member: ${formatExpected(e.ast)}`, e.errors.map(go))
}
})
)
}
}
2 changes: 1 addition & 1 deletion test/Cause/cause.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe("Cause/cause", () => {
await Util.expectParseFailure(
schema,
{ _tag: "Parallel", left: { _tag: "Fail" }, right: { _tag: "Interrupt" } },
`union member: /left union member: /error is missing`
`Union member: /left Union member: /error is missing`
)
})

Expand Down
4 changes: 2 additions & 2 deletions test/Cause/causeFromSelf.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ describe("Cause/causeFromSelf", () => {
await Util.expectParseFailure(
schema,
Cause.fail("a"),
`union member: /error Expected <anonymous transformation string <-> number>, actual "a"`
`Union member: /error Expected <anonymous transformation string <-> number>, actual "a"`
)
await Util.expectParseFailure(
schema,
Cause.parallel(Cause.die("error"), Cause.fail("a")),
`union member: /right union member: /error Expected <anonymous transformation string <-> number>, actual "a"`
`Union member: /right Union member: /error Expected <anonymous transformation string <-> number>, actual "a"`
)
})

Expand Down
2 changes: 1 addition & 1 deletion test/FiberId/FiberId.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe("FiberId", () => {
await Util.expectParseFailure(
schema,
{ _tag: "Composite", left: { _tag: "None" }, right: { _tag: "-" } },
`union member: /right /_tag Expected "Composite" or "Runtime" or "None", actual "-"`
`Union member: /right /_tag Expected "Composite" or "Runtime" or "None", actual "-"`
)
})
})
4 changes: 2 additions & 2 deletions test/Option/optionFromNullable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ describe("Option/optionFromNullable", () => {
await Util.expectParseFailure(
schema,
undefined,
`union member: Expected null, actual undefined, union member: Expected string, actual undefined`
`Union member: Expected null, actual undefined, Union member: Expected string, actual undefined`
)
await Util.expectParseFailure(
schema,
{},
`union member: Expected null, actual {}, union member: Expected string, actual {}`
`Union member: Expected null, actual {}, Union member: Expected string, actual {}`
)
})

Expand Down
2 changes: 1 addition & 1 deletion test/Option/optionFromNullish.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe("Option/optionFromNullish", () => {
await Util.expectParseFailure(
schema,
{},
`union member: Expected null, actual {}, union member: Expected undefined, actual {}, union member: Expected string, actual {}`
`Union member: Expected null, actual {}, Union member: Expected undefined, actual {}, Union member: Expected string, actual {}`
)
})

Expand Down
2 changes: 1 addition & 1 deletion test/Schema/Forbidden.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe("Schema/Forbidden", () => {
expectForbidden(
S.union(S.string, S.string.pipe(S.minLength(2))),
"a",
`union member: is forbidden, union member: is forbidden`
`Union member: is forbidden, Union member: is forbidden`
)
})

Expand Down
9 changes: 5 additions & 4 deletions test/Schema/literal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ describe("Schema/literal", () => {
schema,
null,
`error(s) found
├─ union member: 1
│ └─ Expected 1, actual null
└─ union member: "a"
└─ Expected "a", actual null`
└─ Union (2 members): 1 or "a"
├─ Union member: 1
│ └─ Expected 1, actual null
└─ Union member: "a"
└─ Expected "a", actual null`
)
})
})
Expand Down
6 changes: 3 additions & 3 deletions test/Schema/onExcess.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe("Schema/onExcess", () => {
await Util.expectParseFailure(
schema,
{ a: 1, b: "b", c: true },
`union member: /c is unexpected, expected "a" or "b", union member: /b is unexpected, expected "a"`,
`Union member: /c is unexpected, expected "a" or "b", Union member: /b is unexpected, expected "a"`,
Util.onExcessPropertyError
)
await Util.expectEncodeSuccess(
Expand All @@ -52,12 +52,12 @@ describe("Schema/onExcess", () => {
await Util.expectParseFailure(
schema,
[1, "b", true],
`union member: /2 is unexpected, union member: /1 is unexpected`
`Union member: /2 is unexpected, Union member: /1 is unexpected`
)
await Util.expectParseFailure(
schema,
[1, "b", true],
`union member: /2 is unexpected, union member: /1 is unexpected`,
`Union member: /2 is unexpected, Union member: /1 is unexpected`,
Util.onExcessPropertyError
)
await Util.expectEncodeSuccess(
Expand Down
14 changes: 7 additions & 7 deletions test/Schema/optional.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe("optional APIs", () => {
await Util.expectParseFailure(
schema,
{ a: "a" },
`/a union member: Expected undefined, actual "a", union member: Expected <anonymous transformation string <-> number>, actual "a"`
`/a Union member: Expected undefined, actual "a", Union member: Expected <anonymous transformation string <-> number>, actual "a"`
)

await Util.expectEncodeSuccess(schema, {}, {})
Expand Down Expand Up @@ -77,7 +77,7 @@ describe("optional APIs", () => {
{
a: "a"
},
`/a union member: Expected null, actual "a", union member: Expected <anonymous transformation string <-> number>, actual "a"`
`/a Union member: Expected null, actual "a", Union member: Expected <anonymous transformation string <-> number>, actual "a"`
)

await Util.expectEncodeSuccess(schema, { a: O.some(1) }, { a: "1" })
Expand All @@ -96,7 +96,7 @@ describe("optional APIs", () => {
{
a: "a"
},
`/a union member: Expected undefined, actual "a", union member: Expected <anonymous transformation string <-> number>, actual "a"`
`/a Union member: Expected undefined, actual "a", Union member: Expected <anonymous transformation string <-> number>, actual "a"`
)

await Util.expectEncodeSuccess(schema, { a: O.some(1) }, { a: "1" })
Expand All @@ -118,7 +118,7 @@ describe("optional APIs", () => {
{
a: "a"
},
`/a union member: Expected null, actual "a", union member: Expected undefined, actual "a", union member: Expected <anonymous transformation string <-> number>, actual "a"`
`/a Union member: Expected null, actual "a", Union member: Expected undefined, actual "a", Union member: Expected <anonymous transformation string <-> number>, actual "a"`
)

await Util.expectEncodeSuccess(schema, { a: O.some(1) }, { a: "1" })
Expand Down Expand Up @@ -155,7 +155,7 @@ describe("optional APIs", () => {
await Util.expectParseFailure(
schema,
{ a: "a" },
`/a union member: Expected undefined, actual "a", union member: Expected <anonymous transformation string <-> number>, actual "a"`
`/a Union member: Expected undefined, actual "a", Union member: Expected <anonymous transformation string <-> number>, actual "a"`
)

await Util.expectEncodeSuccess(schema, { a: 1 }, { a: "1" })
Expand All @@ -175,7 +175,7 @@ describe("optional APIs", () => {
await Util.expectParseFailure(
schema,
{ a: "a" },
`/a union member: Expected null, actual "a", union member: Expected undefined, actual "a", union member: Expected <anonymous transformation string <-> number>, actual "a"`
`/a Union member: Expected null, actual "a", Union member: Expected undefined, actual "a", Union member: Expected <anonymous transformation string <-> number>, actual "a"`
)

await Util.expectEncodeSuccess(schema, { a: 1 }, { a: "1" })
Expand All @@ -194,7 +194,7 @@ describe("optional APIs", () => {
await Util.expectParseFailure(
schema,
{ a: "a" },
`/a union member: Expected null, actual "a", union member: Expected <anonymous transformation string <-> number>, actual "a"`
`/a Union member: Expected null, actual "a", Union member: Expected <anonymous transformation string <-> number>, actual "a"`
)

await Util.expectEncodeSuccess(schema, { a: 1 }, { a: "1" })
Expand Down
Loading

0 comments on commit b12f320

Please sign in to comment.