Skip to content

Commit

Permalink
Extend schema walker to account for conditional instance locations
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <[email protected]>
  • Loading branch information
jviotti committed Feb 12, 2025
1 parent 77e6776 commit 2f9a11e
Show file tree
Hide file tree
Showing 24 changed files with 416 additions and 314 deletions.
8 changes: 4 additions & 4 deletions src/core/jsonschema/frame.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1037,7 +1037,7 @@ auto find_adjacent_dependencies(
}

// Static
case SchemaKeywordType::ApplicatorElementsInPlaceInline:
case SchemaKeywordType::ApplicatorElementsInPlace:
for (std::size_t index = 0; index < property.second.size(); index++) {
find_adjacent_dependencies(
current, schema, frame, walker, resolver, keywords, root,
Expand All @@ -1048,7 +1048,7 @@ auto find_adjacent_dependencies(
break;

// Dynamic
case SchemaKeywordType::ApplicatorElementsInPlace:
case SchemaKeywordType::ApplicatorElementsInPlaceSome:
if (property.second.is_array()) {
for (std::size_t index = 0; index < property.second.size(); index++) {
find_adjacent_dependencies(
Expand All @@ -1062,7 +1062,7 @@ auto find_adjacent_dependencies(
[[fallthrough]];
case SchemaKeywordType::ApplicatorValueTraverseParent:
[[fallthrough]];
case SchemaKeywordType::ApplicatorValueInPlace:
case SchemaKeywordType::ApplicatorValueInPlaceMaybe:
if (is_schema(property.second)) {
find_adjacent_dependencies(
current, schema, frame, walker, resolver, keywords, root,
Expand All @@ -1084,7 +1084,7 @@ auto find_adjacent_dependencies(
}

break;
case SchemaKeywordType::ApplicatorMembersInPlace:
case SchemaKeywordType::ApplicatorMembersInPlaceSome:
if (property.second.is_object()) {
for (const auto &pair : property.second.as_object()) {
find_adjacent_dependencies(
Expand Down
28 changes: 16 additions & 12 deletions src/core/jsonschema/include/sourcemeta/core/jsonschema_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ enum class SchemaKeywordType : std::uint8_t {
ApplicatorMembersTraversePropertyRegex,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument
/// The instance traverses to any property
ApplicatorValueTraverseAnyProperty,
/// The instance traverses to some of the properties
ApplicatorValueTraverseSomeProperty,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument
/// The instance traverses to any property key
Expand All @@ -99,6 +99,10 @@ enum class SchemaKeywordType : std::uint8_t {
ApplicatorValueTraverseAnyItem,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument
/// The instance traverses to some of the items
ApplicatorValueTraverseSomeItem,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument
/// The instance traverses back to the parent
ApplicatorValueTraverseParent,
/// The JSON Schema keyword is an applicator that potentially
Expand All @@ -120,23 +124,23 @@ enum class SchemaKeywordType : std::uint8_t {
/// takes an object as argument, whose values are potentially
/// JSON Schema definitions without affecting the instance location.
/// The instance does not traverse
ApplicatorMembersInPlace,
ApplicatorMembersInPlaceSome,
/// The JSON Schema keyword is an applicator that potentially
/// takes an array of potentially JSON Schema definitions
/// as an argument without affecting the instance location
/// as an argument without affecting the instance location.
/// The instance does not traverse
ApplicatorElementsInPlace,
/// The JSON Schema keyword is an applicator that potentially
/// takes an array of potentially JSON Schema definitions
/// as an argument without affecting the instance location
/// The instance does not traverse, and only some of the
/// elements apply.
ApplicatorElementsInPlaceSome,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument without affecting the
/// instance location.
/// The instance does not traverse
ApplicatorValueInPlace,
/// The JSON Schema keyword is an applicator that potentially
/// takes an array of potentially JSON Schema definitions
/// as an argument without affecting the instance location and that can be
/// statically inlined.
/// The instance does not traverse
ApplicatorElementsInPlaceInline,
/// The instance does not traverse, and only applies some of the times.
ApplicatorValueInPlaceMaybe,
/// The JSON Schema keyword is an applicator that potentially
/// takes a JSON Schema definition as an argument but its evaluation follows
/// special rules.
Expand Down
141 changes: 73 additions & 68 deletions src/core/jsonschema/official_walker.cc

Large diffs are not rendered by default.

67 changes: 58 additions & 9 deletions src/core/jsonschema/walker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,17 @@ auto walk(const std::optional<sourcemeta::core::Pointer> &parent,
for (auto &pair : subschema.as_object()) {
switch (walker(pair.first, vocabularies).type) {
case sourcemeta::core::SchemaKeywordType::
ApplicatorValueTraverseAnyProperty: {
ApplicatorValueTraverseSomeProperty: {
sourcemeta::core::Pointer new_pointer{pointer};
new_pointer.emplace_back(pair.first);
auto new_instance_location{instance_location};
new_instance_location.emplace_back(
sourcemeta::core::PointerTemplate::Conditional{});
new_instance_location.emplace_back(
sourcemeta::core::PointerTemplate::Wildcard::Property);
walk(pointer, new_pointer, new_instance_location,
{sourcemeta::core::PointerTemplate::Wildcard::Property},
{sourcemeta::core::PointerTemplate::Conditional{},
sourcemeta::core::PointerTemplate::Wildcard::Property},
subschemas, pair.second, walker, resolver, new_dialect, type,
level + 1, orphan);
} break;
Expand Down Expand Up @@ -90,6 +93,22 @@ auto walk(const std::optional<sourcemeta::core::Pointer> &parent,
orphan);
} break;

case sourcemeta::core::SchemaKeywordType::
ApplicatorValueTraverseSomeItem: {
sourcemeta::core::Pointer new_pointer{pointer};
new_pointer.emplace_back(pair.first);
auto new_instance_location{instance_location};
new_instance_location.emplace_back(
sourcemeta::core::PointerTemplate::Conditional{});
new_instance_location.emplace_back(
sourcemeta::core::PointerTemplate::Wildcard::Item);
walk(pointer, new_pointer, new_instance_location,
{sourcemeta::core::PointerTemplate::Conditional{},
sourcemeta::core::PointerTemplate::Wildcard::Item},
subschemas, pair.second, walker, resolver, new_dialect, type,
level + 1, orphan);
} break;

case sourcemeta::core::SchemaKeywordType::ApplicatorValueTraverseParent: {
sourcemeta::core::Pointer new_pointer{pointer};
new_pointer.emplace_back(pair.first);
Expand All @@ -100,16 +119,26 @@ auto walk(const std::optional<sourcemeta::core::Pointer> &parent,
orphan);
} break;

case sourcemeta::core::SchemaKeywordType::ApplicatorValueInPlaceOther:
[[fallthrough]];
case sourcemeta::core::SchemaKeywordType::ApplicatorValueInPlace: {
case sourcemeta::core::SchemaKeywordType::ApplicatorValueInPlaceOther: {
sourcemeta::core::Pointer new_pointer{pointer};
new_pointer.emplace_back(pair.first);
walk(pointer, new_pointer, instance_location, {}, subschemas,
pair.second, walker, resolver, new_dialect, type, level + 1,
orphan);
} break;

case sourcemeta::core::SchemaKeywordType::ApplicatorValueInPlaceMaybe: {
sourcemeta::core::Pointer new_pointer{pointer};
new_pointer.emplace_back(pair.first);
auto new_instance_location{instance_location};
new_instance_location.emplace_back(
sourcemeta::core::PointerTemplate::Conditional{});
walk(pointer, new_pointer, new_instance_location,
{sourcemeta::core::PointerTemplate::Conditional{}}, subschemas,
pair.second, walker, resolver, new_dialect, type, level + 1,
orphan);
} break;

case sourcemeta::core::SchemaKeywordType::ApplicatorElementsTraverseItem:
if (pair.second.is_array()) {
for (std::size_t index = 0; index < pair.second.size(); index++) {
Expand All @@ -126,8 +155,6 @@ auto walk(const std::optional<sourcemeta::core::Pointer> &parent,

break;

case sourcemeta::core::SchemaKeywordType::ApplicatorElementsInPlaceInline:
[[fallthrough]];
case sourcemeta::core::SchemaKeywordType::ApplicatorElementsInPlace:
if (pair.second.is_array()) {
for (std::size_t index = 0; index < pair.second.size(); index++) {
Expand All @@ -142,6 +169,24 @@ auto walk(const std::optional<sourcemeta::core::Pointer> &parent,

break;

case sourcemeta::core::SchemaKeywordType::ApplicatorElementsInPlaceSome:
if (pair.second.is_array()) {
for (std::size_t index = 0; index < pair.second.size(); index++) {
sourcemeta::core::Pointer new_pointer{pointer};
new_pointer.emplace_back(pair.first);
new_pointer.emplace_back(index);
auto new_instance_location{instance_location};
new_instance_location.emplace_back(
sourcemeta::core::PointerTemplate::Conditional{});
walk(pointer, new_pointer, new_instance_location,
{sourcemeta::core::PointerTemplate::Conditional{}}, subschemas,
pair.second.at(index), walker, resolver, new_dialect, type,
level + 1, orphan);
}
}

break;

case sourcemeta::core::SchemaKeywordType::
ApplicatorMembersTraversePropertyStatic:
if (pair.second.is_object()) {
Expand Down Expand Up @@ -176,13 +221,17 @@ auto walk(const std::optional<sourcemeta::core::Pointer> &parent,

break;

case sourcemeta::core::SchemaKeywordType::ApplicatorMembersInPlace:
case sourcemeta::core::SchemaKeywordType::ApplicatorMembersInPlaceSome:
if (pair.second.is_object()) {
for (auto &subpair : pair.second.as_object()) {
sourcemeta::core::Pointer new_pointer{pointer};
new_pointer.emplace_back(pair.first);
new_pointer.emplace_back(subpair.first);
walk(pointer, new_pointer, instance_location, {}, subschemas,
auto new_instance_location{instance_location};
new_instance_location.emplace_back(
sourcemeta::core::PointerTemplate::Conditional{});
walk(pointer, new_pointer, new_instance_location,
{sourcemeta::core::PointerTemplate::Conditional{}}, subschemas,
subpair.second, walker, resolver, new_dialect, type, level + 1,
orphan);
}
Expand Down
Loading

0 comments on commit 2f9a11e

Please sign in to comment.