Skip to content

Commit 9a4cb4e

Browse files
committed
FIX ATTEMPT
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent e8ad3ee commit 9a4cb4e

File tree

2 files changed

+52
-18
lines changed

2 files changed

+52
-18
lines changed

src/core/jsonschema/frame.cc

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -539,12 +539,11 @@ auto SchemaFrame::analyse(const JSON &root, const SchemaWalker &walker,
539539
entry.parent = path.concat(relative_entry.parent.value());
540540
}
541541

542-
// Dialect
542+
// Dialect and Base dialect
543543
assert(entry.dialect.has_value());
544-
base_dialects.insert({entry.pointer, {entry.dialect.value()}});
545-
546-
// Base dialect
547544
assert(entry.base_dialect.has_value());
545+
base_dialects.insert(
546+
{entry.pointer, {entry.dialect.value(), entry.base_dialect.value()}});
548547

549548
// Schema identifier
550549
std::optional<JSON::String> id{sourcemeta::core::identify(
@@ -651,6 +650,21 @@ auto SchemaFrame::analyse(const JSON &root, const SchemaWalker &walker,
651650
}
652651
}
653652
}
653+
} else if (!entry.id.has_value() &&
654+
entry.common.subschema.get().is_object() &&
655+
entry.common.subschema.get().defines("$schema") &&
656+
ref_overrides_adjacent_keywords(
657+
entry.common.base_dialect.value())) {
658+
// Handle $schema without $id in Draft 7 and older
659+
// Already inserted into base_dialects with both dialect and
660+
// base_dialect above Just need to insert into base_uris with parent's
661+
// base URI
662+
const auto bases{
663+
find_nearest_bases(base_uris, entry.common.pointer, std::nullopt)};
664+
if (!bases.first.empty()) {
665+
const auto &parent_base{bases.first.front()};
666+
base_uris.insert({entry.common.pointer, {parent_base}});
667+
}
654668
}
655669

656670
if (this->mode_ != SchemaFrame::Mode::Locations) {
@@ -800,7 +814,7 @@ auto SchemaFrame::analyse(const JSON &root, const SchemaWalker &walker,
800814

801815
const auto dialects{
802816
find_nearest_bases(base_dialects, pointer, root_dialect)};
803-
assert(dialects.first.size() == 1);
817+
assert(dialects.first.size() >= 1);
804818

805819
auto every_base_result = find_every_base(base_uris, pointer);
806820

@@ -826,10 +840,15 @@ auto SchemaFrame::analyse(const JSON &root, const SchemaWalker &walker,
826840
const auto maybe_base_entry{this->locations_.find(
827841
{SchemaReferenceType::Static, current_base})};
828842

843+
// Look up base_dialect from base_dialects (second element if present)
844+
const auto base_dialect_result{
845+
find_nearest_bases(base_dialects, pointer, root_dialect)};
829846
const auto current_base_dialect{
830-
maybe_base_entry == this->locations_.cend()
831-
? root_base_dialect.value()
832-
: maybe_base_entry->second.base_dialect};
847+
base_dialect_result.first.size() >= 2
848+
? base_dialect_result.first[1]
849+
: (maybe_base_entry == this->locations_.cend()
850+
? root_base_dialect.value()
851+
: maybe_base_entry->second.base_dialect)};
833852

834853
const auto subschema{subschemas.find(pointer)};
835854

src/core/jsonschema/walker.cc

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ auto walk(const std::optional<sourcemeta::core::Pointer> &parent,
4949
// / base dialect and ignore the invalid standalone `$schema`. The caller has
5050
// enough information to detect those cases and throw an error if they desire
5151
// to be more strict.
52+
//
53+
// However, this is a 2020-12 restriction and we CAN accept `$schema` without
54+
// an identifier on older versions
5255
const auto maybe_current_dialect{
5356
sourcemeta::core::dialect(subschema, dialect)};
5457
assert(maybe_current_dialect.has_value());
@@ -57,13 +60,26 @@ auto walk(const std::optional<sourcemeta::core::Pointer> &parent,
5760
sourcemeta::core::SchemaIdentificationStrategy::Strict,
5861
maybe_current_dialect)};
5962
const auto is_schema_resource{level == 0 || id.has_value()};
60-
const auto current_dialect{is_schema_resource ? maybe_current_dialect.value()
61-
: dialect};
62-
const auto current_base_dialect{
63-
is_schema_resource
64-
? sourcemeta::core::base_dialect(subschema, resolver, current_dialect)
65-
.value_or(base_dialect)
66-
: base_dialect};
63+
const auto has_schema_keyword{subschema.is_object() &&
64+
subschema.defines("$schema")};
65+
const auto subschema_base_dialect{
66+
has_schema_keyword ? sourcemeta::core::base_dialect(subschema, resolver,
67+
maybe_current_dialect)
68+
.value_or(base_dialect)
69+
: base_dialect};
70+
const auto should_process_schema_without_id{
71+
has_schema_keyword &&
72+
ref_overrides_adjacent_keywords(subschema_base_dialect)};
73+
const auto current_dialect{is_schema_resource ||
74+
should_process_schema_without_id
75+
? maybe_current_dialect.value()
76+
: dialect};
77+
const auto current_base_dialect{is_schema_resource ||
78+
should_process_schema_without_id
79+
? subschema_base_dialect
80+
: base_dialect};
81+
const auto current_ref_overrides{
82+
ref_overrides_adjacent_keywords(current_base_dialect)};
6783

6884
const auto vocabularies{sourcemeta::core::vocabularies(
6985
resolver, current_base_dialect, current_dialect)};
@@ -88,9 +104,8 @@ auto walk(const std::optional<sourcemeta::core::Pointer> &parent,
88104
return;
89105
}
90106

91-
const auto has_overriding_ref{
92-
subschema.defines("$ref") &&
93-
ref_overrides_adjacent_keywords(current_base_dialect)};
107+
const auto has_overriding_ref{subschema.defines("$ref") &&
108+
current_ref_overrides};
94109
for (auto &pair : subschema.as_object()) {
95110
const auto keyword_info{walker(pair.first, vocabularies)};
96111

0 commit comments

Comments
 (0)