Skip to content

Commit b4e0d37

Browse files
hchokshifacebook-github-bot
authored andcommitted
Add name property to prototypes
Reviewed By: praihan Differential Revision: D79455426 fbshipit-source-id: 0b6f99721a106b57e9fe6f5918871b653b8578ee
1 parent ff25a53 commit b4e0d37

File tree

6 files changed

+105
-22
lines changed

6 files changed

+105
-22
lines changed

third-party/thrift/src/thrift/compiler/generate/t_mstch_cpp2_generator.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ class t_mstch_cpp2_generator : public t_mstch_generator {
312312
prototype<t_program>::ptr make_prototype_for_program(
313313
const prototype_database& proto) const override {
314314
auto base = t_whisker_generator::make_prototype_for_program(proto);
315-
auto def = whisker::dsl::prototype_builder<h_program>::extends(base);
315+
auto def = whisker::dsl::prototype_builder<h_program>::patches(base);
316316
def.property(
317317
"cpp_qualified_namespace", &cpp2::get_gen_unprefixed_namespace);
318318
return std::move(def).make();
@@ -321,7 +321,7 @@ class t_mstch_cpp2_generator : public t_mstch_generator {
321321
prototype<t_named>::ptr make_prototype_for_named(
322322
const prototype_database& proto) const override {
323323
auto base = t_whisker_generator::make_prototype_for_named(proto);
324-
auto def = whisker::dsl::prototype_builder<h_named>::extends(base);
324+
auto def = whisker::dsl::prototype_builder<h_named>::patches(base);
325325
def.property("cpp_name", [](const t_named& named) {
326326
return cpp2::get_name(&named);
327327
});
@@ -331,7 +331,7 @@ class t_mstch_cpp2_generator : public t_mstch_generator {
331331
prototype<t_type>::ptr make_prototype_for_type(
332332
const prototype_database& proto) const override {
333333
auto base = t_whisker_generator::make_prototype_for_type(proto);
334-
auto def = whisker::dsl::prototype_builder<h_type>::extends(base);
334+
auto def = whisker::dsl::prototype_builder<h_type>::patches(base);
335335

336336
def.property("cpp_qualified_underlying_name", [this](const t_type& type) {
337337
return cpp_context_->resolver().get_underlying_namespaced_name(type);
@@ -351,7 +351,7 @@ class t_mstch_cpp2_generator : public t_mstch_generator {
351351
prototype<t_typedef>::ptr make_prototype_for_typedef(
352352
const prototype_database& proto) const override {
353353
auto base = t_whisker_generator::make_prototype_for_typedef(proto);
354-
auto def = whisker::dsl::prototype_builder<h_typedef>::extends(base);
354+
auto def = whisker::dsl::prototype_builder<h_typedef>::patches(base);
355355

356356
def.property("cpp_type", [&](const t_typedef& t) {
357357
return cpp_context_->resolver().get_underlying_type_name(t);
@@ -363,7 +363,7 @@ class t_mstch_cpp2_generator : public t_mstch_generator {
363363
prototype<t_enum>::ptr make_prototype_for_enum(
364364
const prototype_database& proto) const override {
365365
auto base = t_whisker_generator::make_prototype_for_enum(proto);
366-
auto def = whisker::dsl::prototype_builder<h_enum>::extends(base);
366+
auto def = whisker::dsl::prototype_builder<h_enum>::patches(base);
367367

368368
def.property("cpp_min", [](const t_enum& e) -> whisker::object {
369369
auto values = e.values();
@@ -436,7 +436,7 @@ class t_mstch_cpp2_generator : public t_mstch_generator {
436436
prototype<t_function>::ptr make_prototype_for_function(
437437
const prototype_database& proto) const override {
438438
auto base = t_whisker_generator::make_prototype_for_function(proto);
439-
auto def = whisker::dsl::prototype_builder<h_function>::extends(base);
439+
auto def = whisker::dsl::prototype_builder<h_function>::patches(base);
440440

441441
def.property("cpp_return_type", [&](const t_function& f) -> std::string {
442442
return cpp_context_->resolver().get_return_type(f);
@@ -454,7 +454,7 @@ class t_mstch_cpp2_generator : public t_mstch_generator {
454454
prototype<t_service>::ptr make_prototype_for_service(
455455
const prototype_database& proto) const override {
456456
auto base = t_whisker_generator::make_prototype_for_service(proto);
457-
auto def = whisker::dsl::prototype_builder<h_service>::extends(base);
457+
auto def = whisker::dsl::prototype_builder<h_service>::patches(base);
458458

459459
def.property("cpp_name", [](const t_service& service) {
460460
return service.is_interaction() ? service.name()

third-party/thrift/src/thrift/compiler/generate/t_mstch_python_generator.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,7 @@ class t_mstch_python_prototypes_generator : public t_mstch_generator {
12431243
prototype<t_named>::ptr make_prototype_for_named(
12441244
const prototype_database& proto) const override {
12451245
auto base = t_whisker_generator::make_prototype_for_named(proto);
1246-
auto def = whisker::dsl::prototype_builder<h_named>::extends(base);
1246+
auto def = whisker::dsl::prototype_builder<h_named>::patches(base);
12471247

12481248
def.property("py_name", &python::get_py3_name<t_named>);
12491249

@@ -1253,7 +1253,7 @@ class t_mstch_python_prototypes_generator : public t_mstch_generator {
12531253
prototype<t_program>::ptr make_prototype_for_program(
12541254
const prototype_database& proto) const override {
12551255
auto base = t_whisker_generator::make_prototype_for_program(proto);
1256-
auto def = whisker::dsl::prototype_builder<h_program>::extends(base);
1256+
auto def = whisker::dsl::prototype_builder<h_program>::patches(base);
12571257

12581258
def.property("module_mangle", [&](const t_program& self) {
12591259
return mangle_program_path(&self, get_option("root_module_prefix"));
@@ -1265,7 +1265,7 @@ class t_mstch_python_prototypes_generator : public t_mstch_generator {
12651265
prototype<t_service>::ptr make_prototype_for_service(
12661266
const prototype_database& proto) const override {
12671267
auto base = t_whisker_generator::make_prototype_for_service(proto);
1268-
auto def = whisker::dsl::prototype_builder<h_service>::extends(base);
1268+
auto def = whisker::dsl::prototype_builder<h_service>::patches(base);
12691269

12701270
def.property("module_mangle", [&](const t_service& self) {
12711271
return mangle_program_path(
@@ -1278,7 +1278,7 @@ class t_mstch_python_prototypes_generator : public t_mstch_generator {
12781278
prototype<t_type>::ptr make_prototype_for_type(
12791279
const prototype_database& proto) const override {
12801280
auto base = t_whisker_generator::make_prototype_for_type(proto);
1281-
auto def = whisker::dsl::prototype_builder<h_type>::extends(base);
1281+
auto def = whisker::dsl::prototype_builder<h_type>::patches(base);
12821282

12831283
def.property("module_mangle", [&](const t_type& self) {
12841284
return mangle_program_path(

third-party/thrift/src/thrift/compiler/whisker/dsl.h

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,15 @@ class prototype_builder {
635635
template <
636636
typename Parent,
637637
std::enable_if_t<std::is_base_of_v<Parent, self_type>, int> = 0>
638-
explicit prototype_builder(prototype_ptr<Parent> parent)
639-
: parent_(std::move(parent)) {
638+
explicit prototype_builder(
639+
prototype_ptr<Parent> parent, const std::string_view& name = "")
640+
: parent_(std::move(parent)), name_(name) {
640641
assert(parent_ != nullptr);
641642
}
643+
644+
explicit prototype_builder(const std::string_view& name)
645+
: parent_(nullptr), name_(name) {}
646+
642647
prototype_builder() = default;
643648

644649
/**
@@ -686,14 +691,31 @@ class prototype_builder {
686691
*/
687692
result make() && {
688693
return std::make_shared<basic_prototype<self_type>>(
689-
std::move(descriptors_), std::move(parent_));
694+
std::move(descriptors_), std::move(parent_), std::move(name_));
690695
}
691696

697+
// Define a prototype which extends from a parent prototype of a super type.
698+
// To extend the functionality of a prototype for the same type, use
699+
// `patches`.
692700
template <
693701
typename Parent,
694-
std::enable_if_t<std::is_base_of_v<Parent, self_type>, int> = 0>
695-
static prototype_builder extends(prototype_ptr<Parent> parent) {
696-
return prototype_builder{std::move(parent)};
702+
std::enable_if_t<
703+
(std::is_base_of_v<Parent, self_type> &&
704+
!std::is_same_v<Parent, self_type>),
705+
int> = 0>
706+
static prototype_builder extends(
707+
prototype_ptr<Parent> parent, const std::string_view& name = "") {
708+
return prototype_builder{std::move(parent), name};
709+
}
710+
711+
// Define a prototype which extends from a parent prototype of the same type.
712+
// This will return an extension builder which accepts the name (if any) of
713+
// the parent.
714+
static prototype_builder patches(prototype_ptr<self_type> parent) {
715+
const std::string_view name = parent->name();
716+
auto builder = prototype_builder{std::move(parent), name};
717+
718+
return builder;
697719
}
698720

699721
private:
@@ -707,6 +729,17 @@ class prototype_builder {
707729

708730
prototype<>::ptr parent_;
709731
prototype<>::descriptors_map descriptors_;
732+
733+
/**
734+
* Optional explicit name.
735+
* The name can be used in contexts like loops which implicitly change the
736+
* scope from the parent object to the looped type. By using an explicit name
737+
* for the prototype, the type of the template variable can be explicitly
738+
* specified for readability and as an assertion of the type being operated
739+
* on. Names can also be used to explicitly access parent prototype members
740+
* on child objects.
741+
*/
742+
std::string_view name_;
710743
};
711744

712745
/**

third-party/thrift/src/thrift/compiler/whisker/object.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,11 @@ std::string native_function::describe_type() const {
318318
}
319319

320320
/* static */ prototype<>::ptr prototype<>::from(
321-
descriptors_map descriptors, prototype::ptr parent) {
321+
descriptors_map descriptors,
322+
prototype::ptr parent,
323+
const std::string_view& name) {
322324
return std::make_shared<basic_prototype<>>(
323-
std::move(descriptors), std::move(parent));
325+
std::move(descriptors), std::move(parent), name);
324326
}
325327

326328
std::string detail::describe_native_handle_for_type(

third-party/thrift/src/thrift/compiler/whisker/object.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,12 +1008,18 @@ class prototype<void> {
10081008
*/
10091009
virtual const ptr& parent() const = 0;
10101010

1011+
/**
1012+
* Returns the name for this prototype, if one is registered.
1013+
*/
1014+
virtual const std::string_view& name() const = 0;
1015+
10111016
using descriptors_map = std::map<std::string, descriptor, std::less<>>;
10121017
/**
10131018
* Creates a prototype from the provided map of descriptors and
10141019
* (optionally) a parent.
10151020
*/
1016-
static ptr from(descriptors_map, ptr parent = nullptr);
1021+
static ptr from(
1022+
descriptors_map, ptr parent = nullptr, const std::string_view& name = "");
10171023
};
10181024

10191025
/**
@@ -1062,13 +1068,20 @@ class basic_prototype : public prototype<T> {
10621068

10631069
const prototype<>::ptr& parent() const override { return parent_; }
10641070

1071+
const std::string_view& name() const override { return name_; }
1072+
10651073
basic_prototype(
1066-
prototype<>::descriptors_map descriptors, prototype<>::ptr parent)
1067-
: descriptors_(std::move(descriptors)), parent_(std::move(parent)) {}
1074+
prototype<>::descriptors_map descriptors,
1075+
prototype<>::ptr parent,
1076+
const std::string_view& name)
1077+
: descriptors_(std::move(descriptors)),
1078+
parent_(std::move(parent)),
1079+
name_(name) {}
10681080

10691081
private:
10701082
prototype<>::descriptors_map descriptors_;
10711083
prototype<>::ptr parent_;
1084+
std::string_view name_;
10721085
};
10731086

10741087
template <typename T>
@@ -1416,6 +1429,9 @@ class prototype_database {
14161429
const prototype<>::ptr& parent() const final {
14171430
return this->resolve()->parent();
14181431
}
1432+
const std::string_view& name() const final {
1433+
return this->resolve()->name();
1434+
}
14191435

14201436
private:
14211437
prototype_ptr<T> resolve() const {

third-party/thrift/src/thrift/compiler/whisker/test/dsl_test.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,36 @@ TEST(DslTest, make_polymorphic_native_handle) {
5353
EXPECT_TRUE((std::is_same_v<A, poly<t_A, t_B, t_B2, t_C, t_C2>>));
5454
}
5555

56+
TEST(DslTest, test_alias_inheritance) {
57+
struct t_Base {
58+
virtual ~t_Base() = default;
59+
};
60+
struct t_Child : public t_Base {
61+
~t_Child() override;
62+
};
63+
64+
using h_Child = make_poly<t_Child>;
65+
using h_Base = make_poly<t_Base, h_Child>;
66+
67+
EXPECT_TRUE((std::is_same_v<h_Child, poly<t_Child>>));
68+
EXPECT_TRUE((std::is_same_v<h_Base, poly<t_Base, t_Child>>));
69+
70+
prototype_database proto{};
71+
prototype_builder<h_Base> proto_base{"base"};
72+
proto.define(std::move(proto_base).make());
73+
74+
prototype_builder<h_Child> proto_child =
75+
prototype_builder<h_Child>::extends(proto.of<t_Base>());
76+
EXPECT_EQ("", std::move(proto_child).make()->name())
77+
<< "Extending a parent type should not inherit its name";
78+
79+
proto_child =
80+
prototype_builder<h_Child>::extends(proto.of<t_Base>(), "child");
81+
82+
prototype_builder<h_Child> proto_child_extension =
83+
prototype_builder<h_Child>::patches(std::move(proto_child).make());
84+
EXPECT_EQ("child", std::move(proto_child_extension).make()->name())
85+
<< "Extending the same type should inherit its name";
86+
}
87+
5688
} // namespace whisker::dsl

0 commit comments

Comments
 (0)