Skip to content

Commit e93d6e4

Browse files
vitautfacebook-github-bot
authored andcommitted
Merge namespace into name resolver
Summary: Name resolver already contains a namespace resolver but only provides a subset of the API. As a result some users end up creating duplicate caches. Merge the two to keep all name resolution and caches in one place, fix some names that don't follow the conventions and cleanup name resolver tests. Reviewed By: yoney Differential Revision: D63923307 fbshipit-source-id: 4cee15d94f17edd518f9f8fb1fd3bc16bec38faf
1 parent dfafb5d commit e93d6e4

File tree

12 files changed

+233
-395
lines changed

12 files changed

+233
-395
lines changed

third-party/thrift/src/thrift/compiler/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,6 @@ target_link_libraries(
129129
add_library(
130130
compiler
131131

132-
gen/cpp/gen.cc
133-
gen/cpp/namespace_resolver.cc
134132
gen/cpp/reference_type.cc
135133
gen/cpp/name_resolver.cc
136134

third-party/thrift/src/thrift/compiler/gen/cpp/gen.cc

Lines changed: 0 additions & 34 deletions
This file was deleted.

third-party/thrift/src/thrift/compiler/gen/cpp/gen.h

Lines changed: 0 additions & 36 deletions
This file was deleted.

third-party/thrift/src/thrift/compiler/gen/cpp/name_resolver.cc

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
#include <stdexcept>
2020

2121
#include <fmt/core.h>
22+
#include <thrift/compiler/ast/t_function.h>
2223
#include <thrift/compiler/ast/t_list.h>
2324
#include <thrift/compiler/ast/t_map.h>
2425
#include <thrift/compiler/ast/t_node.h>
26+
#include <thrift/compiler/ast/t_program.h>
2527
#include <thrift/compiler/ast/t_set.h>
2628
#include <thrift/compiler/ast/t_struct.h>
2729
#include <thrift/compiler/ast/t_typedef.h>
@@ -44,6 +46,23 @@ const t_type* find_first_type(const t_type& node) {
4446

4547
} // namespace
4648

49+
namespace detail {
50+
51+
std::string gen_template_type(
52+
std::string template_name, std::initializer_list<std::string> args) {
53+
template_name += "<";
54+
auto delim = "";
55+
for (const auto& arg : args) {
56+
template_name += delim;
57+
delim = ", ";
58+
template_name += arg;
59+
}
60+
template_name += ">";
61+
return template_name;
62+
}
63+
64+
} // namespace detail
65+
4766
const std::string& cpp_name_resolver::get_native_type(
4867
const t_field& field, const t_structured& parent) {
4968
const t_type& type = *field.type();
@@ -65,7 +84,7 @@ const std::string& cpp_name_resolver::get_native_type(
6584
// If @cpp.Adapter is used on typedef of the field, use the typedef name.
6685
if (const auto* typedf = dynamic_cast<const t_typedef*>(&type)) {
6786
if (find_structured_adapter_annotation(*typedf)) {
68-
return namespaces_.get_namespaced_name(*typedf);
87+
return get_namespaced_name(*typedf);
6988
}
7089
}
7190

@@ -181,7 +200,7 @@ const std::string& cpp_name_resolver::get_underlying_namespaced_name(
181200
auto extra = get_extra_namespace(node);
182201
return fmt::format(
183202
"{}::{}{}",
184-
namespaces_.get_namespace(*program),
203+
get_namespace(*program),
185204
extra ? *extra + "::" : "",
186205
get_underlying_name(node));
187206
}
@@ -198,7 +217,7 @@ const std::string& cpp_name_resolver::get_underlying_name(const t_type& node) {
198217
return value->get_string();
199218
}
200219
}
201-
return gen::cpp::namespace_resolver::get_cpp_name(node);
220+
return cpp_name_resolver::get_cpp_name(node);
202221
}
203222

204223
const std::string* cpp_name_resolver::get_extra_namespace(const t_type& node) {
@@ -212,8 +231,8 @@ const std::string* cpp_name_resolver::get_extra_namespace(const t_type& node) {
212231
const auto* name = annotation->get_value_from_structured_annotation_or_null(
213232
"underlyingName");
214233
if (name == nullptr || name->get_string().empty()) {
215-
static const std::string kDefault = "detail";
216-
return &kDefault;
234+
static const std::string detail = "detail";
235+
return &detail;
217236
}
218237
}
219238
return nullptr;
@@ -265,6 +284,28 @@ const std::string* cpp_name_resolver::find_first_adapter(const t_field& field) {
265284
return nullptr;
266285
}
267286

287+
std::vector<std::string> cpp_name_resolver::gen_namespace_components(
288+
const t_program& program) {
289+
t_program::namespace_config conf;
290+
conf.no_top_level_domain = true;
291+
auto components = program.gen_namespace_or_default("cpp2", conf);
292+
if (components.empty()) {
293+
components = program.gen_namespace_or_default("cpp", conf);
294+
components.push_back("cpp2");
295+
}
296+
return components;
297+
}
298+
299+
std::string cpp_name_resolver::gen_namespace(const t_program& program) {
300+
return "::" + gen_unprefixed_namespace(program);
301+
}
302+
303+
std::string cpp_name_resolver::gen_unprefixed_namespace(
304+
const t_program& program) {
305+
const auto components = gen_namespace_components(program);
306+
return fmt::format("{}", fmt::join(components, "::"));
307+
}
308+
268309
bool cpp_name_resolver::can_resolve_to_scalar(const t_type& node) {
269310
return node.get_true_type()->is_scalar() || find_first_adapter(node) ||
270311
find_first_type(node);
@@ -274,16 +315,16 @@ const std::string& cpp_name_resolver::default_template(
274315
t_container::type ctype) {
275316
switch (ctype) {
276317
case t_container::type::t_list: {
277-
static const auto& kValue = *new std::string("::std::vector");
278-
return kValue;
318+
static const auto& value = *new std::string("::std::vector");
319+
return value;
279320
}
280321
case t_container::type::t_set: {
281-
static const auto& kValue = *new std::string("::std::set");
282-
return kValue;
322+
static const auto& value = *new std::string("::std::set");
323+
return value;
283324
}
284325
case t_container::type::t_map: {
285-
static const auto& kValue = *new std::string("::std::map");
286-
return kValue;
326+
static const auto& value = *new std::string("::std::map");
327+
return value;
287328
}
288329
}
289330
throw std::runtime_error(
@@ -294,41 +335,41 @@ const std::string& cpp_name_resolver::default_type(
294335
t_primitive_type::type btype) {
295336
switch (btype) {
296337
case t_primitive_type::type::t_void: {
297-
static const auto& kValue = *new std::string("void");
298-
return kValue;
338+
static const auto& value = *new std::string("void");
339+
return value;
299340
}
300341
case t_primitive_type::type::t_bool: {
301-
static const auto& kValue = *new std::string("bool");
302-
return kValue;
342+
static const auto& value = *new std::string("bool");
343+
return value;
303344
}
304345
case t_primitive_type::type::t_byte: {
305-
static const auto& kValue = *new std::string("::std::int8_t");
306-
return kValue;
346+
static const auto& value = *new std::string("::std::int8_t");
347+
return value;
307348
}
308349
case t_primitive_type::type::t_i16: {
309-
static const auto& kValue = *new std::string("::std::int16_t");
310-
return kValue;
350+
static const auto& value = *new std::string("::std::int16_t");
351+
return value;
311352
}
312353
case t_primitive_type::type::t_i32: {
313-
static const auto& kValue = *new std::string("::std::int32_t");
314-
return kValue;
354+
static const auto& value = *new std::string("::std::int32_t");
355+
return value;
315356
}
316357
case t_primitive_type::type::t_i64: {
317-
static const auto& kValue = *new std::string("::std::int64_t");
318-
return kValue;
358+
static const auto& value = *new std::string("::std::int64_t");
359+
return value;
319360
}
320361
case t_primitive_type::type::t_float: {
321-
static const auto& kValue = *new std::string("float");
322-
return kValue;
362+
static const auto& value = *new std::string("float");
363+
return value;
323364
}
324365
case t_primitive_type::type::t_double: {
325-
static const auto& kValue = *new std::string("double");
326-
return kValue;
366+
static const auto& value = *new std::string("double");
367+
return value;
327368
}
328369
case t_primitive_type::type::t_string:
329370
case t_primitive_type::type::t_binary: {
330-
static const auto& kValue = *new std::string("::std::string");
331-
return kValue;
371+
static const auto& value = *new std::string("::std::string");
372+
return value;
332373
}
333374
}
334375
throw std::runtime_error(
@@ -421,7 +462,7 @@ std::string cpp_name_resolver::gen_standard_type(
421462
}
422463

423464
// For everything else, just use namespaced name.
424-
return namespaces_.get_namespaced_name(node);
465+
return get_namespaced_name(node);
425466
}
426467

427468
std::string cpp_name_resolver::gen_container_type(

third-party/thrift/src/thrift/compiler/gen/cpp/name_resolver.h

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#pragma once
1818

1919
#include <stdint.h>
20+
#include <initializer_list>
2021
#include <string>
2122
#include <unordered_map>
2223
#include <utility>
@@ -25,8 +26,6 @@
2526
#include <thrift/compiler/ast/t_field.h>
2627
#include <thrift/compiler/ast/t_primitive_type.h>
2728
#include <thrift/compiler/ast/t_type.h>
28-
#include <thrift/compiler/gen/cpp/gen.h>
29-
#include <thrift/compiler/gen/cpp/namespace_resolver.h>
3029
#include <thrift/compiler/gen/cpp/reference_type.h>
3130
#include <thrift/compiler/lib/uri.h>
3231

@@ -48,11 +47,27 @@ struct std::hash<std::pair<
4847
};
4948

5049
namespace apache::thrift::compiler {
50+
namespace detail {
51+
template <typename C, typename K = typename C::key_type, typename G>
52+
auto& get_or_gen(C& cache, const K& key, const G& gen_func) {
53+
auto itr = cache.find(key);
54+
if (itr == cache.end()) {
55+
itr = cache.emplace(key, gen_func()).first;
56+
}
57+
return itr->second;
58+
}
59+
60+
std::string gen_template_type(
61+
std::string template_name, std::initializer_list<std::string> args);
62+
} // namespace detail
5163

64+
class t_function;
5265
class t_named;
5366
class t_program;
5467
class t_sink;
5568
class t_stream;
69+
class t_structured;
70+
class t_typedef;
5671

5772
using cpp_reference_type = gen::cpp::reference_type;
5873

@@ -96,11 +111,41 @@ class cpp_name_resolver {
96111
field_type_tag_cache_, &node, [&] { return gen_type_tag(node); });
97112
}
98113

99-
std::string get_namespaced_name(
114+
// Returns C++ namespace for the given program.
115+
const std::string& get_namespace(const t_program& node) {
116+
return detail::get_or_gen(
117+
namespace_cache_, &node, [&]() { return gen_namespace(node); });
118+
}
119+
120+
const std::string& get_namespaced_name(
100121
const t_program& program, const t_named& node) {
101-
return namespaces_.get_namespaced_name(program, node);
122+
return detail::get_or_gen(name_cache_, &node, [&]() {
123+
return gen_namespaced_name(program, node);
124+
});
125+
}
126+
const std::string& get_namespaced_name(
127+
const t_program* program, const t_named& node) {
128+
return program == nullptr ? get_cpp_name(node)
129+
: get_namespaced_name(*program, node);
130+
}
131+
const std::string& get_namespaced_name(const t_type& node) {
132+
return get_namespaced_name(node.program(), node);
102133
}
103134

135+
static const std::string& get_cpp_name(const t_named& node) {
136+
if (const auto* cpp_name =
137+
node.find_structured_annotation_or_null(kCppNameUri)) {
138+
return cpp_name->get_value_from_structured_annotation("value")
139+
.get_string();
140+
}
141+
return node.get_annotation("cpp.name", &node.name());
142+
}
143+
144+
static std::string gen_namespace(const t_program& progam);
145+
static std::string gen_unprefixed_namespace(const t_program& progam);
146+
static std::vector<std::string> gen_namespace_components(
147+
const t_program& program);
148+
104149
const std::string& get_underlying_namespaced_name(const t_type& node);
105150

106151
static const std::string& get_underlying_name(const t_type& node);
@@ -154,7 +199,8 @@ class cpp_name_resolver {
154199
using type_resolve_fn =
155200
const std::string& (cpp_name_resolver::*)(const t_type& node);
156201

157-
gen::cpp::namespace_resolver namespaces_;
202+
std::unordered_map<const t_program*, std::string> namespace_cache_;
203+
std::unordered_map<const t_named*, std::string> name_cache_;
158204
std::unordered_map<const t_type*, std::string> type_cache_;
159205
std::unordered_map<const t_sink*, std::string> sink_cache_;
160206
std::unordered_map<const t_const*, std::string> const_cache_;
@@ -169,14 +215,16 @@ class cpp_name_resolver {
169215
std::unordered_map<const t_field*, std::string> field_type_tag_cache_;
170216
std::unordered_map<const t_field*, std::string> field_reference_type_cache_;
171217

218+
std::string gen_namespaced_name(
219+
const t_program& program, const t_named& node) {
220+
return get_namespace(program) + "::" + get_cpp_name(node);
221+
}
172222
static const std::string* get_string_from_annotation_or_null(
173223
const t_named& node, const char* uri, const char* key);
174224

175225
static const std::string& default_type(t_primitive_type::type btype);
176226
static const std::string& default_template(t_container::type ctype);
177227

178-
const std::string& get_namespace(const t_program& program);
179-
180228
// Generating functions.
181229
std::string gen_type(const t_type& node);
182230
std::string gen_field_type(

0 commit comments

Comments
 (0)