Skip to content

Commit acc3bc1

Browse files
committed
[WIP] Throw a better exception on invalid $ref targets
See: sourcemeta/jsonschema#624 Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 132dcca commit acc3bc1

File tree

5 files changed

+43
-16
lines changed

5 files changed

+43
-16
lines changed

src/compiler/compile.cc

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,8 @@ auto compile(const sourcemeta::core::JSON &schema,
342342
entry.type != sourcemeta::core::SchemaFrame::LocationType::Resource &&
343343
entry.type != sourcemeta::core::SchemaFrame::LocationType::Anchor) {
344344
assert(reference_pointer != nullptr);
345-
throw sourcemeta::core::SchemaReferenceError(
346-
destination_uri, to_pointer(*reference_pointer),
347-
"The target of the reference is not a valid schema");
345+
throw CompilerReferenceTargetNotSchemaError(
346+
destination_uri, to_pointer(*reference_pointer));
348347
}
349348

350349
auto subschema{sourcemeta::core::get(context.root, entry.pointer)};
@@ -441,12 +440,7 @@ auto compile(const Context &context, const SchemaContext &schema_context,
441440
const auto &entry{context.frame.locations().at(
442441
{sourcemeta::core::SchemaReferenceType::Static, destination})};
443442
const auto &new_schema{get(context.root, entry.pointer)};
444-
445-
if (!is_schema(new_schema)) {
446-
throw sourcemeta::core::SchemaReferenceError(
447-
destination, to_pointer(schema_context.relative_pointer),
448-
"The target of the reference is not a valid schema");
449-
}
443+
assert(is_schema(new_schema));
450444

451445
const sourcemeta::core::WeakPointer destination_pointer{
452446
dynamic_context.keyword.empty()

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

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
#include <sourcemeta/core/jsonpointer.h>
99
#include <sourcemeta/core/uri.h>
1010

11-
#include <exception> // std::exception
12-
#include <string> // std::string
13-
#include <utility> // std::move
11+
#include <exception> // std::exception
12+
#include <string> // std::string
13+
#include <string_view> // std::string_view
14+
#include <utility> // std::move
1415

1516
namespace sourcemeta::blaze {
1617

@@ -48,6 +49,34 @@ class SOURCEMETA_BLAZE_COMPILER_EXPORT CompilerError : public std::exception {
4849
std::string message_;
4950
};
5051

52+
/// @ingroup jsonschema
53+
/// An error that represents a reference target that is not a valid schema
54+
class SOURCEMETA_BLAZE_COMPILER_EXPORT CompilerReferenceTargetNotSchemaError
55+
: public std::exception {
56+
public:
57+
CompilerReferenceTargetNotSchemaError(
58+
const std::string_view identifier,
59+
sourcemeta::core::Pointer schema_location)
60+
: identifier_{identifier}, schema_location_{std::move(schema_location)} {}
61+
62+
[[nodiscard]] auto what() const noexcept -> const char * override {
63+
return "The target of the reference is not a valid schema";
64+
}
65+
66+
[[nodiscard]] auto identifier() const noexcept -> const std::string & {
67+
return this->identifier_;
68+
}
69+
70+
[[nodiscard]] auto location() const noexcept
71+
-> const sourcemeta::core::Pointer & {
72+
return this->schema_location_;
73+
}
74+
75+
private:
76+
std::string identifier_;
77+
sourcemeta::core::Pointer schema_location_;
78+
};
79+
5180
#if defined(_MSC_VER)
5281
#pragma warning(default : 4251 4275)
5382
#endif

test/evaluator/evaluator_draft4_test.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9087,7 +9087,8 @@ TEST(Evaluator_draft4, reference_from_unknown_keyword) {
90879087
sourcemeta::blaze::compile(schema, sourcemeta::core::schema_walker,
90889088
sourcemeta::core::schema_resolver,
90899089
sourcemeta::blaze::default_schema_compiler);
9090-
} catch (const sourcemeta::core::SchemaReferenceError &error) {
9090+
} catch (
9091+
const sourcemeta::blaze::CompilerReferenceTargetNotSchemaError &error) {
90919092
EXPECT_EQ(error.identifier(), "#/$defs/bar");
90929093
EXPECT_EQ(error.location(),
90939094
sourcemeta::core::Pointer({"properties", "foo", "$ref"}));
@@ -9163,7 +9164,8 @@ TEST(Evaluator_draft4, ref_to_non_schema) {
91639164
sourcemeta::core::schema_resolver,
91649165
sourcemeta::blaze::default_schema_compiler);
91659166
FAIL() << "The compile function was expected to throw";
9166-
} catch (const sourcemeta::core::SchemaReferenceError &error) {
9167+
} catch (
9168+
const sourcemeta::blaze::CompilerReferenceTargetNotSchemaError &error) {
91679169
EXPECT_EQ(error.identifier(), "#/definitions/array/items");
91689170
EXPECT_EQ(sourcemeta::core::to_string(error.location()),
91699171
"/additionalProperties/$ref");

test/evaluator/evaluator_draft6_test.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1952,7 +1952,8 @@ TEST(Evaluator_draft6, reference_from_unknown_keyword) {
19521952
sourcemeta::blaze::compile(schema, sourcemeta::core::schema_walker,
19531953
sourcemeta::core::schema_resolver,
19541954
sourcemeta::blaze::default_schema_compiler);
1955-
} catch (const sourcemeta::core::SchemaReferenceError &error) {
1955+
} catch (
1956+
const sourcemeta::blaze::CompilerReferenceTargetNotSchemaError &error) {
19561957
EXPECT_EQ(error.identifier(), "#/$defs/bar");
19571958
EXPECT_EQ(error.location(),
19581959
sourcemeta::core::Pointer({"properties", "foo", "$ref"}));

test/evaluator/evaluator_draft7_test.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,8 @@ TEST(Evaluator_draft7, reference_from_unknown_keyword) {
536536
sourcemeta::blaze::compile(schema, sourcemeta::core::schema_walker,
537537
sourcemeta::core::schema_resolver,
538538
sourcemeta::blaze::default_schema_compiler);
539-
} catch (const sourcemeta::core::SchemaReferenceError &error) {
539+
} catch (
540+
const sourcemeta::blaze::CompilerReferenceTargetNotSchemaError &error) {
540541
EXPECT_EQ(error.identifier(), "#/$defs/bar");
541542
EXPECT_EQ(error.location(),
542543
sourcemeta::core::Pointer({"properties", "foo", "$ref"}));

0 commit comments

Comments
 (0)