Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 4 additions & 2 deletions config_utilities/include/config_utilities/internal/visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,15 @@ struct Visitor {
// Dispatch populating field input info from conversions.
template <typename Conversion,
typename ConfigT,
typename IntermediateT,
typename std::enable_if<!hasFieldInputInfo<Conversion>() || isConfig<ConfigT>(), bool>::type = true>
static void getFieldInputInfo(const std::string& field_name);
static void getFieldInputInfo(const IntermediateT& intermediate, const std::string& field_name);

template <typename Conversion,
typename ConfigT,
typename IntermediateT,
typename std::enable_if<hasFieldInputInfo<Conversion>() && !isConfig<ConfigT>(), bool>::type = true>
static void getFieldInputInfo(const std::string& field_name);
static void getFieldInputInfo(const IntermediateT& intermediate, const std::string& field_name);

// Computes the default values for all fields in the meta data. This assumes that the meta data is already created,
// and the meta data was created from ConfigT.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,13 @@ void Visitor::visitField(T& field, const std::string& field_name, const std::str
auto intermediate = Conversion::toIntermediate(field, error);
if (!error.empty()) {
visitor.data.errors.emplace_back(new Warning(field_name, error));
error.clear();
}

Visitor::visitField(intermediate, field_name, unit);

// Get type information if requested.
if (visitor.mode == Visitor::Mode::kGetInfo) {
Visitor::getFieldInputInfo<Conversion, T>(field_name);
Visitor::getFieldInputInfo<Conversion, T>(intermediate, field_name);
}
}
}
Expand Down Expand Up @@ -457,8 +456,9 @@ void Visitor::getDefaultValues(const ConfigT& config, MetaData& data) {
// intentional no-op
template <typename Conversion,
typename ConfigT,
typename IntermediateT,
typename std::enable_if<!hasFieldInputInfo<Conversion>() || isConfig<ConfigT>(), bool>::type>
void Visitor::getFieldInputInfo(const std::string& field_name) {
void Visitor::getFieldInputInfo(const IntermediateT&, const std::string& field_name) {
static_assert(!isConfig<ConfigT>() || !hasFieldInputInfo<Conversion>(),
"Config types (with declare_config) cannot have field input information!");

Expand All @@ -471,14 +471,18 @@ void Visitor::getFieldInputInfo(const std::string& field_name) {
visitor.data.errors.emplace_back(
new Warning(field_name, "Invalid parsing state! Field info should already exist!"));
} else {
visitor.data.field_infos.back().input_info.reset(); // clear field input info for underlying intermediate type
// Default: Create the field input info of the intermediate type.
auto input_info = createFieldInputInfo<IntermediateT>();
auto& info = visitor.data.field_infos.back();
info.input_info = FieldInputInfo::merge(input_info, info.input_info);
}
}

template <typename Conversion,
typename ConfigT,
typename IntermediateT,
typename std::enable_if<hasFieldInputInfo<Conversion>() && !isConfig<ConfigT>(), bool>::type>
void Visitor::getFieldInputInfo(const std::string& field_name) {
void Visitor::getFieldInputInfo(const IntermediateT&, const std::string& field_name) {
auto input_info = Conversion::getFieldInputInfo();

auto& visitor = Visitor::instance();
Expand Down
6 changes: 4 additions & 2 deletions config_utilities/test/tests/conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,10 @@ TEST(Conversions, FieldInputInfo) {
ConversionStruct without_info;
data = internal::Visitor::getInfo(without_info);
EXPECT_EQ(data.field_infos.size(), 2);
EXPECT_FALSE(data.field_infos[0].input_info);
EXPECT_FALSE(data.field_infos[1].input_info);
EXPECT_TRUE(data.field_infos[0].input_info);
EXPECT_TRUE(data.field_infos[1].input_info);
EXPECT_EQ(data.field_infos[0].input_info->type, internal::FieldInputInfo::Type::kInt); // num_threads
EXPECT_EQ(data.field_infos[1].input_info->type, internal::FieldInputInfo::Type::kString); // some_character
}

TEST(Conversions, ConversionDeclareConfigDispatch) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,10 @@ def parse_rec(config, indent, prefix):
prefix_str = "".join([f"{p}{NS_SEP}" for p in prefix])
for field in config["fields"]:
if field["type"] == "field":
# Default the input info to just strings if no details are present.
if "input_info" not in field:
field["input_info"] = {"type": "yaml"}

# Data for each field (leaves of the config).
field["id"] = f"{prefix_str}{field['name']}"
field["indent"] = indent
Expand Down