@effect/schema
Advanced tools
Comparing version 0.72.2 to 0.72.3
@@ -30,4 +30,4 @@ "use strict"; | ||
*/ | ||
const arbitrary = handler => self => self.annotations({ | ||
[ArbitraryHookId]: handler | ||
const arbitrary = annotation => self => self.annotations({ | ||
[ArbitraryHookId]: annotation | ||
}); | ||
@@ -41,3 +41,5 @@ /** | ||
exports.arbitrary = arbitrary; | ||
const makeLazy = schema => go(schema.ast, {}, []); | ||
const makeLazy = schema => go(schema.ast, { | ||
maxDepth: 2 | ||
}, []); | ||
/** | ||
@@ -52,26 +54,38 @@ * Returns a fast-check Arbitrary for the `A` type of the provided schema. | ||
exports.make = make; | ||
const depthSize = 1; | ||
const record = (fc, key, value, options) => { | ||
return (options.isSuspend ? fc.oneof({ | ||
depthSize | ||
}, fc.constant([]), fc.array(fc.tuple(key, value), { | ||
minLength: 1, | ||
maxLength: 2 | ||
})) : fc.array(fc.tuple(key, value))).map(tuples => { | ||
const out = {}; | ||
for (const [k, v] of tuples) { | ||
out[k] = v; | ||
} | ||
return out; | ||
}); | ||
}; | ||
const getHook = /*#__PURE__*/AST.getAnnotation(ArbitraryHookId); | ||
const getRefinementFromArbitrary = (ast, options, path) => { | ||
const constraints = combineConstraints(options.constraints, getConstraints(ast)); | ||
const getRefinementFromArbitrary = (ast, ctx, path) => { | ||
const constraints = combineConstraints(ctx.constraints, getConstraints(ast)); | ||
return go(ast.from, constraints ? { | ||
...options, | ||
...ctx, | ||
constraints | ||
} : options, path); | ||
} : ctx, path); | ||
}; | ||
const go = (ast, options, path) => { | ||
const getSuspendedContext = (ctx, ast) => { | ||
if (ctx.depthIdentifier !== undefined) { | ||
return ctx; | ||
} | ||
const depthIdentifier = AST.getIdentifierAnnotation(ast).pipe(Option.orElse(() => AST.getIdentifierAnnotation(ast.f())), Option.getOrElse(() => "SuspendDefaultDepthIdentifier")); | ||
return { | ||
...ctx, | ||
depthIdentifier | ||
}; | ||
}; | ||
const getSuspendedArray = (fc, depthIdentifier, maxDepth, item, constraints) => { | ||
let minLength = 1; | ||
let maxLength = 2; | ||
if (constraints && constraints.minLength !== undefined && constraints.minLength > minLength) { | ||
minLength = constraints.minLength; | ||
if (minLength > maxLength) { | ||
maxLength = minLength; | ||
} | ||
} | ||
return fc.oneof({ | ||
maxDepth, | ||
depthIdentifier | ||
}, fc.constant([]), fc.array(item, { | ||
minLength, | ||
maxLength | ||
})); | ||
}; | ||
const go = (ast, ctx, path) => { | ||
const hook = getHook(ast); | ||
@@ -81,7 +95,7 @@ if (Option.isSome(hook)) { | ||
case "Declaration": | ||
return hook.value(...ast.typeParameters.map(p => go(p, options, path))); | ||
return hook.value(...ast.typeParameters.map(p => go(p, ctx, path)), ctx); | ||
case "Refinement": | ||
return hook.value(getRefinementFromArbitrary(ast, options, path)); | ||
return hook.value(getRefinementFromArbitrary(ast, ctx, path), ctx); | ||
default: | ||
return hook.value(); | ||
return hook.value(ctx); | ||
} | ||
@@ -110,6 +124,6 @@ } | ||
return fc => { | ||
if (options.constraints) { | ||
switch (options.constraints._tag) { | ||
if (ctx.constraints) { | ||
switch (ctx.constraints._tag) { | ||
case "StringConstraints": | ||
return fc.string(options.constraints.constraints); | ||
return fc.string(ctx.constraints.constraints); | ||
} | ||
@@ -121,8 +135,8 @@ } | ||
return fc => { | ||
if (options.constraints) { | ||
switch (options.constraints._tag) { | ||
if (ctx.constraints) { | ||
switch (ctx.constraints._tag) { | ||
case "NumberConstraints": | ||
return fc.float(options.constraints.constraints); | ||
return fc.float(ctx.constraints.constraints); | ||
case "IntegerConstraints": | ||
return fc.integer(options.constraints.constraints); | ||
return fc.integer(ctx.constraints.constraints); | ||
} | ||
@@ -136,6 +150,6 @@ } | ||
return fc => { | ||
if (options.constraints) { | ||
switch (options.constraints._tag) { | ||
if (ctx.constraints) { | ||
switch (ctx.constraints._tag) { | ||
case "BigIntConstraints": | ||
return fc.bigInt(options.constraints.constraints); | ||
return fc.bigInt(ctx.constraints.constraints); | ||
} | ||
@@ -176,3 +190,3 @@ } | ||
for (const element of ast.elements) { | ||
elements.push(go(element.type, options, path.concat(i++))); | ||
elements.push(go(element.type, ctx, path.concat(i++))); | ||
if (element.isOptional) { | ||
@@ -182,3 +196,3 @@ hasOptionals = true; | ||
} | ||
const rest = ast.rest.map(annotatedAST => go(annotatedAST.type, options, path)); | ||
const rest = ast.rest.map(annotatedAST => go(annotatedAST.type, ctx, path)); | ||
return fc => { | ||
@@ -205,17 +219,6 @@ // --------------------------------------------- | ||
const [head, ...tail] = rest; | ||
const arb = head(fc); | ||
const constraints = options.constraints; | ||
const item = head(fc); | ||
const constraints = ctx.constraints && ctx.constraints._tag === "ArrayConstraints" ? ctx.constraints.constraints : undefined; | ||
output = output.chain(as => { | ||
let out = fc.array(arb); | ||
if (options.isSuspend) { | ||
out = fc.oneof({ | ||
depthSize | ||
}, fc.constant([]), fc.array(arb, { | ||
minLength: 1, | ||
maxLength: 2 | ||
})); | ||
} else if (constraints && constraints._tag === "ArrayConstraints") { | ||
out = fc.array(arb, constraints.constraints); | ||
} | ||
return out.map(rest => [...as, ...rest]); | ||
return (ctx.depthIdentifier !== undefined ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, constraints) : fc.array(item, constraints)).map(rest => [...as, ...rest]); | ||
}); | ||
@@ -234,4 +237,4 @@ // --------------------------------------------- | ||
{ | ||
const propertySignaturesTypes = ast.propertySignatures.map(ps => go(ps.type, options, path.concat(ps.name))); | ||
const indexSignatures = ast.indexSignatures.map(is => [go(is.parameter, options, path), go(is.type, options, path)]); | ||
const propertySignaturesTypes = ast.propertySignatures.map(ps => go(ps.type, ctx, path.concat(ps.name))); | ||
const indexSignatures = ast.indexSignatures.map(is => [go(is.parameter, ctx, path), go(is.type, ctx, path)]); | ||
return fc => { | ||
@@ -258,7 +261,9 @@ const arbs = {}; | ||
for (let i = 0; i < indexSignatures.length; i++) { | ||
const parameter = indexSignatures[i][0](fc); | ||
const type = indexSignatures[i][1](fc); | ||
const key = indexSignatures[i][0](fc); | ||
const value = indexSignatures[i][1](fc); | ||
output = output.chain(o => { | ||
return record(fc, parameter, type, options).map(d => ({ | ||
...d, | ||
const item = fc.tuple(key, value); | ||
const arr = ctx.depthIdentifier !== undefined ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item) : fc.array(item); | ||
return arr.map(tuples => ({ | ||
...Object.fromEntries(tuples), | ||
...o | ||
@@ -273,6 +278,4 @@ })); | ||
{ | ||
const types = ast.types.map(t => go(t, options, path)); | ||
return fc => fc.oneof({ | ||
depthSize | ||
}, ...types.map(arb => arb(fc))); | ||
const types = ast.types.map(member => go(member, ctx, path)); | ||
return fc => fc.oneof(...types.map(arb => arb(fc))); | ||
} | ||
@@ -288,3 +291,3 @@ case "Enums": | ||
{ | ||
const from = getRefinementFromArbitrary(ast, options, path); | ||
const from = getRefinementFromArbitrary(ast, ctx, path); | ||
return fc => from(fc).filter(a => Option.isNone(ast.filter(a, AST.defaultParseOption, ast))); | ||
@@ -294,10 +297,9 @@ } | ||
{ | ||
const get = util_.memoizeThunk(() => go(ast.f(), { | ||
...options, | ||
isSuspend: true | ||
}, path)); | ||
const get = util_.memoizeThunk(() => { | ||
return go(ast.f(), getSuspendedContext(ctx, ast), path); | ||
}); | ||
return fc => fc.constant(null).chain(() => get()(fc)); | ||
} | ||
case "Transformation": | ||
return go(ast.to, options, path); | ||
return go(ast.to, ctx, path); | ||
} | ||
@@ -304,0 +306,0 @@ }; |
@@ -24,6 +24,19 @@ /** | ||
/** | ||
* @category hooks | ||
* @since 0.72.3 | ||
*/ | ||
export interface GenerationContext { | ||
readonly depthIdentifier?: string; | ||
readonly maxDepth: number; | ||
} | ||
/** | ||
* @category hooks | ||
* @since 0.72.3 | ||
*/ | ||
export type ArbitraryAnnotation<A> = (...args: [...ReadonlyArray<LazyArbitrary<any>>, GenerationContext]) => LazyArbitrary<A>; | ||
/** | ||
* @category annotations | ||
* @since 0.67.0 | ||
*/ | ||
export declare const arbitrary: <A>(handler: (...args: ReadonlyArray<LazyArbitrary<any>>) => LazyArbitrary<A>) => <I, R>(self: Schema.Schema<A, I, R>) => Schema.Schema<A, I, R>; | ||
export declare const arbitrary: <A>(annotation: ArbitraryAnnotation<A>) => <I, R>(self: Schema.Schema<A, I, R>) => Schema.Schema<A, I, R>; | ||
/** | ||
@@ -30,0 +43,0 @@ * Returns a LazyArbitrary for the `A` type of the provided schema. |
@@ -21,4 +21,4 @@ /** | ||
*/ | ||
export const arbitrary = handler => self => self.annotations({ | ||
[ArbitraryHookId]: handler | ||
export const arbitrary = annotation => self => self.annotations({ | ||
[ArbitraryHookId]: annotation | ||
}); | ||
@@ -31,3 +31,5 @@ /** | ||
*/ | ||
export const makeLazy = schema => go(schema.ast, {}, []); | ||
export const makeLazy = schema => go(schema.ast, { | ||
maxDepth: 2 | ||
}, []); | ||
/** | ||
@@ -40,26 +42,38 @@ * Returns a fast-check Arbitrary for the `A` type of the provided schema. | ||
export const make = schema => makeLazy(schema)(FastCheck); | ||
const depthSize = 1; | ||
const record = (fc, key, value, options) => { | ||
return (options.isSuspend ? fc.oneof({ | ||
depthSize | ||
}, fc.constant([]), fc.array(fc.tuple(key, value), { | ||
minLength: 1, | ||
maxLength: 2 | ||
})) : fc.array(fc.tuple(key, value))).map(tuples => { | ||
const out = {}; | ||
for (const [k, v] of tuples) { | ||
out[k] = v; | ||
} | ||
return out; | ||
}); | ||
}; | ||
const getHook = /*#__PURE__*/AST.getAnnotation(ArbitraryHookId); | ||
const getRefinementFromArbitrary = (ast, options, path) => { | ||
const constraints = combineConstraints(options.constraints, getConstraints(ast)); | ||
const getRefinementFromArbitrary = (ast, ctx, path) => { | ||
const constraints = combineConstraints(ctx.constraints, getConstraints(ast)); | ||
return go(ast.from, constraints ? { | ||
...options, | ||
...ctx, | ||
constraints | ||
} : options, path); | ||
} : ctx, path); | ||
}; | ||
const go = (ast, options, path) => { | ||
const getSuspendedContext = (ctx, ast) => { | ||
if (ctx.depthIdentifier !== undefined) { | ||
return ctx; | ||
} | ||
const depthIdentifier = AST.getIdentifierAnnotation(ast).pipe(Option.orElse(() => AST.getIdentifierAnnotation(ast.f())), Option.getOrElse(() => "SuspendDefaultDepthIdentifier")); | ||
return { | ||
...ctx, | ||
depthIdentifier | ||
}; | ||
}; | ||
const getSuspendedArray = (fc, depthIdentifier, maxDepth, item, constraints) => { | ||
let minLength = 1; | ||
let maxLength = 2; | ||
if (constraints && constraints.minLength !== undefined && constraints.minLength > minLength) { | ||
minLength = constraints.minLength; | ||
if (minLength > maxLength) { | ||
maxLength = minLength; | ||
} | ||
} | ||
return fc.oneof({ | ||
maxDepth, | ||
depthIdentifier | ||
}, fc.constant([]), fc.array(item, { | ||
minLength, | ||
maxLength | ||
})); | ||
}; | ||
const go = (ast, ctx, path) => { | ||
const hook = getHook(ast); | ||
@@ -69,7 +83,7 @@ if (Option.isSome(hook)) { | ||
case "Declaration": | ||
return hook.value(...ast.typeParameters.map(p => go(p, options, path))); | ||
return hook.value(...ast.typeParameters.map(p => go(p, ctx, path)), ctx); | ||
case "Refinement": | ||
return hook.value(getRefinementFromArbitrary(ast, options, path)); | ||
return hook.value(getRefinementFromArbitrary(ast, ctx, path), ctx); | ||
default: | ||
return hook.value(); | ||
return hook.value(ctx); | ||
} | ||
@@ -98,6 +112,6 @@ } | ||
return fc => { | ||
if (options.constraints) { | ||
switch (options.constraints._tag) { | ||
if (ctx.constraints) { | ||
switch (ctx.constraints._tag) { | ||
case "StringConstraints": | ||
return fc.string(options.constraints.constraints); | ||
return fc.string(ctx.constraints.constraints); | ||
} | ||
@@ -109,8 +123,8 @@ } | ||
return fc => { | ||
if (options.constraints) { | ||
switch (options.constraints._tag) { | ||
if (ctx.constraints) { | ||
switch (ctx.constraints._tag) { | ||
case "NumberConstraints": | ||
return fc.float(options.constraints.constraints); | ||
return fc.float(ctx.constraints.constraints); | ||
case "IntegerConstraints": | ||
return fc.integer(options.constraints.constraints); | ||
return fc.integer(ctx.constraints.constraints); | ||
} | ||
@@ -124,6 +138,6 @@ } | ||
return fc => { | ||
if (options.constraints) { | ||
switch (options.constraints._tag) { | ||
if (ctx.constraints) { | ||
switch (ctx.constraints._tag) { | ||
case "BigIntConstraints": | ||
return fc.bigInt(options.constraints.constraints); | ||
return fc.bigInt(ctx.constraints.constraints); | ||
} | ||
@@ -164,3 +178,3 @@ } | ||
for (const element of ast.elements) { | ||
elements.push(go(element.type, options, path.concat(i++))); | ||
elements.push(go(element.type, ctx, path.concat(i++))); | ||
if (element.isOptional) { | ||
@@ -170,3 +184,3 @@ hasOptionals = true; | ||
} | ||
const rest = ast.rest.map(annotatedAST => go(annotatedAST.type, options, path)); | ||
const rest = ast.rest.map(annotatedAST => go(annotatedAST.type, ctx, path)); | ||
return fc => { | ||
@@ -193,17 +207,6 @@ // --------------------------------------------- | ||
const [head, ...tail] = rest; | ||
const arb = head(fc); | ||
const constraints = options.constraints; | ||
const item = head(fc); | ||
const constraints = ctx.constraints && ctx.constraints._tag === "ArrayConstraints" ? ctx.constraints.constraints : undefined; | ||
output = output.chain(as => { | ||
let out = fc.array(arb); | ||
if (options.isSuspend) { | ||
out = fc.oneof({ | ||
depthSize | ||
}, fc.constant([]), fc.array(arb, { | ||
minLength: 1, | ||
maxLength: 2 | ||
})); | ||
} else if (constraints && constraints._tag === "ArrayConstraints") { | ||
out = fc.array(arb, constraints.constraints); | ||
} | ||
return out.map(rest => [...as, ...rest]); | ||
return (ctx.depthIdentifier !== undefined ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, constraints) : fc.array(item, constraints)).map(rest => [...as, ...rest]); | ||
}); | ||
@@ -222,4 +225,4 @@ // --------------------------------------------- | ||
{ | ||
const propertySignaturesTypes = ast.propertySignatures.map(ps => go(ps.type, options, path.concat(ps.name))); | ||
const indexSignatures = ast.indexSignatures.map(is => [go(is.parameter, options, path), go(is.type, options, path)]); | ||
const propertySignaturesTypes = ast.propertySignatures.map(ps => go(ps.type, ctx, path.concat(ps.name))); | ||
const indexSignatures = ast.indexSignatures.map(is => [go(is.parameter, ctx, path), go(is.type, ctx, path)]); | ||
return fc => { | ||
@@ -246,7 +249,9 @@ const arbs = {}; | ||
for (let i = 0; i < indexSignatures.length; i++) { | ||
const parameter = indexSignatures[i][0](fc); | ||
const type = indexSignatures[i][1](fc); | ||
const key = indexSignatures[i][0](fc); | ||
const value = indexSignatures[i][1](fc); | ||
output = output.chain(o => { | ||
return record(fc, parameter, type, options).map(d => ({ | ||
...d, | ||
const item = fc.tuple(key, value); | ||
const arr = ctx.depthIdentifier !== undefined ? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item) : fc.array(item); | ||
return arr.map(tuples => ({ | ||
...Object.fromEntries(tuples), | ||
...o | ||
@@ -261,6 +266,4 @@ })); | ||
{ | ||
const types = ast.types.map(t => go(t, options, path)); | ||
return fc => fc.oneof({ | ||
depthSize | ||
}, ...types.map(arb => arb(fc))); | ||
const types = ast.types.map(member => go(member, ctx, path)); | ||
return fc => fc.oneof(...types.map(arb => arb(fc))); | ||
} | ||
@@ -276,3 +279,3 @@ case "Enums": | ||
{ | ||
const from = getRefinementFromArbitrary(ast, options, path); | ||
const from = getRefinementFromArbitrary(ast, ctx, path); | ||
return fc => from(fc).filter(a => Option.isNone(ast.filter(a, AST.defaultParseOption, ast))); | ||
@@ -282,10 +285,9 @@ } | ||
{ | ||
const get = util_.memoizeThunk(() => go(ast.f(), { | ||
...options, | ||
isSuspend: true | ||
}, path)); | ||
const get = util_.memoizeThunk(() => { | ||
return go(ast.f(), getSuspendedContext(ctx, ast), path); | ||
}); | ||
return fc => fc.constant(null).chain(() => get()(fc)); | ||
} | ||
case "Transformation": | ||
return go(ast.to, options, path); | ||
return go(ast.to, ctx, path); | ||
} | ||
@@ -292,0 +294,0 @@ }; |
{ | ||
"name": "@effect/schema", | ||
"version": "0.72.2", | ||
"version": "0.72.3", | ||
"description": "Modeling the schema of data structures as first-class values", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -36,2 +36,19 @@ /** | ||
/** | ||
* @category hooks | ||
* @since 0.72.3 | ||
*/ | ||
export interface GenerationContext { | ||
readonly depthIdentifier?: string | ||
readonly maxDepth: number | ||
} | ||
/** | ||
* @category hooks | ||
* @since 0.72.3 | ||
*/ | ||
export type ArbitraryAnnotation<A> = ( | ||
...args: [...ReadonlyArray<LazyArbitrary<any>>, GenerationContext] | ||
) => LazyArbitrary<A> | ||
/** | ||
* @category annotations | ||
@@ -41,4 +58,4 @@ * @since 0.67.0 | ||
export const arbitrary = | ||
<A>(handler: (...args: ReadonlyArray<LazyArbitrary<any>>) => LazyArbitrary<A>) => | ||
<I, R>(self: Schema.Schema<A, I, R>): Schema.Schema<A, I, R> => self.annotations({ [ArbitraryHookId]: handler }) | ||
<A>(annotation: ArbitraryAnnotation<A>) => <I, R>(self: Schema.Schema<A, I, R>): Schema.Schema<A, I, R> => | ||
self.annotations({ [ArbitraryHookId]: annotation }) | ||
@@ -51,3 +68,4 @@ /** | ||
*/ | ||
export const makeLazy = <A, I, R>(schema: Schema.Schema<A, I, R>): LazyArbitrary<A> => go(schema.ast, {}, []) | ||
export const makeLazy = <A, I, R>(schema: Schema.Schema<A, I, R>): LazyArbitrary<A> => | ||
go(schema.ast, { maxDepth: 2 }, []) | ||
@@ -62,40 +80,58 @@ /** | ||
const depthSize = 1 | ||
const getHook = AST.getAnnotation<ArbitraryAnnotation<any>>(ArbitraryHookId) | ||
const record = <K extends PropertyKey, V>( | ||
fc: typeof FastCheck, | ||
key: FastCheck.Arbitrary<K>, | ||
value: FastCheck.Arbitrary<V>, | ||
options: Options | ||
): FastCheck.Arbitrary<{ readonly [k in K]: V }> => { | ||
return (options.isSuspend ? | ||
fc.oneof( | ||
{ depthSize }, | ||
fc.constant([]), | ||
fc.array(fc.tuple(key, value), { minLength: 1, maxLength: 2 }) | ||
) : | ||
fc.array(fc.tuple(key, value))).map((tuples) => { | ||
const out: { [k in K]: V } = {} as any | ||
for (const [k, v] of tuples) { | ||
out[k] = v | ||
} | ||
return out | ||
}) | ||
const getRefinementFromArbitrary = ( | ||
ast: AST.Refinement, | ||
ctx: Context, | ||
path: ReadonlyArray<PropertyKey> | ||
) => { | ||
const constraints = combineConstraints(ctx.constraints, getConstraints(ast)) | ||
return go(ast.from, constraints ? { ...ctx, constraints } : ctx, path) | ||
} | ||
const getHook = AST.getAnnotation< | ||
(...args: ReadonlyArray<LazyArbitrary<any>>) => LazyArbitrary<any> | ||
>(ArbitraryHookId) | ||
const getSuspendedContext = ( | ||
ctx: Context, | ||
ast: AST.Suspend | ||
): Context => { | ||
if (ctx.depthIdentifier !== undefined) { | ||
return ctx | ||
} | ||
const depthIdentifier = AST.getIdentifierAnnotation(ast).pipe( | ||
Option.orElse(() => AST.getIdentifierAnnotation(ast.f())), | ||
Option.getOrElse(() => "SuspendDefaultDepthIdentifier") | ||
) | ||
return { ...ctx, depthIdentifier } | ||
} | ||
type Options = { | ||
readonly constraints?: Constraints | ||
readonly isSuspend?: boolean | ||
const getSuspendedArray = ( | ||
fc: typeof FastCheck, | ||
depthIdentifier: string, | ||
maxDepth: number, | ||
item: FastCheck.Arbitrary<any>, | ||
constraints?: FastCheck.ArrayConstraints | ||
) => { | ||
let minLength = 1 | ||
let maxLength = 2 | ||
if (constraints && constraints.minLength !== undefined && constraints.minLength > minLength) { | ||
minLength = constraints.minLength | ||
if (minLength > maxLength) { | ||
maxLength = minLength | ||
} | ||
} | ||
return fc.oneof( | ||
{ maxDepth, depthIdentifier }, | ||
fc.constant([]), | ||
fc.array(item, { minLength, maxLength }) | ||
) | ||
} | ||
const getRefinementFromArbitrary = (ast: AST.Refinement, options: Options, path: ReadonlyArray<PropertyKey>) => { | ||
const constraints = combineConstraints(options.constraints, getConstraints(ast)) | ||
return go(ast.from, constraints ? { ...options, constraints } : options, path) | ||
interface Context extends GenerationContext { | ||
readonly constraints?: Constraints | ||
} | ||
const go = (ast: AST.AST, options: Options, path: ReadonlyArray<PropertyKey>): LazyArbitrary<any> => { | ||
const go = ( | ||
ast: AST.AST, | ||
ctx: Context, | ||
path: ReadonlyArray<PropertyKey> | ||
): LazyArbitrary<any> => { | ||
const hook = getHook(ast) | ||
@@ -105,7 +141,7 @@ if (Option.isSome(hook)) { | ||
case "Declaration": | ||
return hook.value(...ast.typeParameters.map((p) => go(p, options, path))) | ||
return hook.value(...ast.typeParameters.map((p) => go(p, ctx, path)), ctx) | ||
case "Refinement": | ||
return hook.value(getRefinementFromArbitrary(ast, options, path)) | ||
return hook.value(getRefinementFromArbitrary(ast, ctx, path), ctx) | ||
default: | ||
return hook.value() | ||
return hook.value(ctx) | ||
} | ||
@@ -133,6 +169,6 @@ } | ||
return (fc) => { | ||
if (options.constraints) { | ||
switch (options.constraints._tag) { | ||
if (ctx.constraints) { | ||
switch (ctx.constraints._tag) { | ||
case "StringConstraints": | ||
return fc.string(options.constraints.constraints) | ||
return fc.string(ctx.constraints.constraints) | ||
} | ||
@@ -144,8 +180,8 @@ } | ||
return (fc) => { | ||
if (options.constraints) { | ||
switch (options.constraints._tag) { | ||
if (ctx.constraints) { | ||
switch (ctx.constraints._tag) { | ||
case "NumberConstraints": | ||
return fc.float(options.constraints.constraints) | ||
return fc.float(ctx.constraints.constraints) | ||
case "IntegerConstraints": | ||
return fc.integer(options.constraints.constraints) | ||
return fc.integer(ctx.constraints.constraints) | ||
} | ||
@@ -159,6 +195,6 @@ } | ||
return (fc) => { | ||
if (options.constraints) { | ||
switch (options.constraints._tag) { | ||
if (ctx.constraints) { | ||
switch (ctx.constraints._tag) { | ||
case "BigIntConstraints": | ||
return fc.bigInt(options.constraints.constraints) | ||
return fc.bigInt(ctx.constraints.constraints) | ||
} | ||
@@ -193,3 +229,3 @@ } | ||
for (const element of ast.elements) { | ||
elements.push(go(element.type, options, path.concat(i++))) | ||
elements.push(go(element.type, ctx, path.concat(i++))) | ||
if (element.isOptional) { | ||
@@ -199,3 +235,3 @@ hasOptionals = true | ||
} | ||
const rest = ast.rest.map((annotatedAST) => go(annotatedAST.type, options, path)) | ||
const rest = ast.rest.map((annotatedAST) => go(annotatedAST.type, ctx, path)) | ||
return (fc) => { | ||
@@ -227,16 +263,11 @@ // --------------------------------------------- | ||
const [head, ...tail] = rest | ||
const arb = head(fc) | ||
const constraints = options.constraints | ||
const item = head(fc) | ||
const constraints: FastCheck.ArrayConstraints | undefined = | ||
ctx.constraints && ctx.constraints._tag === "ArrayConstraints" | ||
? ctx.constraints.constraints | ||
: undefined | ||
output = output.chain((as) => { | ||
let out = fc.array(arb) | ||
if (options.isSuspend) { | ||
out = fc.oneof( | ||
{ depthSize }, | ||
fc.constant([]), | ||
fc.array(arb, { minLength: 1, maxLength: 2 }) | ||
) | ||
} else if (constraints && constraints._tag === "ArrayConstraints") { | ||
out = fc.array(arb, constraints.constraints) | ||
} | ||
return out.map((rest) => [...as, ...rest]) | ||
return (ctx.depthIdentifier !== undefined | ||
? getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item, constraints) | ||
: fc.array(item, constraints)).map((rest) => [...as, ...rest]) | ||
}) | ||
@@ -255,5 +286,5 @@ // --------------------------------------------- | ||
case "TypeLiteral": { | ||
const propertySignaturesTypes = ast.propertySignatures.map((ps) => go(ps.type, options, path.concat(ps.name))) | ||
const propertySignaturesTypes = ast.propertySignatures.map((ps) => go(ps.type, ctx, path.concat(ps.name))) | ||
const indexSignatures = ast.indexSignatures.map((is) => | ||
[go(is.parameter, options, path), go(is.type, options, path)] as const | ||
[go(is.parameter, ctx, path), go(is.type, ctx, path)] as const | ||
) | ||
@@ -279,6 +310,10 @@ return (fc) => { | ||
for (let i = 0; i < indexSignatures.length; i++) { | ||
const parameter = indexSignatures[i][0](fc) | ||
const type = indexSignatures[i][1](fc) | ||
const key = indexSignatures[i][0](fc) | ||
const value = indexSignatures[i][1](fc) | ||
output = output.chain((o) => { | ||
return record(fc, parameter, type, options).map((d) => ({ ...d, ...o })) | ||
const item = fc.tuple(key, value) | ||
const arr = ctx.depthIdentifier !== undefined ? | ||
getSuspendedArray(fc, ctx.depthIdentifier, ctx.maxDepth, item) : | ||
fc.array(item) | ||
return arr.map((tuples) => ({ ...Object.fromEntries(tuples), ...o })) | ||
}) | ||
@@ -291,4 +326,4 @@ } | ||
case "Union": { | ||
const types = ast.types.map((t) => go(t, options, path)) | ||
return (fc) => fc.oneof({ depthSize }, ...types.map((arb) => arb(fc))) | ||
const types = ast.types.map((member) => go(member, ctx, path)) | ||
return (fc) => fc.oneof(...types.map((arb) => arb(fc))) | ||
} | ||
@@ -302,11 +337,13 @@ case "Enums": { | ||
case "Refinement": { | ||
const from = getRefinementFromArbitrary(ast, options, path) | ||
const from = getRefinementFromArbitrary(ast, ctx, path) | ||
return (fc) => from(fc).filter((a) => Option.isNone(ast.filter(a, AST.defaultParseOption, ast))) | ||
} | ||
case "Suspend": { | ||
const get = util_.memoizeThunk(() => go(ast.f(), { ...options, isSuspend: true }, path)) | ||
const get = util_.memoizeThunk(() => { | ||
return go(ast.f(), getSuspendedContext(ctx, ast), path) | ||
}) | ||
return (fc) => fc.constant(null).chain(() => get()(fc)) | ||
} | ||
case "Transformation": | ||
return go(ast.to, options, path) | ||
return go(ast.to, ctx, path) | ||
} | ||
@@ -313,0 +350,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2293123
42674