diff --git a/thrift/compiler/whisker/mstch_compat.cc b/thrift/compiler/whisker/mstch_compat.cc index 05fa250fe09..3ba258f89f8 100644 --- a/thrift/compiler/whisker/mstch_compat.cc +++ b/thrift/compiler/whisker/mstch_compat.cc @@ -62,15 +62,7 @@ class mstch_array_proxy final void print_to(tree_printer::scope scope, const object_print_options& options) const override { - assert(scope.semantic_depth() <= options.max_depth); - - const auto size = proxied_.size(); - scope.println("mstch::array (size={})", size); - for (std::size_t i = 0; i < size; ++i) { - auto element_scope = scope.open_transparent_property(); - element_scope.println("[{}]", i); - whisker::print_to(*at(i), element_scope.open_node(), options); - } + default_print_to("mstch::array", std::move(scope), options); } bool operator==(const native_object& untyped_other) const override { @@ -129,17 +121,13 @@ class mstch_map_proxy final void print_to(tree_printer::scope scope, const object_print_options& options) const override { - assert(scope.semantic_depth() <= options.max_depth); - const auto size = proxied_.size(); - scope.println("mstch::map (size={})", size); - + std::vector property_names; + property_names.reserve(proxied_.size()); for (const auto& [key, _] : proxied_) { - auto cached = lookup_property(key); - assert(cached != nullptr); - auto element_scope = scope.open_transparent_property(); - element_scope.println("'{}'", key); - whisker::print_to(*cached, element_scope.open_node(), options); + property_names.push_back(key); } + default_print_to( + "mstch::map", std::move(property_names), std::move(scope), options); } bool operator==(const native_object& untyped_other) const override { diff --git a/thrift/compiler/whisker/object.cc b/thrift/compiler/whisker/object.cc index 0f9ce2b3d5b..2598b8bda45 100644 --- a/thrift/compiler/whisker/object.cc +++ b/thrift/compiler/whisker/object.cc @@ -134,6 +134,39 @@ class to_string_visitor { } // namespace +void native_object::map_like::default_print_to( + std::string_view name, + std::vector property_names, + tree_printer::scope scope, + const object_print_options& options) const { + assert(scope.semantic_depth() <= options.max_depth); + const auto size = property_names.size(); + scope.println("{} (size={})", name, size); + + for (const std::string& key : property_names) { + auto cached = lookup_property(key); + assert(cached != nullptr); + auto element_scope = scope.open_transparent_property(); + element_scope.println("'{}'", key); + whisker::print_to(*cached, element_scope.open_node(), options); + } +} + +void native_object::array_like::default_print_to( + std::string_view name, + tree_printer::scope scope, + const object_print_options& options) const { + assert(scope.semantic_depth() <= options.max_depth); + + const auto sz = size(); + scope.println("{} (size={})", name, sz); + for (std::size_t i = 0; i < sz; ++i) { + auto element_scope = scope.open_transparent_property(); + element_scope.println("[{}]", i); + whisker::print_to(*at(i), element_scope.open_node(), options); + } +} + void native_object::print_to( tree_printer::scope scope, const object_print_options&) const { scope.println(""); diff --git a/thrift/compiler/whisker/object.h b/thrift/compiler/whisker/object.h index 9957cc23319..61f7e1dc9e4 100644 --- a/thrift/compiler/whisker/object.h +++ b/thrift/compiler/whisker/object.h @@ -175,6 +175,22 @@ class native_object { */ virtual managed_object_ptr<> lookup_property( std::string_view identifier) const = 0; + + protected: + /** + * A default implementation of whisker::print_to for native object + * subclasses of map_like to use. + * + * For the default implementation to work, property names must be explicitly + * enumerated. + * + * The provided name allows the caller to expose type information. + */ + void default_print_to( + std::string_view name, + std::vector property_names, + tree_printer::scope, + const object_print_options&) const; }; /** * Returns an implementation of map_list if this object supports map-like @@ -219,6 +235,18 @@ class native_object { * - index < size() */ virtual managed_object_ptr<> at(std::size_t index) const = 0; + + protected: + /** + * A default implementation of whisker::print_to for native object + * subclasses of array_like to use. + * + * The provided name allows the caller to expose type information. + */ + void default_print_to( + std::string_view name, + tree_printer::scope, + const object_print_options&) const; }; /** * Returns an implementation of array_like if this object supports array-like