Skip to content

Commit ac8ce8d

Browse files
committed
[WIP] Add rich error information to every possible exception
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 2e3342c commit ac8ce8d

File tree

57 files changed

+611
-451
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+611
-451
lines changed

DEPENDENCIES

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02
2-
core https://github.com/sourcemeta/core 8b34af868820407091f108486798b4c73dec6631
2+
core https://github.com/sourcemeta/core eababe4f4a967bfa546146c8531b8668913a3880
33
jsonbinpack https://github.com/sourcemeta/jsonbinpack abd40e41050d14d74af1fddb5c397de5cca3b13c
44
blaze https://github.com/sourcemeta/blaze bfdc479b5ae0c17a356be5f42dcc713ab31f976a
55
hydra https://github.com/sourcemeta/hydra af9f2c54709d620872ead0c3f8f683c15a0fa702

src/command_bundle.cc

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,52 @@ auto sourcemeta::jsonschema::bundle(const sourcemeta::core::Options &options)
2525
const auto configuration_path{find_configuration(schema_path)};
2626
const auto &configuration{read_configuration(options, configuration_path)};
2727
const auto dialect{default_dialect(options, configuration)};
28-
const auto &custom_resolver{
29-
resolver(options, options.contains("http"), dialect, configuration)};
3028
auto schema{sourcemeta::core::read_yaml_or_json(schema_path)};
3129

32-
sourcemeta::core::bundle(schema, sourcemeta::core::schema_official_walker,
33-
custom_resolver, dialect,
34-
sourcemeta::core::URI::from_path(
35-
sourcemeta::core::weakly_canonical(schema_path))
36-
.recompose());
37-
38-
if (options.contains("without-id")) {
39-
sourcemeta::jsonschema::LOG_WARNING()
40-
<< "You are opting in to remove schema identifiers in "
41-
"the bundled schema.\n"
42-
<< "The only legit use case of this advanced feature we know of "
43-
"is to workaround\n"
44-
<< "non-compliant JSON Schema implementations such as Visual "
45-
"Studio Code.\n"
46-
<< "Otherwise, this is not needed and may harm other use "
47-
"cases. For example,\n"
48-
<< "you will be unable to reference the resulting schema from "
49-
"other schemas\n"
50-
<< "using the --resolve/-r option.\n";
51-
sourcemeta::core::for_editor(schema,
52-
sourcemeta::core::schema_official_walker,
53-
custom_resolver, dialect);
30+
try {
31+
const auto &custom_resolver{
32+
resolver(options, options.contains("http"), dialect, configuration)};
33+
sourcemeta::core::bundle(
34+
schema, sourcemeta::core::schema_official_walker, custom_resolver,
35+
dialect,
36+
sourcemeta::core::URI::from_path(
37+
sourcemeta::core::weakly_canonical(schema_path))
38+
.recompose());
39+
40+
if (options.contains("without-id")) {
41+
sourcemeta::jsonschema::LOG_WARNING()
42+
<< "You are opting in to remove schema identifiers in "
43+
"the bundled schema.\n"
44+
<< "The only legit use case of this advanced feature we know of "
45+
"is to workaround\n"
46+
<< "non-compliant JSON Schema implementations such as Visual "
47+
"Studio Code.\n"
48+
<< "Otherwise, this is not needed and may harm other use "
49+
"cases. For example,\n"
50+
<< "you will be unable to reference the resulting schema from "
51+
"other schemas\n"
52+
<< "using the --resolve/-r option.\n";
53+
sourcemeta::core::for_editor(schema,
54+
sourcemeta::core::schema_official_walker,
55+
custom_resolver, dialect);
56+
}
57+
58+
sourcemeta::core::format(schema, sourcemeta::core::schema_official_walker,
59+
custom_resolver, dialect);
60+
} catch (
61+
const sourcemeta::core::SchemaRelativeMetaschemaResolutionError &error) {
62+
throw FileError<sourcemeta::core::SchemaRelativeMetaschemaResolutionError>(
63+
schema_path, error);
64+
} catch (const sourcemeta::core::SchemaResolutionError &error) {
65+
throw FileError<sourcemeta::core::SchemaResolutionError>(schema_path,
66+
error);
67+
} catch (const sourcemeta::core::SchemaUnknownBaseDialectError &error) {
68+
throw FileError<sourcemeta::core::SchemaUnknownBaseDialectError>(
69+
schema_path);
70+
} catch (const sourcemeta::core::SchemaError &error) {
71+
throw FileError<sourcemeta::core::SchemaError>(schema_path, error.what());
5472
}
5573

56-
sourcemeta::core::format(schema, sourcemeta::core::schema_official_walker,
57-
custom_resolver, dialect);
5874
sourcemeta::core::prettify(schema, std::cout);
5975
std::cout << "\n";
6076
}

src/command_compile.cc

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ auto sourcemeta::jsonschema::compile(const sourcemeta::core::Options &options)
2424
const auto configuration_path{find_configuration(schema_path)};
2525
const auto &configuration{read_configuration(options, configuration_path)};
2626
const auto dialect{default_dialect(options, configuration)};
27-
const auto &custom_resolver{
28-
resolver(options, options.contains("http"), dialect, configuration)};
2927

3028
const auto schema{sourcemeta::core::read_yaml_or_json(schema_path)};
3129

@@ -34,15 +32,33 @@ auto sourcemeta::jsonschema::compile(const sourcemeta::core::Options &options)
3432
}
3533

3634
const auto fast_mode{options.contains("fast")};
37-
const auto schema_template{sourcemeta::blaze::compile(
38-
schema, sourcemeta::core::schema_official_walker, custom_resolver,
39-
sourcemeta::blaze::default_schema_compiler,
40-
fast_mode ? sourcemeta::blaze::Mode::FastValidation
41-
: sourcemeta::blaze::Mode::Exhaustive,
42-
dialect,
43-
sourcemeta::core::URI::from_path(
44-
sourcemeta::core::weakly_canonical(schema_path))
45-
.recompose())};
35+
36+
sourcemeta::blaze::Template schema_template;
37+
try {
38+
const auto &custom_resolver{
39+
resolver(options, options.contains("http"), dialect, configuration)};
40+
schema_template = sourcemeta::blaze::compile(
41+
schema, sourcemeta::core::schema_official_walker, custom_resolver,
42+
sourcemeta::blaze::default_schema_compiler,
43+
fast_mode ? sourcemeta::blaze::Mode::FastValidation
44+
: sourcemeta::blaze::Mode::Exhaustive,
45+
dialect,
46+
sourcemeta::core::URI::from_path(
47+
sourcemeta::core::weakly_canonical(schema_path))
48+
.recompose());
49+
} catch (
50+
const sourcemeta::core::SchemaRelativeMetaschemaResolutionError &error) {
51+
throw FileError<sourcemeta::core::SchemaRelativeMetaschemaResolutionError>(
52+
schema_path, error);
53+
} catch (const sourcemeta::core::SchemaResolutionError &error) {
54+
throw FileError<sourcemeta::core::SchemaResolutionError>(schema_path,
55+
error);
56+
} catch (const sourcemeta::core::SchemaUnknownBaseDialectError &error) {
57+
throw FileError<sourcemeta::core::SchemaUnknownBaseDialectError>(
58+
schema_path);
59+
} catch (const sourcemeta::core::SchemaError &error) {
60+
throw FileError<sourcemeta::core::SchemaError>(schema_path, error.what());
61+
}
4662

4763
const auto template_json{sourcemeta::blaze::to_json(schema_template)};
4864
if (options.contains("minify")) {

src/command_fmt.cc

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -33,42 +33,58 @@ auto sourcemeta::jsonschema::fmt(const sourcemeta::core::Options &options)
3333
LOG_VERBOSE(options) << "Formatting: " << entry.first.string() << "\n";
3434
}
3535

36-
const auto configuration_path{find_configuration(entry.first)};
37-
const auto &configuration{read_configuration(options, configuration_path)};
38-
const auto dialect{default_dialect(options, configuration)};
39-
const auto &custom_resolver{
40-
resolver(options, options.contains("http"), dialect, configuration)};
36+
try {
37+
const auto configuration_path{find_configuration(entry.first)};
38+
const auto &configuration{
39+
read_configuration(options, configuration_path)};
40+
const auto dialect{default_dialect(options, configuration)};
41+
const auto &custom_resolver{
42+
resolver(options, options.contains("http"), dialect, configuration)};
4143

42-
std::ostringstream expected;
43-
if (options.contains("keep-ordering")) {
44-
sourcemeta::core::prettify(entry.second, expected, indentation);
45-
} else {
46-
auto copy = entry.second;
47-
sourcemeta::core::format(copy, sourcemeta::core::schema_official_walker,
48-
custom_resolver, dialect);
49-
sourcemeta::core::prettify(copy, expected, indentation);
50-
}
51-
expected << "\n";
44+
std::ostringstream expected;
45+
if (options.contains("keep-ordering")) {
46+
sourcemeta::core::prettify(entry.second, expected, indentation);
47+
} else {
48+
auto copy = entry.second;
49+
sourcemeta::core::format(copy, sourcemeta::core::schema_official_walker,
50+
custom_resolver, dialect);
51+
sourcemeta::core::prettify(copy, expected, indentation);
52+
}
53+
expected << "\n";
5254

53-
std::ifstream current_stream{entry.first};
54-
std::ostringstream current;
55-
current << current_stream.rdbuf();
55+
std::ifstream current_stream{entry.first};
56+
std::ostringstream current;
57+
current << current_stream.rdbuf();
5658

57-
if (options.contains("check")) {
58-
if (current.str() == expected.str()) {
59-
LOG_VERBOSE(options) << "ok: " << entry.first.string() << "\n";
60-
} else if (output_json) {
61-
failed_files.push_back(entry.first.string());
62-
result = false;
59+
if (options.contains("check")) {
60+
if (current.str() == expected.str()) {
61+
LOG_VERBOSE(options) << "ok: " << entry.first.string() << "\n";
62+
} else if (output_json) {
63+
failed_files.push_back(entry.first.string());
64+
result = false;
65+
} else {
66+
std::cerr << "fail: " << entry.first.string() << "\n";
67+
result = false;
68+
}
6369
} else {
64-
std::cerr << "fail: " << entry.first.string() << "\n";
65-
result = false;
66-
}
67-
} else {
68-
if (current.str() != expected.str()) {
69-
std::ofstream output{entry.first};
70-
output << expected.str();
70+
if (current.str() != expected.str()) {
71+
std::ofstream output{entry.first};
72+
output << expected.str();
73+
}
7174
}
75+
} catch (const sourcemeta::core::SchemaRelativeMetaschemaResolutionError
76+
&error) {
77+
throw FileError<
78+
sourcemeta::core::SchemaRelativeMetaschemaResolutionError>(
79+
entry.first, error);
80+
} catch (const sourcemeta::core::SchemaResolutionError &error) {
81+
throw FileError<sourcemeta::core::SchemaResolutionError>(entry.first,
82+
error);
83+
} catch (const sourcemeta::core::SchemaUnknownBaseDialectError &error) {
84+
throw FileError<sourcemeta::core::SchemaUnknownBaseDialectError>(
85+
entry.first);
86+
} catch (const sourcemeta::core::SchemaError &error) {
87+
throw FileError<sourcemeta::core::SchemaError>(entry.first, error.what());
7288
}
7389
}
7490

src/command_inspect.cc

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -159,27 +159,41 @@ auto sourcemeta::jsonschema::inspect(const sourcemeta::core::Options &options)
159159
const auto configuration_path{find_configuration(schema_path)};
160160
const auto &configuration{read_configuration(options, configuration_path)};
161161
const auto dialect{default_dialect(options, configuration)};
162-
const auto &custom_resolver{
163-
resolver(options, options.contains("http"), dialect, configuration)};
164-
165-
const auto identifier{
166-
sourcemeta::core::identify(schema, custom_resolver, dialect)};
167162

168163
sourcemeta::core::SchemaFrame frame{
169164
sourcemeta::core::SchemaFrame::Mode::Instances};
170165

171-
frame.analyse(
172-
schema, sourcemeta::core::schema_official_walker, custom_resolver,
173-
dialect,
174-
175-
// Only use the file-based URI if the schema has no identifier,
176-
// as otherwise we make the output unnecessarily hard when it
177-
// comes to debugging schemas
178-
identifier.has_value()
179-
? std::optional<sourcemeta::core::JSON::String>(std::nullopt)
180-
: sourcemeta::core::URI::from_path(
181-
sourcemeta::core::weakly_canonical(schema_path))
182-
.recompose());
166+
try {
167+
const auto &custom_resolver{
168+
resolver(options, options.contains("http"), dialect, configuration)};
169+
const auto identifier{
170+
sourcemeta::core::identify(schema, custom_resolver, dialect)};
171+
172+
frame.analyse(
173+
schema, sourcemeta::core::schema_official_walker, custom_resolver,
174+
dialect,
175+
176+
// Only use the file-based URI if the schema has no identifier,
177+
// as otherwise we make the output unnecessarily hard when it
178+
// comes to debugging schemas
179+
identifier.has_value()
180+
? std::optional<sourcemeta::core::JSON::String>(std::nullopt)
181+
: sourcemeta::core::URI::from_path(
182+
sourcemeta::core::weakly_canonical(schema_path))
183+
.recompose());
184+
} catch (
185+
const sourcemeta::core::SchemaRelativeMetaschemaResolutionError &error) {
186+
throw FileError<sourcemeta::core::SchemaRelativeMetaschemaResolutionError>(
187+
schema_path, error);
188+
} catch (const sourcemeta::core::SchemaResolutionError &error) {
189+
throw FileError<sourcemeta::core::SchemaResolutionError>(schema_path,
190+
error);
191+
} catch (const sourcemeta::core::SchemaUnknownBaseDialectError &error) {
192+
throw FileError<sourcemeta::core::SchemaUnknownBaseDialectError>(
193+
schema_path);
194+
} catch (const sourcemeta::core::SchemaError &error) {
195+
throw FileError<sourcemeta::core::SchemaError>(schema_path, error.what());
196+
}
183197

184198
if (options.contains("json")) {
185199
sourcemeta::core::prettify(frame.to_json(positions), std::cout);

0 commit comments

Comments
 (0)