diff --git a/thrift/compiler/sema/sema.cc b/thrift/compiler/sema/sema.cc index 38e499c4191..c269163d655 100644 --- a/thrift/compiler/sema/sema.cc +++ b/thrift/compiler/sema/sema.cc @@ -435,6 +435,51 @@ void update_annotations( node.reset_annotations(std::move(annotations)); } +// Updates field or typedef's type field to hold annotations +template +void add_annotations_to_node_type( + Node& node, + std::map annotations, + t_program& program) { + const t_type* node_type = node.get_type(); + + if (annotations.empty()) { + if (!node_type->annotations().empty()) { + update_annotations(const_cast(*node_type)); + } + return; + } + + if (node_type->is_container() || + (node_type->is_typedef() && + static_cast(node_type)->typedef_kind() != + t_typedef::kind::defined) || + (node_type->is_primitive_type() && !node_type->annotations().empty())) { + // This is a new type we can modify in place + update_annotations(const_cast(*node_type), std::move(annotations)); + } else if (node_type->is_primitive_type()) { + // Copy type as we don't handle unnamed typedefs to base types :( + auto unnamed = std::make_unique( + *static_cast(node_type)); + for (auto& pair : annotations) { + unnamed->set_annotation(pair.first, pair.second); + } + node.set_type(t_type_ref::from_ptr(unnamed.get())); + program.add_unnamed_type(std::move(unnamed)); + } else { + // Wrap in an unnamed typedef :( + auto unnamed = t_typedef::make_unnamed( + const_cast(node_type->get_program()), + node_type->get_name(), + t_type_ref::from_ptr(node_type)); + for (auto& pair : annotations) { + unnamed->set_annotation(pair.first, pair.second); + } + node.set_type(t_type_ref::from_ptr(unnamed.get())); + program.add_unnamed_typedef(std::move(unnamed)); + } +} + void lower_deprecated_annotations( sema_context& ctx, mutator_context& mCtx, t_named& node) { if (auto cnst = node.find_structured_annotation_or_null( @@ -494,6 +539,15 @@ void lower_deprecated_annotations( } } + // cpp.indirection does not handle typedefs correctly + if (auto* typedf = dynamic_cast(&node); + typedf && map.count("cpp.indirection")) { + add_annotations_to_node_type( + *typedf, + {{"cpp.indirection", map.at("cpp.indirection").value}}, + mCtx.program()); + } + node.reset_annotations(std::move(map)); } else { update_annotations(node); @@ -540,46 +594,7 @@ void lower_type_annotations( } } - const t_type* node_type = node.get_type(); - - if (unstructured.empty()) { - if (!node_type->annotations().empty()) { - update_annotations(const_cast(*node_type)); - } - return; - } - - if (node_type->is_container() || - (node_type->is_typedef() && - static_cast(node_type)->typedef_kind() != - t_typedef::kind::defined) || - (node_type->is_primitive_type() && !node_type->annotations().empty())) { - // This is a new type we can modify in place - update_annotations( - const_cast(*node_type), std::move(unstructured)); - } else if (node_type->is_primitive_type()) { - // Copy type as we don't handle unnamed typedefs to base types :( - auto& program = mctx.program(); - auto unnamed = std::make_unique( - *static_cast(node_type)); - for (auto& pair : unstructured) { - unnamed->set_annotation(pair.first, pair.second); - } - node.set_type(t_type_ref::from_ptr(unnamed.get())); - program.add_unnamed_type(std::move(unnamed)); - } else { - // Wrap in an unnamed typedef :( - auto& program = mctx.program(); - auto unnamed = t_typedef::make_unnamed( - const_cast(node_type->get_program()), - node_type->get_name(), - t_type_ref::from_ptr(node_type)); - for (auto& pair : unstructured) { - unnamed->set_annotation(pair.first, pair.second); - } - node.set_type(t_type_ref::from_ptr(unnamed.get())); - program.add_unnamed_typedef(std::move(unnamed)); - } + add_annotations_to_node_type(node, std::move(unstructured), mctx.program()); } void inject_schema_const(sema_context& ctx, mutator_context&, t_program& prog) {