From e22ce4506564f3630e4cd63dc0795115df90be71 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 21 Jun 2020 13:28:00 +0200 Subject: [PATCH] :children_crossing: improve diagnostics --- include/nlohmann/detail/input/lexer.hpp | 7 ++++++- single_include/nlohmann/json.hpp | 7 ++++++- test/src/unit-class_lexer.cpp | 25 +++++++++++++++++++++++++ test/src/unit-class_parser.cpp | 6 ++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/input/lexer.hpp b/include/nlohmann/detail/input/lexer.hpp index 9dba2972..580b1c22 100644 --- a/include/nlohmann/detail/input/lexer.hpp +++ b/include/nlohmann/detail/input/lexer.hpp @@ -865,7 +865,10 @@ class lexer : public lexer_base { case std::char_traits::eof(): case '\0': + { + error_message = "invalid comment; missing closing '*/'"; return false; + } case '*': { @@ -890,7 +893,10 @@ class lexer : public lexer_base // unexpected character after reading '/' default: + { + error_message = "invalid comment; expecting '/' or '*' after '/'"; return false; + } } } @@ -1504,7 +1510,6 @@ scan_number_done: { if (not scan_comment()) { - error_message = "invalid comment"; return token_type::parse_error; } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index f4fe8642..cdc3de09 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -8932,7 +8932,10 @@ class lexer : public lexer_base { case std::char_traits::eof(): case '\0': + { + error_message = "invalid comment; missing closing '*/'"; return false; + } case '*': { @@ -8957,7 +8960,10 @@ class lexer : public lexer_base // unexpected character after reading '/' default: + { + error_message = "invalid comment; expecting '/' or '*' after '/'"; return false; + } } } @@ -9571,7 +9577,6 @@ scan_number_done: { if (not scan_comment()) { - error_message = "invalid comment"; return token_type::parse_error; } diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index aee4703f..d8304ccf 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -45,6 +45,15 @@ json::lexer::token_type scan_string(const char* s, const bool ignore_comments) } } +std::string get_error_message(const char* s, const bool ignore_comments = false); +std::string get_error_message(const char* s, const bool ignore_comments) +{ + auto ia = nlohmann::detail::input_adapter(s); + auto lexer = nlohmann::detail::lexer(std::move(ia), ignore_comments); + lexer.scan(); + return lexer.get_error_message(); +} + TEST_CASE("lexer class") { SECTION("scan") @@ -185,32 +194,48 @@ TEST_CASE("lexer class") SECTION("fail on comments") { CHECK((scan_string("/", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/", false) == "invalid literal"); CHECK((scan_string("/!", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/!", false) == "invalid literal"); CHECK((scan_string("/*", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/*", false) == "invalid literal"); CHECK((scan_string("/**", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/**", false) == "invalid literal"); CHECK((scan_string("//", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("//", false) == "invalid literal"); CHECK((scan_string("/**/", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/**/", false) == "invalid literal"); CHECK((scan_string("/** /", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/** /", false) == "invalid literal"); CHECK((scan_string("/***/", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/***/", false) == "invalid literal"); CHECK((scan_string("/* true */", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/* true */", false) == "invalid literal"); CHECK((scan_string("/*/**/", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/*/**/", false) == "invalid literal"); CHECK((scan_string("/*/* */", false) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/*/* */", false) == "invalid literal"); } SECTION("ignore comments") { CHECK((scan_string("/", true) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/", true) == "invalid comment; expecting '/' or '*' after '/'"); CHECK((scan_string("/!", true) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/!", true) == "invalid comment; expecting '/' or '*' after '/'"); CHECK((scan_string("/*", true) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/*", true) == "invalid comment; missing closing '*/'"); CHECK((scan_string("/**", true) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/**", true) == "invalid comment; missing closing '*/'"); CHECK((scan_string("//", true) == json::lexer::token_type::end_of_input)); CHECK((scan_string("/**/", true) == json::lexer::token_type::end_of_input)); CHECK((scan_string("/** /", true) == json::lexer::token_type::parse_error)); + CHECK(get_error_message("/** /", true) == "invalid comment; missing closing '*/'"); CHECK((scan_string("/***/", true) == json::lexer::token_type::end_of_input)); CHECK((scan_string("/* true */", true) == json::lexer::token_type::end_of_input)); diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index de5c9638..da16ffca 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -1877,4 +1877,10 @@ TEST_CASE("parser class") } } } + + SECTION("error messages for comments") + { + CHECK_THROWS_WITH_AS(json::parse("/a", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid comment; expecting '/' or '*' after '/'; last read: '/a'", json::parse_error); + CHECK_THROWS_WITH_AS(json::parse("/*", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid comment; missing closing '*/'; last read: '/*'", json::parse_error); + } }