Skip to content

Commit

Permalink
Make Auto parsing failure print the Label
Browse files Browse the repository at this point in the history
  • Loading branch information
wthrowe committed Feb 15, 2024
1 parent 70fcc77 commit a65cbc8
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 7 deletions.
40 changes: 33 additions & 7 deletions src/Options/Auto.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <ostream>
#include <string>
#include <utility>
#include <variant>

#include "Options/Options.hpp"
#include "Options/ParseOptions.hpp"
Expand Down Expand Up @@ -92,27 +93,52 @@ std::ostream& operator<<(std::ostream& os, const Auto<T, Label>& x) {
}
}

namespace Auto_detail {
template <typename Label>
struct AutoLabel {};
} // namespace Auto_detail

template <typename Label>
struct create_from_yaml<Auto_detail::AutoLabel<Label>> {
template <typename Metavariables>
static Auto_detail::AutoLabel<Label> create(const Option& options) {
const auto label_string = pretty_type::name<Label>();
try {
if (options.parse_as<std::string>() == label_string) {
return {};
}
} catch (...) {
// The node failed to parse as a string. It is not the Label.
}
// The error if the std::variant parse fails will print the value
// from the input file (and the T parse probably will too), so we
// don't need to print it again.
PARSE_ERROR(options.context(),
"Failed to parse as Auto label \"" << label_string << "\"");
}
};

template <typename T, typename Label>
struct create_from_yaml<Auto<T, Label>> {
template <typename Metavariables>
static Auto<T, Label> create(const Option& options) {
try {
if (options.parse_as<std::string>() == pretty_type::name<Label>()) {
auto parsed_variant =
options.parse_as<std::variant<Auto_detail::AutoLabel<Label>, T>,
Metavariables>();
if (std::holds_alternative<T>(parsed_variant)) {
return Auto<T, Label>{std::move(std::get<T>(parsed_variant))};
} else {
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 && __GNUC__ < 10
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif // defined(__GNUC__) && !defined(__clang__) && __GNUC__ => 8 && __GNUC__
// < 10
return {};
return Auto<T, Label>{};
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 && __GNUC__ < 10
#pragma GCC diagnostic pop
#endif // defined(__GNUC__) && !defined(__clang__) && __GNUC__ => 8 && __GNUC__
// < 10
}
} catch (...) {
// The node failed to parse as a string. It is not the AutoLabel.
}
return Auto<T, Label>{options.parse_as<T, Metavariables>()};
}
};
} // namespace Options
20 changes: 20 additions & 0 deletions tests/Unit/Options/Test_Auto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,30 @@ void test_use_as_option() {
// Make sure this compiles.
TestHelpers::test_creation<NonCopyableArgument>("AutoArg: Auto");
}

struct LabelThatShouldPrint {
static std::string name() { return "PrintedName"; }
};

void test_error_message() {
CHECK_THROWS_WITH(
(TestHelpers::test_creation<Options::Auto<double, LabelThatShouldPrint>>(
"NotValid")),
Catch::Matchers::ContainsSubstring("PrintedName") and
Catch::Matchers::ContainsSubstring("to type double") and
Catch::Matchers::ContainsSubstring("NotValid"));
CHECK_THROWS_WITH((TestHelpers::test_creation<
Options::Auto<std::string, LabelThatShouldPrint>>(
"[not, a, string]")),
Catch::Matchers::ContainsSubstring("PrintedName") and
Catch::Matchers::ContainsSubstring("to type string") and
Catch::Matchers::ContainsSubstring("not, a, string"));
}
} // namespace

SPECTRE_TEST_CASE("Unit.Options.Auto", "[Unit][Options]") {
test_class();
test_parsing();
test_use_as_option();
test_error_message();
}

0 comments on commit a65cbc8

Please sign in to comment.