Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better diagnostics #2562

Merged
merged 45 commits into from
Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
a4d491e
:construction: better diagnostics
nlohmann Jan 1, 2021
7b04786
:construction: add diagnostics to exceptions
nlohmann Jan 2, 2021
ecaab32
:construction: add switch for diagnostics
nlohmann Jan 2, 2021
c6e7fa2
:construction: fix preprocessor check
nlohmann Jan 2, 2021
09cd4ed
:construction: fix preprocessor check
nlohmann Jan 2, 2021
7323a8e
:construction: add tests
nlohmann Jan 2, 2021
ec0b179
:construction: implement more parent relations
nlohmann Jan 2, 2021
294fa34
:bug: fix bug in move constructor
nlohmann Jan 3, 2021
7cdf34b
Merge branch 'develop' of https://github.com/nlohmann/json into diagn…
nlohmann Jan 8, 2021
ddc3bb1
:ok_hand: remove unnecessary assignment from destructor
nlohmann Jan 8, 2021
0617bd2
:ok_hand: fix operator[]
nlohmann Jan 8, 2021
04a0a07
:ok_hand: fix move constructor and move assignment
nlohmann Jan 8, 2021
e4af1dd
:ok_hand: fix operator[]
nlohmann Jan 8, 2021
d4a91b7
:ok_hand: clean operator[]
nlohmann Jan 8, 2021
43cd5c8
:ok_hand: fix constructor
nlohmann Jan 8, 2021
e160749
:recycle: move diagnostic code in header
nlohmann Jan 9, 2021
a834045
:rotating_light: fix warnings
nlohmann Jan 10, 2021
1d6ba22
:recycle: simplify code
nlohmann Jan 10, 2021
9d0150c
:recycle: simplify code
nlohmann Jan 10, 2021
ff57bdc
:bug: fix invariants
nlohmann Jan 10, 2021
10751d1
Merge branch 'develop' of https://github.com/nlohmann/json into diagn…
nlohmann Jan 14, 2021
b9d3aa4
:recycle: split set_parent function
nlohmann Jan 14, 2021
a776216
:memo: fix comment
nlohmann Jan 14, 2021
0d1fb38
:ok_hand: address comment
nlohmann Jan 14, 2021
f803766
:recycle: add iterator set_parent function
nlohmann Jan 14, 2021
1a467a8
Merge branch 'develop' of https://github.com/nlohmann/json into diagn…
nlohmann Jan 15, 2021
b0d8628
:ok_hand: address comments
nlohmann Jan 15, 2021
7633a21
:green_heart: fix build
nlohmann Jan 15, 2021
e9d6411
:bug: proper JSON Pointer escape in diagnostic messages
nlohmann Jan 16, 2021
aeecc09
:white_check_mark: add tests for diagnostics
nlohmann Jan 16, 2021
e23af74
:rotating_light: fix warnings
nlohmann Jan 17, 2021
65107f7
:green_heart: fix build
nlohmann Jan 17, 2021
5ec0980
:green_heart: fix build
nlohmann Jan 17, 2021
3337968
:white_check_mark: improve coverage
nlohmann Jan 17, 2021
d6ff059
:ok_hand: addressed review comments
nlohmann Jan 20, 2021
51ac600
:white_check_mark: improve coverage
nlohmann Jan 21, 2021
d00ad33
:memo: update documentation
nlohmann Jan 21, 2021
7b7da08
:memo: update documentation
nlohmann Jan 23, 2021
380a613
:bug: fix bug in diagnostics_t
nlohmann Jan 23, 2021
c190a72
:ok_hand: apply suggestion
nlohmann Jan 24, 2021
e8dba10
:white_check_mark: add test
nlohmann Jan 24, 2021
74cc0ab
:recycle: remove diagnostics_t class
nlohmann Jan 25, 2021
524eea5
:ok_hand: remove unused template parameter
nlohmann Jan 26, 2021
4917e7c
Merge branch 'develop' of https://github.com/nlohmann/json into diagn…
nlohmann Feb 7, 2021
56a6dec
:twisted_rightwards_arrows: merge develop branch
nlohmann Feb 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${M
option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT})
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
option(JSON_ImplicitConversions "Enable implicit conversions." ON)
option(JSON_Diagnostics "Enable better diagnostic messages." OFF)

##
## CONFIGURATION
Expand Down Expand Up @@ -63,6 +64,10 @@ if (NOT JSON_ImplicitConversions)
message(STATUS "Implicit conversions are disabled")
endif()

if (JSON_Diagnostics)
message(STATUS "Diagnostics enabled")
endif()

##
## TARGET
## create target and add include path
Expand All @@ -79,6 +84,7 @@ target_compile_definitions(
${NLOHMANN_JSON_TARGET_NAME}
INTERFACE
JSON_USE_IMPLICIT_CONVERSIONS=$<BOOL:${JSON_ImplicitConversions}>
JSON_DIAGNOSTICS=$<BOOL:${JSON_Diagnostics}>
)

target_include_directories(
Expand Down
30 changes: 15 additions & 15 deletions include/nlohmann/detail/conversions/from_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
{
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be null, but is " + std::string(j.type_name())));
nlohmann marked this conversation as resolved.
Show resolved Hide resolved
}
n = nullptr;
}
Expand Down Expand Up @@ -58,7 +58,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
}

default:
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be number, but is " + std::string(j.type_name())));
}
}

Expand All @@ -67,7 +67,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
{
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be boolean, but is " + std::string(j.type_name())));
}
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
}
Expand All @@ -77,7 +77,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be string, but is " + std::string(j.type_name())));
}
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
Expand All @@ -93,7 +93,7 @@ void from_json(const BasicJsonType& j, ConstructibleStringType& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be string, but is " + std::string(j.type_name())));
}

s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
Expand Down Expand Up @@ -133,7 +133,7 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(j.type_name())));
}
l.clear();
std::transform(j.rbegin(), j.rend(),
Expand All @@ -150,7 +150,7 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(j.type_name())));
}
l.resize(j.size());
std::transform(j.begin(), j.end(), std::begin(l),
Expand Down Expand Up @@ -241,7 +241,7 @@ void())
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " +
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " +
std::string(j.type_name())));
}

Expand All @@ -253,7 +253,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
{
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be binary, but is " + std::string(j.type_name())));
}

bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
Expand All @@ -265,7 +265,7 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
{
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be object, but is " + std::string(j.type_name())));
}

ConstructibleObjectType ret;
Expand Down Expand Up @@ -319,7 +319,7 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
}

default:
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be number, but is " + std::string(j.type_name())));
}
}

Expand Down Expand Up @@ -348,14 +348,14 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>&
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(j.type_name())));
}
m.clear();
for (const auto& p : j)
{
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(p.type_name())));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
Expand All @@ -368,14 +368,14 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(j.type_name())));
}
m.clear();
for (const auto& p : j)
{
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
JSON_THROW(type_error::create(302, j.diagnostics() + "type must be array, but is " + std::string(p.type_name())));
}
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
}
Expand Down
22 changes: 17 additions & 5 deletions include/nlohmann/detail/input/json_sax.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class json_sax_dom_parser

if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
JSON_THROW(out_of_range::create(408, ref_stack.back()->diagnostics() +
"excessive object size: " + std::to_string(len)));
}

Expand All @@ -245,7 +245,7 @@ class json_sax_dom_parser

if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
JSON_THROW(out_of_range::create(408, ref_stack.back()->diagnostics() +
"excessive array size: " + std::to_string(len)));
}

Expand Down Expand Up @@ -298,12 +298,18 @@ class json_sax_dom_parser
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
#if JSON_DIAGNOSTICS
ref_stack.back()->m_value.array->back().m_parent = ref_stack.back();
#endif
return &(ref_stack.back()->m_value.array->back());
}

JSON_ASSERT(ref_stack.back()->is_object());
JSON_ASSERT(object_element);
*object_element = BasicJsonType(std::forward<Value>(v));
#if JSON_DIAGNOSTICS
object_element->m_parent = ref_stack.back();
#endif
return object_element;
}

Expand Down Expand Up @@ -400,7 +406,7 @@ class json_sax_dom_callback_parser
// check object limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
JSON_THROW(out_of_range::create(408, ref_stack.back()->diagnostics() + "excessive object size: " + std::to_string(len)));
}

return true;
Expand Down Expand Up @@ -463,7 +469,7 @@ class json_sax_dom_callback_parser
// check array limit
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
JSON_THROW(out_of_range::create(408, ref_stack.back()->diagnostics() + "excessive array size: " + std::to_string(len)));
}

return true;
Expand Down Expand Up @@ -574,7 +580,10 @@ class json_sax_dom_callback_parser
// array
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->push_back(std::move(value));
ref_stack.back()->m_value.array->emplace_back(std::move(value));
#if JSON_DIAGNOSTICS
ref_stack.back()->m_value.array->back().m_parent = ref_stack.back();
#endif
return {true, &(ref_stack.back()->m_value.array->back())};
}

Expand All @@ -592,6 +601,9 @@ class json_sax_dom_callback_parser

JSON_ASSERT(object_element);
*object_element = std::move(value);
#if JSON_DIAGNOSTICS
object_element->m_parent = ref_stack.back();
#endif
return {true, object_element};
}

Expand Down
24 changes: 12 additions & 12 deletions include/nlohmann/detail/iterators/iter_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ class iter_impl
}

case value_t::null:
JSON_THROW(invalid_iterator::create(214, "cannot get value"));
JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));

default:
{
Expand All @@ -266,7 +266,7 @@ class iter_impl
return *m_object;
}

JSON_THROW(invalid_iterator::create(214, "cannot get value"));
JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));
}
}
}
Expand Down Expand Up @@ -300,7 +300,7 @@ class iter_impl
return m_object;
}

JSON_THROW(invalid_iterator::create(214, "cannot get value"));
JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));
}
}
}
Expand Down Expand Up @@ -401,7 +401,7 @@ class iter_impl
// if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
JSON_THROW(invalid_iterator::create(212, m_object->diagnostics() + "cannot compare iterators of different containers"));
}

JSON_ASSERT(m_object != nullptr);
Expand Down Expand Up @@ -438,15 +438,15 @@ class iter_impl
// if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
JSON_THROW(invalid_iterator::create(212, m_object->diagnostics() + "cannot compare iterators of different containers"));
}

JSON_ASSERT(m_object != nullptr);

switch (m_object->m_type)
{
case value_t::object:
JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
JSON_THROW(invalid_iterator::create(213, m_object->diagnostics() + "cannot compare order of object iterators"));

case value_t::array:
return (m_it.array_iterator < other.m_it.array_iterator);
Expand Down Expand Up @@ -494,7 +494,7 @@ class iter_impl
switch (m_object->m_type)
{
case value_t::object:
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
JSON_THROW(invalid_iterator::create(209, m_object->diagnostics() + "cannot use offsets with object iterators"));

case value_t::array:
{
Expand Down Expand Up @@ -565,7 +565,7 @@ class iter_impl
switch (m_object->m_type)
{
case value_t::object:
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
JSON_THROW(invalid_iterator::create(209, m_object->diagnostics() + "cannot use offsets with object iterators"));

case value_t::array:
return m_it.array_iterator - other.m_it.array_iterator;
Expand All @@ -586,13 +586,13 @@ class iter_impl
switch (m_object->m_type)
{
case value_t::object:
JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
JSON_THROW(invalid_iterator::create(208, m_object->diagnostics() + "cannot use operator[] for object iterators"));

case value_t::array:
return *std::next(m_it.array_iterator, n);

case value_t::null:
JSON_THROW(invalid_iterator::create(214, "cannot get value"));
JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));

default:
{
Expand All @@ -601,7 +601,7 @@ class iter_impl
return *m_object;
}

JSON_THROW(invalid_iterator::create(214, "cannot get value"));
JSON_THROW(invalid_iterator::create(214, m_object->diagnostics() + "cannot get value"));
}
}
}
Expand All @@ -619,7 +619,7 @@ class iter_impl
return m_it.object_iterator->first;
}

JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
JSON_THROW(invalid_iterator::create(207, m_object->diagnostics() + "cannot use key() for non-object iterators"));
}

/*!
Expand Down
Loading