massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / table / node_modules / ajv / lib / compile / errors.ts
1 import type {KeywordErrorCxt, KeywordErrorDefinition} from "../types"
2 import type {SchemaCxt} from "./index"
3 import {CodeGen, _, str, strConcat, Code, Name} from "./codegen"
4 import {SafeExpr} from "./codegen/code"
5 import {getErrorPath, Type} from "./util"
6 import N from "./names"
7
8 export const keywordError: KeywordErrorDefinition = {
9   message: ({keyword}) => str`must pass "${keyword}" keyword validation`,
10 }
11
12 export const keyword$DataError: KeywordErrorDefinition = {
13   message: ({keyword, schemaType}) =>
14     schemaType
15       ? str`"${keyword}" keyword must be ${schemaType} ($data)`
16       : str`"${keyword}" keyword is invalid ($data)`,
17 }
18
19 export interface ErrorPaths {
20   instancePath?: Code
21   schemaPath?: string
22   parentSchema?: boolean
23 }
24
25 export function reportError(
26   cxt: KeywordErrorCxt,
27   error: KeywordErrorDefinition = keywordError,
28   errorPaths?: ErrorPaths,
29   overrideAllErrors?: boolean
30 ): void {
31   const {it} = cxt
32   const {gen, compositeRule, allErrors} = it
33   const errObj = errorObjectCode(cxt, error, errorPaths)
34   if (overrideAllErrors ?? (compositeRule || allErrors)) {
35     addError(gen, errObj)
36   } else {
37     returnErrors(it, _`[${errObj}]`)
38   }
39 }
40
41 export function reportExtraError(
42   cxt: KeywordErrorCxt,
43   error: KeywordErrorDefinition = keywordError,
44   errorPaths?: ErrorPaths
45 ): void {
46   const {it} = cxt
47   const {gen, compositeRule, allErrors} = it
48   const errObj = errorObjectCode(cxt, error, errorPaths)
49   addError(gen, errObj)
50   if (!(compositeRule || allErrors)) {
51     returnErrors(it, N.vErrors)
52   }
53 }
54
55 export function resetErrorsCount(gen: CodeGen, errsCount: Name): void {
56   gen.assign(N.errors, errsCount)
57   gen.if(_`${N.vErrors} !== null`, () =>
58     gen.if(
59       errsCount,
60       () => gen.assign(_`${N.vErrors}.length`, errsCount),
61       () => gen.assign(N.vErrors, null)
62     )
63   )
64 }
65
66 export function extendErrors({
67   gen,
68   keyword,
69   schemaValue,
70   data,
71   errsCount,
72   it,
73 }: KeywordErrorCxt): void {
74   /* istanbul ignore if */
75   if (errsCount === undefined) throw new Error("ajv implementation error")
76   const err = gen.name("err")
77   gen.forRange("i", errsCount, N.errors, (i) => {
78     gen.const(err, _`${N.vErrors}[${i}]`)
79     gen.if(_`${err}.instancePath === undefined`, () =>
80       gen.assign(_`${err}.instancePath`, strConcat(N.instancePath, it.errorPath))
81     )
82     gen.assign(_`${err}.schemaPath`, str`${it.errSchemaPath}/${keyword}`)
83     if (it.opts.verbose) {
84       gen.assign(_`${err}.schema`, schemaValue)
85       gen.assign(_`${err}.data`, data)
86     }
87   })
88 }
89
90 function addError(gen: CodeGen, errObj: Code): void {
91   const err = gen.const("err", errObj)
92   gen.if(
93     _`${N.vErrors} === null`,
94     () => gen.assign(N.vErrors, _`[${err}]`),
95     _`${N.vErrors}.push(${err})`
96   )
97   gen.code(_`${N.errors}++`)
98 }
99
100 function returnErrors(it: SchemaCxt, errs: Code): void {
101   const {gen, validateName, schemaEnv} = it
102   if (schemaEnv.$async) {
103     gen.throw(_`new ${it.ValidationError as Name}(${errs})`)
104   } else {
105     gen.assign(_`${validateName}.errors`, errs)
106     gen.return(false)
107   }
108 }
109
110 const E = {
111   keyword: new Name("keyword"),
112   schemaPath: new Name("schemaPath"), // also used in JTD errors
113   params: new Name("params"),
114   propertyName: new Name("propertyName"),
115   message: new Name("message"),
116   schema: new Name("schema"),
117   parentSchema: new Name("parentSchema"),
118 }
119
120 function errorObjectCode(
121   cxt: KeywordErrorCxt,
122   error: KeywordErrorDefinition,
123   errorPaths?: ErrorPaths
124 ): Code {
125   const {createErrors} = cxt.it
126   if (createErrors === false) return _`{}`
127   return errorObject(cxt, error, errorPaths)
128 }
129
130 function errorObject(
131   cxt: KeywordErrorCxt,
132   error: KeywordErrorDefinition,
133   errorPaths: ErrorPaths = {}
134 ): Code {
135   const {gen, it} = cxt
136   const keyValues: [Name, SafeExpr | string][] = [
137     errorInstancePath(it, errorPaths),
138     errorSchemaPath(cxt, errorPaths),
139   ]
140   extraErrorProps(cxt, error, keyValues)
141   return gen.object(...keyValues)
142 }
143
144 function errorInstancePath({errorPath}: SchemaCxt, {instancePath}: ErrorPaths): [Name, Code] {
145   const instPath = instancePath
146     ? str`${errorPath}${getErrorPath(instancePath, Type.Str)}`
147     : errorPath
148   return [N.instancePath, strConcat(N.instancePath, instPath)]
149 }
150
151 function errorSchemaPath(
152   {keyword, it: {errSchemaPath}}: KeywordErrorCxt,
153   {schemaPath, parentSchema}: ErrorPaths
154 ): [Name, string | Code] {
155   let schPath = parentSchema ? errSchemaPath : str`${errSchemaPath}/${keyword}`
156   if (schemaPath) {
157     schPath = str`${schPath}${getErrorPath(schemaPath, Type.Str)}`
158   }
159   return [E.schemaPath, schPath]
160 }
161
162 function extraErrorProps(
163   cxt: KeywordErrorCxt,
164   {params, message}: KeywordErrorDefinition,
165   keyValues: [Name, SafeExpr | string][]
166 ): void {
167   const {keyword, data, schemaValue, it} = cxt
168   const {opts, propertyName, topSchemaRef, schemaPath} = it
169   keyValues.push(
170     [E.keyword, keyword],
171     [E.params, typeof params == "function" ? params(cxt) : params || _`{}`]
172   )
173   if (opts.messages) {
174     keyValues.push([E.message, typeof message == "function" ? message(cxt) : message])
175   }
176   if (opts.verbose) {
177     keyValues.push(
178       [E.schema, schemaValue],
179       [E.parentSchema, _`${topSchemaRef}${schemaPath}`],
180       [N.data, data]
181     )
182   }
183   if (propertyName) keyValues.push([E.propertyName, propertyName])
184 }