Skip to content

Commit

Permalink
Add cpp.indirection to type lowering mechanism
Browse files Browse the repository at this point in the history
Summary: The implementation of cpp.indirection does not handle typedefs correctly. Lower the annotation onto the inner type of typedefs to unblock the codemod while this is fixed.

Reviewed By: dtolnay

Differential Revision: D69195637

fbshipit-source-id: 87e53baafa89ecb832bb188ea20ab81755aa5e8f
  • Loading branch information
iahs authored and facebook-github-bot committed Feb 6, 2025
1 parent c7abd10 commit 1c4165c
Showing 1 changed file with 55 additions and 40 deletions.
95 changes: 55 additions & 40 deletions thrift/compiler/sema/sema.cc
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,51 @@ void update_annotations(
node.reset_annotations(std::move(annotations));
}

// Updates field or typedef's type field to hold annotations
template <typename Node>
void add_annotations_to_node_type(
Node& node,
std::map<std::string, std::string> annotations,
t_program& program) {
const t_type* node_type = node.get_type();

if (annotations.empty()) {
if (!node_type->annotations().empty()) {
update_annotations(const_cast<t_type&>(*node_type));
}
return;
}

if (node_type->is_container() ||
(node_type->is_typedef() &&
static_cast<const t_typedef*>(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<t_type&>(*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<t_primitive_type>(
*static_cast<const t_primitive_type*>(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<t_program*>(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(
Expand Down Expand Up @@ -494,6 +539,15 @@ void lower_deprecated_annotations(
}
}

// cpp.indirection does not handle typedefs correctly
if (auto* typedf = dynamic_cast<t_typedef*>(&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);
Expand Down Expand Up @@ -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<t_type&>(*node_type));
}
return;
}

if (node_type->is_container() ||
(node_type->is_typedef() &&
static_cast<const t_typedef*>(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<t_type&>(*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<t_primitive_type>(
*static_cast<const t_primitive_type*>(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<t_program*>(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) {
Expand Down

0 comments on commit 1c4165c

Please sign in to comment.