Skip to content

Commit d9a902a

Browse files
authored
Don't emit annotations in propertyNames (#445)
Fixes: #444 Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 5e4971e commit d9a902a

File tree

8 files changed

+190
-7
lines changed

8 files changed

+190
-7
lines changed

src/compiler/compile.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ auto compile_subschema(const sourcemeta::blaze::Context &context,
4444
{schema_context.relative_pointer.concat({keyword}),
4545
schema_context.schema, entry.vocabularies, schema_context.base,
4646
// TODO: This represents a copy
47-
schema_context.labels, schema_context.references},
47+
schema_context.labels, schema_context.references,
48+
schema_context.is_property_name},
4849
{keyword, dynamic_context.base_schema_location,
4950
dynamic_context.base_instance_location,
5051
dynamic_context.property_as_target},
@@ -84,7 +85,8 @@ auto precompile(
8485
std::move(nested_vocabularies),
8586
entry.second.base,
8687
{},
87-
{}};
88+
{},
89+
schema_context.is_property_name};
8890

8991
return {make(sourcemeta::blaze::InstructionIndex::ControlMark, context,
9092
nested_schema_context, dynamic_context,
@@ -137,7 +139,8 @@ auto compile(const sourcemeta::core::JSON &schema,
137139
vocabularies(schema, resolver, root_frame_entry.dialect),
138140
sourcemeta::core::URI::canonicalize(root_frame_entry.base),
139141
{},
140-
{}};
142+
{},
143+
false};
141144

142145
std::vector<std::string> resources;
143146
for (const auto &entry : frame.locations()) {
@@ -331,7 +334,8 @@ auto compile(const Context &context, const SchemaContext &schema_context,
331334
sourcemeta::core::URI{entry.base}.recompose_without_fragment().value_or(
332335
""),
333336
// TODO: This represents a copy
334-
schema_context.labels, schema_context.references},
337+
schema_context.labels, schema_context.references,
338+
schema_context.is_property_name},
335339
{dynamic_context.keyword, destination_pointer,
336340
dynamic_context.base_instance_location.concat(instance_suffix),
337341
dynamic_context.property_as_target},

src/compiler/default_compiler.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,8 @@ auto sourcemeta::blaze::default_schema_compiler(
642642
return {};
643643
}
644644

645-
if (context.mode == Mode::FastValidation) {
645+
if (context.mode == Mode::FastValidation ||
646+
schema_context.is_property_name) {
646647
return {};
647648
}
648649

src/compiler/default_compiler_2019_09.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ auto compiler_2019_09_applicator_contains_with_options(
110110
const Context &context, const SchemaContext &schema_context,
111111
const DynamicContext &dynamic_context, const Instructions &,
112112
const bool annotate, const bool track_evaluation) -> Instructions {
113+
if (schema_context.is_property_name) {
114+
return {};
115+
}
116+
113117
if (schema_context.schema.defines("type") &&
114118
schema_context.schema.at("type").is_string() &&
115119
schema_context.schema.at("type").to_string() != "array") {

src/compiler/default_compiler_draft4.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,8 @@ auto compiler_draft4_validation_required(const Context &context,
579579
schema_context.vocabularies,
580580
schema_context.base,
581581
schema_context.labels,
582-
schema_context.references};
582+
schema_context.references,
583+
schema_context.is_property_name};
583584
const DynamicContext new_dynamic_context{
584585
"properties", sourcemeta::core::empty_pointer,
585586
sourcemeta::core::empty_pointer, false};
@@ -889,6 +890,10 @@ auto compiler_draft4_applicator_properties_with_options(
889890
const Context &context, const SchemaContext &schema_context,
890891
const DynamicContext &dynamic_context, const Instructions &current,
891892
const bool annotate, const bool track_evaluation) -> Instructions {
893+
if (schema_context.is_property_name) {
894+
return {};
895+
}
896+
892897
assert(schema_context.schema.at(dynamic_context.keyword).is_object());
893898
if (schema_context.schema.at(dynamic_context.keyword).empty()) {
894899
return {};
@@ -1542,6 +1547,10 @@ auto compiler_draft4_applicator_items_array(
15421547
const Context &context, const SchemaContext &schema_context,
15431548
const DynamicContext &dynamic_context, const bool annotate,
15441549
const bool track_evaluation) -> Instructions {
1550+
if (schema_context.is_property_name) {
1551+
return {};
1552+
}
1553+
15451554
assert(schema_context.schema.at(dynamic_context.keyword).is_array());
15461555
const auto items_size{
15471556
schema_context.schema.at(dynamic_context.keyword).size()};

src/compiler/default_compiler_draft6.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,11 @@ auto compiler_draft6_validation_propertynames(
402402
return {};
403403
}
404404

405+
// TODO: How can we avoid this copy?
406+
auto nested_schema_context = schema_context;
407+
nested_schema_context.is_property_name = true;
405408
Instructions children{compile(
406-
context, schema_context, property_relative_dynamic_context(),
409+
context, nested_schema_context, property_relative_dynamic_context(),
407410
sourcemeta::core::empty_pointer, sourcemeta::core::empty_pointer)};
408411

409412
if (children.empty()) {

src/compiler/include/sourcemeta/blaze/compiler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ struct SchemaContext {
4545
std::set<std::size_t> labels;
4646
/// The set of references destinations traversed so far
4747
std::set<std::string> references;
48+
/// Whether the current schema targets a property name
49+
bool is_property_name;
4850
};
4951

5052
/// @ingroup compiler

test/evaluator/evaluator_2019_09_test.cc

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5888,3 +5888,82 @@ TEST(Evaluator_2019_09, definitions_1_exhaustive) {
58885888
"The string value was expected to validate "
58895889
"against the statically referenced schema");
58905890
}
5891+
5892+
TEST(Evaluator_2019_09, propertyNames_1) {
5893+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
5894+
"$schema": "https://json-schema.org/draft/2019-09/schema",
5895+
"propertyNames": {
5896+
"title": "Test",
5897+
"description": "Test",
5898+
"default": "Test",
5899+
"deprecated": true,
5900+
"examples": [ "foo" ],
5901+
"readOnly": true,
5902+
"writeOnly": true,
5903+
5904+
"x-foo": "bar",
5905+
5906+
"format": "email",
5907+
5908+
"contentEncoding": "base64",
5909+
"contentMediaType": "application/json",
5910+
"contentSchema": true,
5911+
5912+
"items": [ { "type": "string" } ],
5913+
"additionalItems": { "type": "string" },
5914+
"unevaluatedItems": { "type": "string" },
5915+
5916+
"properties": { "foo": { "type": "string" } },
5917+
"patternProperties": { "^f": { "type": "string" } },
5918+
"additionalProperties": { "type": "string" },
5919+
"unevaluatedProperties": { "type": "string" }
5920+
}
5921+
})JSON")};
5922+
5923+
const sourcemeta::core::JSON instance{
5924+
sourcemeta::core::parse_json("{ \"foo\": 1 }")};
5925+
EVALUATE_WITH_TRACE_FAST_SUCCESS(schema, instance, 0);
5926+
}
5927+
5928+
TEST(Evaluator_2019_09, propertyNames_1_exhaustive) {
5929+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
5930+
"$schema": "https://json-schema.org/draft/2019-09/schema",
5931+
"propertyNames": {
5932+
"title": "Test",
5933+
"description": "Test",
5934+
"default": "Test",
5935+
"deprecated": true,
5936+
"examples": [ "foo" ],
5937+
"readOnly": true,
5938+
"writeOnly": true,
5939+
5940+
"x-foo": "bar",
5941+
5942+
"format": "email",
5943+
5944+
"contentEncoding": "base64",
5945+
"contentMediaType": "application/json",
5946+
"contentSchema": true,
5947+
5948+
"items": [ { "type": "string" } ],
5949+
"additionalItems": { "type": "string" },
5950+
"unevaluatedItems": { "type": "string" },
5951+
5952+
"properties": { "foo": { "type": "string" } },
5953+
"patternProperties": { "^f": { "type": "string" } },
5954+
"additionalProperties": { "type": "string" },
5955+
"unevaluatedProperties": { "type": "string" }
5956+
}
5957+
})JSON")};
5958+
5959+
const sourcemeta::core::JSON instance{
5960+
sourcemeta::core::parse_json("{ \"foo\": 1 }")};
5961+
EVALUATE_WITH_TRACE_EXHAUSTIVE_SUCCESS(schema, instance, 1);
5962+
5963+
EVALUATE_TRACE_PRE(0, LoopKeys, "/propertyNames", "#/propertyNames", "");
5964+
EVALUATE_TRACE_POST_SUCCESS(0, LoopKeys, "/propertyNames", "#/propertyNames",
5965+
"");
5966+
EVALUATE_TRACE_POST_DESCRIBE(instance, 0,
5967+
"The object property \"foo\" was expected to "
5968+
"validate against the given subschema");
5969+
}

test/evaluator/evaluator_2020_12_test.cc

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2123,3 +2123,84 @@ TEST(Evaluator_2020_12, cross_id_1) {
21232123
EVALUATE_TRACE_POST_DESCRIBE(instance, 0,
21242124
"The value was expected to be of type string");
21252125
}
2126+
2127+
TEST(Evaluator_2020_12, propertyNames_1) {
2128+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
2129+
"$schema": "https://json-schema.org/draft/2020-12/schema",
2130+
"propertyNames": {
2131+
"title": "Test",
2132+
"description": "Test",
2133+
"default": "Test",
2134+
"deprecated": true,
2135+
"examples": [ "foo" ],
2136+
"readOnly": true,
2137+
"writeOnly": true,
2138+
2139+
"x-foo": "bar",
2140+
2141+
"format": "email",
2142+
2143+
"contentEncoding": "base64",
2144+
"contentMediaType": "application/json",
2145+
"contentSchema": true,
2146+
2147+
"prefixItems": [ { "type": "string" } ],
2148+
"items": { "type": "string" },
2149+
"unevaluatedItems": { "type": "string" },
2150+
"contains": { "type": "string" },
2151+
2152+
"properties": { "foo": { "type": "string" } },
2153+
"patternProperties": { "^f": { "type": "string" } },
2154+
"additionalProperties": { "type": "string" },
2155+
"unevaluatedProperties": { "type": "string" }
2156+
}
2157+
})JSON")};
2158+
2159+
const sourcemeta::core::JSON instance{
2160+
sourcemeta::core::parse_json("{ \"foo\": 1 }")};
2161+
EVALUATE_WITH_TRACE_FAST_SUCCESS(schema, instance, 0);
2162+
}
2163+
2164+
TEST(Evaluator_2020_12, propertyNames_1_exhaustive) {
2165+
const sourcemeta::core::JSON schema{sourcemeta::core::parse_json(R"JSON({
2166+
"$schema": "https://json-schema.org/draft/2020-12/schema",
2167+
"propertyNames": {
2168+
"title": "Test",
2169+
"description": "Test",
2170+
"default": "Test",
2171+
"deprecated": true,
2172+
"examples": [ "foo" ],
2173+
"readOnly": true,
2174+
"writeOnly": true,
2175+
2176+
"x-foo": "bar",
2177+
2178+
"format": "email",
2179+
2180+
"contentEncoding": "base64",
2181+
"contentMediaType": "application/json",
2182+
"contentSchema": true,
2183+
2184+
"prefixItems": [ { "type": "string" } ],
2185+
"items": { "type": "string" },
2186+
"unevaluatedItems": { "type": "string" },
2187+
"contains": { "type": "string" },
2188+
2189+
"properties": { "foo": { "type": "string" } },
2190+
"patternProperties": { "^f": { "type": "string" } },
2191+
"additionalProperties": { "type": "string" },
2192+
"unevaluatedProperties": { "type": "string" }
2193+
}
2194+
})JSON")};
2195+
2196+
const sourcemeta::core::JSON instance{
2197+
sourcemeta::core::parse_json("{ \"foo\": 1 }")};
2198+
EVALUATE_WITH_TRACE_EXHAUSTIVE_SUCCESS(schema, instance, 1);
2199+
2200+
EVALUATE_TRACE_PRE(0, LoopKeys, "/propertyNames", "#/propertyNames", "");
2201+
EVALUATE_TRACE_POST_SUCCESS(0, LoopKeys, "/propertyNames", "#/propertyNames",
2202+
"");
2203+
EVALUATE_TRACE_POST_DESCRIBE(instance, 0,
2204+
"The object property \"foo\" was expected to "
2205+
"validate against the given subschema");
2206+
}

0 commit comments

Comments
 (0)