Skip to content

Commit

Permalink
refactor: "properties" keyword to typescript (WIP - 2 tests fail)
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Aug 22, 2020
1 parent 5f1b665 commit e82d0f1
Show file tree
Hide file tree
Showing 17 changed files with 69 additions and 203 deletions.
2 changes: 1 addition & 1 deletion lib/compile/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default function rules(): ValidationRules {
{type: "array", rules: []},
{
type: "object",
rules: [{properties: ["additionalProperties"]}],
rules: ["additionalProperties"],
},
{rules: ["$ref"]},
],
Expand Down
42 changes: 20 additions & 22 deletions lib/compile/validate/keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,29 @@ export function schemaKeywords(
if (!allErrors) gen.code("}")
return
}
let closeBlocks = ""
const ruleGroups = RULES.rules.filter((group) => shouldUseGroup(schema, group))
const last = ruleGroups.length - 1
ruleGroups.forEach((group, i) => {
if (group.type) {
// TODO refactor `data${dataLevel || ""}`
const checkType = checkDataType(group.type, `data${dataLevel || ""}`, strictNumbers)
// TODO refactor ifs
gen.if(checkType)
iterateKeywords(it, group)
if (types.length === 1 && types[0] === group.type && typeErrors) {
gen.else()
reportTypeError(it)
gen.block(() =>
ruleGroups.forEach((group, i) => {
if (group.type) {
// TODO refactor `data${dataLevel || ""}`
const checkType = checkDataType(group.type, `data${dataLevel || ""}`, strictNumbers)
gen.if(checkType)
iterateKeywords(it, group)
if (types.length === 1 && types[0] === group.type && typeErrors) {
gen.else()
reportTypeError(it)
}
gen.endIf()
} else {
iterateKeywords(it, group)
}
gen.endIf()
} else {
iterateKeywords(it, group)
}
if (!allErrors && i < last) {
const errCount = top ? "0" : `errs_${level}`
gen.code(`if (errors === ${errCount}) {`)
closeBlocks += "}"
}
})
if (!allErrors) gen.code(closeBlocks)
if (!allErrors && i < last) {
const errCount = top ? "0" : `errs_${level}`
gen.if(`errors === ${errCount}`)
}
})
)
}

function iterateKeywords(it: CompilationContext, group: RuleGroup) {
Expand Down
56 changes: 2 additions & 54 deletions lib/dot/properties.jst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{{ $keyword = "properties"; }}

{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
Expand Down Expand Up @@ -123,60 +125,6 @@ var {{=$nextValid}} = true;
{{# def.ifResultValid }}
{{?}}

{{ var $useDefaults = it.opts.useDefaults && !it.compositeRule; }}

{{? $schemaKeys.length }}
{{~ $schemaKeys:$propertyKey }}
{{ var $sch = $schema[$propertyKey]; }}

{{? {{# def.nonEmptySchema:$sch}} }}
{{
var $prop = it.util.getProperty($propertyKey)
, $passData = $data + $prop
, $hasDefault = $useDefaults && $sch.default !== undefined;
$it.schema = $sch;
$it.schemaPath = $schemaPath + $prop;
$it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($propertyKey);
$it.errorPath = it.util.getPath(it.errorPath, $propertyKey, it.opts.jsonPointers);
$it.dataPathArr[$dataNxt] = it.util.toQuotedString($propertyKey);
}}

{{# def.generateSubschemaCode }}

{{? {{# def.willOptimize }} }}
{{
$code = {{# def._optimizeValidate }};
var $useData = $passData;
}}
{{??}}
{{ var $useData = $nextData; }}
var {{=$nextData}} = {{=$passData}};
{{?}}

{{? $hasDefault }}
{{= $code }}
{{??}}
{{? $breakOnError }}
if ({{# def.noPropertyInData }}) {
{{=$nextValid}} = true;
} else {
{{??}}
if ({{=$useData}} !== undefined
{{? $ownProperties }}
&& {{# def.isOwnProperty }}
{{?}}
) {
{{?}}

{{= $code }}
}
{{?}} {{ /* $hasDefault */ }}
{{?}} {{ /* def.nonEmptySchema */ }}

{{# def.ifResultValid }}
{{~}}
{{?}}

{{? $breakOnError }}
{{= $closingBraces }}
if ({{=$errs}} == errors) {
Expand Down
2 changes: 1 addition & 1 deletion lib/dotjs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
module.exports = {
$ref: require("./ref"),
format: require("./format"),
properties: require("./properties"),
additionalProperties: require("./properties"),
}
6 changes: 4 additions & 2 deletions lib/keyword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,10 @@ function ruleCode(it: CompilationContext, keyword: string /*, ruleType */): void
}

function ok(condition?: string): void {
if (condition) fail(`!(${condition})`)
else if (!allErrors) gen.code("if (true) {")
if (!allErrors) {
if (condition) gen.code(`if (${condition}) {`)
else gen.code("if (true) {")
}
}

function errorParams(obj: KeywordContextParams, assign?: true) {
Expand Down
25 changes: 10 additions & 15 deletions lib/vocabularies/applicator/allOf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,17 @@ const def: KeywordDefinition = {
code({gen, ok, schema, it}) {
let emptySchemas = true
const valid = gen.name("valid")
let count = 0
schema.forEach((sch: object | boolean, i: number) => {
if (alwaysValidSchema(it, sch)) return
emptySchemas = false
applySubschema(it, {keyword: "allOf", schemaProp: i}, valid)
if (!it.allErrors) {
if (count === 1) gen.block()
count++
gen.if(valid)
}
})
gen.block(() =>
schema.forEach((sch: object | boolean, i: number) => {
if (alwaysValidSchema(it, sch)) return
emptySchemas = false
applySubschema(it, {keyword: "allOf", schemaProp: i}, valid)
if (!it.allErrors) gen.if(valid)
})
)

if (!it.allErrors) {
if (emptySchemas) ok()
else if (count > 1) gen.endBlock(count - 1)
}
if (emptySchemas) ok()
else ok(valid)

// TODO possibly add allOf error
},
Expand Down
6 changes: 2 additions & 4 deletions lib/vocabularies/applicator/anyOf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ const def: KeywordDefinition = {
code(cxt) {
const {gen, ok, schema, it} = cxt
const alwaysValid = schema.some((sch: object | boolean) => alwaysValidSchema(it, sch))
if (alwaysValid) {
ok()
return
}
if (alwaysValid) return ok()

const valid = gen.name("valid")
const schValid = gen.name("_valid")
const errsCount = gen.name("_errs")
Expand Down
5 changes: 1 addition & 4 deletions lib/vocabularies/applicator/contains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ const def: KeywordDefinition = {
const errsCount = gen.name("_errs")
gen.code(`const ${errsCount} = errors;`)

if (alwaysValidSchema(it, schema)) {
fail(`${data}.length === 0`)
return
}
if (alwaysValidSchema(it, schema)) return fail(`${data}.length === 0`)

const valid = gen.name("valid")
const i = gen.name("i")
Expand Down
5 changes: 2 additions & 3 deletions lib/vocabularies/applicator/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const def: KeywordDefinition = {
type: "object",
schemaType: "object",
code(cxt) {
const {gen, errorParams, schema, data, it} = cxt
const {gen, ok, errorParams, schema, data, it} = cxt

const [propDeps, schDeps] = splitDependencies()

Expand All @@ -29,8 +29,7 @@ const def: KeywordDefinition = {
validateSchemaDeps(schDeps)
})

// TODO refactor ifs
if (!it.allErrors) gen.code(`if (${errsCount} === errors) {`)
ok(`${errsCount} === errors`)

function splitDependencies(): [PropertyDependencies, SchemaDependencies] {
const propertyDeps: PropertyDependencies = {}
Expand Down
2 changes: 1 addition & 1 deletion lib/vocabularies/applicator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const applicator: Vocabulary = [
// object
require("./dependencies"),
require("./propertyNames"),
// require("./properties"),
require("./properties"),
require("./patternProperties"),
// any
require("./not"),
Expand Down
12 changes: 3 additions & 9 deletions lib/vocabularies/applicator/items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,15 @@ const def: KeywordDefinition = {
code(cxt) {
// TODO strict mode: fail or warning if "additionalItems" is present without "items"

const {gen, /* fail, */ schema, parentSchema, data, it} = cxt
const {gen, ok, schema, parentSchema, data, it} = cxt
const errsCount = gen.name("_errs")
const len = gen.name("len")
gen.code(
`const ${errsCount} = errors;
const ${len} = ${data}.length;`
)

if (it.allErrors) {
validateItemsKeyword()
} else {
gen.block(validateItemsKeyword)
// TODO refactor ifs
gen.code(`if (${errsCount} === errors) {`)
}
gen.block(validateItemsKeyword)
ok(`${errsCount} === errors`)

function validateItemsKeyword(): void {
if (Array.isArray(schema)) {
Expand Down
5 changes: 1 addition & 4 deletions lib/vocabularies/applicator/not.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ const def: KeywordDefinition = {
schemaType: ["object", "boolean"],
code(cxt) {
const {gen, fail, schema, it} = cxt
if (alwaysValidSchema(it, schema)) {
fail()
return
}
if (alwaysValidSchema(it, schema)) return fail()

const valid = gen.name("valid")
const errsCount = gen.name("_errs")
Expand Down
9 changes: 2 additions & 7 deletions lib/vocabularies/applicator/patternProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@ const def: KeywordDefinition = {
code(cxt) {
const {gen, ok, schema, it} = cxt
const patterns = schemaProperties(it, schema)
if (patterns.length === 0) {
ok()
return
}
if (patterns.length === 0) return ok()

const valid = gen.name("valid")
const errsCount = gen.name("_errs")
gen.code(`const ${errsCount} = errors;`)

gen.block(validatePatternProperties)

// TODO refactor ifs
if (!it.allErrors) gen.code(`if (${errsCount} === errors) {`)
ok(`${errsCount} === errors`)

function validatePatternProperties() {
for (const pat of patterns) {
Expand Down
9 changes: 2 additions & 7 deletions lib/vocabularies/applicator/properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@ const def: KeywordDefinition = {
code(cxt) {
const {gen, ok, schema, data, it} = cxt
const properties = schemaProperties(it, schema)
if (properties.length === 0) {
ok()
return
}
if (properties.length === 0) return ok()

const valid = gen.name("valid")
const errsCount = gen.name("_errs")
gen.code(`const ${errsCount} = errors;`)

gen.block(validateProperties)

// TODO refactor ifs
if (!it.allErrors) gen.code(`if (${errsCount} === errors) {`)
ok(`${errsCount} === errors`)

function validateProperties() {
for (const prop of properties) {
Expand Down
5 changes: 1 addition & 4 deletions lib/vocabularies/applicator/propertyNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ const def: KeywordDefinition = {
schemaType: ["object", "boolean"],
code(cxt) {
const {gen, ok, errorParams, schema, it} = cxt
if (alwaysValidSchema(it, schema)) {
ok()
return
}
if (alwaysValidSchema(it, schema)) return ok()

const valid = gen.name("valid")
const errsCount = gen.name("_errs")
Expand Down
5 changes: 1 addition & 4 deletions lib/vocabularies/validation/required.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ const def: KeywordDefinition = {
$data: true,
code(cxt) {
const {gen, ok, fail, errorParams, schema, schemaCode, data, $data, it} = cxt
if (!$data && schema.length === 0) {
ok()
return
}
if (!$data && schema.length === 0) return ok()

const loopRequired = $data || schema.length >= <number>it.opts.loopRequired

Expand Down
Loading

0 comments on commit e82d0f1

Please sign in to comment.