1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <cctype>
18 #include <set>
19
20 #include <boost/algorithm/string.hpp>
21 #include <boost/algorithm/string/predicate.hpp>
22 #include <boost/algorithm/string/replace.hpp>
23 #include <thrift/compiler/lib/java/util.h>
24
25 #include <thrift/compiler/generate/t_mstch_generator.h>
26 #include <thrift/compiler/generate/t_mstch_objects.h>
27
28 using namespace std;
29
30 namespace apache {
31 namespace thrift {
32 namespace compiler {
33
34 namespace {
35 /**
36 * Gets the swift namespace, throws a runtime error if not found.
37 */
get_namespace_or_default(const t_program & prog)38 std::string get_namespace_or_default(const t_program& prog) {
39 const auto& prog_namespace = prog.get_namespace("java.swift");
40 if (prog_namespace != "") {
41 return prog_namespace;
42 } else {
43 throw std::runtime_error{"No namespace 'java.swift' in " + prog.name()};
44 }
45 }
46
get_constants_class_name(const t_program & prog)47 std::string get_constants_class_name(const t_program& prog) {
48 const auto& constant_name = prog.get_namespace("java.swift.constants");
49 if (constant_name == "") {
50 return "Constants";
51 } else {
52 auto java_name_space = get_namespace_or_default(prog);
53 std::string java_class_name;
54 if (constant_name.rfind(java_name_space) == 0) {
55 java_class_name = constant_name.substr(java_name_space.length() + 1);
56 } else {
57 java_class_name = constant_name;
58 }
59
60 if (java_class_name == "" ||
61 java_class_name.find('.') != std::string::npos) {
62 throw std::runtime_error{
63 "Java Constants Class Name `" + java_class_name +
64 "` is not well formatted."};
65 }
66
67 return java_class_name;
68 }
69 }
70
71 template <typename Node>
get_java_swift_name(const Node * node)72 std::string get_java_swift_name(const Node* node) {
73 return node->get_annotation(
74 "java.swift.name", java::mangle_java_name(node->get_name(), false));
75 }
76
77 } // namespace
78
79 class t_mstch_swift_generator : public t_mstch_generator {
80 public:
t_mstch_swift_generator(t_program * program,t_generation_context context,const std::map<std::string,std::string> & parsed_options,const std::string &)81 t_mstch_swift_generator(
82 t_program* program,
83 t_generation_context context,
84 const std::map<std::string, std::string>& parsed_options,
85 const std::string& /* option_string */)
86 : t_mstch_generator(
87 program, std::move(context), "java/swift", parsed_options) {
88 out_dir_base_ = "gen-swift";
89 }
90
91 void generate_program() override;
92
93 private:
94 void set_mstch_generators();
95
96 /*
97 * Generate multiple Java items according to the given template. Writes
98 * output to package_dir underneath the global output directory.
99 */
100
101 template <typename T, typename Generator, typename Cache>
generate_items(Generator const * generator,Cache & c,const t_program * program,const std::vector<T * > & items,const std::string & tpl_path)102 void generate_items(
103 Generator const* generator,
104 Cache& c,
105 const t_program* program,
106 const std::vector<T*>& items,
107 const std::string& tpl_path) {
108 const auto& id = program->path();
109 if (!cache_->programs_.count(id)) {
110 cache_->programs_[id] = generators_->program_generator_->generate(
111 program, generators_, cache_);
112 }
113 auto package_dir = boost::filesystem::path{
114 java::package_to_path(get_namespace_or_default(*program))};
115
116 for (const T* item : items) {
117 auto filename = java::mangle_java_name(item->get_name(), true) + ".java";
118 const auto& item_id = id + item->get_name();
119 if (!c.count(item_id)) {
120 c[item_id] = generator->generate(item, generators_, cache_);
121 }
122
123 render_to_file(c[item_id], tpl_path, package_dir / filename);
124 }
125 }
126
127 /*
128 * Generate Service Client implementation - Sync & Async. Writes
129 * output to package_dir
130 */
131 template <typename T, typename Generator, typename Cache>
generate_client(Generator const * generator,Cache & c,const t_program * program,const std::vector<T * > & services)132 void generate_client(
133 Generator const* generator,
134 Cache& c,
135 const t_program* program,
136 const std::vector<T*>& services) {
137 const auto& id = program->path();
138 if (!cache_->programs_.count(id)) {
139 cache_->programs_[id] = generators_->program_generator_->generate(
140 program, generators_, cache_);
141 }
142 auto package_dir = boost::filesystem::path{
143 java::package_to_path(get_namespace_or_default(*program))};
144
145 // Iterate through services
146 for (const T* service : services) {
147 auto service_name = java::mangle_java_name(service->get_name(), true);
148 // Generate sync client
149 auto sync_filename = service_name + "ClientImpl.java";
150 const auto& sync_service_id = id + service->get_name() + "Client";
151 if (!c.count(sync_service_id)) {
152 c[sync_service_id] = generator->generate(service, generators_, cache_);
153 }
154
155 render_to_file(
156 c[sync_service_id], "ServiceClient", package_dir / sync_filename);
157
158 // Generate async client
159 auto async_filename = service_name + "AsyncClientImpl.java";
160 const auto& async_service_id = id + service->get_name() + "AsyncClient";
161 if (!c.count(async_service_id)) {
162 c[async_service_id] = generator->generate(service, generators_, cache_);
163 }
164
165 render_to_file(
166 c[async_service_id],
167 "ServiceAsyncClient",
168 package_dir / async_filename);
169
170 // Generate Async to Reactive Wrapper
171 auto async_reactive_wrapper_filename =
172 service_name + "AsyncReactiveWrapper.java";
173 const auto& async_reactive_wrapper_id =
174 id + service->get_name() + "AsyncReactiveWrapper";
175 if (!c.count(async_reactive_wrapper_id)) {
176 c[async_reactive_wrapper_id] =
177 generator->generate(service, generators_, cache_);
178 }
179
180 render_to_file(
181 c[async_reactive_wrapper_id],
182 "AsyncReactiveWrapper",
183 package_dir / async_reactive_wrapper_filename);
184
185 // Generate Blocking to Reactive Wrapper
186 auto blocking_reactive_wrapper_filename =
187 service_name + "BlockingReactiveWrapper.java";
188 const auto& blocking_reactive_wrapper_id =
189 id + service->get_name() + "BlockingReactiveWrapper";
190 if (!c.count(blocking_reactive_wrapper_id)) {
191 c[blocking_reactive_wrapper_id] =
192 generator->generate(service, generators_, cache_);
193 }
194
195 render_to_file(
196 c[blocking_reactive_wrapper_id],
197 "BlockingReactiveWrapper",
198 package_dir / blocking_reactive_wrapper_filename);
199
200 // Generate Reactive to Async Wrapper
201 auto reactive_async_wrapper_filename =
202 service_name + "ReactiveAsyncWrapper.java";
203 const auto& reactive_async_wrapper_id =
204 id + service->get_name() + "ReactiveAsyncWrapper";
205 if (!c.count(reactive_async_wrapper_id)) {
206 c[reactive_async_wrapper_id] =
207 generator->generate(service, generators_, cache_);
208 }
209
210 render_to_file(
211 c[reactive_async_wrapper_id],
212 "ReactiveAsyncWrapper",
213 package_dir / reactive_async_wrapper_filename);
214
215 // Generate Reactive to Blocking Wrapper
216 auto reactive_blocking_wrapper_filename =
217 service_name + "ReactiveBlockingWrapper.java";
218 const auto& reactive_blocking_wrapper_id =
219 id + service->get_name() + "ReactiveBlockingWrapper";
220 if (!c.count(reactive_blocking_wrapper_id)) {
221 c[reactive_blocking_wrapper_id] =
222 generator->generate(service, generators_, cache_);
223 }
224
225 render_to_file(
226 c[reactive_blocking_wrapper_id],
227 "ReactiveBlockingWrapper",
228 package_dir / reactive_blocking_wrapper_filename);
229
230 // Generate Reactive Client
231 auto reactive_client_filename = service_name + "ReactiveClient.java";
232 const auto& reactive_client_wrapper_id =
233 id + service->get_name() + "ReactiveClient";
234 if (!c.count(reactive_client_wrapper_id)) {
235 c[reactive_client_wrapper_id] =
236 generator->generate(service, generators_, cache_);
237 }
238
239 render_to_file(
240 c[reactive_client_wrapper_id],
241 "ReactiveClient",
242 package_dir / reactive_client_filename);
243
244 // Generate RpcServerHandler
245 auto rpc_server_handler_filename = service_name + "RpcServerHandler.java";
246 const auto& rpc_server_handler_id =
247 id + service->get_name() + "RpcServerHandler";
248 if (!c.count(rpc_server_handler_id)) {
249 c[rpc_server_handler_id] =
250 generator->generate(service, generators_, cache_);
251 }
252
253 render_to_file(
254 c[rpc_server_handler_id],
255 "RpcServerHandler",
256 package_dir / rpc_server_handler_filename);
257 }
258 }
259
generate_constants(const t_program * program)260 void generate_constants(const t_program* program) {
261 if (program->consts().empty()) {
262 // Only generate Constants.java if we actually have constants
263 return;
264 }
265 auto name = program->name();
266 const auto& prog = cached_program(program);
267
268 auto package_dir = boost::filesystem::path{
269 java::package_to_path(get_namespace_or_default(*program))};
270 auto constant_file_name = get_constants_class_name(*program) + ".java";
271 render_to_file(prog, "Constants", package_dir / constant_file_name);
272 }
273
generate_placeholder(const t_program * program)274 void generate_placeholder(const t_program* program) {
275 auto package_dir = boost::filesystem::path{
276 java::package_to_path(get_namespace_or_default(*program))};
277 auto placeholder_file_name = ".generated_" + program->name();
278 write_output(package_dir / placeholder_file_name, "");
279 }
280 };
281
282 class mstch_swift_program : public mstch_program {
283 public:
mstch_swift_program(t_program const * program,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos)284 mstch_swift_program(
285 t_program const* program,
286 std::shared_ptr<mstch_generators const> generators,
287 std::shared_ptr<mstch_cache> cache,
288 ELEMENT_POSITION const pos)
289 : mstch_program(program, generators, cache, pos) {
290 register_methods(
291 this,
292 {
293 {"program:javaPackage", &mstch_swift_program::java_package},
294 {"program:constantClassName",
295 &mstch_swift_program::constant_class_name},
296 });
297 }
java_package()298 mstch::node java_package() { return get_namespace_or_default(*program_); }
constant_class_name()299 mstch::node constant_class_name() {
300 return get_constants_class_name(*program_);
301 }
302 };
303
304 class mstch_swift_struct : public mstch_struct {
305 // A struct is a "big struct" if it contains > 127 members. The reason for
306 // this limit is that we generate exhaustive constructor for Thrift struct
307 // but Java methods are limited to 255 arguments (and since long/double
308 // types count twice, 127 is a safe threshold).
309 static constexpr uint64_t bigStructThreshold = 127;
310
311 public:
mstch_swift_struct(t_struct const * strct,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos)312 mstch_swift_struct(
313 t_struct const* strct,
314 std::shared_ptr<mstch_generators const> generators,
315 std::shared_ptr<mstch_cache> cache,
316 ELEMENT_POSITION const pos)
317 : mstch_struct(strct, generators, cache, pos) {
318 register_methods(
319 this,
320 {
321 {"struct:javaPackage", &mstch_swift_struct::java_package},
322 {"struct:unionFieldTypeUnique?",
323 &mstch_swift_struct::is_union_field_type_unique},
324 {"struct:asBean?", &mstch_swift_struct::is_as_bean},
325 {"struct:isBigStruct?", &mstch_swift_struct::is_BigStruct},
326 {"struct:javaCapitalName", &mstch_swift_struct::java_capital_name},
327 {"struct:javaAnnotations?",
328 &mstch_swift_struct::has_java_annotations},
329 {"struct:isUnion?", &mstch_swift_struct::is_struct_union},
330 {"struct:javaAnnotations", &mstch_swift_struct::java_annotations},
331 {"struct:exceptionMessage", &mstch_swift_struct::exception_message},
332 {"struct:needsExceptionMessage?",
333 &mstch_swift_struct::needs_exception_message},
334 {"struct:enableIsSet?", &mstch_swift_struct::enable_is_set},
335 });
336 register_has_option(
337 "struct:extendRuntimeException?", "legacy_extend_runtime_exception");
338 }
java_package()339 mstch::node java_package() {
340 return get_namespace_or_default(*(strct_->program()));
341 }
is_struct_union()342 mstch::node is_struct_union() { return strct_->is_union(); }
is_union_field_type_unique()343 mstch::node is_union_field_type_unique() {
344 std::set<std::string> field_types;
345 for (const auto& field : strct_->fields()) {
346 auto type_name = field.type()->get_full_name();
347 std::string type_with_erasure = type_name.substr(0, type_name.find('<'));
348 if (field_types.find(type_with_erasure) != field_types.end()) {
349 return false;
350 } else {
351 field_types.insert(type_with_erasure);
352 }
353 }
354 return true;
355 }
is_as_bean()356 mstch::node is_as_bean() {
357 if (!strct_->is_xception() && !strct_->is_union()) {
358 return strct_->get_annotation("java.swift.mutable") == "true";
359 } else {
360 return false;
361 }
362 }
363
is_BigStruct()364 mstch::node is_BigStruct() {
365 return (
366 strct_->is_struct() && strct_->fields().size() > bigStructThreshold);
367 }
368
java_capital_name()369 mstch::node java_capital_name() {
370 return java::mangle_java_name(strct_->get_name(), true);
371 }
has_java_annotations()372 mstch::node has_java_annotations() {
373 return strct_->has_annotation("java.swift.annotations");
374 }
java_annotations()375 mstch::node java_annotations() {
376 return strct_->get_annotation("java.swift.annotations");
377 }
exception_message()378 mstch::node exception_message() {
379 const auto& field_name_to_use = strct_->get_annotation("message");
380 if (const auto* field = strct_->get_field_by_name(field_name_to_use)) {
381 return get_java_swift_name(field);
382 }
383
384 throw std::runtime_error{
385 "The exception message field '" + field_name_to_use +
386 "' is not found in " + strct_->get_name() + "!"};
387 }
388 // we can only override Throwable's getMessage() if:
389 // 1 - there is provided 'message' annotation
390 // 2 - there is no struct field named 'message'
391 // (since it will generate getMessage() as well)
needs_exception_message()392 mstch::node needs_exception_message() {
393 return strct_->is_xception() && strct_->has_annotation("message") &&
394 strct_->get_field_by_name("message") == nullptr;
395 }
enable_is_set()396 mstch::node enable_is_set() {
397 return strct_->has_annotation("java.swift.enable_is_set");
398 }
399 };
400
401 class mstch_swift_service : public mstch_service {
402 public:
mstch_swift_service(t_service const * service,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos)403 mstch_swift_service(
404 t_service const* service,
405 std::shared_ptr<mstch_generators const> generators,
406 std::shared_ptr<mstch_cache> cache,
407 ELEMENT_POSITION const pos)
408 : mstch_service(service, generators, cache, pos) {
409 register_methods(
410 this,
411 {
412 {"service:javaPackage", &mstch_swift_service::java_package},
413 {"service:javaCapitalName",
414 &mstch_swift_service::java_capital_name},
415 {"service:onewayFunctions",
416 &mstch_swift_service::get_oneway_functions},
417 {"service:requestResponseFunctions",
418 &mstch_swift_service::get_request_response_functions},
419 {"service:supportedFunctions",
420 &mstch_swift_service::get_supported_functions},
421 {"service:streamingFunctions",
422 &mstch_swift_service::get_streaming_functions},
423 {"service:sinkFunctions", &mstch_swift_service::get_sink_functions},
424 });
425 }
java_package()426 mstch::node java_package() {
427 return get_namespace_or_default(*(service_->program()));
428 }
java_capital_name()429 mstch::node java_capital_name() {
430 return java::mangle_java_name(service_->get_name(), true);
431 }
get_oneway_functions()432 mstch::node get_oneway_functions() {
433 std::vector<t_function*> funcs;
434 for (auto func : service_->get_functions()) {
435 if (func->is_oneway()) {
436 funcs.push_back(func);
437 }
438 }
439 return generate_functions(funcs);
440 }
get_request_response_functions()441 mstch::node get_request_response_functions() {
442 std::vector<t_function*> funcs;
443 for (auto func : service_->get_functions()) {
444 if (!func->returns_stream() && !func->returns_sink() &&
445 !func->get_returntype()->is_service() && !func->is_oneway()) {
446 funcs.push_back(func);
447 }
448 }
449 return generate_functions(funcs);
450 }
get_supported_functions()451 mstch::node get_supported_functions() {
452 std::vector<t_function*> funcs;
453 for (auto func : service_->get_functions()) {
454 if (!func->returns_stream() && !func->returns_sink() &&
455 !func->get_returntype()->is_service()) {
456 funcs.push_back(func);
457 }
458 }
459 return generate_functions(funcs);
460 }
461
get_streaming_functions()462 mstch::node get_streaming_functions() {
463 std::vector<t_function*> funcs;
464 for (auto func : service_->get_functions()) {
465 if (func->returns_stream()) {
466 funcs.push_back(func);
467 }
468 }
469 return generate_functions(funcs);
470 }
471
get_sink_functions()472 mstch::node get_sink_functions() {
473 std::vector<t_function*> funcs;
474 for (auto func : service_->get_functions()) {
475 if (func->returns_sink()) {
476 funcs.push_back(func);
477 }
478 }
479 return generate_functions(funcs);
480 }
481 };
482
483 class mstch_swift_function : public mstch_function {
484 public:
mstch_swift_function(t_function const * function,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos)485 mstch_swift_function(
486 t_function const* function,
487 std::shared_ptr<mstch_generators const> generators,
488 std::shared_ptr<mstch_cache> cache,
489 ELEMENT_POSITION const pos)
490 : mstch_function(function, generators, cache, pos) {
491 register_methods(
492 this,
493 {
494 {"function:javaName", &mstch_swift_function::java_name},
495 {"function:voidType", &mstch_swift_function::is_void_type},
496 {"function:nestedDepth", &mstch_swift_function::get_nested_depth},
497 {"function:nestedDepth++",
498 &mstch_swift_function::increment_nested_depth},
499 {"function:nestedDepth--",
500 &mstch_swift_function::decrement_nested_depth},
501 {"function:isFirstDepth?", &mstch_swift_function::is_first_depth},
502 {"function:prevNestedDepth",
503 &mstch_swift_function::preceding_nested_depth},
504 {"function:isNested?",
505 &mstch_swift_function::get_nested_container_flag},
506 {"function:setIsNested",
507 &mstch_swift_function::set_nested_container_flag},
508 {"function:unsetIsNested",
509 &mstch_swift_function::unset_nested_container_flag},
510 });
511 }
512
513 int32_t nestedDepth = 0;
514 bool isNestedContainerFlag = false;
515
get_nested_depth()516 mstch::node get_nested_depth() { return nestedDepth; }
preceding_nested_depth()517 mstch::node preceding_nested_depth() { return (nestedDepth - 1); }
is_first_depth()518 mstch::node is_first_depth() { return (nestedDepth == 1); }
get_nested_container_flag()519 mstch::node get_nested_container_flag() { return isNestedContainerFlag; }
set_nested_container_flag()520 mstch::node set_nested_container_flag() {
521 isNestedContainerFlag = true;
522 return mstch::node();
523 }
unset_nested_container_flag()524 mstch::node unset_nested_container_flag() {
525 isNestedContainerFlag = false;
526 return mstch::node();
527 }
increment_nested_depth()528 mstch::node increment_nested_depth() {
529 nestedDepth++;
530 return mstch::node();
531 }
decrement_nested_depth()532 mstch::node decrement_nested_depth() {
533 nestedDepth--;
534 return mstch::node();
535 }
536
java_name()537 mstch::node java_name() {
538 return java::mangle_java_name(function_->get_name(), false);
539 }
540
is_void_type()541 mstch::node is_void_type() { return function_->get_returntype()->is_void(); }
542 };
543
544 class mstch_swift_field : public mstch_field {
545 public:
mstch_swift_field(t_field const * field,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos,int32_t index,field_generator_context const * field_context)546 mstch_swift_field(
547 t_field const* field,
548 std::shared_ptr<mstch_generators const> generators,
549 std::shared_ptr<mstch_cache> cache,
550 ELEMENT_POSITION const pos,
551 int32_t index,
552 field_generator_context const* field_context)
553 : mstch_field(field, generators, cache, pos, index, field_context) {
554 register_methods(
555 this,
556 {
557 {"field:javaName", &mstch_swift_field::java_name},
558 {"field:javaCapitalName", &mstch_swift_field::java_capital_name},
559 {"field:javaDefaultValue", &mstch_swift_field::java_default_value},
560 {"field:javaAllCapsName", &mstch_swift_field::java_all_caps_name},
561 {"field:recursive?", &mstch_swift_field::is_recursive_reference},
562 {"field:negativeId?", &mstch_swift_field::is_negative_id},
563 {"field:javaAnnotations?",
564 &mstch_swift_field::has_java_annotations},
565 {"field:javaAnnotations", &mstch_swift_field::java_annotations},
566 {"field:javaTFieldName", &mstch_swift_field::java_tfield_name},
567 {"field:isNullableOrOptionalNotEnum?",
568 &mstch_swift_field::is_nullable_or_optional_not_enum},
569 {"field:nestedDepth", &mstch_swift_field::get_nested_depth},
570 {"field:nestedDepth++", &mstch_swift_field::increment_nested_depth},
571 {"field:nestedDepth--", &mstch_swift_field::decrement_nested_depth},
572 {"field:isFirstDepth?", &mstch_swift_field::is_first_depth},
573 {"field:prevNestedDepth",
574 &mstch_swift_field::preceding_nested_depth},
575 {"field:isContainer?", &mstch_swift_field::is_container},
576 {"field:isNested?", &mstch_swift_field::get_nested_container_flag},
577 {"field:setIsNested",
578 &mstch_swift_field::set_nested_container_flag},
579 {"field:typeFieldName", &mstch_swift_field::type_field_name},
580 {"field:isSensitive?", &mstch_swift_field::is_sensitive},
581 {"field:hasInitialValue?", &mstch_swift_field::has_initial_value},
582 {"field:isPrimitive?", &mstch_swift_field::is_primitive},
583 });
584 }
585
586 int32_t nestedDepth = 0;
587 bool isNestedContainerFlag = false;
588
has_initial_value()589 mstch::node has_initial_value() {
590 if (field_->get_req() == t_field::e_req::optional) {
591 // default values are ignored for optional fields
592 return false;
593 }
594 return field_->get_value();
595 }
get_nested_depth()596 mstch::node get_nested_depth() { return nestedDepth; }
preceding_nested_depth()597 mstch::node preceding_nested_depth() { return (nestedDepth - 1); }
is_first_depth()598 mstch::node is_first_depth() { return (nestedDepth == 1); }
get_nested_container_flag()599 mstch::node get_nested_container_flag() { return isNestedContainerFlag; }
set_nested_container_flag()600 mstch::node set_nested_container_flag() {
601 isNestedContainerFlag = true;
602 return mstch::node();
603 }
increment_nested_depth()604 mstch::node increment_nested_depth() {
605 nestedDepth++;
606 return mstch::node();
607 }
decrement_nested_depth()608 mstch::node decrement_nested_depth() {
609 nestedDepth--;
610 return mstch::node();
611 }
is_primitive()612 mstch::node is_primitive() {
613 auto type = field_->get_type()->get_true_type();
614 return type->is_void() || type->is_bool() || type->is_byte() ||
615 type->is_i16() || type->is_i32() || type->is_i64() ||
616 type->is_double() || type->is_float();
617 }
618
is_nullable_or_optional_not_enum()619 mstch::node is_nullable_or_optional_not_enum() {
620 if (field_->get_req() == t_field::e_req::optional) {
621 return true;
622 }
623 const t_type* field_type = field_->get_type()->get_true_type();
624 return !(
625 field_type->is_bool() || field_type->is_byte() ||
626 field_type->is_float() || field_type->is_i16() ||
627 field_type->is_i32() || field_type->is_i64() ||
628 field_type->is_double() || field_type->is_enum());
629 }
630
is_container()631 mstch::node is_container() {
632 return field_->get_type()->get_true_type()->is_container();
633 }
java_name()634 mstch::node java_name() { return get_java_swift_name(field_); }
635
type_field_name()636 mstch::node type_field_name() {
637 auto type_name = field_->get_type()->get_full_name();
638 return java::mangle_java_name(type_name, true);
639 }
640
java_tfield_name()641 mstch::node java_tfield_name() {
642 return constant_name(field_->get_name()) + "_FIELD_DESC";
643 }
java_capital_name()644 mstch::node java_capital_name() {
645 return java::mangle_java_name(
646 field_->get_annotation("java.swift.name", &field_->get_name()), true);
647 }
java_all_caps_name()648 mstch::node java_all_caps_name() {
649 auto field_name = field_->get_name();
650 boost::to_upper(field_name);
651 return field_name;
652 }
java_default_value()653 mstch::node java_default_value() { return default_value_for_field(field_); }
is_recursive_reference()654 mstch::node is_recursive_reference() {
655 return field_->get_annotation("swift.recursive_reference") == "true";
656 }
is_negative_id()657 mstch::node is_negative_id() { return field_->get_key() < 0; }
default_value_for_field(const t_field * field)658 std::string default_value_for_field(const t_field* field) {
659 if (field_->get_req() == t_field::e_req::optional) {
660 return "null";
661 }
662 return default_value_for_type(field->get_type());
663 }
default_value_for_type(const t_type * type)664 std::string default_value_for_type(const t_type* type) {
665 if (type->is_typedef()) {
666 auto typedef_type = dynamic_cast<const t_typedef*>(type)->get_type();
667 return default_value_for_type(typedef_type);
668 } else {
669 if (type->is_byte() || type->is_i16() || type->is_i32()) {
670 return "0";
671 } else if (type->is_i64()) {
672 return "0L";
673 } else if (type->is_float()) {
674 return "0.f";
675 } else if (type->is_double()) {
676 return "0.";
677 } else if (type->is_bool()) {
678 return "false";
679 } else if (type->is_enum()) {
680 // we use fromInteger(0) as default value as it may be null or the enum
681 // entry for 0.
682 auto javaNamespace = get_namespace_or_default(*(type->program()));
683 auto enumType = java::mangle_java_name(type->get_name(), true);
684 return javaNamespace + "." + enumType + ".fromInteger(0)";
685 }
686 return "null";
687 }
688 }
has_java_annotations()689 mstch::node has_java_annotations() {
690 return field_->has_annotation("java.swift.annotations");
691 }
is_sensitive()692 mstch::node is_sensitive() {
693 return field_->has_annotation("java.sensitive");
694 }
constant_name(string name)695 std::string constant_name(string name) {
696 string constant_str;
697
698 bool is_first = true;
699 bool was_previous_char_upper = false;
700 for (string::iterator iter = name.begin(); iter != name.end(); ++iter) {
701 string::value_type character = (*iter);
702 bool is_upper = isupper(character);
703 if (is_upper && !is_first && !was_previous_char_upper) {
704 constant_str += '_';
705 }
706 constant_str += toupper(character);
707 is_first = false;
708 was_previous_char_upper = is_upper;
709 }
710 return constant_str;
711 }
java_annotations()712 mstch::node java_annotations() {
713 return field_->get_annotation("java.swift.annotations");
714 }
715 };
716
717 class mstch_swift_enum : public mstch_enum {
718 public:
mstch_swift_enum(t_enum const * enm,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos)719 mstch_swift_enum(
720 t_enum const* enm,
721 std::shared_ptr<mstch_generators const> generators,
722 std::shared_ptr<mstch_cache> cache,
723 ELEMENT_POSITION const pos)
724 : mstch_enum(enm, generators, cache, pos) {
725 register_methods(
726 this,
727 {
728 {"enum:javaPackage", &mstch_swift_enum::java_package},
729 {"enum:javaCapitalName", &mstch_swift_enum::java_capital_name},
730 {"enum:skipEnumNameMap?",
731 &mstch_swift_enum::java_skip_enum_name_map},
732 });
733 }
java_package()734 mstch::node java_package() {
735 return get_namespace_or_default(*(enm_->program()));
736 }
java_capital_name()737 mstch::node java_capital_name() {
738 return java::mangle_java_name(enm_->get_name(), true);
739 }
java_skip_enum_name_map()740 mstch::node java_skip_enum_name_map() {
741 return enm_->has_annotation("java.swift.skip_enum_name_map");
742 }
743 };
744
745 class mstch_swift_enum_value : public mstch_enum_value {
746 public:
mstch_swift_enum_value(t_enum_value const * enm_value,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos)747 mstch_swift_enum_value(
748 t_enum_value const* enm_value,
749 std::shared_ptr<mstch_generators const> generators,
750 std::shared_ptr<mstch_cache> cache,
751 ELEMENT_POSITION const pos)
752 : mstch_enum_value(enm_value, generators, cache, pos) {
753 register_methods(
754 this,
755 {
756 {"enum_value:javaConstantName",
757 &mstch_swift_enum_value::java_constant_name},
758 });
759 }
java_constant_name()760 mstch::node java_constant_name() {
761 return java::mangle_java_constant_name(enm_value_->get_name());
762 }
763 };
764
765 class mstch_swift_const : public mstch_const {
766 public:
mstch_swift_const(t_const const * cnst,t_const const * current_const,t_type const * expected_type,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos,int32_t index,t_field const * field)767 mstch_swift_const(
768 t_const const* cnst,
769 t_const const* current_const,
770 t_type const* expected_type,
771 std::shared_ptr<mstch_generators const> generators,
772 std::shared_ptr<mstch_cache> cache,
773 ELEMENT_POSITION const pos,
774 int32_t index,
775 t_field const* field)
776 : mstch_const(
777 cnst,
778 current_const,
779 expected_type,
780 generators,
781 cache,
782 pos,
783 index,
784 field) {
785 register_methods(
786 this,
787 {
788 {"constant:javaCapitalName", &mstch_swift_const::java_capital_name},
789 {"constant:javaFieldName", &mstch_swift_const::java_field_name},
790 {"constant:javaIgnoreConstant?",
791 &mstch_swift_const::java_ignore_constant},
792 });
793 }
java_capital_name()794 mstch::node java_capital_name() {
795 return java::mangle_java_constant_name(cnst_->get_name());
796 }
java_field_name()797 mstch::node java_field_name() {
798 return java::mangle_java_name(field_->get_name(), true);
799 }
java_ignore_constant()800 mstch::node java_ignore_constant() {
801 // we have to ignore constants if they are enums that we handled as ints, as
802 // we don't have the constant values to work with.
803 if (cnst_->get_type()->is_map()) {
804 t_map* map = (t_map*)cnst_->get_type();
805 if (map->get_key_type()->is_enum()) {
806 return map->get_key_type()->has_annotation(
807 "java.swift.skip_enum_name_map");
808 }
809 }
810 if (cnst_->get_type()->is_list()) {
811 t_list* list = (t_list*)cnst_->get_type();
812 if (list->get_elem_type()->is_enum()) {
813 return list->get_elem_type()->has_annotation(
814 "java.swift.skip_enum_name_map");
815 }
816 }
817 if (cnst_->get_type()->is_set()) {
818 t_set* set = (t_set*)cnst_->get_type();
819 if (set->get_elem_type()->is_enum()) {
820 return set->get_elem_type()->has_annotation(
821 "java.swift.skip_enum_name_map");
822 }
823 }
824 return mstch::node();
825 }
826 };
827
828 class mstch_swift_const_value : public mstch_const_value {
829 public:
mstch_swift_const_value(t_const_value const * const_value,t_const const * current_const,t_type const * expected_type,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t index)830 mstch_swift_const_value(
831 t_const_value const* const_value,
832 t_const const* current_const,
833 t_type const* expected_type,
834 std::shared_ptr<mstch_generators const> generators,
835 std::shared_ptr<mstch_cache> cache,
836 ELEMENT_POSITION pos,
837 int32_t index)
838 : mstch_const_value(
839 const_value,
840 current_const,
841 expected_type,
842 generators,
843 cache,
844 pos,
845 index) {
846 register_methods(
847 this,
848 {
849 {"value:quotedString", &mstch_swift_const_value::quote_java_string},
850 {"value:javaEnumValueName",
851 &mstch_swift_const_value::java_enum_value_name},
852 });
853 }
quote_java_string()854 mstch::node quote_java_string() {
855 return java::quote_java_string(const_value_->get_string());
856 }
java_enum_value_name()857 mstch::node java_enum_value_name() {
858 if (type_ == cv::CV_INTEGER && const_value_->is_enum()) {
859 const t_enum_value* enum_value = const_value_->get_enum_value();
860 if (enum_value != nullptr) {
861 return java::mangle_java_constant_name(enum_value->get_name());
862 }
863 return "fromInteger(" + std::to_string(const_value_->get_integer()) + ")";
864 }
865 return mstch::node();
866 }
same_type_as_expected() const867 bool same_type_as_expected() const override { return true; }
868 };
869
870 class mstch_swift_type : public mstch_type {
871 public:
mstch_swift_type(t_type const * type,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION const pos)872 mstch_swift_type(
873 t_type const* type,
874 std::shared_ptr<mstch_generators const> generators,
875 std::shared_ptr<mstch_cache> cache,
876 ELEMENT_POSITION const pos)
877 : mstch_type(type, generators, cache, pos) {
878 register_methods(
879 this,
880 {
881 {"type:primitive?", &mstch_swift_type::is_primitive},
882 {"type:isContainer?", &mstch_swift_type::is_container_type},
883 {"type:javaType", &mstch_swift_type::java_type},
884 {"type:setIsMapKey", &mstch_swift_type::set_is_map_key},
885 {"type:isMapKey?", &mstch_swift_type::get_map_key_flag},
886 {"type:setIsMapValue", &mstch_swift_type::set_is_map_value},
887 {"type:isMapValue?", &mstch_swift_type::get_map_value_flag},
888 {"type:isBinaryString?", &mstch_swift_type::is_binary_string},
889 {"type:setIsNotMap", &mstch_swift_type::set_is_not_map},
890 });
891 }
892 bool isMapValueFlag = false;
893 bool isMapKeyFlag = false;
894
set_is_not_map()895 mstch::node set_is_not_map() {
896 isMapValueFlag = false;
897 isMapKeyFlag = false;
898 return mstch::node();
899 }
get_map_value_flag()900 mstch::node get_map_value_flag() { return isMapValueFlag; }
get_map_key_flag()901 mstch::node get_map_key_flag() { return isMapKeyFlag; }
set_is_map_value()902 mstch::node set_is_map_value() {
903 isMapValueFlag = true;
904 return mstch::node();
905 }
set_is_map_key()906 mstch::node set_is_map_key() {
907 isMapKeyFlag = true;
908 return mstch::node();
909 }
910
is_container_type()911 mstch::node is_container_type() {
912 return type_->get_true_type()->is_container();
913 }
914
is_primitive()915 mstch::node is_primitive() {
916 return type_->is_void() || type_->is_bool() || type_->is_byte() ||
917 type_->is_i16() || type_->is_i32() || type_->is_i64() ||
918 type_->is_double() || type_->is_float();
919 }
java_type()920 mstch::node java_type() {
921 return type_->get_true_type()->get_annotation("java.swift.type");
922 }
is_binary_string()923 mstch::node is_binary_string() {
924 return type_->get_true_type()->get_annotation("java.swift.binary_string");
925 }
926 };
927
928 class program_swift_generator : public program_generator {
929 public:
930 program_swift_generator() = default;
931 ~program_swift_generator() override = default;
generate(t_program const * program,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t) const932 std::shared_ptr<mstch_base> generate(
933 t_program const* program,
934 std::shared_ptr<mstch_generators const> generators,
935 std::shared_ptr<mstch_cache> cache,
936 ELEMENT_POSITION pos,
937 int32_t /*index*/) const override {
938 return std::make_shared<mstch_swift_program>(
939 program, generators, cache, pos);
940 }
941 };
942
943 class struct_swift_generator : public struct_generator {
944 public:
945 explicit struct_swift_generator() = default;
946 ~struct_swift_generator() override = default;
generate(t_struct const * strct,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t) const947 std::shared_ptr<mstch_base> generate(
948 t_struct const* strct,
949 std::shared_ptr<mstch_generators const> generators,
950 std::shared_ptr<mstch_cache> cache,
951 ELEMENT_POSITION pos,
952 int32_t /*index*/) const override {
953 return std::make_shared<mstch_swift_struct>(strct, generators, cache, pos);
954 }
955 };
956
957 class service_swift_generator : public service_generator {
958 public:
959 explicit service_swift_generator() = default;
960 ~service_swift_generator() override = default;
generate(t_service const * service,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t) const961 std::shared_ptr<mstch_base> generate(
962 t_service const* service,
963 std::shared_ptr<mstch_generators const> generators,
964 std::shared_ptr<mstch_cache> cache,
965 ELEMENT_POSITION pos,
966 int32_t /*index*/) const override {
967 return std::make_shared<mstch_swift_service>(
968 service, generators, cache, pos);
969 }
970 };
971
972 class function_swift_generator : public function_generator {
973 public:
974 function_swift_generator() = default;
975 ~function_swift_generator() override = default;
generate(t_function const * function,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t) const976 std::shared_ptr<mstch_base> generate(
977 t_function const* function,
978 std::shared_ptr<mstch_generators const> generators,
979 std::shared_ptr<mstch_cache> cache,
980 ELEMENT_POSITION pos,
981 int32_t /*index*/) const override {
982 return std::make_shared<mstch_swift_function>(
983 function, generators, cache, pos);
984 }
985 };
986
987 class field_swift_generator : public field_generator {
988 public:
989 field_swift_generator() = default;
990 ~field_swift_generator() override = default;
generate(t_field const * field,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t index,field_generator_context const * field_context) const991 std::shared_ptr<mstch_base> generate(
992 t_field const* field,
993 std::shared_ptr<mstch_generators const> generators,
994 std::shared_ptr<mstch_cache> cache,
995 ELEMENT_POSITION pos,
996 int32_t index,
997 field_generator_context const* field_context) const override {
998 return std::make_shared<mstch_swift_field>(
999 field, generators, cache, pos, index, field_context);
1000 }
1001 };
1002
1003 class enum_swift_generator : public enum_generator {
1004 public:
1005 explicit enum_swift_generator() = default;
1006 ~enum_swift_generator() override = default;
generate(t_enum const * enm,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t) const1007 std::shared_ptr<mstch_base> generate(
1008 t_enum const* enm,
1009 std::shared_ptr<mstch_generators const> generators,
1010 std::shared_ptr<mstch_cache> cache,
1011 ELEMENT_POSITION pos,
1012 int32_t /*index*/) const override {
1013 return std::make_shared<mstch_swift_enum>(enm, generators, cache, pos);
1014 }
1015 };
1016
1017 class enum_value_swift_generator : public enum_value_generator {
1018 public:
1019 enum_value_swift_generator() = default;
1020 ~enum_value_swift_generator() override = default;
generate(t_enum_value const * enm_value,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t) const1021 std::shared_ptr<mstch_base> generate(
1022 t_enum_value const* enm_value,
1023 std::shared_ptr<mstch_generators const> generators,
1024 std::shared_ptr<mstch_cache> cache,
1025 ELEMENT_POSITION pos,
1026 int32_t /*index*/) const override {
1027 return std::make_shared<mstch_swift_enum_value>(
1028 enm_value, generators, cache, pos);
1029 }
1030 };
1031
1032 class type_swift_generator : public type_generator {
1033 public:
1034 type_swift_generator() = default;
1035 ~type_swift_generator() override = default;
generate(t_type const * type,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t) const1036 std::shared_ptr<mstch_base> generate(
1037 t_type const* type,
1038 std::shared_ptr<mstch_generators const> generators,
1039 std::shared_ptr<mstch_cache> cache,
1040 ELEMENT_POSITION pos,
1041 int32_t /*index*/) const override {
1042 return std::make_shared<mstch_swift_type>(type, generators, cache, pos);
1043 }
1044 };
1045
1046 class const_swift_generator : public const_generator {
1047 public:
1048 const_swift_generator() = default;
1049 ~const_swift_generator() override = default;
generate(t_const const * cnst,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t index,t_const const * current_const,t_type const * expected_type,t_field const * field) const1050 std::shared_ptr<mstch_base> generate(
1051 t_const const* cnst,
1052 std::shared_ptr<mstch_generators const> generators,
1053 std::shared_ptr<mstch_cache> cache,
1054 ELEMENT_POSITION pos,
1055 int32_t index,
1056 t_const const* current_const,
1057 t_type const* expected_type,
1058 t_field const* field) const override {
1059 return std::make_shared<mstch_swift_const>(
1060 cnst,
1061 current_const,
1062 expected_type,
1063 generators,
1064 cache,
1065 pos,
1066 index,
1067 field);
1068 }
1069 };
1070
1071 class const_value_swift_generator : public const_value_generator {
1072 public:
1073 const_value_swift_generator() = default;
1074 ~const_value_swift_generator() override = default;
generate(t_const_value const * const_value,std::shared_ptr<mstch_generators const> generators,std::shared_ptr<mstch_cache> cache,ELEMENT_POSITION pos,int32_t index,t_const const * current_const,t_type const * expected_type) const1075 std::shared_ptr<mstch_base> generate(
1076 t_const_value const* const_value,
1077 std::shared_ptr<mstch_generators const> generators,
1078 std::shared_ptr<mstch_cache> cache,
1079 ELEMENT_POSITION pos,
1080 int32_t index,
1081 t_const const* current_const,
1082 t_type const* expected_type) const override {
1083 return std::make_shared<mstch_swift_const_value>(
1084 const_value,
1085 current_const,
1086 expected_type,
1087 generators,
1088 cache,
1089 pos,
1090 index);
1091 }
1092 };
1093
generate_program()1094 void t_mstch_swift_generator::generate_program() {
1095 set_mstch_generators();
1096
1097 auto name = get_program()->name();
1098 const auto& id = get_program()->path();
1099 if (!cache_->programs_.count(id)) {
1100 cache_->programs_[id] = generators_->program_generator_->generate(
1101 get_program(), generators_, cache_);
1102 }
1103
1104 generate_items(
1105 generators_->struct_generator_.get(),
1106 cache_->structs_,
1107 get_program(),
1108 get_program()->objects(),
1109 "Object");
1110 generate_items(
1111 generators_->service_generator_.get(),
1112 cache_->services_,
1113 get_program(),
1114 get_program()->services(),
1115 "Service");
1116 generate_client(
1117 generators_->service_generator_.get(),
1118 cache_->services_,
1119 get_program(),
1120 get_program()->services());
1121 generate_items(
1122 generators_->enum_generator_.get(),
1123 cache_->enums_,
1124 get_program(),
1125 get_program()->enums(),
1126 "Enum");
1127 generate_constants(get_program());
1128 generate_placeholder(get_program());
1129 }
1130
set_mstch_generators()1131 void t_mstch_swift_generator::set_mstch_generators() {
1132 generators_->set_program_generator(
1133 std::make_unique<program_swift_generator>());
1134 generators_->set_struct_generator(std::make_unique<struct_swift_generator>());
1135 generators_->set_service_generator(
1136 std::make_unique<service_swift_generator>());
1137 generators_->set_function_generator(
1138 std::make_unique<function_swift_generator>());
1139 generators_->set_field_generator(std::make_unique<field_swift_generator>());
1140 generators_->set_enum_generator(std::make_unique<enum_swift_generator>());
1141 generators_->set_enum_value_generator(
1142 std::make_unique<enum_value_swift_generator>());
1143 generators_->set_type_generator(std::make_unique<type_swift_generator>());
1144 generators_->set_const_generator(std::make_unique<const_swift_generator>());
1145 generators_->set_const_value_generator(
1146 std::make_unique<const_value_swift_generator>());
1147 }
1148
1149 THRIFT_REGISTER_GENERATOR(mstch_swift, "Java Swift", "");
1150
1151 } // namespace compiler
1152 } // namespace thrift
1153 } // namespace apache
1154