|
7 | 7 |
|
8 | 8 | #include "ir_default_compiler.h" |
9 | 9 |
|
10 | | -namespace sourcemeta::codegen { |
| 10 | +namespace { |
| 11 | + |
| 12 | +auto is_validation_subschema( |
| 13 | + const sourcemeta::core::SchemaFrame &frame, |
| 14 | + const sourcemeta::core::SchemaFrame::Location &location, |
| 15 | + const sourcemeta::core::SchemaWalker &walker, |
| 16 | + const sourcemeta::core::SchemaResolver &resolver) -> bool { |
| 17 | + if (!location.parent.has_value()) { |
| 18 | + return false; |
| 19 | + } |
11 | 20 |
|
12 | | -static auto |
13 | | -is_validation_only_location(const sourcemeta::core::WeakPointer &pointer) |
14 | | - -> bool { |
15 | | - static const std::unordered_set<std::string_view> validation_only_keywords{ |
16 | | - "propertyNames", "contains"}; |
17 | | - static const std::unordered_set<std::string_view> container_keywords{ |
18 | | - "properties", "patternProperties", "$defs", "definitions"}; |
19 | | - for (std::size_t index = 0; index < pointer.size(); ++index) { |
20 | | - const auto &token{pointer.at(index)}; |
21 | | - if (!token.is_property() || |
22 | | - !validation_only_keywords.contains(token.to_property())) { |
23 | | - continue; |
24 | | - } |
| 21 | + const auto &parent{location.parent.value()}; |
| 22 | + if (parent.size() >= location.pointer.size()) { |
| 23 | + return false; |
| 24 | + } |
25 | 25 |
|
26 | | - if (index == 0 || !pointer.at(index - 1).is_property() || |
27 | | - !container_keywords.contains(pointer.at(index - 1).to_property())) { |
28 | | - return true; |
29 | | - } |
| 26 | + const auto &keyword_token{location.pointer.at(parent.size())}; |
| 27 | + if (!keyword_token.is_property()) { |
| 28 | + return false; |
30 | 29 | } |
31 | 30 |
|
32 | | - return false; |
| 31 | + const auto parent_location{frame.traverse(parent)}; |
| 32 | + if (!parent_location.has_value()) { |
| 33 | + return false; |
| 34 | + } |
| 35 | + |
| 36 | + const auto vocabularies{ |
| 37 | + frame.vocabularies(parent_location.value().get(), resolver)}; |
| 38 | + const auto &walker_result{walker(keyword_token.to_property(), vocabularies)}; |
| 39 | + using Type = sourcemeta::core::SchemaKeywordType; |
| 40 | + if (walker_result.type == Type::ApplicatorValueTraverseAnyPropertyKey || |
| 41 | + walker_result.type == Type::ApplicatorValueTraverseAnyItem) { |
| 42 | + return true; |
| 43 | + } |
| 44 | + |
| 45 | + return is_validation_subschema(frame, parent_location.value().get(), walker, |
| 46 | + resolver); |
33 | 47 | } |
34 | 48 |
|
| 49 | +} // anonymous namespace |
| 50 | + |
| 51 | +namespace sourcemeta::codegen { |
| 52 | + |
35 | 53 | auto compile(const sourcemeta::core::JSON &input, |
36 | 54 | const sourcemeta::core::SchemaWalker &walker, |
37 | 55 | const sourcemeta::core::SchemaResolver &resolver, |
@@ -91,8 +109,8 @@ auto compile(const sourcemeta::core::JSON &input, |
91 | 109 | } |
92 | 110 |
|
93 | 111 | // Skip subschemas under validation-only keywords that do not contribute |
94 | | - // to the type structure |
95 | | - if (is_validation_only_location(location.pointer)) { |
| 112 | + // to the type structure (like `contains`) |
| 113 | + if (is_validation_subschema(frame, location, walker, resolver)) { |
96 | 114 | continue; |
97 | 115 | } |
98 | 116 |
|
|
0 commit comments