@@ -188,26 +188,16 @@ void Visitor::visitField(T& field, const std::string& field_name, const std::str
188188}
189189
190190// Visits a non-config field with conversion.
191- template <typename Conversion, typename T, typename std::enable_if<!isConfig<T>(), bool >::type >
191+ template <typename Conversion, typename T>
192192void Visitor::visitField (T& field, const std::string& field_name, const std::string& unit) {
193193 auto & visitor = Visitor::instance ();
194194
195- // record the field that we visited without storing the value
196- // kGet and kGetDefaults will populate the value field
197- auto & info = visitor.data .field_infos .emplace_back ();
198- info.name = field_name;
199- info.unit = unit;
200-
201195 if (visitor.mode == Visitor::Mode::kSet ) {
202196 std::string error;
203197 auto intermediate = Conversion::toIntermediate (field, error);
204198 error.clear (); // We don't care about setting up the intermediate just to get data.
205199
206- info.was_parsed = YamlParser::fromYaml (visitor.data .data , field_name, intermediate, visitor.name_space , error);
207- if (!error.empty ()) {
208- visitor.data .errors .emplace_back (new Warning (field_name, error));
209- error.clear ();
210- }
200+ Visitor::visitField (intermediate, field_name, unit);
211201
212202 Conversion::fromIntermediate (intermediate, field, error);
213203 if (!error.empty ()) {
@@ -218,23 +208,17 @@ void Visitor::visitField(T& field, const std::string& field_name, const std::str
218208 if (visitor.mode == Visitor::Mode::kGet || visitor.mode == Visitor::Mode::kGetDefaults ||
219209 visitor.mode == Visitor::Mode::kGetInfo ) {
220210 std::string error;
221- const auto intermediate = Conversion::toIntermediate (field, error);
211+ auto intermediate = Conversion::toIntermediate (field, error);
222212 if (!error.empty ()) {
223213 visitor.data .errors .emplace_back (new Warning (field_name, error));
224214 error.clear ();
225215 }
226- YAML::Node node = YamlParser::toYaml (field_name, intermediate, visitor.name_space , error);
227- mergeYamlNodes (visitor.data .data , node);
228- // This stores a reference to the node in the data.
229- info.value = lookupNamespace (node, joinNamespace (visitor.name_space , field_name));
230- if (!error.empty ()) {
231- visitor.data .errors .emplace_back (new Warning (field_name, error));
232- }
216+
217+ Visitor::visitField (intermediate, field_name, unit);
233218
234219 // Get type information if requested.
235220 if (visitor.mode == Visitor::Mode::kGetInfo ) {
236- auto input_info = Visitor::getFieldInputInfo<Conversion>();
237- info.input_info = FieldInputInfo::merge (input_info, info.input_info );
221+ Visitor::getFieldInputInfo<Conversion, T>(field_name);
238222 }
239223 }
240224}
@@ -268,7 +252,7 @@ void Visitor::visitField(std::vector<ConfigT>& config, const std::string& field_
268252 }
269253
270254 if (visitor.mode == Visitor::Mode::kSet ) {
271- const auto array_ns = visitor. name_space . empty () ? field_name : visitor.name_space + " / " + field_name;
255+ const auto array_ns = joinNamespace ( visitor.name_space , field_name) ;
272256 const auto subnode = lookupNamespace (visitor.data .data , array_ns);
273257 if (!subnode) {
274258 return ; // don't override the field if not present
@@ -346,7 +330,7 @@ void Visitor::visitField(OrderedMap<K, ConfigT>& config, const std::string& fiel
346330 }
347331
348332 if (visitor.mode == Visitor::Mode::kSet ) {
349- const auto map_ns = visitor. name_space . empty () ? field_name : visitor.name_space + " / " + field_name;
333+ const auto map_ns = joinNamespace ( visitor.name_space , field_name) ;
350334 const auto subnode = lookupNamespace (visitor.data .data , map_ns);
351335 if (!subnode) {
352336 return ; // don't override the field if not present
@@ -470,14 +454,41 @@ void Visitor::getDefaultValues(const ConfigT& config, MetaData& data) {
470454 }
471455}
472456
473- template <typename Conversion, typename std::enable_if<!hasFieldInputInfo<Conversion>(), bool >::type>
474- FieldInputInfo::Ptr Visitor::getFieldInputInfo () {
475- return nullptr ;
457+ // intentional no-op
458+ template <typename Conversion,
459+ typename ConfigT,
460+ typename std::enable_if<!hasFieldInputInfo<Conversion>() || isConfig<ConfigT>(), bool >::type>
461+ void Visitor::getFieldInputInfo (const std::string& field_name) {
462+ static_assert (!isConfig<ConfigT>() || !hasFieldInputInfo<Conversion>(),
463+ " Config types (with declare_config) cannot have field input information!" );
464+
465+ if (isConfig<ConfigT>()) {
466+ return ; // don't touch field info fields
467+ }
468+
469+ auto & visitor = Visitor::instance ();
470+ if (visitor.data .field_infos .empty ()) {
471+ visitor.data .errors .emplace_back (
472+ new Warning (field_name, " Invalid parsing state! Field info should already exist!" ));
473+ } else {
474+ visitor.data .field_infos .back ().input_info .reset (); // clear field input info for underlying intermediate type
475+ }
476476}
477477
478- template <typename Conversion, typename std::enable_if<hasFieldInputInfo<Conversion>(), bool >::type>
479- FieldInputInfo::Ptr Visitor::getFieldInputInfo () {
480- return Conversion::getFieldInputInfo ();
478+ template <typename Conversion,
479+ typename ConfigT,
480+ typename std::enable_if<hasFieldInputInfo<Conversion>() && !isConfig<ConfigT>(), bool >::type>
481+ void Visitor::getFieldInputInfo (const std::string& field_name) {
482+ auto input_info = Conversion::getFieldInputInfo ();
483+
484+ auto & visitor = Visitor::instance ();
485+ if (visitor.data .field_infos .empty ()) {
486+ visitor.data .errors .emplace_back (
487+ new Warning (field_name, " Invalid parsing state! Field info should already exist!" ));
488+ } else {
489+ auto & info = visitor.data .field_infos .back ();
490+ info.input_info = FieldInputInfo::merge (input_info, info.input_info );
491+ }
481492}
482493
483494} // namespace config::internal
0 commit comments