Skip to content

Commit 6e0f46c

Browse files
committed
Eliminate ParseError.
Another pseudo-extraction from microsoft#1210 ; this means that ExpectedL is the only ExpectedT that exists.
1 parent b652f06 commit 6e0f46c

16 files changed

+107
-168
lines changed

include/vcpkg/base/json.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,8 @@ namespace vcpkg::Json
327327
JsonStyle style;
328328
};
329329

330-
ExpectedT<ParsedJson, std::unique_ptr<ParseError>> parse_file(const ReadOnlyFilesystem&,
331-
const Path&,
332-
std::error_code& ec);
333-
ExpectedT<ParsedJson, std::unique_ptr<ParseError>> parse(StringView text, StringView origin);
330+
ExpectedL<ParsedJson> parse_file(const ReadOnlyFilesystem&, const Path&, std::error_code& ec);
331+
ExpectedL<ParsedJson> parse(StringView text, StringView origin);
334332
ParsedJson parse_file(LineInfo li, const ReadOnlyFilesystem&, const Path&);
335333
ExpectedL<Json::Object> parse_object(StringView text, StringView origin);
336334

include/vcpkg/base/message-data.inc.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -1340,10 +1340,7 @@ DECLARE_MESSAGE(
13401340
(),
13411341
"",
13421342
"Environment variable VCPKG_FORCE_SYSTEM_BINARIES must be set on arm, s390x, ppc64le and riscv platforms.")
1343-
DECLARE_MESSAGE(FormattedParseMessageExpression,
1344-
(msg::value),
1345-
"Example of {value} is 'x64 & windows'",
1346-
"on expression: {value}")
1343+
DECLARE_MESSAGE(FormattedParseMessageExpressionPrefix, (), "", "on expression:")
13471344
DECLARE_MESSAGE(ForMoreHelp,
13481345
(),
13491346
"Printed before a suggestion for the user to run `vcpkg help <topic>`",

include/vcpkg/base/parse.h

+3-38
Original file line numberDiff line numberDiff line change
@@ -9,43 +9,8 @@
99

1010
#include <vcpkg/textrowcol.h>
1111

12-
#include <memory>
1312
#include <string>
1413

15-
namespace vcpkg
16-
{
17-
struct ParseError
18-
{
19-
ParseError(std::string origin, int row, int column, int caret_col, std::string line, LocalizedString message)
20-
: origin(std::move(origin))
21-
, row(row)
22-
, column(column)
23-
, caret_col(caret_col)
24-
, line(std::move(line))
25-
, message(std::move(message))
26-
{
27-
}
28-
29-
const std::string origin;
30-
const int row;
31-
const int column;
32-
const int caret_col;
33-
const std::string line;
34-
const LocalizedString message;
35-
36-
std::string to_string() const;
37-
};
38-
39-
constexpr struct ParseErrorFormatter
40-
{
41-
LocalizedString operator()(const std::unique_ptr<ParseError>& up)
42-
{
43-
return LocalizedString::from_raw(up->to_string());
44-
}
45-
} parse_error_formatter;
46-
47-
} // namespace vcpkg
48-
4914
namespace vcpkg
5015
{
5116
struct SourceLoc
@@ -66,7 +31,7 @@ namespace vcpkg
6631

6732
struct ParseMessages
6833
{
69-
std::unique_ptr<ParseError> error;
34+
Optional<LocalizedString> error;
7035
std::vector<ParseMessage> warnings;
7136

7237
void exit_if_errors_or_warnings(StringView origin) const;
@@ -141,8 +106,8 @@ namespace vcpkg
141106
void add_warning(LocalizedString&& message);
142107
void add_warning(LocalizedString&& message, const SourceLoc& loc);
143108

144-
const ParseError* get_error() const { return m_messages.error.get(); }
145-
std::unique_ptr<ParseError> extract_error() { return std::move(m_messages.error); }
109+
const LocalizedString* get_error() const& { return m_messages.error.get(); }
110+
LocalizedString* get_error() && { return m_messages.error.get(); }
146111

147112
const ParseMessages& messages() const { return m_messages; }
148113
ParseMessages&& extract_messages() { return std::move(m_messages); }

src/vcpkg-fuzz/main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ namespace
137137
auto res = Json::parse(text, origin);
138138
if (!res)
139139
{
140-
Checks::exit_with_message(VCPKG_LINE_INFO, res.error()->to_string());
140+
Checks::msg_exit_with_message(VCPKG_LINE_INFO, res.error());
141141
}
142142

143143
Checks::exit_success(VCPKG_LINE_INFO);

src/vcpkg-test/ci-baseline.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,7 @@ static void check_error(const std::string& input, const std::string& expected_er
250250
auto actual = parse_ci_baseline(input, "test", m);
251251
CHECK(actual.empty());
252252
CHECK(m.warnings.empty());
253-
REQUIRE(m.error);
254-
CHECK(m.error->to_string() == expected_error);
253+
CHECK(m.error.value_or_exit(VCPKG_LINE_INFO) == LocalizedString::from_raw(expected_error));
255254
}
256255

257256
TEST_CASE ("Parse Errors", "[ci-baseline]")

src/vcpkg-test/json.cpp

+18-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <vcpkg-test/util.h>
22

33
#include <vcpkg/base/json.h>
4+
#include <vcpkg/base/messages.h>
45

56
#include <iostream>
67

@@ -18,7 +19,7 @@ static auto u8_string_to_char_string(const char8_t (&literal)[Sz]) -> const char
1819
#define U8_STR(s) (u8"" s)
1920
#endif
2021

21-
namespace Json = vcpkg::Json;
22+
using namespace vcpkg;
2223
using Json::Value;
2324

2425
TEST_CASE ("JSON stringify weird strings", "[json]")
@@ -55,9 +56,9 @@ TEST_CASE ("JSON parse strings", "[json]")
5556
REQUIRE(res.get()->value.is_string());
5657
REQUIRE(res.get()->value.string(VCPKG_LINE_INFO) == "\xED\xA0\x80");
5758

58-
const auto make_json_string = [](vcpkg::StringView sv) { return '"' + sv.to_string() + '"'; };
59-
const vcpkg::StringView radical = U8_STR("");
60-
const vcpkg::StringView grin = U8_STR("😁");
59+
const auto make_json_string = [](StringView sv) { return '"' + sv.to_string() + '"'; };
60+
const StringView radical = U8_STR("");
61+
const StringView grin = U8_STR("😁");
6162

6263
res = Json::parse(R"("\uD83D\uDE01")", "test"); // paired surrogates for grin
6364
REQUIRE(res);
@@ -212,14 +213,14 @@ TEST_CASE ("JSON parse objects", "[json]")
212213

213214
TEST_CASE ("JSON parse full file", "[json]")
214215
{
215-
vcpkg::StringView json =
216+
StringView json =
216217
#include "large-json-document.json.inc"
217218
;
218219

219220
auto res = Json::parse(json, "test");
220221
if (!res)
221222
{
222-
std::cerr << res.error()->to_string() << '\n';
223+
std::cerr << res.error() << '\n';
223224
}
224225
REQUIRE(res);
225226
}
@@ -228,47 +229,43 @@ TEST_CASE ("JSON track newlines", "[json]")
228229
{
229230
auto res = Json::parse("{\n,", "filename");
230231
REQUIRE(!res);
231-
REQUIRE(res.error()->to_string() ==
232-
R"(filename:2:1: error: Unexpected character; expected property name
232+
REQUIRE(res.error() ==
233+
LocalizedString::from_raw(R"(filename:2:1: error: Unexpected character; expected property name
233234
on expression: ,
234-
^)");
235+
^)"));
235236
}
236237

237238
TEST_CASE ("JSON duplicated object keys", "[json]")
238239
{
239240
auto res = Json::parse("{\"name\": 1, \"name\": 2}", "filename");
240241
REQUIRE(!res);
241-
REQUIRE(res.error()->to_string() ==
242-
R"(filename:1:13: error: Duplicated key "name" in an object
242+
REQUIRE(res.error() == LocalizedString::from_raw(R"(filename:1:13: error: Duplicated key "name" in an object
243243
on expression: {"name": 1, "name": 2}
244-
^)");
244+
^)"));
245245
}
246246

247247
TEST_CASE ("JSON support unicode characters in errors", "[json]")
248248
{
249249
// unicode characters w/ bytes >1
250250
auto res = Json::parse(R"json("Δx/Δt" "")json", "filename");
251251
REQUIRE(!res);
252-
CHECK(res.error()->to_string() ==
253-
R"(filename:1:9: error: Unexpected character; expected EOF
252+
CHECK(res.error() == LocalizedString::from_raw(R"(filename:1:9: error: Unexpected character; expected EOF
254253
on expression: "Δx/Δt" ""
255-
^)");
254+
^)"));
256255

257256
// full width unicode characters
258257
// note that the A is full width
259258
res = Json::parse(R"json("姐姐aA" "")json", "filename");
260259
REQUIRE(!res);
261-
CHECK(res.error()->to_string() ==
262-
R"(filename:1:8: error: Unexpected character; expected EOF
260+
CHECK(res.error() == LocalizedString::from_raw(R"(filename:1:8: error: Unexpected character; expected EOF
263261
on expression: "姐姐aA" ""
264-
^)");
262+
^)"));
265263

266264
// incorrect errors in the face of combining characters
267265
// (this test should be fixed once the underlying bug is fixed)
268266
res = Json::parse(R"json("é" "")json", "filename");
269267
REQUIRE(!res);
270-
CHECK(res.error()->to_string() ==
271-
R"(filename:1:6: error: Unexpected character; expected EOF
268+
CHECK(res.error() == LocalizedString::from_raw(R"(filename:1:6: error: Unexpected character; expected EOF
272269
on expression: "é" ""
273-
^)");
270+
^)"));
274271
}

src/vcpkg-test/manifests.cpp

+18-18
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ static Json::Object parse_json_object(StringView sv)
2222
{
2323
INFO("Error found while parsing JSON document:");
2424
INFO(sv.to_string());
25-
FAIL(json.error()->to_string());
25+
FAIL(json.error());
2626
return Json::Object{};
2727
}
2828
}
@@ -1179,13 +1179,13 @@ static bool license_is_parsable(StringView license)
11791179
{
11801180
ParseMessages messages;
11811181
parse_spdx_license_expression(license, messages);
1182-
return messages.error == nullptr;
1182+
return !messages.error.has_value();
11831183
}
11841184
static bool license_is_strict(StringView license)
11851185
{
11861186
ParseMessages messages;
11871187
parse_spdx_license_expression(license, messages);
1188-
return messages.error == nullptr && messages.warnings.empty();
1188+
return !messages.error.has_value() && messages.warnings.empty();
11891189
}
11901190

11911191
static std::string test_format_parse_warning(const ParseMessage& msg)
@@ -1242,32 +1242,32 @@ TEST_CASE ("license error messages", "[manifests][license]")
12421242
{
12431243
ParseMessages messages;
12441244
parse_spdx_license_expression("", messages);
1245-
REQUIRE(messages.error);
1246-
CHECK(messages.error->to_string() == R"(<license string>:1:1: error: SPDX license expression was empty.
1245+
CHECK(messages.error.value_or_exit(VCPKG_LINE_INFO) ==
1246+
LocalizedString::from_raw(R"(<license string>:1:1: error: SPDX license expression was empty.
12471247
on expression:
1248-
^)");
1248+
^)"));
12491249

12501250
parse_spdx_license_expression("MIT ()", messages);
1251-
REQUIRE(messages.error);
1252-
CHECK(messages.error->to_string() ==
1253-
R"(<license string>:1:5: error: Expected a compound or the end of the string, found a parenthesis.
1251+
CHECK(messages.error.value_or_exit(VCPKG_LINE_INFO) ==
1252+
LocalizedString::from_raw(
1253+
R"(<license string>:1:5: error: Expected a compound or the end of the string, found a parenthesis.
12541254
on expression: MIT ()
1255-
^)");
1255+
^)"));
12561256

12571257
parse_spdx_license_expression("MIT +", messages);
1258-
REQUIRE(messages.error);
12591258
CHECK(
1260-
messages.error->to_string() ==
1261-
R"(<license string>:1:5: error: SPDX license expression contains an extra '+'. These are only allowed directly after a license identifier.
1259+
messages.error.value_or_exit(VCPKG_LINE_INFO) ==
1260+
LocalizedString::from_raw(
1261+
R"(<license string>:1:5: error: SPDX license expression contains an extra '+'. These are only allowed directly after a license identifier.
12621262
on expression: MIT +
1263-
^)");
1263+
^)"));
12641264

12651265
parse_spdx_license_expression("MIT AND", messages);
1266-
REQUIRE(messages.error);
1267-
CHECK(messages.error->to_string() ==
1268-
R"(<license string>:1:8: error: Expected a license name, found the end of the string.
1266+
CHECK(
1267+
messages.error.value_or_exit(VCPKG_LINE_INFO) ==
1268+
LocalizedString::from_raw(R"(<license string>:1:8: error: Expected a license name, found the end of the string.
12691269
on expression: MIT AND
1270-
^)");
1270+
^)"));
12711271

12721272
parse_spdx_license_expression("MIT AND unknownlicense", messages);
12731273
CHECK(!messages.error);

src/vcpkg/base/json.cpp

+13-24
Original file line numberDiff line numberDiff line change
@@ -992,7 +992,7 @@ namespace vcpkg::Json
992992
}
993993
}
994994

995-
static ExpectedT<ParsedJson, std::unique_ptr<ParseError>> parse(StringView json, StringView origin)
995+
static ExpectedL<ParsedJson> parse(StringView json, StringView origin)
996996
{
997997
StatsTimer t(g_json_parsing_stats);
998998

@@ -1004,16 +1004,14 @@ namespace vcpkg::Json
10041004
if (!parser.at_eof())
10051005
{
10061006
parser.add_error(msg::format(msgUnexpectedEOFExpectedChar));
1007-
return parser.extract_error();
10081007
}
1009-
else if (parser.get_error())
1010-
{
1011-
return parser.extract_error();
1012-
}
1013-
else
1008+
1009+
if (const auto maybe_error = std::move(parser).get_error())
10141010
{
1015-
return ParsedJson{std::move(val), parser.style()};
1011+
return std::move(*maybe_error);
10161012
}
1013+
1014+
return ParsedJson{std::move(val), parser.style()};
10171015
}
10181016

10191017
JsonStyle style() const noexcept { return style_; }
@@ -1100,14 +1098,12 @@ namespace vcpkg::Json
11001098
return true;
11011099
}
11021100

1103-
ExpectedT<ParsedJson, std::unique_ptr<ParseError>> parse_file(const ReadOnlyFilesystem& fs,
1104-
const Path& json_file,
1105-
std::error_code& ec)
1101+
ExpectedL<ParsedJson> parse_file(const ReadOnlyFilesystem& fs, const Path& json_file, std::error_code& ec)
11061102
{
11071103
auto res = fs.read_contents(json_file, ec);
11081104
if (ec)
11091105
{
1110-
return std::unique_ptr<ParseError>();
1106+
return format_filesystem_call_error(ec, "read_contents", {json_file});
11111107
}
11121108

11131109
return parse(res, json_file);
@@ -1116,34 +1112,27 @@ namespace vcpkg::Json
11161112
ParsedJson parse_file(vcpkg::LineInfo li, const ReadOnlyFilesystem& fs, const Path& json_file)
11171113
{
11181114
std::error_code ec;
1119-
auto ret = parse_file(fs, json_file, ec).map_error(parse_error_formatter);
1115+
auto ret = parse_file(fs, json_file, ec);
11201116
if (ec)
11211117
{
11221118
Checks::msg_exit_with_error(li, format_filesystem_call_error(ec, "read_contents", {json_file}));
11231119
}
11241120
return std::move(ret).value_or_exit(VCPKG_LINE_INFO);
11251121
}
11261122

1127-
ExpectedT<ParsedJson, std::unique_ptr<ParseError>> parse(StringView json, StringView origin)
1128-
{
1129-
return Parser::parse(json, origin);
1130-
}
1123+
ExpectedL<ParsedJson> parse(StringView json, StringView origin) { return Parser::parse(json, origin); }
11311124

11321125
ExpectedL<Json::Object> parse_object(StringView text, StringView origin)
11331126
{
1134-
auto maybeValueIsh = parse(text, origin);
1135-
if (auto asValueIsh = maybeValueIsh.get())
1136-
{
1137-
auto& asValue = asValueIsh->value;
1127+
return parse(text, origin).then([&](ParsedJson&& mabeValueIsh) -> ExpectedL<Json::Object> {
1128+
auto& asValue = mabeValueIsh.value;
11381129
if (asValue.is_object())
11391130
{
11401131
return std::move(asValue).object(VCPKG_LINE_INFO);
11411132
}
11421133

11431134
return msg::format(msgJsonErrorMustBeAnObject, msg::path = origin);
1144-
}
1145-
1146-
return LocalizedString::from_raw(maybeValueIsh.error()->to_string());
1135+
});
11471136
}
11481137
// } auto parse()
11491138

0 commit comments

Comments
 (0)