Просмотр исходного кода

fix: handling of rootless $id and unevaluated->$ref

Sam Jaffe 1 год назад
Родитель
Сommit
92418f9596
2 измененных файлов с 22 добавлено и 7 удалено
  1. 12 4
      include/jvalidate/reference_handler.h
  2. 10 3
      include/jvalidate/validation_visitor.h

+ 12 - 4
include/jvalidate/reference_handler.h

@@ -56,7 +56,6 @@ public:
 
   detail::Reference canonicalize(detail::Reference const & ref,
                                  detail::Reference const & parent) const {
-
     // Relative URI, not in the HEREDOC (or we set an $id)
     if (ref.uri().empty() and ref.anchor().empty()) {
       return detail::Reference(canonicalize(parent).root(), ref.pointer());
@@ -64,7 +63,15 @@ public:
 
     // TODO(samjaffe): Clean this clause up
     URI uri = ref.uri().empty() ? parent.root().uri() : ref.uri();
-    if (uri.is_rootless() && not uri.empty()) {
+    if (uri.empty()) {
+      auto parent_uri = canonicalize(parent).uri();
+      if (parent_uri == parent.uri() && parent.uri().empty()) {
+        auto it = absolute_to_canonical_.find(detail::Reference());
+        if (it != absolute_to_canonical_.end()) {
+          uri = it->second.uri();
+        }
+      }
+    } else if (uri.is_rootless()) {
       auto parent_uri = canonicalize(parent).uri();
       if (parent_uri == parent.uri() && parent.uri().empty()) {
         auto it = absolute_to_canonical_.find(detail::Reference());
@@ -131,9 +138,10 @@ private:
       root = detail::RootReference(schema[id].as_string());
       if (root.uri().empty()) {
         root = detail::RootReference(where.uri(), root.anchor());
-      } else if (root.uri().is_rootless() && not where.uri().empty()) {
-        // TODO(samjaffe): Should there also be something for is_relative?
+      } else if (root.uri().is_relative() && not where.uri().empty()) {
         root = detail::RootReference(where.uri().parent() / root.uri(), root.anchor());
+      } else if (root.uri().is_rootless() && not where.uri().empty()) {
+        root = detail::RootReference(where.uri().root() / root.uri(), root.anchor());
       }
 
       cache(root, where, json);

+ 10 - 3
include/jvalidate/validation_visitor.h

@@ -457,6 +457,10 @@ private:
     result_->add_error(where_, schema_path_, ss.str());
   }
 
+  template <typename C> static void merge_visited(C & to, C const & from) {
+    to.insert(from.begin(), from.end());
+  }
+
   ValidationVisitor(A const & json, schema::Node const & schema, ValidationConfig const & cfg,
                     std::unordered_map<std::string, RE> & regex_cache,
                     detail::Pointer const & where, detail::Pointer const & schema_path,
@@ -467,9 +471,12 @@ private:
   template <typename K>
   Status validate_subschema(schema::Node const * subschema, K const & key) const {
     EXPECT(subschema != &schema_); // TODO(samjaffe) - Figure out what's causing this infinite loop
-    return ValidationVisitor(document_, *subschema, cfg_, regex_cache_, where_, schema_path_ / key,
-                             result_)
-        .validate();
+    ValidationVisitor next(document_, *subschema, cfg_, regex_cache_, where_, schema_path_ / key,
+                           result_);
+    Status rval = next.validate();
+    merge_visited(std::get<0>(visited_), std::get<0>(next.visited_));
+    merge_visited(std::get<1>(visited_), std::get<1>(next.visited_));
+    return rval;
   }
 
   template <typename K>