2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
29 #include "thrift/platform.h"
30 #include "thrift/generate/t_oop_generator.h"
34 using std::ostringstream
;
37 using std::stringstream
;
40 static const string endl
= "\n"; // avoid ostream << std::endl flushes
43 * Swift 3 code generator.
45 * Designed from the Swift/Cocoa code generator(s)
47 class t_swift_generator
: public t_oop_generator
{
49 t_swift_generator(t_program
* program
,
50 const map
<string
, string
>& parsed_options
,
51 const string
& option_string
)
52 : t_oop_generator(program
) {
54 map
<string
, string
>::const_iterator iter
;
56 log_unexpected_
= false;
57 async_clients_
= false;
58 debug_descriptions_
= false;
65 for( iter
= parsed_options
.begin(); iter
!= parsed_options
.end(); ++iter
) {
66 if( iter
->first
.compare("log_unexpected") == 0) {
67 log_unexpected_
= true;
68 } else if( iter
->first
.compare("async_clients") == 0) {
69 async_clients_
= true;
70 } else if( iter
->first
.compare("no_strict") == 0) {
72 } else if( iter
->first
.compare("debug_descriptions") == 0) {
73 debug_descriptions_
= true;
74 } else if( iter
->first
.compare("namespaced") == 0) {
76 } else if( iter
->first
.compare("cocoa") == 0) {
78 } else if( iter
->first
.compare("safe_enums") == 0) {
80 } else if( iter
->first
.compare("promise_kit") == 0) {
81 if (gen_cocoa_
== false) {
82 throw "PromiseKit only available with Swift 2.x, use `cocoa` option" + iter
->first
;
86 throw "unknown option swift:" + iter
->first
;
90 out_dir_base_
= "gen-swift";
94 * Init and close methods
97 void init_generator() override
;
98 void close_generator() override
;
100 void generate_consts(vector
<t_const
*> consts
) override
;
103 * Program-level generation functions
106 void generate_typedef(t_typedef
* ttypedef
) override
;
107 void generate_enum(t_enum
* tenum
) override
;
108 void generate_struct(t_struct
* tstruct
) override
;
109 void generate_xception(t_struct
* txception
) override
;
110 void generate_service(t_service
* tservice
) override
;
113 void render_const_value(ostream
& out
,
115 t_const_value
* value
);
117 void generate_swift_struct(ostream
& out
,
121 void generate_swift_struct_init(ostream
& out
,
126 void generate_swift_struct_implementation(ostream
& out
,
130 void generate_swift_struct_hashable_extension(ostream
& out
,
133 void generate_swift_struct_equatable_extension(ostream
& out
,
136 void generate_swift_struct_thrift_extension(ostream
& out
,
140 void generate_swift_struct_reader(ostream
& out
, t_struct
* tstruct
, bool is_private
);
143 void generate_swift_struct_printable_extension(ostream
& out
, t_struct
* tstruct
);
144 void generate_swift_union_reader(ostream
& out
, t_struct
* tstruct
);
146 string
function_result_helper_struct_type(t_service
*tservice
, t_function
* tfunction
);
147 string
function_args_helper_struct_type(t_service
* tservice
, t_function
* tfunction
);
148 void generate_function_helpers(t_service
*tservice
, t_function
* tfunction
);
151 * Service-level generation functions
154 void generate_swift_service_protocol(ostream
& out
, t_service
* tservice
);
155 void generate_swift_service_protocol_async(ostream
& out
, t_service
* tservice
);
157 void generate_swift_service_client(ostream
& out
, t_service
* tservice
);
158 void generate_swift_service_client_async(ostream
& out
, t_service
* tservice
);
160 void generate_swift_service_client_send_function_implementation(ostream
& out
,
162 t_function
* tfunction
,
163 bool needs_protocol
);
164 void generate_swift_service_client_send_function_invocation(ostream
& out
, t_function
* tfunction
);
165 void generate_swift_service_client_send_async_function_invocation(ostream
& out
,
166 t_function
* tfunction
);
167 void generate_swift_service_client_recv_function_implementation(ostream
& out
,
169 t_function
* tfunction
,
170 bool needs_protocol
);
171 void generate_swift_service_client_implementation(ostream
& out
, t_service
* tservice
);
172 void generate_swift_service_client_async_implementation(ostream
& out
, t_service
* tservice
);
174 void generate_swift_service_server(ostream
& out
, t_service
* tservice
);
175 void generate_swift_service_server_implementation(ostream
& out
, t_service
* tservice
);
176 void generate_swift_service_helpers(t_service
* tservice
);
179 * Helper rendering functions
182 string
swift_imports();
183 string
swift_thrift_imports();
184 string
type_name(t_type
* ttype
, bool is_optional
=false, bool is_forced
=false);
185 string
base_type_name(t_base_type
* tbase
);
186 string
declare_property(t_field
* tfield
, bool is_private
);
187 string
function_signature(t_function
* tfunction
);
188 string
async_function_signature(t_function
* tfunction
);
191 string
argument_list(t_struct
* tstruct
, string protocol_name
, bool is_internal
);
192 string
type_to_enum(t_type
* ttype
, bool qualified
=false);
193 string
maybe_escape_identifier(const string
& identifier
);
194 void populate_reserved_words();
195 /** Swift 3 specific */
196 string
enum_case_name(t_enum_value
* tenum_case
, bool declaration
);
197 string
enum_const_name(string enum_identifier
);
198 void function_docstring(ostream
& out
, t_function
* tfunction
);
199 void async_function_docstring(ostream
& out
, t_function
* tfunction
);
200 void generate_docstring(ostream
& out
, string
& doc
);
202 /** Swift 2/Cocoa carryover */
203 string
promise_function_signature(t_function
* tfunction
);
204 string
function_name(t_function
* tfunction
);
205 void generate_old_swift_struct_writer(ostream
& out
,t_struct
* tstruct
, bool is_private
);
206 void generate_old_swift_struct_result_writer(ostream
& out
, t_struct
* tstruct
);
208 /** Swift 2/Cocoa backwards compatibility*/
209 void generate_old_enum(t_enum
* tenum
);
210 void generate_old_swift_struct(ostream
& out
,
213 void generate_old_swift_service_client_async_implementation(ostream
& out
,
214 t_service
* tservice
);
216 static std::string
get_real_swift_module(const t_program
* program
) {
217 std::string real_module
= program
->get_namespace("swift");
218 if (real_module
.empty()) {
219 return program
->get_name();
225 void block_open(ostream
& out
) {
230 void block_close(ostream
& out
, bool end_line
=true) {
233 if (end_line
) out
<< endl
;
236 bool field_is_optional(t_field
* tfield
) {
237 bool opt
= tfield
->get_req() == t_field::T_OPTIONAL
;
238 if (tfield
->annotations_
.find("swift.nullable") != tfield
->annotations_
.end() && tfield
->get_req() != t_field::T_REQUIRED
) {
241 if (gen_cocoa_
) { // Backwards compatibility, only if its actually "optional"
242 opt
= tfield
->get_req() == t_field::T_OPTIONAL
;
247 bool struct_has_required_fields(t_struct
* tstruct
) {
248 const vector
<t_field
*>& members
= tstruct
->get_members();
249 vector
<t_field
*>::const_iterator m_iter
;
250 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
251 if (!field_is_optional(*m_iter
)) {
258 bool struct_has_optional_fields(t_struct
* tstruct
) {
259 const vector
<t_field
*>& members
= tstruct
->get_members();
260 vector
<t_field
*>::const_iterator m_iter
;
261 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
262 if (field_is_optional(*m_iter
)) {
269 string constants_declarations_
;
275 ofstream_with_content_based_conditional_update f_decl_
;
276 ofstream_with_content_based_conditional_update f_impl_
;
278 bool log_unexpected_
;
281 bool debug_descriptions_
;
285 set
<string
> swift_reserved_words_
;
287 /** Swift 2/Cocoa compatibility */
294 * Prepares for file generation by opening up the necessary file output
297 void t_swift_generator::init_generator() {
298 // Make output directory
299 string module
= get_real_swift_module(program_
);
300 string out_dir
= get_out_dir();
301 string module_path
= out_dir
;
302 string name
= program_name_
;
303 if (namespaced_
&& !module
.empty()) {
304 module_path
= module_path
+ "/" + module
;
307 MKDIR(module_path
.c_str());
309 populate_reserved_words();
311 // we have a .swift declarations file...
312 string f_decl_name
= name
+ ".swift";
313 string f_decl_fullname
= module_path
+ "/" + f_decl_name
;
314 f_decl_
.open(f_decl_fullname
.c_str());
316 f_decl_
<< autogen_comment() << endl
;
318 f_decl_
<< swift_imports() << swift_thrift_imports() << endl
;
320 // ...and a .swift implementation extensions file
321 string f_impl_name
= name
+ "+Exts.swift";
322 string f_impl_fullname
= module_path
+ "/" + f_impl_name
;
323 f_impl_
.open(f_impl_fullname
.c_str());
325 f_impl_
<< autogen_comment() << endl
;
327 f_impl_
<< swift_imports() << swift_thrift_imports() << endl
;
332 * Prints standard Cocoa imports
334 * @return List of imports for Cocoa libraries
336 string
t_swift_generator::swift_imports() {
338 vector
<string
> includes_list
;
339 includes_list
.emplace_back("Foundation");
341 ostringstream includes
;
343 vector
<string
>::const_iterator i_iter
;
344 for (i_iter
=includes_list
.begin(); i_iter
!=includes_list
.end(); ++i_iter
) {
345 includes
<< "import " << *i_iter
<< endl
;
349 const vector
<t_program
*>& program_includes
= program_
->get_includes();
350 for (auto program_include
: program_includes
) {
351 includes
<< ("import " + get_real_swift_module(program_include
)) << endl
;
356 return includes
.str();
360 * Prints Thrift runtime imports
362 * @return List of imports necessary for Thrift runtime
364 string
t_swift_generator::swift_thrift_imports() {
366 vector
<string
> includes_list
;
367 includes_list
.emplace_back("Thrift");
369 if (gen_cocoa_
&& promise_kit_
) {
370 includes_list
.emplace_back("PromiseKit");
373 ostringstream includes
;
375 vector
<string
>::const_iterator i_iter
;
376 for (i_iter
=includes_list
.begin(); i_iter
!=includes_list
.end(); ++i_iter
) {
377 includes
<< "import " << *i_iter
<< endl
;
382 return includes
.str();
386 * Finish up generation.
388 void t_swift_generator::close_generator() {
389 // stick our constants declarations at the end of the header file
390 // since they refer to things we are defining.
391 f_decl_
<< constants_declarations_
<< endl
;
395 * Generates a typedef. This is just a simple 1-liner in Swift
397 * @param ttypedef The type definition
399 void t_swift_generator::generate_typedef(t_typedef
* ttypedef
) {
400 f_decl_
<< indent() << "public typealias " << ttypedef
->get_symbolic()
401 << " = " << type_name(ttypedef
->get_type()) << endl
;
407 * Generates code for an enumerated type. In Swift, this is
408 * essentially the same as the thrift definition itself, using
409 * Swift syntax. Conforms to TEnum which
410 * implementes read/write.
412 * @param tenum The enumeration
414 void t_swift_generator::generate_enum(t_enum
* tenum
) {
416 generate_old_enum(tenum
);
419 f_decl_
<< indent() << "public enum " << tenum
->get_name() << " : TEnum";
422 vector
<t_enum_value
*> constants
= tenum
->get_constants();
423 vector
<t_enum_value
*>::iterator c_iter
;
425 for (c_iter
= constants
.begin(); c_iter
!= constants
.end(); ++c_iter
) {
426 f_decl_
<< indent() << "case " << enum_case_name((*c_iter
), true) << endl
;
429 // unknown associated value case for safety and similar behavior to other languages
431 f_decl_
<< indent() << "case unknown(Int32)" << endl
;
435 // TSerializable read(from:)
436 f_decl_
<< indent() << "public static func read(from proto: TProtocol) throws -> "
437 << tenum
->get_name();
439 f_decl_
<< indent() << "let raw: Int32 = try proto.read()" << endl
;
440 f_decl_
<< indent() << "let new = " << tenum
->get_name() << "(rawValue: raw)" << endl
;
442 f_decl_
<< indent() << "if let unwrapped = new {" << endl
;
444 f_decl_
<< indent() << "return unwrapped" << endl
;
446 f_decl_
<< indent() << "} else {" << endl
;
448 f_decl_
<< indent() << "throw TProtocolError(error: .invalidData," << endl
;
449 f_decl_
<< indent() << " message: \"Invalid enum value (\\(raw)) for \\("
450 << tenum
->get_name() << ".self)\")" << endl
;
452 f_decl_
<< indent() << "}" << endl
;
453 block_close(f_decl_
);
455 // empty init for TSerializable
457 f_decl_
<< indent() << "public init()";
460 f_decl_
<< indent() << "self = ." << enum_case_name(constants
.front(), false) << endl
;
461 block_close(f_decl_
);
465 f_decl_
<< indent() << "public var rawValue: Int32";
467 f_decl_
<< indent() << "switch self {" << endl
;
468 for (c_iter
= constants
.begin(); c_iter
!= constants
.end(); ++c_iter
) {
469 f_decl_
<< indent() << "case ." << enum_case_name((*c_iter
), true)
470 << ": return " << (*c_iter
)->get_value() << endl
;
473 f_decl_
<< indent() << "case .unknown(let value): return value" << endl
;
475 f_decl_
<< indent() << "}" << endl
;
476 block_close(f_decl_
);
479 // convenience rawValue initalizer
480 f_decl_
<< indent() << "public init?(rawValue: Int32)";
482 f_decl_
<< indent() << "switch rawValue {" << endl
;;
483 for (c_iter
= constants
.begin(); c_iter
!= constants
.end(); ++c_iter
) {
484 f_decl_
<< indent() << "case " << (*c_iter
)->get_value()
485 << ": self = ." << enum_case_name((*c_iter
), true) << endl
;
488 f_decl_
<< indent() << "default: return nil" << endl
;
490 f_decl_
<< indent() << "default: self = .unknown(rawValue)" << endl
;
492 f_decl_
<< indent() << "}" << endl
;
493 block_close(f_decl_
);
498 block_close(f_decl_
);
503 * Generates code for an enumerated type. This is for Swift 2.x/Cocoa
504 * backwards compatibility
506 * @param tenum The enumeration
508 void t_swift_generator::generate_old_enum(t_enum
* tenum
) {
509 f_decl_
<< indent() << "public enum " << tenum
->get_name() << " : Int32";
512 vector
<t_enum_value
*> constants
= tenum
->get_constants();
513 vector
<t_enum_value
*>::iterator c_iter
;
515 for (c_iter
= constants
.begin(); c_iter
!= constants
.end(); ++c_iter
) {
516 f_decl_
<< indent() << "case " << (*c_iter
)->get_name()
517 << " = " << (*c_iter
)->get_value() << endl
;
521 f_decl_
<< indent() << "public init() { self.init(rawValue: " << constants
.front()->get_value() << ")! }" << endl
;
523 block_close(f_decl_
);
526 f_impl_
<< indent() << "extension " << tenum
->get_name() << " : TEnum";
531 f_impl_
<< indent() << "public static func readValueFromProtocol(proto: TProtocol) throws -> " << tenum
->get_name();
533 f_impl_
<< indent() << "var raw = Int32()" << endl
534 << indent() << "try proto.readI32(&raw)" << endl
535 << indent() << "return " << tenum
->get_name() << "(rawValue: raw)!" << endl
;
536 block_close(f_impl_
);
539 f_impl_
<< indent() << "public static func writeValue(value: " << tenum
->get_name() << ", toProtocol proto: TProtocol) throws";
541 f_impl_
<< indent() << "try proto.writeI32(value.rawValue)" << endl
;
542 block_close(f_impl_
);
545 block_close(f_impl_
);
549 string
t_swift_generator::enum_case_name(t_enum_value
* tenum_case
, bool declaration
) {
550 string name
= tenum_case
->get_name();
551 // force to lowercase for Swift style, maybe escape if its a keyword
552 std::transform(name
.begin(), name
.end(), name
.begin(), ::tolower
);
554 name
= maybe_escape_identifier(name
);
560 * Renders a constant enum value by transforming the value portion to lowercase
563 string
t_swift_generator::enum_const_name(string enum_identifier
) {
565 for (it
= enum_identifier
.begin(); it
< enum_identifier
.end(); ++it
) {
570 std::transform(it
, enum_identifier
.end(), it
, ::tolower
);
571 return enum_identifier
;
575 * Generates public constants for all Thrift constants.
577 * @param consts Constants to generate
579 void t_swift_generator::generate_consts(vector
<t_const
*> consts
) {
581 ostringstream const_interface
;
583 // Public constants for base types & strings
584 vector
<t_const
*>::iterator c_iter
;
585 for (c_iter
= consts
.begin(); c_iter
!= consts
.end(); ++c_iter
) {
586 t_type
* type
= (*c_iter
)->get_type();
587 const_interface
<< "public let " << capitalize((*c_iter
)->get_name()) << " : " << type_name(type
) << " = ";
588 render_const_value(const_interface
, type
, (*c_iter
)->get_value());
589 const_interface
<< endl
<< endl
;
592 // this gets spit into the header file in ::close_generator
593 constants_declarations_
= const_interface
.str();
598 * Generates a struct definition for a thrift data type. This is a struct
599 * with public members. Optional types are used for optional properties to
600 * allow them to be tested for availability. Separate inits are included for
601 * required properties & all properties.
603 * Generates extensions to provide conformance to TStruct, TSerializable,
604 * Hashable & Equatable
606 * @param tstruct The struct definition
608 void t_swift_generator::generate_struct(t_struct
* tstruct
) {
609 generate_swift_struct(f_decl_
, tstruct
, false);
610 generate_swift_struct_implementation(f_impl_
, tstruct
, false, false);
614 * Exceptions are structs, but they conform to Error
616 * @param tstruct The struct definition
618 void t_swift_generator::generate_xception(t_struct
* txception
) {
619 generate_swift_struct(f_decl_
, txception
, false);
620 generate_swift_struct_implementation(f_impl_
, txception
, false, false);
623 void t_swift_generator::generate_docstring(ostream
& out
, string
& doc
) {
625 std::vector
<std::string
> strings
;
627 std::string::size_type pos
= 0;
628 std::string::size_type prev
= 0;
629 while (((pos
= doc
.find("\n", prev
)) != std::string::npos
)
630 || ((pos
= doc
.find("\r", prev
)) != std::string::npos
)
631 || ((pos
= doc
.find("\r\n", prev
)) != std::string::npos
))
633 strings
.push_back(doc
.substr(prev
, pos
- prev
));
637 // To get the last substring (or only, if delimiter is not found)
638 strings
.push_back(doc
.substr(prev
));
640 vector
<string
>::const_iterator d_iter
;
641 for (d_iter
= strings
.begin(); d_iter
!= strings
.end(); ++d_iter
) {
642 if ((*d_iter
) != "") {
643 out
<< indent() << "/// " << (*d_iter
) << endl
;
652 * Generate the interface for a struct. Only properties and
653 * init methods are included.
655 * @param tstruct The struct definition
657 * Is the struct public or private
659 void t_swift_generator::generate_swift_struct(ostream
& out
,
664 generate_old_swift_struct(out
, tstruct
, is_private
);
667 string doc
= tstruct
->get_doc();
668 generate_docstring(out
, doc
);
672 const vector
<t_field
*>& members
= tstruct
->get_members();
673 vector
<t_field
*>::const_iterator m_iter
;
676 if (tstruct
->is_union()) {
678 out
<< indent() << "public enum " << tstruct
->get_name();
680 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
682 string doc
= (*m_iter
)->get_doc();
683 generate_docstring(out
, doc
);
684 out
<< indent() << "case "
685 << maybe_escape_identifier((*m_iter
)->get_name()) << "(val: "
686 << type_name((*m_iter
)->get_type(), false) << ")" << endl
;
691 string visibility
= is_private
? (gen_cocoa_
? "private" : "fileprivate") : "public";
693 out
<< indent() << visibility
<< " final class " << tstruct
->get_name();
695 if (tstruct
->is_xception()) {
696 out
<< " : Swift.Error"; // Error seems to be a common exception name in thrift
700 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
704 string doc
= (*m_iter
)->get_doc();
705 generate_docstring(out
, doc
);
707 out
<< indent() << declare_property(*m_iter
, is_private
) << endl
;
713 if (!struct_has_required_fields(tstruct
)) {
714 indent(out
) << visibility
<< " init() { }" << endl
;
716 if (struct_has_required_fields(tstruct
)) {
717 generate_swift_struct_init(out
, tstruct
, false, is_private
);
719 if (struct_has_optional_fields(tstruct
)) {
720 generate_swift_struct_init(out
, tstruct
, true, is_private
);
730 * Legacy Swift2/Cocoa generator
737 void t_swift_generator::generate_old_swift_struct(ostream
& out
,
740 string visibility
= is_private
? "private" : "public";
742 out
<< indent() << visibility
<< " final class " << tstruct
->get_name();
744 if (tstruct
->is_xception()) {
745 out
<< " : ErrorType";
751 const vector
<t_field
*>& members
= tstruct
->get_members();
752 vector
<t_field
*>::const_iterator m_iter
;
754 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
756 out
<< indent() << declare_property(*m_iter
, is_private
) << endl
;
763 indent(out
) << visibility
<< " init()";
769 if (struct_has_required_fields(tstruct
)) {
770 generate_swift_struct_init(out
, tstruct
, false, is_private
);
772 if (struct_has_optional_fields(tstruct
)) {
773 generate_swift_struct_init(out
, tstruct
, true, is_private
);
782 * Generate struct init for properties
784 * @param tstruct The structure definition
785 * @param all Generate init with all or just required properties
787 * Is the initializer public or private
789 void t_swift_generator::generate_swift_struct_init(ostream
& out
,
794 string visibility
= is_private
? (gen_cocoa_
? "private" : "fileprivate") : "public";
796 indent(out
) << visibility
<< " init(";
798 const vector
<t_field
*>& members
= tstruct
->get_members();
799 vector
<t_field
*>::const_iterator m_iter
;
802 for (m_iter
= members
.begin(); m_iter
!= members
.end();) {
803 if (all
|| !field_is_optional(*m_iter
)) {
810 out
<< (*m_iter
)->get_name() << ": "
811 << maybe_escape_identifier(type_name((*m_iter
)->get_type(), field_is_optional(*m_iter
)));
819 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
821 bool should_set
= all
;
822 should_set
= should_set
|| !field_is_optional((*m_iter
));
824 out
<< indent() << "self." << maybe_escape_identifier((*m_iter
)->get_name()) << " = "
825 << maybe_escape_identifier((*m_iter
)->get_name()) << endl
;
828 /** legacy Swift2/Cocoa */
829 if (all
|| (*m_iter
)->get_req() == t_field::T_REQUIRED
|| (*m_iter
)->get_req() == t_field::T_OPT_IN_REQ_OUT
) {
830 out
<< indent() << "self." << maybe_escape_identifier((*m_iter
)->get_name()) << " = "
831 << maybe_escape_identifier((*m_iter
)->get_name()) << endl
;
842 * Generate the hashable protocol implmentation
844 * @param tstruct The structure definition
846 * Is the struct public or private
848 void t_swift_generator::generate_swift_struct_hashable_extension(ostream
& out
,
852 string visibility
= is_private
? (gen_cocoa_
? "private" : "fileprivate") : "public";
853 indent(out
) << "extension " << tstruct
->get_name() << " : Hashable";
856 indent(out
) << visibility
<< " var hashValue : Int";
859 const vector
<t_field
*>& members
= tstruct
->get_members();
860 vector
<t_field
*>::const_iterator m_iter
;
862 if (!members
.empty()) {
863 indent(out
) << "let prime = 31" << endl
;
864 indent(out
) << "var result = 1" << endl
;
865 if (!tstruct
->is_union()) {
866 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
867 t_field
* tfield
= *m_iter
;
868 string accessor
= field_is_optional(tfield
) ? "?." : ".";
869 string defaultor
= field_is_optional(tfield
) ? " ?? 0" : "";
870 indent(out
) << "result = prime &* result &+ (" << maybe_escape_identifier(tfield
->get_name()) << accessor
871 << "hashValue" << defaultor
<< ")" << endl
;
874 indent(out
) << "switch self {" << endl
;
875 for (m_iter
= members
.begin(); m_iter
!= members
.end(); m_iter
++) {
876 t_field
*tfield
= *m_iter
;
877 indent(out
) << "case ." << tfield
->get_name() << "(let val): result = prime &* val.hashValue" << endl
;
879 indent(out
) << "}" << endl
<< endl
;
881 indent(out
) << "return result" << endl
;
884 indent(out
) << "return 31" << endl
;
894 * Generate the equatable protocol implementation
896 * @param tstruct The structure definition
898 * Is the struct public or private
900 void t_swift_generator::generate_swift_struct_equatable_extension(ostream
& out
,
904 string visibility
= is_private
? (gen_cocoa_
? "private" : "fileprivate") : "public";
906 indent(out
) << visibility
<< " func ==(lhs: " << type_name(tstruct
) << ", rhs: "
907 << type_name(tstruct
) << ") -> Bool";
909 indent(out
) << "return";
911 const vector
<t_field
*>& members
= tstruct
->get_members();
912 vector
<t_field
*>::const_iterator m_iter
;
914 if (members
.size()) {
915 if (!tstruct
->is_union()) {
919 for (m_iter
= members
.begin(); m_iter
!= members
.end();) {
920 t_field
* tfield
= *m_iter
;
921 indent(out
) << "(lhs." << maybe_escape_identifier(tfield
->get_name())
922 << (gen_cocoa_
? " ?" : " ") << "== rhs." << maybe_escape_identifier(tfield
->get_name()) << ")"; // swift 2 ?== operator not in 3?
923 if (++m_iter
!= members
.end()) {
931 indent(out
) << "switch (lhs, rhs) {" << endl
;
932 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
933 t_field
* tfield
= *m_iter
;
934 indent(out
) << "case (." << tfield
->get_name() << "(let lval), ."
935 << tfield
->get_name() << "(let rval)): return lval == rval"
938 indent(out
) << "default: return false" << endl
;
939 indent(out
) << "}" << endl
;
941 indent(out
) << "}()" << endl
;
945 out
<< " true" << endl
;
953 * Generate struct implementation. Produces extensions that
954 * fulfill the requisite protocols to complete the value.
956 * @param tstruct The struct definition
958 * If this is a result it needs a different writer
960 * Is the struct public or private
962 void t_swift_generator::generate_swift_struct_implementation(ostream
& out
,
967 generate_swift_struct_equatable_extension(out
, tstruct
, is_private
);
969 if (!is_private
&& !is_result
&& !gen_cocoa_
) { // old compiler didn't use debug_descriptions, OR it with gen_cocoa_ so the flag doesn't matter w/ cocoa
970 generate_swift_struct_printable_extension(out
, tstruct
);
973 generate_swift_struct_hashable_extension(out
, tstruct
, is_private
);
974 generate_swift_struct_thrift_extension(out
, tstruct
, is_result
, is_private
);
980 * Generate the TStruct protocol implementation.
982 * @param tstruct The structure definition
984 * Is the struct a result value
986 * Is the struct public or private
988 void t_swift_generator::generate_swift_struct_thrift_extension(ostream
& out
,
993 indent(out
) << "extension " << tstruct
->get_name() << " : TStruct";
999 /** Swift 3, no writer we just write field ID's */
1000 string access
= (is_private
) ? (gen_cocoa_
? "private" : "fileprivate") : "public";
1001 // generate fieldID's dictionary
1002 out
<< indent() << access
<< " static var fieldIds: [String: Int32]";
1004 out
<< indent() << "return [";
1005 const vector
<t_field
*>& fields
= tstruct
->get_members();
1006 vector
<t_field
*>::const_iterator f_iter
;
1008 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1010 out
<< "\"" << (*f_iter
)->get_name() << "\": " << (*f_iter
)->get_key() << ", ";
1019 out
<< indent() << access
<< " static var structName: String { return \""
1020 << tstruct
->get_name() << "\" }" << endl
<< endl
;
1022 if (tstruct
->is_union()) {
1023 generate_swift_union_reader(out
, tstruct
);
1025 generate_swift_struct_reader(out
, tstruct
, is_private
);
1028 /** Legacy Swift2/Cocoa */
1030 generate_swift_struct_reader(out
, tstruct
, is_private
);
1033 generate_old_swift_struct_result_writer(out
, tstruct
);
1036 generate_old_swift_struct_writer(out
, tstruct
, is_private
);
1044 void t_swift_generator::generate_swift_union_reader(ostream
& out
, t_struct
* tstruct
) {
1045 indent(out
) << "public static func read(from proto: TProtocol) throws -> "
1046 << tstruct
->get_name();
1048 indent(out
) << "_ = try proto.readStructBegin()" << endl
;
1050 indent(out
) << "var ret: " << tstruct
->get_name() << "?";
1052 indent(out
) << "fields: while true";
1055 indent(out
) << "let (_, fieldType, fieldID) = try proto.readFieldBegin()" << endl
<< endl
;
1056 indent(out
) << "switch (fieldID, fieldType)";
1058 indent(out
) << "case (_, .stop): break fields" << endl
;
1060 const vector
<t_field
*>& fields
= tstruct
->get_members();
1061 vector
<t_field
*>::const_iterator f_iter
;
1062 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1063 indent(out
) << "case (" << (*f_iter
)->get_key() << ", " << type_to_enum((*f_iter
)->get_type()) << "):";
1064 string padding
= "";
1066 t_type
* type
= get_true_type((*f_iter
)->get_type());
1067 if (type
->is_base_type()) {
1068 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1070 case t_base_type::TYPE_STRING
:
1071 case t_base_type::TYPE_DOUBLE
:
1075 case t_base_type::TYPE_BOOL
:
1076 case t_base_type::TYPE_I8
:
1079 case t_base_type::TYPE_I16
:
1080 case t_base_type::TYPE_I32
:
1081 case t_base_type::TYPE_I64
:
1086 } else if (type
->is_enum() || type
->is_set() || type
->is_map()) {
1088 } else if (type
->is_struct() || type
->is_xception()) {
1090 } else if (type
->is_list()) {
1094 indent(out
) << padding
<< "ret = " << tstruct
->get_name() << "."
1095 << (*f_iter
)->get_name() << "(val: " << "try "
1096 << type_name((*f_iter
)->get_type(), false, false)
1097 << ".read(from: proto))" << endl
;
1100 indent(out
) << "case let (_, unknownType): try proto.skip(type: unknownType)" << endl
;
1103 indent(out
) << "try proto.readFieldEnd()" << endl
;
1108 indent(out
) << "try proto.readStructEnd()" << endl
;
1110 indent(out
) << "if let ret = ret";
1112 indent(out
) << "return ret" << endl
;
1115 indent(out
) << "throw TProtocolError(error: .unknown, message: \"Missing required value for type: "
1116 << tstruct
->get_name() << "\")";
1123 * Generates a function to read a struct from
1124 * from a protocol. (TStruct compliance)
1126 * @param tstruct The structure definition
1128 * Is the struct public or private
1130 void t_swift_generator::generate_swift_struct_reader(ostream
& out
,
1136 string visibility
= is_private
? "fileprivate" : "public";
1138 indent(out
) << visibility
<< " static func read(from proto: TProtocol) throws -> "
1139 << tstruct
->get_name();
1142 indent(out
) << "_ = try proto.readStructBegin()" << endl
;
1144 const vector
<t_field
*>& fields
= tstruct
->get_members();
1145 vector
<t_field
*>::const_iterator f_iter
;
1147 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1148 bool optional
= field_is_optional(*f_iter
);
1149 indent(out
) << "var " << maybe_escape_identifier((*f_iter
)->get_name()) << ": "
1150 << type_name((*f_iter
)->get_type(), optional
, !optional
) << endl
;
1155 // Loop over reading in fields
1156 indent(out
) << "fields: while true";
1160 indent(out
) << "let (_, fieldType, fieldID) = try proto.readFieldBegin()" << endl
<< endl
;
1161 indent(out
) << "switch (fieldID, fieldType)";
1163 indent(out
) << "case (_, .stop): break fields" << endl
;
1166 // Generate deserialization code for known cases
1167 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1168 indent(out
) << "case (" << (*f_iter
)->get_key() << ", " << type_to_enum((*f_iter
)->get_type()) << "):";
1169 string padding
= "";
1171 t_type
* type
= get_true_type((*f_iter
)->get_type());
1172 if (type
->is_base_type()) {
1173 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1175 case t_base_type::TYPE_STRING
:
1176 case t_base_type::TYPE_DOUBLE
:
1180 case t_base_type::TYPE_BOOL
:
1181 case t_base_type::TYPE_I8
:
1184 case t_base_type::TYPE_I16
:
1185 case t_base_type::TYPE_I32
:
1186 case t_base_type::TYPE_I64
:
1191 } else if (type
->is_enum() || type
->is_set() || type
->is_map()) {
1193 } else if (type
->is_struct() || type
->is_xception()) {
1195 } else if (type
->is_list()) {
1199 out
<< padding
<< maybe_escape_identifier((*f_iter
)->get_name()) << " = try "
1200 << type_name((*f_iter
)->get_type(), false, false) << ".read(from: proto)" << endl
;
1203 indent(out
) << "case let (_, unknownType): try proto.skip(type: unknownType)" << endl
;
1207 // Read field end marker
1208 indent(out
) << "try proto.readFieldEnd()" << endl
;
1211 indent(out
) << "try proto.readStructEnd()" << endl
;
1213 if (struct_has_required_fields(tstruct
)) {
1214 // performs various checks (e.g. check that all required fields are set)
1215 indent(out
) << "// Required fields" << endl
;
1217 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1218 if (field_is_optional(*f_iter
)) {
1221 indent(out
) << "try proto.validateValue(" << (*f_iter
)->get_name() << ", "
1222 << "named: \"" << (*f_iter
)->get_name() << "\")" << endl
;
1228 indent(out
) << "return " << tstruct
->get_name() << "(";
1229 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
1230 out
<< (*f_iter
)->get_name() << ": " << maybe_escape_identifier((*f_iter
)->get_name());
1231 if (++f_iter
!= fields
.end()) {
1237 /** Legacy Swif2/Cocoa case */
1238 string visibility
= is_private
? "private" : "public";
1240 indent(out
) << visibility
<< " static func readValueFromProtocol(__proto: TProtocol) throws -> "
1241 << tstruct
->get_name();
1245 indent(out
) << "try __proto.readStructBegin()" << endl
<< endl
;
1247 const vector
<t_field
*>& fields
= tstruct
->get_members();
1248 vector
<t_field
*>::const_iterator f_iter
;
1250 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1251 bool optional
= field_is_optional(*f_iter
);
1252 indent(out
) << "var " << maybe_escape_identifier((*f_iter
)->get_name()) << " : "
1253 << type_name((*f_iter
)->get_type(), optional
, !optional
) << endl
;
1258 // Loop over reading in fields
1259 indent(out
) << "fields: while true";
1263 indent(out
) << "let (_, fieldType, fieldID) = try __proto.readFieldBegin()" << endl
<< endl
;
1264 indent(out
) << "switch (fieldID, fieldType)";
1268 indent(out
) << "case (_, .STOP):" << endl
;
1270 indent(out
) << "break fields" << endl
<< endl
;
1273 // Generate deserialization code for known cases
1274 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1276 indent(out
) << "case (" << (*f_iter
)->get_key() << ", " << type_to_enum((*f_iter
)->get_type()) << "):" << endl
;
1278 indent(out
) << maybe_escape_identifier((*f_iter
)->get_name()) << " = try __proto.readValue() as "
1279 << type_name((*f_iter
)->get_type()) << endl
<< endl
;
1284 indent(out
) << "case let (_, unknownType):" << endl
;
1286 indent(out
) << "try __proto.skipType(unknownType)" << endl
;
1291 // Read field end marker
1292 indent(out
) << "try __proto.readFieldEnd()" << endl
;
1296 indent(out
) << "try __proto.readStructEnd()" << endl
;
1299 if (struct_has_required_fields(tstruct
)) {
1300 // performs various checks (e.g. check that all required fields are set)
1301 indent(out
) << "// Required fields" << endl
;
1303 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1304 if (field_is_optional(*f_iter
)) {
1307 indent(out
) << "try __proto.validateValue(" << (*f_iter
)->get_name() << ", "
1308 << "named: \"" << (*f_iter
)->get_name() << "\")" << endl
;
1314 indent(out
) << "return " << tstruct
->get_name() << "(";
1315 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
1316 out
<< (*f_iter
)->get_name() << ": " << maybe_escape_identifier((*f_iter
)->get_name());
1317 if (++f_iter
!= fields
.end()) {
1330 * Generates a function to write a struct to
1331 * a protocol. (TStruct compliance) ONLY FOR SWIFT2/COCOA
1333 * @param tstruct The structure definition
1335 * Is the struct public or private
1337 void t_swift_generator::generate_old_swift_struct_writer(ostream
& out
,
1341 string visibility
= is_private
? "private" : "public";
1343 indent(out
) << visibility
<< " static func writeValue(__value: " << tstruct
->get_name()
1344 << ", toProtocol __proto: TProtocol) throws";
1348 string name
= tstruct
->get_name();
1349 const vector
<t_field
*>& fields
= tstruct
->get_members();
1350 vector
<t_field
*>::const_iterator f_iter
;
1352 indent(out
) << "try __proto.writeStructBeginWithName(\"" << name
<< "\")" << endl
;
1355 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1356 t_field
*tfield
= *f_iter
;
1358 bool optional
= field_is_optional(tfield
);
1360 indent(out
) << "if let " << maybe_escape_identifier(tfield
->get_name())
1361 << " = __value." << maybe_escape_identifier(tfield
->get_name());
1365 indent(out
) << "try __proto.writeFieldValue("
1366 << (optional
? "" : "__value.") << maybe_escape_identifier(tfield
->get_name()) << ", "
1367 << "name: \"" << tfield
->get_name() << "\", "
1368 << "type: " << type_to_enum(tfield
->get_type()) << ", "
1369 << "id: " << tfield
->get_key() << ")" << endl
;
1378 indent(out
) << "try __proto.writeFieldStop()" << endl
<< endl
;
1379 indent(out
) << "try __proto.writeStructEnd()" << endl
;
1385 * Generates a function to read a struct from
1386 * from a protocol. (TStruct compliance) ONLY FOR SWIFT 2/COCOA
1388 * This is specifically a function result. Only
1389 * the first available field is written.
1391 * @param tstruct The structure definition
1393 void t_swift_generator::generate_old_swift_struct_result_writer(ostream
& out
, t_struct
* tstruct
) {
1395 indent(out
) << "private static func writeValue(__value: " << tstruct
->get_name()
1396 << ", toProtocol __proto: TProtocol) throws";
1399 string name
= tstruct
->get_name();
1400 const vector
<t_field
*>& fields
= tstruct
->get_members();
1401 vector
<t_field
*>::const_iterator f_iter
;
1402 indent(out
) << "try __proto.writeStructBeginWithName(\"" << name
<< "\")" << endl
;
1405 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1406 t_field
*tfield
= *f_iter
;
1408 indent(out
) << "if let result = __value." << (*f_iter
)->get_name();
1412 indent(out
) << "try __proto.writeFieldValue(result, "
1413 << "name: \"" << tfield
->get_name() << "\", "
1414 << "type: " << type_to_enum(tfield
->get_type()) << ", "
1415 << "id: " << tfield
->get_key() << ")" << endl
;
1419 // Write the struct map
1420 indent(out
) << "try __proto.writeFieldStop()" << endl
<< endl
;
1421 indent(out
) << "try __proto.writeStructEnd()" << endl
;
1427 * Generates a description method for the given struct
1429 * @param tstruct The struct definition
1431 void t_swift_generator::generate_swift_struct_printable_extension(ostream
& out
, t_struct
* tstruct
) {
1433 // Allow use of debugDescription so the app can add description via a cateogory/extension
1435 const vector
<t_field
*>& fields
= tstruct
->get_members();
1436 vector
<t_field
*>::const_iterator f_iter
;
1438 indent(out
) << "extension " << tstruct
->get_name() << " : "
1439 << (debug_descriptions_
? "CustomDebugStringConvertible" : "CustomStringConvertible");
1443 indent(out
) << "public var description : String";
1445 indent(out
) << "var desc = \"" << tstruct
->get_name();
1448 if (!tstruct
->is_union()) {
1449 out
<< "(\"" << endl
;
1450 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
1451 indent(out
) << "desc += \"" << (*f_iter
)->get_name()
1452 << "=\\(String(describing: self." << maybe_escape_identifier((*f_iter
)->get_name()) << "))";
1453 if (++f_iter
!= fields
.end()) {
1456 out
<< "\"" << endl
;
1459 out
<< ".\"" << endl
;
1460 indent(out
) << "switch self {" << endl
;
1461 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();f_iter
++) {
1462 indent(out
) << "case ." << (*f_iter
)->get_name() << "(let val): "
1463 << "desc += \"" << (*f_iter
)->get_name() << "(val: \\(val))\""
1466 indent(out
) << "}" << endl
;
1469 out
<< "(\"" << endl
;
1470 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
1471 indent(out
) << "desc += \"" << (*f_iter
)->get_name()
1472 << "=\\(self." << maybe_escape_identifier((*f_iter
)->get_name()) << ")";
1473 if (++f_iter
!= fields
.end()) {
1476 out
<< "\"" << endl
;
1478 indent(out
) << "desc += \")\"" << endl
;
1481 indent(out
) << "return desc" << endl
;
1489 * Generates a thrift service. In Swift this consists of a
1490 * protocol definition and a client (with it's implementation
1491 * separated into exts file).
1493 * @param tservice The service definition
1495 void t_swift_generator::generate_service(t_service
* tservice
) {
1497 generate_swift_service_protocol(f_decl_
, tservice
);
1498 generate_swift_service_client(f_decl_
, tservice
);
1499 if (async_clients_
) {
1500 generate_swift_service_protocol_async(f_decl_
, tservice
);
1501 generate_swift_service_client_async(f_decl_
, tservice
);
1503 generate_swift_service_server(f_decl_
, tservice
);
1505 generate_swift_service_helpers(tservice
);
1507 generate_swift_service_client_implementation(f_impl_
, tservice
);
1508 if (async_clients_
) {
1509 generate_swift_service_client_async_implementation(f_impl_
, tservice
);
1511 generate_swift_service_server_implementation(f_impl_
, tservice
);
1515 * Generates structs for all the service return types
1517 * @param tservice The service
1519 void t_swift_generator::generate_swift_service_helpers(t_service
* tservice
) {
1520 vector
<t_function
*> functions
= tservice
->get_functions();
1521 vector
<t_function
*>::iterator f_iter
;
1522 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1524 t_struct
* ts
= (*f_iter
)->get_arglist();
1526 string qname
= function_args_helper_struct_type(tservice
, *f_iter
);
1528 t_struct qname_ts
= t_struct(ts
->get_program(), qname
);
1530 const vector
<t_field
*>& members
= ts
->get_members();
1531 vector
<t_field
*>::const_iterator m_iter
;
1532 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
1533 qname_ts
.append(*m_iter
);
1536 generate_swift_struct(f_impl_
, &qname_ts
, true);
1537 generate_swift_struct_implementation(f_impl_
, &qname_ts
, false, true);
1538 generate_function_helpers(tservice
, *f_iter
);
1542 string
t_swift_generator::function_result_helper_struct_type(t_service
*tservice
, t_function
* tfunction
) {
1543 if (tfunction
->is_oneway()) {
1544 return tservice
->get_name() + "_" + tfunction
->get_name();
1546 return tservice
->get_name() + "_" + tfunction
->get_name() + "_result";
1550 string
t_swift_generator::function_args_helper_struct_type(t_service
*tservice
, t_function
* tfunction
) {
1551 return tservice
->get_name() + "_" + tfunction
->get_name() + "_args";
1555 * Generates a struct and helpers for a function.
1557 * @param tfunction The function
1559 void t_swift_generator::generate_function_helpers(t_service
*tservice
, t_function
* tfunction
) {
1560 if (tfunction
->is_oneway()) {
1564 // create a result struct with a success field of the return type,
1565 // and a field for each type of exception thrown
1566 t_struct
result(program_
, function_result_helper_struct_type(tservice
, tfunction
));
1567 if (!tfunction
->get_returntype()->is_void()) {
1568 t_field
* success
= new t_field(tfunction
->get_returntype(), "success", 0);
1569 success
->set_req(t_field::T_OPTIONAL
);
1570 result
.append(success
);
1573 t_struct
* xs
= tfunction
->get_xceptions();
1574 const vector
<t_field
*>& fields
= xs
->get_members();
1575 vector
<t_field
*>::const_iterator f_iter
;
1576 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1577 t_field
*x
= *f_iter
;
1578 t_field
*ox
= new t_field(x
->get_type(), x
->get_name(), x
->get_key());
1579 ox
->set_req(t_field::T_OPTIONAL
);
1583 // generate the result struct
1584 generate_swift_struct(f_impl_
, &result
, true);
1585 generate_swift_struct_implementation(f_impl_
, &result
, true, true);
1587 for (f_iter
= result
.get_members().begin(); f_iter
!= result
.get_members().end(); ++f_iter
) {
1593 * Generates a service protocol definition.
1595 * @param tservice The service to generate a protocol definition for
1597 void t_swift_generator::generate_swift_service_protocol(ostream
& out
, t_service
* tservice
) {
1599 string doc
= tservice
->get_doc();
1600 generate_docstring(out
, doc
);
1602 indent(out
) << "public protocol " << tservice
->get_name();
1603 t_service
* parent
= tservice
->get_extends();
1604 if (parent
!= NULL
) {
1605 out
<< " : " << parent
->get_name();
1610 vector
<t_function
*> functions
= tservice
->get_functions();
1611 vector
<t_function
*>::iterator f_iter
;
1613 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1614 function_docstring(out
, *f_iter
);
1615 indent(out
) << function_signature(*f_iter
) << endl
<< endl
;
1619 indent(out
) << "public protocol " << tservice
->get_name();
1622 vector
<t_function
*> functions
= tservice
->get_functions();
1623 vector
<t_function
*>::iterator f_iter
;
1625 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1627 indent(out
) << function_signature(*f_iter
) << " // exceptions: ";
1628 t_struct
* xs
= (*f_iter
)->get_xceptions();
1629 const vector
<t_field
*>& xceptions
= xs
->get_members();
1630 vector
<t_field
*>::const_iterator x_iter
;
1631 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1632 out
<< type_name((*x_iter
)->get_type()) + ", ";
1642 * Generates an asynchronous service protocol definition.
1644 * @param tservice The service to generate a protocol definition for
1646 void t_swift_generator::generate_swift_service_protocol_async(ostream
& out
, t_service
* tservice
) {
1648 string doc
= tservice
->get_doc();
1649 generate_docstring(out
, doc
);
1651 indent(out
) << "public protocol " << tservice
->get_name() << "Async";
1654 if (!gen_cocoa_
) { out
<< endl
; }
1656 vector
<t_function
*> functions
= tservice
->get_functions();
1657 vector
<t_function
*>::iterator f_iter
;
1660 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1661 async_function_docstring(out
, *f_iter
);
1662 indent(out
) << async_function_signature(*f_iter
) << endl
<< endl
;
1665 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1667 indent(out
) << async_function_signature(*f_iter
) << endl
;
1669 indent(out
) << promise_function_signature(*f_iter
) << endl
;
1679 * Generates a service client interface definition.
1681 * @param tservice The service to generate a client interface definition for
1683 void t_swift_generator::generate_swift_service_client(ostream
& out
, t_service
* tservice
) {
1685 indent(out
) << "open class " << tservice
->get_name() << "Client";// : "
1687 // Inherit from ParentClient
1688 t_service
* parent
= tservice
->get_extends();
1689 out
<< " : " << ((parent
== NULL
) ? "TClient" : parent
->get_name() + "Client");
1690 out
<< " /* , " << tservice
->get_name() << " */";
1695 indent(out
) << "public class " << tservice
->get_name() << "Client /* : " << tservice
->get_name() << " */";
1699 indent(out
) << "let __inProtocol : TProtocol" << endl
<< endl
;
1700 indent(out
) << "let __outProtocol : TProtocol" << endl
<< endl
;
1701 indent(out
) << "public init(inoutProtocol: TProtocol)";
1704 indent(out
) << "__inProtocol = inoutProtocol" << endl
;
1705 indent(out
) << "__outProtocol = inoutProtocol" << endl
;
1709 indent(out
) << "public init(inProtocol: TProtocol, outProtocol: TProtocol)";
1711 indent(out
) << "__inProtocol = inProtocol" << endl
;
1712 indent(out
) << "__outProtocol = outProtocol" << endl
;
1722 * Generates a service client interface definition.
1724 * @param tservice The service to generate a client interface definition for
1726 void t_swift_generator::generate_swift_service_client_async(ostream
& out
, t_service
* tservice
) {
1728 indent(out
) << "open class " << tservice
->get_name()
1729 << "AsyncClient<Protocol: TProtocol, Factory: TAsyncTransportFactory>";// : "
1731 // Inherit from ParentClient
1732 t_service
* parent
= tservice
->get_extends();
1734 out
<< " : " << ((parent
== NULL
) ? "T" : parent
->get_name()) + "AsyncClient<Protocol, Factory>";
1735 out
<< " /* , " << tservice
->get_name() << " */";
1740 indent(out
) << "public class " << tservice
->get_name() << "AsyncClient /* : " << tservice
->get_name() << " */";
1744 indent(out
) << "let __protocolFactory : TProtocolFactory" << endl
<< endl
;
1745 indent(out
) << "let __transportFactory : TAsyncTransportFactory" << endl
<< endl
;
1746 indent(out
) << "public init(protocolFactory: TProtocolFactory, transportFactory: TAsyncTransportFactory)";
1749 indent(out
) << "__protocolFactory = protocolFactory" << endl
;
1750 indent(out
) << "__transportFactory = transportFactory" << endl
;
1759 * Generates a service server interface definition. In other words,
1760 * the TProcess implementation for the service definition.
1762 * @param tservice The service to generate a client interface definition for
1764 void t_swift_generator::generate_swift_service_server(ostream
& out
, t_service
* tservice
) {
1766 indent(out
) << "open class " << tservice
->get_name() << "Processor /* " << tservice
->get_name() << " */";
1770 out
<< indent() << "typealias ProcessorHandlerDictionary = "
1771 << "[String: (Int32, TProtocol, TProtocol, " << tservice
->get_name() << ") throws -> Void]" << endl
1773 << indent() << "public var service: " << tservice
->get_name() << endl
1775 << indent() << "public required init(service: " << tservice
->get_name() << ")";
1777 indent(out
) << "public class " << tservice
->get_name() << "Processor : NSObject /* "
1778 << tservice
->get_name() << " */";
1782 out
<< indent() << "typealias ProcessorHandlerDictionary = "
1783 << "[String: (Int, TProtocol, TProtocol, " << tservice
->get_name() << ") throws -> Void]" << endl
1785 << indent() << "let service : " << tservice
->get_name() << endl
1787 << indent() << "public init(service: " << tservice
->get_name() << ")";
1791 indent(out
) << "self.service = service" << endl
;
1800 * Generates a function that will send the arguments
1801 * for a service function via a protocol.
1803 * @param tservice The service to generate
1804 * @param tfunction The function to generate
1805 * @param needs_protocol
1806 * Wether the first parameter must be a protocol or if
1807 * the protocol is to be assumed
1809 void t_swift_generator::generate_swift_service_client_send_function_implementation(ostream
& out
,
1810 t_service
*tservice
,
1811 t_function
* tfunction
,
1812 bool needs_protocol
) {
1814 string funname
= tfunction
->get_name();
1816 t_function
send_function(g_type_bool
,
1817 "send_" + tfunction
->get_name(),
1818 tfunction
->get_arglist());
1820 string argsname
= function_args_helper_struct_type(tservice
, tfunction
);
1821 t_struct
* arg_struct
= tfunction
->get_arglist();
1823 string proto
= needs_protocol
? (gen_cocoa_
? "__outProtocol" : "on outProtocol") : "";
1825 indent(out
) << "private func " << send_function
.get_name() << "("
1826 << argument_list(tfunction
->get_arglist(), proto
, true)
1830 // Serialize the request
1831 indent(out
) << "try outProtocol.writeMessageBegin(name: \"" << funname
<< "\", "
1832 << "type: " << (tfunction
->is_oneway() ? ".oneway" : ".call") << ", "
1833 << "sequenceID: 0)" << endl
;
1835 indent(out
) << "let args = " << argsname
<< "(";
1837 // write out function parameters
1839 const vector
<t_field
*>& fields
= arg_struct
->get_members();
1840 vector
<t_field
*>::const_iterator f_iter
;
1842 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
1843 t_field
*tfield
= (*f_iter
);
1844 out
<< tfield
->get_name() << ": " << tfield
->get_name();
1845 if (++f_iter
!= fields
.end()) {
1850 indent(out
) << "try args.write(to: outProtocol)" << endl
;
1851 indent(out
) << "try outProtocol.writeMessageEnd()" << endl
;
1855 // Serialize the request
1856 indent(out
) << "try __outProtocol.writeMessageBeginWithName(\"" << funname
<< "\", "
1857 << "type: " << (tfunction
->is_oneway() ? ".ONEWAY" : ".CALL") << ", "
1858 << "sequenceID: 0)" << endl
;
1862 indent(out
) << "let __args = " << argsname
<< "(";
1864 // write out function parameters
1866 const vector
<t_field
*>& fields
= arg_struct
->get_members();
1867 vector
<t_field
*>::const_iterator f_iter
;
1869 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
1870 t_field
*tfield
= (*f_iter
);
1871 out
<< tfield
->get_name() << ": " << tfield
->get_name();
1872 if (++f_iter
!= fields
.end()) {
1877 indent(out
) << "try " << argsname
<< ".writeValue(__args, toProtocol: __outProtocol)" << endl
<< endl
;
1878 indent(out
) << "try __outProtocol.writeMessageEnd()" << endl
;
1886 * Generates a function that will recv the result for a
1887 * service function via a protocol.
1889 * @param tservice The service to generate
1890 * @param tfunction The function to generate
1891 * @param needs_protocol
1892 * Wether the first parameter must be a protocol or if
1893 * the protocol is to be assumed
1895 void t_swift_generator::generate_swift_service_client_recv_function_implementation(ostream
& out
,
1896 t_service
* tservice
,
1897 t_function
* tfunction
,
1898 bool needs_protocol
) {
1901 indent(out
) << "private func recv_" << tfunction
->get_name() << "(";
1903 if (needs_protocol
) {
1904 out
<< "on inProtocol: TProtocol";
1907 if (!tfunction
->get_returntype()->is_void()) {
1908 out
<< " -> " << type_name(tfunction
->get_returntype());
1913 // check for an exception
1915 indent(out
) << "try inProtocol.readResultMessageBegin() " << endl
;
1917 string resultname
= function_result_helper_struct_type(tservice
, tfunction
);
1919 if (!tfunction
->get_returntype()->is_void() || !tfunction
->get_xceptions()->get_members().empty()) {
1920 out
<< "let result = ";
1925 string return_type_name
= type_name(tfunction
->get_returntype());
1926 out
<< "try " << resultname
<< ".read(from: inProtocol)" << endl
;
1928 indent(out
) << "try inProtocol.readMessageEnd()" << endl
<< endl
;
1930 // Careful, only return _result if not a void function
1931 if (!tfunction
->get_returntype()->is_void()) {
1932 indent(out
) << "if let success = result.success";
1934 indent(out
) << "return success" << endl
;
1938 t_struct
* xs
= tfunction
->get_xceptions();
1939 const vector
<t_field
*>& xceptions
= xs
->get_members();
1940 vector
<t_field
*>::const_iterator x_iter
;
1942 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1943 indent(out
) << "if let " << (*x_iter
)->get_name() << " = result." << (*x_iter
)->get_name();
1945 indent(out
) << "throw " << (*x_iter
)->get_name() << endl
;
1949 // If you get here it's an exception, unless a void function
1950 if (!tfunction
->get_returntype()->is_void()) {
1951 indent(out
) << "throw TApplicationError(error: .missingResult(methodName: \""
1952 << tfunction
->get_name() << "\"))" << endl
;
1955 if (needs_protocol
) {
1956 out
<< "__inProtocol: TProtocol";
1961 if (!tfunction
->get_returntype()->is_void()) {
1962 out
<< " -> " << type_name(tfunction
->get_returntype());
1967 // check for an exception
1969 indent(out
) << "try __inProtocol.readResultMessageBegin() " << endl
<< endl
;
1970 string resultname
= function_result_helper_struct_type(tservice
, tfunction
);
1972 if (!tfunction
->get_returntype()->is_void() || !tfunction
->get_xceptions()->get_members().empty()) {
1973 out
<< "let __result = ";
1975 out
<< "try " << resultname
<< ".readValueFromProtocol(__inProtocol)" << endl
<< endl
;
1977 indent(out
) << "try __inProtocol.readMessageEnd()" << endl
<< endl
;
1979 // Careful, only return _result if not a void function
1980 if (!tfunction
->get_returntype()->is_void()) {
1981 indent(out
) << "if let __success = __result.success";
1983 indent(out
) << "return __success" << endl
;
1987 t_struct
* xs
= tfunction
->get_xceptions();
1988 const vector
<t_field
*>& xceptions
= xs
->get_members();
1989 vector
<t_field
*>::const_iterator x_iter
;
1991 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1992 indent(out
) << "if let " << (*x_iter
)->get_name() << " = __result." << (*x_iter
)->get_name();
1994 indent(out
) << "throw " << (*x_iter
)->get_name() << endl
;
1998 // If you get here it's an exception, unless a void function
1999 if (!tfunction
->get_returntype()->is_void()) {
2000 indent(out
) << "throw NSError(" << endl
;
2002 indent(out
) << "domain: TApplicationErrorDomain, " << endl
;
2003 indent(out
) << "code: Int(TApplicationError.MissingResult.rawValue)," << endl
;
2004 indent(out
) << "userInfo: [TApplicationErrorMethodKey: \"" << tfunction
->get_name() << "\"])" << endl
;
2015 * Generates an invocation of a given the send function for the
2018 * @param tfunction The service to generate an implementation for
2020 void t_swift_generator::generate_swift_service_client_send_function_invocation(ostream
& out
,
2021 t_function
* tfunction
) {
2023 indent(out
) << "try send_" << tfunction
->get_name() << "(";
2025 t_struct
* arg_struct
= tfunction
->get_arglist();
2027 const vector
<t_field
*>& fields
= arg_struct
->get_members();
2028 vector
<t_field
*>::const_iterator f_iter
;
2030 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
2031 out
<< (*f_iter
)->get_name() << ": " << (*f_iter
)->get_name();
2032 if (++f_iter
!= fields
.end()) {
2041 * Generates an invocation of a given the send function for the
2042 * service function. This is for asynchronous protocols.
2044 * @param tfunction The service to generate an implementation for
2046 void t_swift_generator::generate_swift_service_client_send_async_function_invocation(ostream
& out
,
2047 t_function
* tfunction
) {
2049 t_struct
* arg_struct
= tfunction
->get_arglist();
2050 const vector
<t_field
*>& fields
= arg_struct
->get_members();
2051 vector
<t_field
*>::const_iterator f_iter
;
2054 indent(out
) << "try send_" << tfunction
->get_name() << "(on: proto";
2056 indent(out
) << "try send_" << tfunction
->get_name() << "(__protocol"; //
2059 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
2060 out
<< ", " << (*f_iter
)->get_name() << ": " << (*f_iter
)->get_name();
2067 * Generates a service client protocol implementation via extension.
2069 * @param tservice The service to generate an implementation for
2071 void t_swift_generator::generate_swift_service_client_implementation(ostream
& out
,
2072 t_service
* tservice
) {
2074 string name
= tservice
->get_name() + "Client";
2075 indent(out
) << "extension " << name
<< " : " << tservice
->get_name();
2079 // generate client method implementations
2080 vector
<t_function
*> functions
= tservice
->get_functions();
2081 vector
<t_function
*>::const_iterator f_iter
;
2082 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
2084 generate_swift_service_client_send_function_implementation(out
, tservice
, *f_iter
, false);
2086 if (!(*f_iter
)->is_oneway()) {
2087 generate_swift_service_client_recv_function_implementation(out
, tservice
, *f_iter
, false);
2091 indent(out
) << "public " << function_signature(*f_iter
);
2094 if (gen_cocoa_
) { out
<< endl
; }
2096 generate_swift_service_client_send_function_invocation(out
, *f_iter
);
2098 indent(out
) << "try outProtocol.transport.flush()" << endl
;
2101 indent(out
) << "try __outProtocol.transport().flush()" << endl
<< endl
;
2104 if (!(*f_iter
)->is_oneway()) {
2105 if ((*f_iter
)->get_returntype()->is_void()) {
2106 indent(out
) << "try recv_" << (*f_iter
)->get_name() << "()" << endl
;
2108 indent(out
) << "return try recv_" << (*f_iter
)->get_name() << "()" << endl
;
2119 * Generates a service asynchronous client protocol implementation via extension.
2121 * @param tservice The service to generate an implementation for
2123 void t_swift_generator::generate_swift_service_client_async_implementation(ostream
& out
, t_service
* tservice
) {
2125 generate_old_swift_service_client_async_implementation(out
, tservice
);
2128 string name
= tservice
->get_name() + "AsyncClient";
2129 string protocol_name
= tservice
->get_name() + "Async";
2131 indent(out
) << "extension " << name
<< " : " << protocol_name
;
2135 // generate client method implementations
2136 vector
<t_function
*> functions
= tservice
->get_functions();
2137 vector
<t_function
*>::const_iterator f_iter
;
2138 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
2140 generate_swift_service_client_send_function_implementation(out
, tservice
, *f_iter
, true);
2142 if (!(*f_iter
)->is_oneway()) {
2143 generate_swift_service_client_recv_function_implementation(out
, tservice
, *f_iter
, true);
2146 indent(out
) << "public " << async_function_signature(*f_iter
);
2149 out
<< indent() << "let transport = factory.newTransport()" << endl
2150 << indent() << "let proto = Protocol(on: transport)" << endl
2153 out
<< indent() << "do";
2156 generate_swift_service_client_send_async_function_invocation(out
, *f_iter
);
2159 out
<< indent() << "} catch let error {" << endl
;
2161 out
<< indent() << "completion(.error(error))" << endl
;
2166 bool ret_is_void
= (*f_iter
)->get_returntype()->is_void();
2167 bool is_oneway
= (*f_iter
)->is_oneway();
2169 string error_completion_call
= "completion(.error(error))";
2170 indent(out
) << "transport.flush";
2172 out
<< indent() << "(trans, error) in" << endl
<< endl
;
2173 out
<< indent() << "if let error = error";
2175 out
<< indent() << error_completion_call
<< endl
;
2179 out
<< indent() << "do";
2183 out
<< "let result = ";
2185 out
<< "try self.recv_" << (*f_iter
)->get_name() << "(on: proto)" << endl
;
2187 out
<< indent() << (ret_is_void
? "completion(.success(Void()))" : "completion(.success(result))") << endl
;
2189 out
<< indent() << "} catch let error {" << endl
;
2191 out
<< indent() << error_completion_call
<< endl
;
2195 out
<< indent() << "completion(.success(Void()))" << endl
;
2205 void t_swift_generator::generate_old_swift_service_client_async_implementation(ostream
& out
,
2206 t_service
* tservice
) {
2208 string name
= tservice
->get_name() + "AsyncClient";
2209 string protocol_name
= tservice
->get_name() + "Async";
2211 indent(out
) << "extension " << name
<< " : " << protocol_name
;
2215 // generate client method implementations
2216 vector
<t_function
*> functions
= tservice
->get_functions();
2217 vector
<t_function
*>::const_iterator f_iter
;
2218 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
2220 generate_swift_service_client_send_function_implementation(out
, tservice
, *f_iter
, true);
2222 if (!(*f_iter
)->is_oneway()) {
2223 generate_swift_service_client_recv_function_implementation(out
, tservice
, *f_iter
, true);
2226 indent(out
) << "public " << async_function_signature(*f_iter
);
2230 out
<< indent() << "let __transport = __transportFactory.newTransport()" << endl
2231 << indent() << "let __protocol = __protocolFactory.newProtocolOnTransport(__transport)" << endl
2234 generate_swift_service_client_send_async_function_invocation(out
, *f_iter
);
2237 indent(out
) << "__transport.flushWithCompletion(";
2239 if ((*f_iter
)->is_oneway()) {
2240 out
<< "success, failure: failure)" << endl
;
2244 indent(out
) << "do";
2248 if (!(*f_iter
)->get_returntype()->is_void()) {
2249 out
<< "let result = ";
2251 out
<< "try self.recv_" << (*f_iter
)->get_name() << "(__protocol)" << endl
;
2253 out
<< indent() << "success(";
2254 if (!(*f_iter
)->get_returntype()->is_void()) {
2260 indent(out
) << "catch let error";
2262 indent(out
) << "failure(error as NSError)" << endl
;
2265 indent(out
) << ", failure: failure)" << endl
;
2274 indent(out
) << "public " << promise_function_signature(*f_iter
);
2277 out
<< indent() << "let (__promise, __fulfill, __reject) = Promise<" << type_name((*f_iter
)->get_returntype()) << ">.pendingPromise()" << endl
<< endl
2278 << indent() << "let __transport = __transportFactory.newTransport()" << endl
2279 << indent() << "let __protocol = __protocolFactory.newProtocolOnTransport(__transport)" << endl
2282 generate_swift_service_client_send_async_function_invocation(out
, *f_iter
);
2284 indent(out
) << "__transport.flushWithCompletion(";
2286 if ((*f_iter
)->is_oneway()) {
2287 out
<< "{ __fulfill() }, failure: { __reject($0) })" << endl
;
2291 indent(out
) << "do";
2295 if (!(*f_iter
)->get_returntype()->is_void()) {
2296 out
<< "let result = ";
2298 out
<< "try self.recv_" << (*f_iter
)->get_name() << "(__protocol)" << endl
;
2300 out
<< indent() << "__fulfill(";
2301 if (!(*f_iter
)->get_returntype()->is_void()) {
2307 indent(out
) << "catch let error";
2309 indent(out
) << "__reject(error)" << endl
;
2313 indent(out
) << ", failure: { error in " << endl
;
2315 indent(out
) << "__reject(error)" << endl
;
2317 indent(out
) << "})" << endl
;
2320 indent(out
) << "return __promise" << endl
;
2332 * Generates a service server implementation.
2334 * Implemented by generating a block for each service function that
2335 * handles the processing of that function. The blocks are stored in
2336 * a map and looked up via function/message name.
2338 * @param tservice The service to generate an implementation for
2340 void t_swift_generator::generate_swift_service_server_implementation(ostream
& out
,
2341 t_service
* tservice
) {
2343 string name
= tservice
->get_name() + "Processor";
2345 indent(out
) << "extension " << name
<< " : TProcessor";
2348 indent(out
) << "static let processorHandlers" << (gen_cocoa_
? " " : "") << ": ProcessorHandlerDictionary =";
2352 out
<< indent() << "var processorHandlers = ProcessorHandlerDictionary()" << endl
<< endl
;
2354 // generate method map for routing incoming calls
2355 vector
<t_function
*> functions
= tservice
->get_functions();
2356 vector
<t_function
*>::const_iterator f_iter
;
2357 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
2359 t_function
* tfunction
= *f_iter
;
2361 string args_type
= function_args_helper_struct_type(tservice
, *f_iter
);
2363 out
<< indent() << "processorHandlers[\"" << tfunction
->get_name() << "\"] = { sequenceID, inProtocol, outProtocol, handler in" << endl
2368 out
<< indent() << "let args = try " << args_type
<< ".read(from: inProtocol)" << endl
2370 << indent() << "try inProtocol.readMessageEnd()" << endl
2373 out
<< indent() << "let args = try " << args_type
<< ".readValueFromProtocol(inProtocol)" << endl
2375 << indent() << "try inProtocol.readMessageEnd()" << endl
2379 if (!tfunction
->is_oneway() ) {
2380 string result_type
= function_result_helper_struct_type(tservice
, tfunction
);
2381 indent(out
) << "var result = " << result_type
<< "()" << endl
;
2383 indent(out
) << "do";
2387 if (!tfunction
->get_returntype()->is_void()) {
2388 out
<< "result.success = ";
2390 out
<< "try handler." << (gen_cocoa_
? function_name(tfunction
) : tfunction
->get_name()) << "(";
2392 t_struct
* arg_struct
= tfunction
->get_arglist();
2393 const vector
<t_field
*>& fields
= arg_struct
->get_members();
2394 vector
<t_field
*>::const_iterator f_iter
;
2396 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
2397 string fieldName
= (*f_iter
)->get_name();
2398 if (!gen_cocoa_
|| f_iter
!= fields
.begin()) {
2399 out
<< fieldName
<< ": ";
2402 out
<< "args." << fieldName
;
2403 if (++f_iter
!= fields
.end()) {
2411 t_struct
* xs
= tfunction
->get_xceptions();
2412 const vector
<t_field
*>& xfields
= xs
->get_members();
2413 vector
<t_field
*>::const_iterator x_iter
;
2416 for (x_iter
= xfields
.begin(); x_iter
!= xfields
.end(); ++x_iter
) {
2417 indent(out
) << "catch let error as ";
2419 t_program
* program
= (*x_iter
)->get_type()->get_program();
2420 if ((*x_iter
)->get_type()->get_name() == "Error" && namespaced_
&& program
!= program_
) {
2421 out
<< get_real_swift_module(program
) << ".";
2423 out
<< (*x_iter
)->get_type()->get_name();
2425 out
<< " { result." << (*x_iter
)->get_name() << " = error }" << endl
;
2428 indent(out
) << "catch let error { throw error }" << endl
;
2431 if (!tfunction
->is_oneway()) {
2432 out
<< indent() << "try outProtocol.writeMessageBegin(name: \"" << tfunction
->get_name() << "\", type: .reply, sequenceID: sequenceID)" << endl
2433 << indent() << "try result.write(to: outProtocol)" << endl
2434 << indent() << "try outProtocol.writeMessageEnd()" << endl
;
2437 for (x_iter
= xfields
.begin(); x_iter
!= xfields
.end(); ++x_iter
) {
2438 indent(out
) << "catch let error as " << (*x_iter
)->get_type()->get_name();
2440 indent(out
) << "result." << (*x_iter
)->get_name() << " = error" << endl
;
2444 indent(out
) << "catch let error";
2446 out
<< indent() << "throw error" << endl
;
2451 if (!tfunction
->is_oneway()) {
2452 out
<< indent() << "try outProtocol.writeMessageBeginWithName(\"" << tfunction
->get_name() << "\", type: .REPLY, sequenceID: sequenceID)" << endl
2453 << indent() << "try " << result_type
<< ".writeValue(result, toProtocol: outProtocol)" << endl
2454 << indent() << "try outProtocol.writeMessageEnd()" << endl
;
2462 indent(out
) << "return processorHandlers" << endl
;
2464 block_close(out
,false);
2465 out
<< "()" << endl
;
2469 indent(out
) << "public func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws";
2471 indent(out
) << "public func processOnInputProtocol(inProtocol: TProtocol, outputProtocol outProtocol: TProtocol) throws";
2476 out
<< indent() << "let (messageName, _, sequenceID) = try inProtocol.readMessageBegin()" << endl
2478 << indent() << "if let processorHandler = " << name
<< ".processorHandlers[messageName]";
2480 out
<< indent() << "do";
2482 out
<< indent() << "try processorHandler(sequenceID, inProtocol, outProtocol, service)" << endl
;
2485 out
<< indent() << "catch let error as TApplicationError";
2487 out
<< indent() << "try outProtocol.writeException(messageName: messageName, sequenceID: sequenceID, ex: error)" << endl
;
2490 out
<< indent() << "else";
2492 out
<< indent() << "try inProtocol.skip(type: .struct)" << endl
2493 << indent() << "try inProtocol.readMessageEnd()" << endl
2494 << indent() << "let ex = TApplicationError(error: .unknownMethod(methodName: messageName))" << endl
2495 << indent() << "try outProtocol.writeException(messageName: messageName, "
2496 << "sequenceID: sequenceID, ex: ex)" << endl
;
2498 out
<< indent() << "catch let error as NSError";
2500 out
<< indent() << "try outProtocol.writeExceptionForMessageName(messageName, sequenceID: sequenceID, ex: error)" << endl
;
2503 out
<< indent() << "else";
2505 out
<< indent() << "try inProtocol.skipType(.STRUCT)" << endl
2506 << indent() << "try inProtocol.readMessageEnd()" << endl
2507 << indent() << "try outProtocol.writeExceptionForMessageName(messageName," << endl
;
2509 out
<< indent() << "sequenceID: sequenceID," << endl
2510 << indent() << "ex: NSError(" << endl
;
2512 out
<< indent() << "domain: TApplicationErrorDomain, " << endl
2513 << indent() << "code: Int(TApplicationError.UnknownMethod.rawValue), " << endl
2514 << indent() << "userInfo: [TApplicationErrorMethodKey: messageName]))" << endl
;
2526 * Returns an Swift name
2528 * @param ttype The type
2529 * @param class_ref Do we want a Class reference istead of a type reference?
2530 * @return Swift type name, i.e. Dictionary<Key,Value>
2532 string
t_swift_generator::type_name(t_type
* ttype
, bool is_optional
, bool is_forced
) {
2535 if (ttype
->is_base_type()) {
2536 result
+= base_type_name((t_base_type
*)ttype
);
2537 } else if (ttype
->is_map()) {
2538 t_map
*map
= (t_map
*)ttype
;
2539 result
+= "TMap<" + type_name(map
->get_key_type()) + ", " + type_name(map
->get_val_type()) + ">";
2540 } else if (ttype
->is_set()) {
2541 t_set
*set
= (t_set
*)ttype
;
2542 result
+= "TSet<" + type_name(set
->get_elem_type()) + ">";
2543 } else if (ttype
->is_list()) {
2544 t_list
*list
= (t_list
*)ttype
;
2545 result
+= "TList<" + type_name(list
->get_elem_type()) + ">";
2548 t_program
* program
= ttype
->get_program();
2549 if (namespaced_
&& program
!= program_
) {
2550 result
+= get_real_swift_module(program
) + ".";
2552 result
+= ttype
->get_name();
2566 * Returns the Swift type that corresponds to the thrift type.
2568 * @param tbase The base type
2570 string
t_swift_generator::base_type_name(t_base_type
* type
) {
2571 t_base_type::t_base tbase
= type
->get_base();
2574 case t_base_type::TYPE_VOID
:
2576 case t_base_type::TYPE_STRING
:
2577 if (type
->is_binary()) {
2578 return gen_cocoa_
? "TBinary" : "Data";
2582 case t_base_type::TYPE_BOOL
:
2584 case t_base_type::TYPE_I8
:
2586 case t_base_type::TYPE_I16
:
2588 case t_base_type::TYPE_I32
:
2590 case t_base_type::TYPE_I64
:
2592 case t_base_type::TYPE_DOUBLE
:
2595 throw "compiler error: no Swift name for base type " + t_base_type::t_base_name(tbase
);
2600 * Renders full constant value (as would be seen after an '=')
2603 void t_swift_generator::render_const_value(ostream
& out
,
2605 t_const_value
* value
) {
2606 type
= get_true_type(type
);
2608 if (type
->is_base_type()) {
2609 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
2611 case t_base_type::TYPE_STRING
:
2612 out
<< "\"" << get_escaped_string(value
) << "\"";
2614 case t_base_type::TYPE_BOOL
:
2615 out
<< ((value
->get_integer() > 0) ? "true" : "false");
2617 case t_base_type::TYPE_I8
:
2618 case t_base_type::TYPE_I16
:
2619 case t_base_type::TYPE_I32
:
2620 case t_base_type::TYPE_I64
:
2621 out
<< type_name(type
) << "(" << value
->get_integer() << ")";
2623 case t_base_type::TYPE_DOUBLE
:
2624 out
<< type_name(type
) << "(";
2625 if (value
->get_type() == t_const_value::CV_INTEGER
) {
2626 out
<< value
->get_integer();
2628 out
<< value
->get_double();
2633 throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase
);
2635 } else if (type
->is_enum()) {
2636 out
<< (gen_cocoa_
? value
->get_identifier() : enum_const_name(value
->get_identifier())); // Swift2/Cocoa compatibility
2637 } else if (type
->is_struct() || type
->is_xception()) {
2639 out
<< type_name(type
) << "(";
2641 const vector
<t_field
*>& fields
= ((t_struct
*)type
)->get_members();
2642 vector
<t_field
*>::const_iterator f_iter
;
2644 const map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>& val
= value
->get_map();
2645 map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>::const_iterator v_iter
;
2647 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
2648 t_field
* tfield
= *f_iter
;
2649 t_const_value
* value
= NULL
;
2650 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
2651 if (tfield
->get_name() == v_iter
->first
->get_string()) {
2652 value
= v_iter
->second
;
2657 out
<< tfield
->get_name() << ": ";
2658 render_const_value(out
, tfield
->get_type(), value
);
2660 else if (!field_is_optional(tfield
)) {
2661 throw "constant error: required field " + type
->get_name() + "." + tfield
->get_name() + " has no value";
2664 if (++f_iter
!= fields
.end()) {
2671 } else if (type
->is_map()) {
2675 t_type
* ktype
= ((t_map
*)type
)->get_key_type();
2676 t_type
* vtype
= ((t_map
*)type
)->get_val_type();
2678 const map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>& val
= value
->get_map();
2679 map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>::const_iterator v_iter
;
2681 for (v_iter
= val
.begin(); v_iter
!= val
.end();) {
2683 render_const_value(out
, ktype
, v_iter
->first
);
2685 render_const_value(out
, vtype
, v_iter
->second
);
2687 if (++v_iter
!= val
.end()) {
2694 } else if (type
->is_list()) {
2698 t_type
* etype
= ((t_list
*)type
)->get_elem_type();
2700 const map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>& val
= value
->get_map();
2701 map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>::const_iterator v_iter
;
2703 for (v_iter
= val
.begin(); v_iter
!= val
.end();) {
2705 render_const_value(out
, etype
, v_iter
->first
);
2707 if (++v_iter
!= val
.end()) {
2714 } else if (type
->is_set()) {
2718 t_type
* etype
= ((t_set
*)type
)->get_elem_type();
2720 const map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>& val
= value
->get_map();
2721 map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>::const_iterator v_iter
;
2723 for (v_iter
= val
.begin(); v_iter
!= val
.end();) {
2725 render_const_value(out
, etype
, v_iter
->first
);
2727 if (++v_iter
!= val
.end()) {
2735 throw "compiler error: no const of type " + type
->get_name();
2741 * Declares an Swift property.
2743 * @param tfield The field to declare a property for
2745 string
t_swift_generator::declare_property(t_field
* tfield
, bool is_private
) {
2747 string visibility
= is_private
? (gen_cocoa_
? "private" : "fileprivate") : "public";
2749 ostringstream render
;
2751 render
<< visibility
<< " var " << maybe_escape_identifier(tfield
->get_name());
2753 if (field_is_optional(tfield
)) {
2754 render
<< (gen_cocoa_
? " " : "") << ": " << type_name(tfield
->get_type(), true);
2758 render
<< ": " << type_name(tfield
->get_type(), false);
2760 // Swift2/Cocoa backward compat, Bad, default init
2761 render
<< " = " << type_name(tfield
->get_type(), false) << "()";
2765 return render
.str();
2769 * Renders a function signature
2771 * @param tfunction Function definition
2772 * @return String of rendered function definition
2774 string
t_swift_generator::function_signature(t_function
* tfunction
) {
2776 string result
= "func " + (gen_cocoa_
? function_name(tfunction
) : tfunction
->get_name());
2778 result
+= "(" + argument_list(tfunction
->get_arglist(), "", false) + ") throws"; /// argsreview
2780 t_type
* ttype
= tfunction
->get_returntype();
2781 if (!ttype
->is_void()) {
2782 result
+= " -> " + type_name(ttype
);
2789 * Renders a function docstring
2791 * @param tfunction Function definition
2792 * @return String of rendered function definition
2794 void t_swift_generator::function_docstring(ostream
& out
, t_function
* tfunction
) {
2796 // Generate docstring with following format:
2797 // /// <Description>
2799 // /// - Parameters:
2800 // /// - <parameter>: <parameter docstring>
2801 // /// - Returns: <return type> (Thrift has no docstring on return val)
2802 // /// - Throws: <exception types>
2805 string doc
= tfunction
->get_doc();
2806 generate_docstring(out
, doc
);
2807 indent(out
) << "///" << endl
;
2810 const vector
<t_field
*>& fields
= tfunction
->get_arglist()->get_members();
2811 vector
<t_field
*>::const_iterator f_iter
;
2812 if (!fields
.empty()) {
2813 indent(out
) << "/// - Parameters:" << endl
;
2814 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
2815 indent(out
) << "/// - " << (*f_iter
)->get_name() << ": ";
2816 string doc
= (*f_iter
)->get_doc();
2817 if (!doc
.empty() && doc
[doc
.length()-1] == '\n') {
2818 doc
.erase(doc
.length()-1);
2825 t_type
* ttype
= tfunction
->get_returntype();
2826 if (!ttype
->is_void()) {
2827 indent(out
) << "/// - Returns: " << type_name(ttype
) << endl
;
2831 indent(out
) << "/// - Throws: ";
2832 t_struct
* xs
= tfunction
->get_xceptions();
2833 const vector
<t_field
*>& xceptions
= xs
->get_members();
2834 vector
<t_field
*>::const_iterator x_iter
;
2835 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
2836 out
<< type_name((*x_iter
)->get_type());
2837 if (*x_iter
!= xceptions
.back()) {
2844 * Renders a function docstring
2846 * @param tfunction Function definition
2847 * @return String of rendered function definition
2849 void t_swift_generator::async_function_docstring(ostream
& out
, t_function
* tfunction
) {
2850 // Generate docstring with following format:
2851 // /// <Description>
2853 // /// - Parameters:
2854 // /// - <parameter>: <parameter docstring>
2855 // /// - callback: <callback types>
2858 string doc
= tfunction
->get_doc();
2859 generate_docstring(out
, doc
);
2860 indent(out
) << "///" << endl
;
2863 const vector
<t_field
*>& fields
= tfunction
->get_arglist()->get_members();
2864 vector
<t_field
*>::const_iterator f_iter
;
2865 if (!fields
.empty()) {
2866 indent(out
) << "/// - Parameters:" << endl
;
2867 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
2868 indent(out
) << "/// - " << (*f_iter
)->get_name() << ": ";
2869 string doc
= (*f_iter
)->get_doc();
2870 if (!doc
.empty() && doc
[doc
.length()-1] == '\n') {
2871 doc
.erase(doc
.length()-1);
2878 indent(out
) << "/// - completion: TAsyncResult<" << type_name(tfunction
->get_returntype())
2879 << "> wrapping return and following Exceptions: ";
2880 t_struct
* xs
= tfunction
->get_xceptions();
2881 const vector
<t_field
*>& xceptions
= xs
->get_members();
2882 vector
<t_field
*>::const_iterator x_iter
;
2883 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
2884 out
<< type_name((*x_iter
)->get_type());
2885 if (*x_iter
!= xceptions
.back()) {
2893 * Renders a function signature that returns asynchronously via blocks.
2895 * @param tfunction Function definition
2896 * @return String of rendered function definition
2898 string
t_swift_generator::async_function_signature(t_function
* tfunction
) {
2899 t_type
* ttype
= tfunction
->get_returntype();
2900 t_struct
* targlist
= tfunction
->get_arglist();
2901 string result
= "func " + (gen_cocoa_
? function_name(tfunction
) : tfunction
->get_name());
2904 string response_string
= "(TAsyncResult<";
2905 response_string
+= (ttype
->is_void()) ? "Void" : type_name(ttype
);
2906 response_string
+= ">) -> Void";
2907 result
+= "(" + argument_list(tfunction
->get_arglist(), "", false)
2908 + (targlist
->get_members().size() ? ", " : "")
2909 + "completion: @escaping " + response_string
+ ")";
2911 string response_param
= "(" + ((ttype
->is_void()) ? "" : type_name(ttype
)) + ") -> Void";
2912 result
+= "(" + argument_list(tfunction
->get_arglist(), "", false)
2913 + (targlist
->get_members().size() ? ", " : "")
2914 + "success: " + response_param
+ ", "
2915 + "failure: (NSError) -> Void) throws";
2921 * Renders a function signature that returns asynchronously via promises.
2922 * ONLY FOR Swift2/Cocoa BACKWARDS COMPATIBILITY
2924 * @param tfunction Function definition
2925 * @return String of rendered function definition
2927 string
t_swift_generator::promise_function_signature(t_function
* tfunction
) {
2928 return "func " + function_name(tfunction
) + "(" + argument_list(tfunction
->get_arglist(), "", false) + ") throws "
2929 + "-> Promise<" + type_name(tfunction
->get_returntype()) + ">";
2933 * Renders a verbose function name suitable for a Swift method. ONLY FOR Swift2/Cocoa BACKWARDS COMPATIBILITY
2935 string
t_swift_generator::function_name(t_function
* tfunction
) {
2936 string name
= tfunction
->get_name();
2937 if (!tfunction
->get_arglist()->get_members().empty()) {
2938 string first_arg
= tfunction
->get_arglist()->get_members().front()->get_name();
2939 if (name
.size() < first_arg
.size() ||
2940 lowercase(name
.substr(name
.size()-first_arg
.size())) != lowercase(first_arg
)) {
2941 name
+= "With" + capitalize(tfunction
->get_arglist()->get_members()[0]->get_name());
2948 * Renders a Swift method argument list
2950 string
t_swift_generator::argument_list(t_struct
* tstruct
, string protocol_name
, bool is_internal
) {
2952 bool include_protocol
= !protocol_name
.empty();
2954 const vector
<t_field
*>& fields
= tstruct
->get_members();
2955 vector
<t_field
*>::const_iterator f_iter
;
2957 if (include_protocol
) {
2958 result
+= protocol_name
+ ": TProtocol";
2959 if (!fields
.empty()) {
2962 } else if (!fields
.empty() && is_internal
&& gen_cocoa_
) {
2963 // Force first argument to be named, Swift2/Cocoa backwards compat
2964 result
+= fields
.front()->get_name() + " ";
2967 for (f_iter
= fields
.begin(); f_iter
!= fields
.end();) {
2968 t_field
* arg
= *f_iter
;
2971 // optional args not usually permitted for some reason, even though dynamic langs handle it
2972 // use annotation "swift.nullable" to achieve
2973 result
+= arg
->get_name() + ": " + type_name(arg
->get_type(), field_is_optional(arg
));
2975 result
+= arg
->get_name() + ": " + type_name(arg
->get_type());
2978 if (++f_iter
!= fields
.end()) {
2986 * https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html
2990 void t_swift_generator::populate_reserved_words() {
2992 swift_reserved_words_
.insert("__COLUMN__");
2993 swift_reserved_words_
.insert("__FILE__");
2994 swift_reserved_words_
.insert("__FUNCTION__");
2995 swift_reserved_words_
.insert("__LINE__");
2996 swift_reserved_words_
.insert("Any");
2997 swift_reserved_words_
.insert("as");
2998 swift_reserved_words_
.insert("associatedtype");
2999 swift_reserved_words_
.insert("associativity");
3000 swift_reserved_words_
.insert("break");
3001 swift_reserved_words_
.insert("case");
3002 swift_reserved_words_
.insert("catch");
3003 swift_reserved_words_
.insert("class");
3004 swift_reserved_words_
.insert("continue");
3005 swift_reserved_words_
.insert("convenience");
3006 swift_reserved_words_
.insert("default");
3007 swift_reserved_words_
.insert("defer");
3008 swift_reserved_words_
.insert("deinit");
3009 swift_reserved_words_
.insert("didSet");
3010 swift_reserved_words_
.insert("do");
3011 swift_reserved_words_
.insert("dynamic");
3012 swift_reserved_words_
.insert("dynamicType");
3013 swift_reserved_words_
.insert("else");
3014 swift_reserved_words_
.insert("enum");
3015 swift_reserved_words_
.insert("extension");
3016 swift_reserved_words_
.insert("fallthrough");
3017 swift_reserved_words_
.insert("false");
3018 swift_reserved_words_
.insert("fileprivate");
3019 swift_reserved_words_
.insert("final");
3020 swift_reserved_words_
.insert("for");
3021 swift_reserved_words_
.insert("func");
3022 swift_reserved_words_
.insert("get");
3023 swift_reserved_words_
.insert("guard");
3024 swift_reserved_words_
.insert("if");
3025 swift_reserved_words_
.insert("import");
3026 swift_reserved_words_
.insert("in");
3027 swift_reserved_words_
.insert("indirect");
3028 swift_reserved_words_
.insert("infix");
3029 swift_reserved_words_
.insert("init");
3030 swift_reserved_words_
.insert("inout");
3031 swift_reserved_words_
.insert("internal");
3032 swift_reserved_words_
.insert("is");
3033 swift_reserved_words_
.insert("lazy");
3034 swift_reserved_words_
.insert("left");
3035 swift_reserved_words_
.insert("let");
3036 swift_reserved_words_
.insert("mutating");
3037 swift_reserved_words_
.insert("nil");
3038 swift_reserved_words_
.insert("none");
3039 swift_reserved_words_
.insert("nonmutating");
3040 swift_reserved_words_
.insert("open");
3041 swift_reserved_words_
.insert("operator");
3042 swift_reserved_words_
.insert("optional");
3043 swift_reserved_words_
.insert("override");
3044 swift_reserved_words_
.insert("postfix");
3045 swift_reserved_words_
.insert("precedence");
3046 swift_reserved_words_
.insert("prefix");
3047 swift_reserved_words_
.insert("private");
3048 swift_reserved_words_
.insert("protocol");
3049 swift_reserved_words_
.insert("Protocol");
3050 swift_reserved_words_
.insert("public");
3051 swift_reserved_words_
.insert("repeat");
3052 swift_reserved_words_
.insert("required");
3053 swift_reserved_words_
.insert("rethrows");
3054 swift_reserved_words_
.insert("return");
3055 swift_reserved_words_
.insert("right");
3056 swift_reserved_words_
.insert("self");
3057 swift_reserved_words_
.insert("Self");
3058 swift_reserved_words_
.insert("set");
3059 swift_reserved_words_
.insert("static");
3060 swift_reserved_words_
.insert("struct");
3061 swift_reserved_words_
.insert("subscript");
3062 swift_reserved_words_
.insert("super");
3063 swift_reserved_words_
.insert("switch");
3064 swift_reserved_words_
.insert("throw");
3065 swift_reserved_words_
.insert("throws");
3066 swift_reserved_words_
.insert("true");
3067 swift_reserved_words_
.insert("try");
3068 swift_reserved_words_
.insert("Type");
3069 swift_reserved_words_
.insert("typealias");
3070 swift_reserved_words_
.insert("unowned");
3071 swift_reserved_words_
.insert("var");
3072 swift_reserved_words_
.insert("weak");
3073 swift_reserved_words_
.insert("where");
3074 swift_reserved_words_
.insert("while");
3075 swift_reserved_words_
.insert("willSet");
3077 swift_reserved_words_
.insert("Self");
3078 swift_reserved_words_
.insert("associatedtype");
3079 swift_reserved_words_
.insert("defer");
3080 swift_reserved_words_
.insert("deinit");
3081 swift_reserved_words_
.insert("dynamicType");
3082 swift_reserved_words_
.insert("enum");
3083 swift_reserved_words_
.insert("extension");
3084 swift_reserved_words_
.insert("fallthrough");
3085 swift_reserved_words_
.insert("false");
3086 swift_reserved_words_
.insert("func");
3087 swift_reserved_words_
.insert("guard");
3088 swift_reserved_words_
.insert("init");
3089 swift_reserved_words_
.insert("inout");
3090 swift_reserved_words_
.insert("internal");
3091 swift_reserved_words_
.insert("let");
3092 swift_reserved_words_
.insert("operator");
3093 swift_reserved_words_
.insert("protocol");
3094 swift_reserved_words_
.insert("repeat");
3095 swift_reserved_words_
.insert("rethrows");
3096 swift_reserved_words_
.insert("struct");
3097 swift_reserved_words_
.insert("subscript");
3098 swift_reserved_words_
.insert("throws");
3099 swift_reserved_words_
.insert("true");
3100 swift_reserved_words_
.insert("typealias");
3101 swift_reserved_words_
.insert("where");
3105 string
t_swift_generator::maybe_escape_identifier(const string
& identifier
) {
3106 if (swift_reserved_words_
.find(identifier
) != swift_reserved_words_
.end()) {
3107 return "`" + identifier
+ "`";
3113 * Converts the parse type to a Swift TType enumeration.
3115 string
t_swift_generator::type_to_enum(t_type
* type
, bool qualified
) {
3116 type
= get_true_type(type
);
3118 string result
= qualified
? "TType." : ".";
3120 if (type
->is_base_type()) {
3121 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
3123 case t_base_type::TYPE_VOID
:
3124 throw "NO T_VOID CONSTRUCT";
3125 case t_base_type::TYPE_STRING
:
3126 return result
+ "string";
3127 case t_base_type::TYPE_BOOL
:
3128 return result
+ "bool";
3129 case t_base_type::TYPE_I8
:
3130 return result
+ "i8";
3131 case t_base_type::TYPE_I16
:
3132 return result
+ "i16";
3133 case t_base_type::TYPE_I32
:
3134 return result
+ "i32";
3135 case t_base_type::TYPE_I64
:
3136 return result
+ "i64";
3137 case t_base_type::TYPE_DOUBLE
:
3138 return result
+ "double";
3140 } else if (type
->is_enum()) {
3141 return result
+ "i32";
3142 } else if (type
->is_struct() || type
->is_xception()) {
3143 return result
+ "struct";
3144 } else if (type
->is_map()) {
3145 return result
+ "map";
3146 } else if (type
->is_set()) {
3147 return result
+ "set";
3148 } else if (type
->is_list()) {
3149 return result
+ "list";
3152 if (type
->is_base_type()) {
3153 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
3155 case t_base_type::TYPE_VOID
:
3156 throw "NO T_VOID CONSTRUCT";
3157 case t_base_type::TYPE_STRING
:
3158 return result
+ "STRING";
3159 case t_base_type::TYPE_BOOL
:
3160 return result
+ "BOOL";
3161 case t_base_type::TYPE_I8
:
3162 return result
+ "BYTE";
3163 case t_base_type::TYPE_I16
:
3164 return result
+ "I16";
3165 case t_base_type::TYPE_I32
:
3166 return result
+ "I32";
3167 case t_base_type::TYPE_I64
:
3168 return result
+ "I64";
3169 case t_base_type::TYPE_DOUBLE
:
3170 return result
+ "DOUBLE";
3172 } else if (type
->is_enum()) {
3173 return result
+ "I32";
3174 } else if (type
->is_struct() || type
->is_xception()) {
3175 return result
+ "STRUCT";
3176 } else if (type
->is_map()) {
3177 return result
+ "MAP";
3178 } else if (type
->is_set()) {
3179 return result
+ "SET";
3180 } else if (type
->is_list()) {
3181 return result
+ "LIST";
3185 throw "INVALID TYPE IN type_to_enum: " + type
->get_name();
3189 THRIFT_REGISTER_GENERATOR(
3192 " log_unexpected: Log every time an unexpected field ID or type is encountered.\n"
3193 " debug_descriptions:\n"
3194 " Allow use of debugDescription so the app can add description via a cateogory/extension\n"
3195 " async_clients: Generate clients which invoke asynchronously via block syntax.\n"
3196 " namespaced: Generate source in Module scoped output directories for Swift Namespacing.\n"
3197 " cocoa: Generate Swift 2.x code compatible with the Thrift/Cocoa library\n"
3198 " promise_kit: Generate clients which invoke asynchronously via promises (only use with cocoa flag)\n"
3199 " safe_enums: Generate enum types with an unknown case to handle unspecified values rather than throw a serialization error\n")