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
30 #include "thrift/platform.h"
31 #include "thrift/generate/t_oop_generator.h"
35 using std::ostringstream
;
37 using std::stringstream
;
40 static const string endl
= "\n"; // avoid ostream << std::endl flushes
41 static const string endl2
= "\n\n";
44 * Use the current Thrift version for static libraries. When releasing, update
45 * the version in these files.
46 * - lib/dart/pubspec.yaml
47 * - test/dart/test_client/pubspec.yaml
48 * - tutorial/dart/client/pubspec.yaml
49 * - tutorial/dart/console_client/pubspec.yaml
50 * - tutorial/dart/server/pubspec.yaml
51 * See https://thrift.apache.org/docs/committers/HowToVersion
53 static const string dart_thrift_version
= THRIFT_VERSION
;
55 /* forward declarations */
56 string
initial_caps_to_underscores(string name
);
62 class t_dart_generator
: public t_oop_generator
{
64 t_dart_generator(t_program
* program
,
65 const std::map
<std::string
, std::string
>& parsed_options
,
66 const std::string
& option_string
)
67 : t_oop_generator(program
) {
69 std::map
<std::string
, std::string
>::const_iterator iter
;
75 for( iter
= parsed_options
.begin(); iter
!= parsed_options
.end(); ++iter
) {
76 if( iter
->first
.compare("library_name") == 0) {
77 library_name_
= (iter
->second
);
78 } else if( iter
->first
.compare("library_prefix") == 0) {
79 library_prefix_
= (iter
->second
) + ".";
80 package_prefix_
= replace_all(library_prefix_
, ".", "/");
81 } else if( iter
->first
.compare("pubspec_lib") == 0) {
82 pubspec_lib_
= (iter
->second
);
84 throw "unknown option dart:" + iter
->first
;
88 out_dir_base_
= "gen-dart";
91 void scope_up(std::ostream
& out
, std::string prefix
=" ") {
92 out
<< prefix
<< "{" << endl
;
96 void scope_down(std::ostream
& out
, std::string postfix
=endl
) {
98 indent(out
) << "}" << postfix
;
101 string
replace_all(string contents
, string search
, string repl
) {
102 string
str(contents
);
104 size_t slen
= search
.length();
105 size_t rlen
= repl
.length();
106 size_t incr
= (rlen
> 0) ? rlen
: 1;
109 size_t found
= str
.find(search
);
110 while ((found
!= string::npos
) && (found
< str
.length())) {
111 str
.replace(found
, slen
, repl
);
112 found
= str
.find(search
, found
+ incr
);
121 * Init and close methods
124 void init_generator() override
;
125 void close_generator() override
;
127 void export_class_to_library(string file_name
, string class_name
);
129 void generate_dart_library();
130 void generate_dart_pubspec();
132 void generate_consts(std::vector
<t_const
*> consts
) override
;
135 * Program-level generation functions
138 void generate_typedef(t_typedef
* ttypedef
) override
;
139 void generate_enum(t_enum
* tenum
) override
;
140 void generate_struct(t_struct
* tstruct
) override
;
141 void generate_xception(t_struct
* txception
) override
;
142 void generate_service(t_service
* tservice
) override
;
144 void print_const_value(std::ostream
& out
,
147 t_const_value
* value
,
149 bool defval
= false);
150 std::string
render_const_value(ostream
& out
,
153 t_const_value
* value
);
156 * Service-level generation functions
159 void generate_dart_struct(t_struct
* tstruct
, bool is_exception
);
161 void generate_dart_struct_definition(std::ostream
& out
,
163 bool is_xception
= false,
164 bool is_result
= false,
165 string export_file_name
= "");
166 void generate_dart_struct_reader(std::ostream
& out
, t_struct
* tstruct
);
167 void generate_dart_validator(std::ostream
& out
, t_struct
* tstruct
);
168 void generate_dart_struct_result_writer(std::ostream
& out
, t_struct
* tstruct
);
169 void generate_dart_struct_writer(std::ostream
& out
, t_struct
* tstruct
);
170 void generate_dart_struct_tostring(std::ostream
& out
, t_struct
* tstruct
);
171 std::string
get_dart_type_string(t_type
* type
);
172 void generate_generic_field_getters(std::ostream
& out
, t_struct
* tstruct
);
173 void generate_generic_field_setters(std::ostream
& out
, t_struct
* tstruct
);
174 void generate_generic_isset_method(std::ostream
& out
, t_struct
* tstruct
);
175 void generate_dart_bean_boilerplate(std::ostream
& out
, t_struct
* tstruct
);
177 void generate_function_helpers(t_function
* tfunction
);
178 std::string
init_value(t_field
* tfield
);
179 std::string
get_cap_name(std::string name
);
180 std::string
get_member_name(std::string name
);
181 std::string
get_args_class_name(std::string name
);
182 std::string
get_result_class_name(std::string name
);
183 std::string
get_file_name(std::string name
);
184 std::string
get_constants_class_name(std::string name
);
185 std::string
generate_isset_check(t_field
* field
);
186 std::string
generate_isset_check(std::string field
);
187 void generate_isset_set(ostream
& out
, t_field
* field
);
189 void generate_service_interface(t_service
* tservice
);
190 void generate_service_helpers(t_service
* tservice
);
191 void generate_service_client(t_service
* tservice
);
192 void generate_service_server(t_service
* tservice
);
193 void generate_process_function(t_service
* tservice
, t_function
* tfunction
);
196 * Serialization constructs
199 void generate_deserialize_field(std::ostream
& out
, t_field
* tfield
, std::string prefix
= "");
201 void generate_deserialize_struct(std::ostream
& out
, t_struct
* tstruct
, std::string prefix
= "");
203 void generate_deserialize_container(std::ostream
& out
, t_type
* ttype
, std::string prefix
= "");
205 void generate_deserialize_set_element(std::ostream
& out
, t_set
* tset
, std::string prefix
= "");
207 void generate_deserialize_map_element(std::ostream
& out
, t_map
* tmap
, std::string prefix
= "");
209 void generate_deserialize_list_element(std::ostream
& out
,
211 std::string prefix
= "");
213 void generate_serialize_field(std::ostream
& out
, t_field
* tfield
, std::string prefix
= "");
215 void generate_serialize_struct(std::ostream
& out
, t_struct
* tstruct
, std::string prefix
= "");
217 void generate_serialize_container(std::ostream
& out
, t_type
* ttype
, std::string prefix
= "");
219 void generate_serialize_map_element(std::ostream
& out
,
224 void generate_serialize_set_element(std::ostream
& out
, t_set
* tmap
, std::string iter
);
226 void generate_serialize_list_element(std::ostream
& out
, t_list
* tlist
, std::string iter
);
228 void generate_dart_doc(std::ostream
& out
, t_doc
* tdoc
);
230 void generate_dart_doc(std::ostream
& out
, t_function
* tdoc
);
233 * Helper rendering functions
236 std::string
find_library_name(t_program
* program
);
237 std::string
dart_library(string file_name
);
238 std::string
service_imports();
239 std::string
dart_thrift_imports();
240 std::string
type_name(t_type
* ttype
);
241 std::string
base_type_name(t_base_type
* tbase
);
242 std::string
declare_field(t_field
* tfield
, bool init
= false);
243 std::string
function_signature(t_function
* tfunction
);
244 std::string
argument_list(t_struct
* tstruct
);
245 std::string
type_to_enum(t_type
* ttype
);
246 std::string
get_ttype_class_name(t_type
* ttype
);
248 bool type_can_be_null(t_type
* ttype
) {
249 ttype
= get_true_type(ttype
);
251 return ttype
->is_container() || ttype
->is_struct() || ttype
->is_xception()
252 || ttype
->is_string();
255 vector
<std::string
> split(const string
& s
, char delim
) {
256 vector
<std::string
> elems
;
259 while (getline(ss
, item
, delim
)) {
260 elems
.push_back(item
);
265 std::string
constant_name(std::string name
);
268 ofstream_with_content_based_conditional_update f_service_
;
270 std::string library_name_
;
271 std::string library_prefix_
;
272 std::string package_prefix_
;
273 std::string pubspec_lib_
;
275 std::string base_dir_
;
276 std::string src_dir_
;
277 std::string library_exports_
;
281 * Prepares for file generation by opening up the necessary file output
284 * @param tprogram The program to generate
286 void t_dart_generator::init_generator() {
287 MKDIR(get_out_dir().c_str());
289 if (library_name_
.empty()) {
290 library_name_
= find_library_name(program_
);
293 string subdir
= get_out_dir() + "/" + library_name_
;
294 MKDIR(subdir
.c_str());
297 if (library_prefix_
.empty()) {
299 MKDIR(subdir
.c_str());
301 MKDIR(subdir
.c_str());
304 src_dir_
= base_dir_
;
308 string
t_dart_generator::find_library_name(t_program
* program
) {
309 string name
= program
->get_namespace("dart");
311 name
= program
->get_name();
313 name
= replace_all(name
, ".", "_");
314 name
= replace_all(name
, "-", "_");
321 * @return String of the library, e.g. "library myservice;"
323 string
t_dart_generator::dart_library(string file_name
) {
324 string out
= "library " + library_prefix_
+ library_name_
;
325 if (!file_name
.empty()) {
326 if (library_prefix_
.empty()) {
327 out
+= ".src." + file_name
;
329 out
+= "." + file_name
;
336 * Prints imports for services
338 * @return List of imports for services
340 string
t_dart_generator::service_imports() {
341 return "import 'dart:async';" + endl
;
345 * Prints standard dart imports
347 * @return List of imports necessary for thrift
349 string
t_dart_generator::dart_thrift_imports() {
350 string imports
= "import 'dart:typed_data' show Uint8List;" + endl
+
351 "import 'package:thrift/thrift.dart';" + endl
;
353 // add import for this library
354 if (package_prefix_
.empty()) {
355 imports
+= "import 'package:" + library_name_
+ "/" + library_name_
+ ".dart';" + endl
;
357 imports
+= "import 'package:" + package_prefix_
+ library_name_
+ ".dart';" + endl
;
360 // add imports for included thrift files
361 const vector
<t_program
*>& includes
= program_
->get_includes();
362 for (auto include
: includes
) {
363 string include_name
= find_library_name(include
);
364 string named_import
= "t_" + include_name
;
365 if (package_prefix_
.empty()) {
366 imports
+= "import 'package:" + include_name
+ "/" + include_name
+ ".dart' as " + named_import
+ ";" + endl
;
368 imports
+= "import 'package:" + package_prefix_
+ include_name
+ ".dart' as " + named_import
+ ";" + endl
;
378 void t_dart_generator::close_generator() {
379 generate_dart_library();
381 if (library_prefix_
.empty()) {
382 generate_dart_pubspec();
386 void t_dart_generator::generate_dart_library() {
387 string f_library_name
;
388 if (library_prefix_
.empty()) {
389 f_library_name
= base_dir_
+ "/lib/" + library_name_
+ ".dart";
391 f_library_name
= get_out_dir() + "/" + library_name_
+ ".dart";
394 ofstream_with_content_based_conditional_update f_library
;
395 f_library
.open(f_library_name
.c_str());
397 f_library
<< autogen_comment() << endl
;
398 f_library
<< "library " << library_prefix_
<< library_name_
<< ";" << endl2
;
399 f_library
<< library_exports_
;
404 void t_dart_generator::export_class_to_library(string file_name
, string class_name
) {
406 if (library_prefix_
.empty()) {
409 subdir
= library_name_
;
411 library_exports_
+= "export '" + subdir
+ "/" + file_name
+ ".dart' show " + class_name
+ ";" + endl
;
414 void t_dart_generator::generate_dart_pubspec() {
415 string f_pubspec_name
= base_dir_
+ "/pubspec.yaml";
416 ofstream_with_content_based_conditional_update f_pubspec
;
417 f_pubspec
.open(f_pubspec_name
.c_str());
419 indent(f_pubspec
) << "name: " << library_name_
<< endl
;
420 indent(f_pubspec
) << "version: 0.0.1" << endl
;
421 indent(f_pubspec
) << "description: Autogenerated by Thrift Compiler" << endl
;
424 indent(f_pubspec
) << "environment:" << endl
;
426 indent(f_pubspec
) << "sdk: '>=1.24.3 <3.0.0'" << endl
;
430 indent(f_pubspec
) << "dependencies:" << endl
;
433 if (pubspec_lib_
.empty()) {
434 // default to relative path within working directory, which works for tests
435 indent(f_pubspec
) << "thrift: # ^" << dart_thrift_version
<< endl
;
437 indent(f_pubspec
) << "path: ../../../../lib/dart" << endl
;
440 const vector
<std::string
> lines
= split(pubspec_lib_
, '|');
441 for (const auto & line
: lines
) {
442 indent(f_pubspec
) << line
<< endl
;
446 // add included thrift files as dependencies
447 const vector
<t_program
*>& includes
= program_
->get_includes();
448 for (auto include
: includes
) {
449 string include_name
= find_library_name(include
);
450 indent(f_pubspec
) << include_name
<< ":" << endl
;
452 indent(f_pubspec
) << "path: ../" << include_name
<< endl
;
465 * @param ttypedef The type definition
467 void t_dart_generator::generate_typedef(t_typedef
* ttypedef
) {
472 * Enums are a class with a set of static constants.
474 * @param tenum The enumeration
476 void t_dart_generator::generate_enum(t_enum
* tenum
) {
478 string file_name
= get_file_name(tenum
->get_name());
480 string f_enum_name
= src_dir_
+ "/" + file_name
+ ".dart";
481 ofstream_with_content_based_conditional_update f_enum
;
482 f_enum
.open(f_enum_name
.c_str());
484 // Comment and add library
485 f_enum
<< autogen_comment() << dart_library(file_name
) << endl
;
487 string class_name
= tenum
->get_name();
488 export_class_to_library(file_name
, class_name
);
489 f_enum
<< "class " << class_name
;
492 vector
<t_enum_value
*> constants
= tenum
->get_constants();
493 vector
<t_enum_value
*>::iterator c_iter
;
494 for (c_iter
= constants
.begin(); c_iter
!= constants
.end(); ++c_iter
) {
495 int value
= (*c_iter
)->get_value();
496 indent(f_enum
) << "static const int " << (*c_iter
)->get_name() << " = " << value
<< ";"
500 // Create a static Set with all valid values for this enum
503 indent(f_enum
) << "static final Set<int> VALID_VALUES = new Set.from([" << endl
;
505 bool firstValue
= true;
506 for (c_iter
= constants
.begin(); c_iter
!= constants
.end(); ++c_iter
) {
508 indent(f_enum
) << (firstValue
? "" : ", ");
509 f_enum
<< (*c_iter
)->get_name() << endl
;
513 indent(f_enum
) << "]);" << endl
;
515 indent(f_enum
) << "static final Map<int, String> VALUES_TO_NAMES = {" << endl
;
518 for (c_iter
= constants
.begin(); c_iter
!= constants
.end(); ++c_iter
) {
519 indent(f_enum
) << (firstValue
? "" : ", ");
520 f_enum
<< (*c_iter
)->get_name() << ": '" << (*c_iter
)->get_name() << "'" << endl
;
524 indent(f_enum
) << "};" << endl
;
526 scope_down(f_enum
); // end class
532 * Generates a class that holds all the constants.
534 void t_dart_generator::generate_consts(std::vector
<t_const
*> consts
) {
535 if (consts
.empty()) {
539 string class_name
= get_constants_class_name(program_name_
);
540 string file_name
= get_file_name(class_name
);
542 string f_consts_name
= src_dir_
+ "/" + file_name
+ ".dart";
543 ofstream_with_content_based_conditional_update f_consts
;
544 f_consts
.open(f_consts_name
.c_str());
547 f_consts
<< autogen_comment() << dart_library(file_name
) << endl
;
548 f_consts
<< dart_thrift_imports() << endl
;
550 export_class_to_library(file_name
, class_name
);
551 indent(f_consts
) << "class " << class_name
;
554 vector
<t_const
*>::iterator c_iter
;
555 for (c_iter
= consts
.begin(); c_iter
!= consts
.end(); ++c_iter
) {
556 print_const_value(f_consts
,
557 (*c_iter
)->get_name(),
558 (*c_iter
)->get_type(),
559 (*c_iter
)->get_value(),
564 scope_down(f_consts
);
569 void t_dart_generator::print_const_value(std::ostream
& out
,
572 t_const_value
* value
,
575 type
= get_true_type(type
);
579 out
<< (in_static
? "var " : "static final ");
581 if (type
->is_base_type()) {
583 out
<< type_name(type
) << " ";
585 string v2
= render_const_value(out
, name
, type
, value
);
587 out
<< " = " << v2
<< ";" << endl
<< endl
;
588 } else if (type
->is_enum()) {
590 out
<< type_name(type
) << " ";
593 out
<< " = " << value
->get_integer() << ";" << endl
<< endl
;
594 } else if (type
->is_struct() || type
->is_xception()) {
595 const vector
<t_field
*>& fields
= ((t_struct
*)type
)->get_members();
596 vector
<t_field
*>::const_iterator f_iter
;
597 const map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>& val
= value
->get_map();
598 map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>::const_iterator v_iter
;
599 out
<< type_name(type
) << " " << name
<< " = new " << type_name(type
) << "()";
601 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
602 t_type
* field_type
= NULL
;
603 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
604 if ((*f_iter
)->get_name() == v_iter
->first
->get_string()) {
605 field_type
= (*f_iter
)->get_type();
608 if (field_type
== NULL
) {
609 throw "type error: " + type
->get_name() + " has no field " + v_iter
->first
->get_string();
611 string val
= render_const_value(out
, name
, field_type
, v_iter
->second
);
613 indent(out
) << ".." << v_iter
->first
->get_string() << " = " << val
;
617 } else if (type
->is_map()) {
619 out
<< type_name(type
) << " ";
624 t_type
* ktype
= ((t_map
*)type
)->get_key_type();
625 t_type
* vtype
= ((t_map
*)type
)->get_val_type();
626 const map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>& val
= value
->get_map();
627 map
<t_const_value
*, t_const_value
*, t_const_value::value_compare
>::const_iterator v_iter
;
629 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
630 string key
= render_const_value(out
, name
, ktype
, v_iter
->first
);
631 string val
= render_const_value(out
, name
, vtype
, v_iter
->second
);
632 indent(out
) << key
<< ": " << val
<< "," << endl
;
634 scope_down(out
, ";" + endl
);
637 } else if (type
->is_list() || type
->is_set()) {
639 out
<< type_name(type
) << " ";
641 out
<< name
<< " = ";
643 if (type
->is_list()) {
645 etype
= ((t_list
*)type
)->get_elem_type();
647 out
<< "new " << type_name(type
) << ".from([" << endl
;
648 etype
= ((t_set
*)type
)->get_elem_type();
650 const vector
<t_const_value
*>& val
= value
->get_list();
651 vector
<t_const_value
*>::const_iterator v_iter
;
654 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
655 string val
= render_const_value(out
, name
, etype
, *v_iter
);
656 indent(out
) << val
<< "," << endl
;
660 if (type
->is_list()) {
661 indent(out
) << "];" << endl
;
663 indent(out
) << "]);" << endl
;
667 throw "compiler error: no const of type " + type
->get_name();
671 string
t_dart_generator::render_const_value(ostream
& out
,
674 t_const_value
* value
) {
676 type
= get_true_type(type
);
677 std::ostringstream render
;
679 if (type
->is_base_type()) {
680 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
682 case t_base_type::TYPE_STRING
:
683 render
<< "'" << get_escaped_string(value
) << "'";
685 case t_base_type::TYPE_BOOL
:
686 render
<< ((value
->get_integer() > 0) ? "true" : "false");
688 case t_base_type::TYPE_I8
:
689 case t_base_type::TYPE_I16
:
690 case t_base_type::TYPE_I32
:
691 case t_base_type::TYPE_I64
:
692 render
<< value
->get_integer();
694 case t_base_type::TYPE_DOUBLE
:
695 if (value
->get_type() == t_const_value::CV_INTEGER
) {
696 render
<< value
->get_integer();
698 render
<< value
->get_double();
702 throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase
);
704 } else if (type
->is_enum()) {
705 render
<< value
->get_integer();
707 string t
= tmp("tmp");
708 print_const_value(out
, t
, type
, value
, true);
717 * Generates a struct definition for a thrift data type. This is a class
718 * with data members, read(), write(), and an inner Isset class.
720 * @param tstruct The struct definition
722 void t_dart_generator::generate_struct(t_struct
* tstruct
) {
723 generate_dart_struct(tstruct
, false);
727 * Exceptions are structs, but they inherit from Exception
729 * @param tstruct The struct definition
731 void t_dart_generator::generate_xception(t_struct
* txception
) {
732 generate_dart_struct(txception
, true);
736 * Dart struct definition.
738 * @param tstruct The struct definition
740 void t_dart_generator::generate_dart_struct(t_struct
* tstruct
, bool is_exception
) {
741 string file_name
= get_file_name(tstruct
->get_name());
742 string f_struct_name
= src_dir_
+ "/" + file_name
+ ".dart";
743 ofstream_with_content_based_conditional_update f_struct
;
744 f_struct
.open(f_struct_name
.c_str());
746 f_struct
<< autogen_comment() << dart_library(file_name
) << endl
;
750 f_struct
<< dart_thrift_imports() << endl
;
752 generate_dart_struct_definition(f_struct
, tstruct
, is_exception
, false, file_name
);
758 * Dart struct definition. This has various parameters, as it could be
759 * generated standalone or inside another class as a helper. If it
760 * is a helper than it is a static class.
762 * @param tstruct The struct definition
763 * @param is_exception Is this an exception?
764 * @param in_class If inside a class, needs to be static class
765 * @param is_result If this is a result it needs a different writer
767 void t_dart_generator::generate_dart_struct_definition(ostream
& out
,
771 string export_file_name
) {
772 generate_dart_doc(out
, tstruct
);
774 string class_name
= tstruct
->get_name();
775 if (!export_file_name
.empty()) {
776 export_class_to_library(export_file_name
, class_name
);
778 indent(out
) << "class " << class_name
<< " ";
780 out
<< "implements TBase";
782 out
<< ", Exception ";
786 indent(out
) << "static final TStruct _STRUCT_DESC = new TStruct(\"" << class_name
789 // Members are public for -dart, private for -dartbean
790 const vector
<t_field
*>& members
= tstruct
->get_members();
791 vector
<t_field
*>::const_iterator m_iter
;
793 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
794 indent(out
) << "static final TField _" << constant_name((*m_iter
)->get_name())
795 << "_FIELD_DESC = new TField(\"" << (*m_iter
)->get_name() << "\", "
796 << type_to_enum((*m_iter
)->get_type()) << ", " << (*m_iter
)->get_key() << ");"
802 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
803 generate_dart_doc(out
, *m_iter
);
804 indent(out
) << type_name((*m_iter
)->get_type()) + " _"
805 << get_member_name((*m_iter
)->get_name()) << init_value(*m_iter
) << ";" << endl
;
807 indent(out
) << "static const int " << upcase_string((*m_iter
)->get_name())
808 << " = " << (*m_iter
)->get_key() << ";" << endl
;
814 if (members
.size() > 0) {
815 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
816 if (!type_can_be_null((*m_iter
)->get_type())) {
817 string field_name
= get_member_name((*m_iter
)->get_name());
818 indent(out
) << "bool __isset_" << field_name
<< " = false;" << endl
;
825 // Default constructor
826 indent(out
) << tstruct
->get_name() << "()";
828 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
829 t_type
* t
= get_true_type((*m_iter
)->get_type());
830 if ((*m_iter
)->get_value() != NULL
) {
831 print_const_value(out
,
832 "this." + get_member_name((*m_iter
)->get_name()),
834 (*m_iter
)->get_value(),
842 generate_dart_bean_boilerplate(out
, tstruct
);
843 generate_generic_field_getters(out
, tstruct
);
844 generate_generic_field_setters(out
, tstruct
);
845 generate_generic_isset_method(out
, tstruct
);
847 generate_dart_struct_reader(out
, tstruct
);
849 generate_dart_struct_result_writer(out
, tstruct
);
851 generate_dart_struct_writer(out
, tstruct
);
853 generate_dart_struct_tostring(out
, tstruct
);
854 generate_dart_validator(out
, tstruct
);
860 * Generates a function to read all the fields of the struct.
862 * @param tstruct The struct definition
864 void t_dart_generator::generate_dart_struct_reader(ostream
& out
, t_struct
* tstruct
) {
865 indent(out
) << "read(TProtocol iprot)";
868 const vector
<t_field
*>& fields
= tstruct
->get_members();
869 vector
<t_field
*>::const_iterator f_iter
;
871 // Declare stack tmp variables and read struct header
872 indent(out
) << "TField field;" << endl
;
873 indent(out
) << "iprot.readStructBegin();" << endl
;
875 // Loop over reading in fields
876 indent(out
) << "while (true)";
879 // Read beginning field marker
880 indent(out
) << "field = iprot.readFieldBegin();" << endl
;
882 // Check for field STOP marker and break
883 indent(out
) << "if (field.type == TType.STOP)";
885 indent(out
) << "break;" << endl
;
888 // Switch statement on the field we are reading
889 indent(out
) << "switch (field.id)";
892 // Generate deserialization code for known cases
893 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
894 indent(out
) << "case " << upcase_string((*f_iter
)->get_name()) << ":" << endl
;
897 indent(out
) << "if (field.type == " << type_to_enum((*f_iter
)->get_type()) << ")";
900 generate_deserialize_field(out
, *f_iter
, "this.");
901 generate_isset_set(out
, *f_iter
);
903 scope_down(out
, " else");
905 indent(out
) << "TProtocolUtil.skip(iprot, field.type);" << endl
;
908 indent(out
) << "break;" << endl
;
912 // In the default case we skip the field
913 indent(out
) << "default:" << endl
;
915 indent(out
) << "TProtocolUtil.skip(iprot, field.type);" << endl
;
916 indent(out
) << "break;" << endl
;
921 // Read field end marker
922 indent(out
) << "iprot.readFieldEnd();" << endl
;
926 indent(out
) << "iprot.readStructEnd();" << endl2
;
928 // in non-beans style, check for required fields of primitive type
929 // (which can be checked here but not in the general validate method)
930 indent(out
) << "// check for required fields of primitive type, which can't be "
931 "checked in the validate method" << endl
;
932 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
933 if ((*f_iter
)->get_req() == t_field::T_REQUIRED
&& !type_can_be_null((*f_iter
)->get_type())) {
934 string field_name
= get_member_name((*f_iter
)->get_name());
935 indent(out
) << "if (!__isset_" << field_name
<< ")";
937 indent(out
) << " throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"Required field '"
939 << "' was not found in serialized data! Struct: \" + toString());" << endl
;
940 scope_down(out
, endl2
);
944 // performs various checks (e.g. check that all required fields are set)
945 indent(out
) << "validate();" << endl
;
947 scope_down(out
, endl2
);
950 // generates dart method to perform various checks
951 // (e.g. check that all required fields are set)
952 void t_dart_generator::generate_dart_validator(ostream
& out
, t_struct
* tstruct
) {
953 indent(out
) << "validate()";
956 const vector
<t_field
*>& fields
= tstruct
->get_members();
957 vector
<t_field
*>::const_iterator f_iter
;
959 indent(out
) << "// check for required fields" << endl
;
960 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
961 if ((*f_iter
)->get_req() == t_field::T_REQUIRED
) {
962 string field_name
= get_member_name((*f_iter
)->get_name());
963 if (type_can_be_null((*f_iter
)->get_type())) {
964 indent(out
) << "if (" << field_name
<< " == null)";
966 indent(out
) << "throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"Required field '"
967 << field_name
<< "' was not present! Struct: \" + toString());"
971 indent(out
) << "// alas, we cannot check '" << field_name
972 << "' because it's a primitive and you chose the non-beans generator." << endl
;
977 // check that fields of type enum have valid values
978 indent(out
) << "// check that fields of type enum have valid values" << endl
;
979 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
980 t_field
* field
= (*f_iter
);
981 t_type
* type
= field
->get_type();
982 // if field is an enum, check that its value is valid
983 if (type
->is_enum()) {
984 string field_name
= get_member_name(field
->get_name());
985 indent(out
) << "if (" << generate_isset_check(field
) << " && !" << get_ttype_class_name(type
)
986 << ".VALID_VALUES.contains(" << field_name
<< "))";
988 indent(out
) << "throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"The field '"
989 << field_name
<< "' has been assigned the invalid value "
990 << "$" << field_name
<< "\");" << endl
;
995 scope_down(out
, endl2
);
999 * Generates a function to write all the fields of the struct
1001 * @param tstruct The struct definition
1003 void t_dart_generator::generate_dart_struct_writer(ostream
& out
, t_struct
* tstruct
) {
1004 out
<< indent() << "write(TProtocol oprot)";
1007 const vector
<t_field
*>& fields
= tstruct
->get_sorted_members();
1008 vector
<t_field
*>::const_iterator f_iter
;
1010 // performs various checks (e.g. check that all required fields are set)
1011 indent(out
) << "validate();" << endl2
;
1013 indent(out
) << "oprot.writeStructBegin(_STRUCT_DESC);" << endl
;
1015 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1016 string field_name
= get_member_name((*f_iter
)->get_name());
1017 bool could_be_unset
= (*f_iter
)->get_req() == t_field::T_OPTIONAL
;
1018 if (could_be_unset
) {
1019 indent(out
) << "if (" << generate_isset_check(*f_iter
) << ")";
1022 bool null_allowed
= type_can_be_null((*f_iter
)->get_type());
1024 indent(out
) << "if (this." << field_name
<< " != null)";
1028 indent(out
) << "oprot.writeFieldBegin(_" << constant_name((*f_iter
)->get_name())
1029 << "_FIELD_DESC);" << endl
;
1031 // Write field contents
1032 generate_serialize_field(out
, *f_iter
, "this.");
1034 // Write field closer
1035 indent(out
) << "oprot.writeFieldEnd();" << endl
;
1040 if (could_be_unset
) {
1044 // Write the struct map
1045 indent(out
) << "oprot.writeFieldStop();" << endl
<< indent() << "oprot.writeStructEnd();"
1048 scope_down(out
, endl2
);
1052 * Generates a function to write all the fields of the struct,
1053 * which is a function result. These fields are only written
1054 * if they are set in the Isset array, and only one of them
1055 * can be set at a time.
1057 * @param tstruct The struct definition
1059 void t_dart_generator::generate_dart_struct_result_writer(ostream
& out
, t_struct
* tstruct
) {
1060 indent(out
) << "write(TProtocol oprot)";
1063 const vector
<t_field
*>& fields
= tstruct
->get_sorted_members();
1064 vector
<t_field
*>::const_iterator f_iter
;
1066 indent(out
) << "oprot.writeStructBegin(_STRUCT_DESC);" << endl2
;
1069 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1072 indent(out
) << "if ";
1077 out
<< "(this." << generate_isset_check(*f_iter
) << ")";
1080 indent(out
) << "oprot.writeFieldBegin(_" << constant_name((*f_iter
)->get_name())
1081 << "_FIELD_DESC);" << endl
;
1083 // Write field contents
1084 generate_serialize_field(out
, *f_iter
, "this.");
1086 // Write field closer
1087 indent(out
) << "oprot.writeFieldEnd();" << endl
;
1089 scope_down(out
, "");
1093 // Write the struct map
1094 indent(out
) << "oprot.writeFieldStop();" << endl
<< indent()
1095 << "oprot.writeStructEnd();" << endl
;
1097 scope_down(out
, endl2
);
1100 void t_dart_generator::generate_generic_field_getters(std::ostream
& out
,
1101 t_struct
* tstruct
) {
1102 // create the getter
1103 indent(out
) << "getFieldValue(int fieldID)";
1106 indent(out
) << "switch (fieldID)";
1109 const vector
<t_field
*>& fields
= tstruct
->get_members();
1110 vector
<t_field
*>::const_iterator f_iter
;
1111 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1112 t_field
* field
= *f_iter
;
1113 std::string field_name
= get_member_name(field
->get_name());
1115 indent(out
) << "case " << upcase_string(field_name
) << ":" << endl
;
1117 indent(out
) << "return this." << field_name
<< ";" << endl
;
1121 indent(out
) << "default:" << endl
;
1123 indent(out
) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl
;
1126 scope_down(out
); // switch
1127 scope_down(out
, endl2
); // method
1130 void t_dart_generator::generate_generic_field_setters(std::ostream
& out
,
1131 t_struct
* tstruct
) {
1133 // create the setter
1134 indent(out
) << "setFieldValue(int fieldID, Object value)";
1137 indent(out
) << "switch (fieldID)";
1140 // build up the bodies of both the getter and setter at once
1141 const vector
<t_field
*>& fields
= tstruct
->get_members();
1142 vector
<t_field
*>::const_iterator f_iter
;
1143 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1144 t_field
* field
= *f_iter
;
1145 std::string field_name
= get_member_name(field
->get_name());
1147 indent(out
) << "case " << upcase_string(field_name
) << ":" << endl
;
1150 indent(out
) << "if (value == null)";
1152 indent(out
) << "unset" << get_cap_name(field_name
) << "();" << endl
;
1154 scope_down(out
, " else");
1156 indent(out
) << "this." << field_name
<< " = value;" << endl
;
1159 indent(out
) << "break;" << endl
;
1165 indent(out
) << "default:" << endl
;
1167 indent(out
) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl
;
1170 scope_down(out
); // switch
1171 scope_down(out
, endl2
); // method
1174 // Creates a generic isSet method that takes the field number as argument
1175 void t_dart_generator::generate_generic_isset_method(std::ostream
& out
, t_struct
* tstruct
) {
1176 const vector
<t_field
*>& fields
= tstruct
->get_members();
1177 vector
<t_field
*>::const_iterator f_iter
;
1179 // create the isSet method
1180 indent(out
) << "// Returns true if field corresponding to fieldID is set (has been assigned a "
1181 "value) and false otherwise" << endl
;
1182 indent(out
) << "bool isSet(int fieldID)";
1185 indent(out
) << "switch (fieldID)";
1188 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1189 t_field
* field
= *f_iter
;
1190 indent(out
) << "case " << upcase_string(field
->get_name()) << ":" << endl
;
1192 indent(out
) << "return " << generate_isset_check(field
) << ";" << endl
;
1196 indent(out
) << "default:" << endl
;
1198 indent(out
) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl
;
1201 scope_down(out
); // switch
1202 scope_down(out
, endl2
); // method
1206 * Generates a set of Dart Bean boilerplate functions (setters, getters, etc.)
1207 * for the given struct.
1209 * @param tstruct The struct definition
1211 void t_dart_generator::generate_dart_bean_boilerplate(ostream
& out
,
1212 t_struct
* tstruct
) {
1213 const vector
<t_field
*>& fields
= tstruct
->get_members();
1214 vector
<t_field
*>::const_iterator f_iter
;
1215 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1216 t_field
* field
= *f_iter
;
1217 t_type
* type
= get_true_type(field
->get_type());
1218 std::string field_name
= get_member_name(field
->get_name());
1219 std::string cap_name
= get_cap_name(field_name
);
1221 indent(out
) << "// " << field_name
<< endl
;
1224 generate_dart_doc(out
, field
);
1225 indent(out
) << type_name(type
) << " get " << field_name
<< " => this._" << field_name
<< ";" << endl2
;
1228 generate_dart_doc(out
, field
);
1229 indent(out
) << "set " << field_name
<< "(" << type_name(type
) << " " << field_name
<< ")";
1231 indent(out
) << "this._" << field_name
<< " = " << field_name
<< ";" << endl
;
1232 generate_isset_set(out
, field
);
1233 scope_down(out
, endl2
);
1236 indent(out
) << "bool is" << get_cap_name("set") << cap_name
<< "()";
1237 if (type_can_be_null(type
)) {
1238 out
<< " => this." << field_name
<< " != null;" << endl2
;
1240 out
<< " => this.__isset_" << field_name
<< ";" << endl2
;
1244 indent(out
) << "unset" << cap_name
<< "()";
1246 if (type_can_be_null(type
)) {
1247 indent(out
) << "this." << field_name
<< " = null;" << endl
;
1249 indent(out
) << "this.__isset_" << field_name
<< " = false;" << endl
;
1251 scope_down(out
, endl2
);
1256 * Generates a toString() method for the given struct
1258 * @param tstruct The struct definition
1260 void t_dart_generator::generate_dart_struct_tostring(ostream
& out
,
1261 t_struct
* tstruct
) {
1262 indent(out
) << "String toString()";
1265 indent(out
) << "StringBuffer ret = new StringBuffer(\""
1266 << tstruct
->get_name() << "(\");" << endl2
;
1268 const vector
<t_field
*>& fields
= tstruct
->get_members();
1269 vector
<t_field
*>::const_iterator f_iter
;
1272 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1273 bool could_be_unset
= (*f_iter
)->get_req() == t_field::T_OPTIONAL
;
1274 if (could_be_unset
) {
1275 indent(out
) << "if (" << generate_isset_check(*f_iter
) << ")";
1279 t_field
* field
= (*f_iter
);
1280 std::string field_name
= get_member_name(field
->get_name());
1283 indent(out
) << "ret.write(\", \");" << endl
;
1285 indent(out
) << "ret.write(\"" << field_name
<< ":\");" << endl
;
1286 bool can_be_null
= type_can_be_null(field
->get_type());
1288 indent(out
) << "if (this." << field_name
<< " == null)";
1290 indent(out
) << "ret.write(\"null\");" << endl
;
1291 scope_down(out
, " else");
1295 if (field
->get_type()->is_binary()) {
1296 indent(out
) << "ret.write(\"BINARY\");" << endl
;
1297 } else if (field
->get_type()->is_enum()) {
1298 indent(out
) << "String " << field_name
<< "_name = "
1299 << get_ttype_class_name(field
->get_type())
1300 << ".VALUES_TO_NAMES[this." << field_name
<< "];" << endl
;
1301 indent(out
) << "if (" << field_name
<< "_name != null)";
1303 indent(out
) << "ret.write(" << field_name
<< "_name);" << endl
;
1304 indent(out
) << "ret.write(\" (\");" << endl
;
1306 indent(out
) << "ret.write(this." << field_name
<< ");" << endl
;
1307 indent(out
) << "if (" << field_name
<< "_name != null)";
1309 indent(out
) << "ret.write(\")\");" << endl
;
1312 indent(out
) << "ret.write(this." << field_name
<< ");" << endl
;
1318 if (could_be_unset
) {
1326 indent(out
) << "ret.write(\")\");" << endl2
;
1328 indent(out
) << "return ret.toString();" << endl
;
1330 scope_down(out
, endl2
);
1334 * Returns a string with the dart representation of the given thrift type
1335 * (e.g. for the type struct it returns "TType.STRUCT")
1337 std::string
t_dart_generator::get_dart_type_string(t_type
* type
) {
1338 if (type
->is_list()) {
1339 return "TType.LIST";
1340 } else if (type
->is_map()) {
1342 } else if (type
->is_set()) {
1344 } else if (type
->is_struct() || type
->is_xception()) {
1345 return "TType.STRUCT";
1346 } else if (type
->is_enum()) {
1348 } else if (type
->is_typedef()) {
1349 return get_dart_type_string(((t_typedef
*)type
)->get_type());
1350 } else if (type
->is_base_type()) {
1351 switch (((t_base_type
*)type
)->get_base()) {
1352 case t_base_type::TYPE_VOID
:
1353 return "TType.VOID";
1355 case t_base_type::TYPE_STRING
:
1356 return "TType.STRING";
1358 case t_base_type::TYPE_BOOL
:
1359 return "TType.BOOL";
1361 case t_base_type::TYPE_I8
:
1362 return "TType.BYTE";
1364 case t_base_type::TYPE_I16
:
1367 case t_base_type::TYPE_I32
:
1370 case t_base_type::TYPE_I64
:
1373 case t_base_type::TYPE_DOUBLE
:
1374 return "TType.DOUBLE";
1377 throw std::runtime_error("Unknown thrift type \"" + type
->get_name()
1378 + "\" passed to t_dart_generator::get_dart_type_string!");
1379 break; // This should never happen!
1382 throw std::runtime_error(
1383 "Unknown thrift type \"" + type
->get_name()
1384 + "\" passed to t_dart_generator::get_dart_type_string!"); // This should never happen!
1388 void t_dart_generator::generate_service(t_service
* tservice
) {
1389 string file_name
= get_file_name(service_name_
);
1390 string f_service_name
= src_dir_
+ "/" + file_name
+ ".dart";
1391 f_service_
.open(f_service_name
.c_str());
1393 f_service_
<< autogen_comment() << dart_library(file_name
) << endl
;
1394 f_service_
<< service_imports() << dart_thrift_imports() << endl
;
1397 generate_service_interface(tservice
);
1398 generate_service_client(tservice
);
1399 generate_service_server(tservice
);
1400 generate_service_helpers(tservice
);
1406 * Generates a service interface definition.
1408 * @param tservice The service to generate a header definition for
1410 void t_dart_generator::generate_service_interface(t_service
* tservice
) {
1411 string extends_iface
= "";
1412 if (tservice
->get_extends() != NULL
) {
1413 extends_iface
= " extends " + get_ttype_class_name(tservice
->get_extends());
1416 generate_dart_doc(f_service_
, tservice
);
1418 string class_name
= service_name_
;
1419 export_class_to_library(get_file_name(service_name_
), class_name
);
1420 indent(f_service_
) << "abstract class " << class_name
<< extends_iface
;
1421 scope_up(f_service_
);
1423 vector
<t_function
*> functions
= tservice
->get_functions();
1424 vector
<t_function
*>::iterator f_iter
;
1425 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1427 generate_dart_doc(f_service_
, *f_iter
);
1428 indent(f_service_
) << function_signature(*f_iter
) << ";" << endl
;
1431 scope_down(f_service_
, endl2
);
1435 * Generates structs for all the service args and return types
1437 * @param tservice The service
1439 void t_dart_generator::generate_service_helpers(t_service
* tservice
) {
1440 vector
<t_function
*> functions
= tservice
->get_functions();
1441 vector
<t_function
*>::iterator f_iter
;
1442 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1443 t_struct
* ts
= (*f_iter
)->get_arglist();
1444 generate_dart_struct_definition(f_service_
, ts
, false, false);
1445 generate_function_helpers(*f_iter
);
1450 * Generates a service client definition.
1452 * @param tservice The service to generate a server for.
1454 void t_dart_generator::generate_service_client(t_service
* tservice
) {
1455 string extends
= "";
1456 string extends_client
= "";
1457 if (tservice
->get_extends() != NULL
) {
1458 extends
= get_ttype_class_name(tservice
->get_extends());
1459 extends_client
= " extends " + extends
+ "Client";
1462 string class_name
= service_name_
+ "Client";
1463 export_class_to_library(get_file_name(service_name_
), class_name
);
1464 indent(f_service_
) << "class " << class_name
<< extends_client
1465 << " implements " << service_name_
;
1466 scope_up(f_service_
);
1469 indent(f_service_
) << class_name
<< "(TProtocol iprot, [TProtocol oprot = null])";
1471 if (!extends
.empty()) {
1474 indent(f_service_
) << ": super(iprot, oprot);" << endl
;
1477 scope_up(f_service_
);
1478 indent(f_service_
) << "_iprot = iprot;" << endl
;
1479 indent(f_service_
) << "_oprot = (oprot == null) ? iprot : oprot;" << endl
;
1480 scope_down(f_service_
);
1484 if (extends
.empty()) {
1485 indent(f_service_
) << "TProtocol _iprot;" << endl2
;
1486 indent(f_service_
) << "TProtocol get iprot => _iprot;" << endl2
;
1487 indent(f_service_
) << "TProtocol _oprot;" << endl2
;
1488 indent(f_service_
) << "TProtocol get oprot => _oprot;" << endl2
;
1489 indent(f_service_
) << "int _seqid = 0;" << endl2
;
1490 indent(f_service_
) << "int get seqid => _seqid;" << endl2
;
1491 indent(f_service_
) << "int nextSeqid() => ++_seqid;" << endl2
;
1494 // Generate client method implementations
1495 vector
<t_function
*> functions
= tservice
->get_functions();
1496 vector
<t_function
*>::const_iterator f_iter
;
1497 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1499 indent(f_service_
) << function_signature(*f_iter
) << " async";
1500 scope_up(f_service_
);
1502 // Get the struct of function call params
1503 t_struct
* arg_struct
= (*f_iter
)->get_arglist();
1505 string argsname
= get_args_class_name((*f_iter
)->get_name());
1506 vector
<t_field
*>::const_iterator fld_iter
;
1507 const vector
<t_field
*>& fields
= arg_struct
->get_members();
1509 // Serialize the request
1510 indent(f_service_
) << "oprot.writeMessageBegin(new TMessage(\"" << (*f_iter
)->get_name() << "\", "
1511 << ((*f_iter
)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL")
1512 << ", nextSeqid()));" << endl
;
1513 indent(f_service_
) << argsname
<< " args = new " << argsname
<< "();" << endl
;
1515 for (fld_iter
= fields
.begin(); fld_iter
!= fields
.end(); ++fld_iter
) {
1516 string arg_field_name
= get_member_name((*fld_iter
)->get_name());
1517 indent(f_service_
) << "args." << arg_field_name
<< " = "
1518 << arg_field_name
<< ";" << endl
;
1521 indent(f_service_
) << "args.write(oprot);" << endl
;
1522 indent(f_service_
) << "oprot.writeMessageEnd();" << endl2
;
1524 indent(f_service_
) << "await oprot.transport.flush();" << endl2
;
1526 if (!(*f_iter
)->is_oneway()) {
1527 indent(f_service_
) << "TMessage msg = iprot.readMessageBegin();" << endl
;
1528 indent(f_service_
) << "if (msg.type == TMessageType.EXCEPTION)";
1529 scope_up(f_service_
);
1530 indent(f_service_
) << "TApplicationError error = TApplicationError.read(iprot);" << endl
;
1531 indent(f_service_
) << "iprot.readMessageEnd();" << endl
;
1532 indent(f_service_
) << "throw error;" << endl
;
1533 scope_down(f_service_
, endl2
);
1535 string result_class
= get_result_class_name((*f_iter
)->get_name());
1536 indent(f_service_
) << result_class
<< " result = new " << result_class
<< "();" << endl
;
1537 indent(f_service_
) << "result.read(iprot);" << endl
;
1538 indent(f_service_
) << "iprot.readMessageEnd();" << endl
;
1540 // Careful, only return _result if not a void function
1541 if (!(*f_iter
)->get_returntype()->is_void()) {
1542 indent(f_service_
) << "if (result." << generate_isset_check("success") << ")";
1543 scope_up(f_service_
);
1544 indent(f_service_
) << "return result.success;" << endl
;
1545 scope_down(f_service_
, endl2
);
1548 t_struct
* xs
= (*f_iter
)->get_xceptions();
1549 const std::vector
<t_field
*>& xceptions
= xs
->get_members();
1550 vector
<t_field
*>::const_iterator x_iter
;
1551 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1552 string result_field_name
= get_member_name((*x_iter
)->get_name());
1553 indent(f_service_
) << "if (result." << result_field_name
<< " != null)";
1554 scope_up(f_service_
);
1555 indent(f_service_
) << "throw result." << result_field_name
<< ";" << endl
;
1556 scope_down(f_service_
);
1559 // If you get here it's an exception, unless a void function
1560 if ((*f_iter
)->get_returntype()->is_void()) {
1561 indent(f_service_
) << "return;" << endl
;
1563 indent(f_service_
) << "throw new TApplicationError(TApplicationErrorType.MISSING_RESULT, \""
1564 << (*f_iter
)->get_name() << " failed: unknown result\");" << endl
;
1568 scope_down(f_service_
, endl2
);
1571 scope_down(f_service_
, endl2
);
1575 * Generates a service server definition.
1577 * @param tservice The service to generate a server for.
1579 void t_dart_generator::generate_service_server(t_service
* tservice
) {
1580 // Generate the dispatch methods
1581 vector
<t_function
*> functions
= tservice
->get_functions();
1582 vector
<t_function
*>::iterator f_iter
;
1585 indent(f_service_
) << "typedef void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);" << endl2
;
1588 string extends
= "";
1589 string extends_processor
= "";
1590 if (tservice
->get_extends() != NULL
) {
1591 extends
= get_ttype_class_name(tservice
->get_extends());
1592 extends_processor
= " extends " + extends
+ "Processor";
1595 // Generate the header portion
1596 string class_name
= service_name_
+ "Processor";
1597 export_class_to_library(get_file_name(service_name_
), class_name
);
1598 indent(f_service_
) << "class " << class_name
<< extends_processor
<< " implements TProcessor";
1599 scope_up(f_service_
);
1601 indent(f_service_
) << class_name
<< "(" << service_name_
<< " iface)";
1602 if (!extends
.empty()) {
1605 indent(f_service_
) << ": super(iface)";
1608 scope_up(f_service_
);
1610 if (extends
.empty()) {
1611 indent(f_service_
) << "iface_ = iface;" << endl
;
1614 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1615 indent(f_service_
) << "PROCESS_MAP[\"" << (*f_iter
)->get_name()
1616 << "\"] = " << get_member_name((*f_iter
)->get_name()) << ";" << endl
;
1618 scope_down(f_service_
, endl2
);
1620 indent(f_service_
) << service_name_
<< " iface_;" << endl
;
1622 if (extends
.empty()) {
1623 indent(f_service_
) << "final Map<String, ProcessFunction> PROCESS_MAP = {};" << endl
;
1628 // Generate the server implementation
1629 indent(f_service_
) << "bool process(TProtocol iprot, TProtocol oprot)";
1630 scope_up(f_service_
);
1631 indent(f_service_
) << "TMessage msg = iprot.readMessageBegin();" << endl
;
1632 indent(f_service_
) << "ProcessFunction fn = PROCESS_MAP[msg.name];" << endl
;
1633 indent(f_service_
) << "if (fn == null)";
1634 scope_up(f_service_
);
1635 indent(f_service_
) << "TProtocolUtil.skip(iprot, TType.STRUCT);" << endl
;
1636 indent(f_service_
) << "iprot.readMessageEnd();" << endl
;
1637 indent(f_service_
) << "TApplicationError x = new TApplicationError(TApplicationErrorType.UNKNOWN_METHOD, "
1638 "\"Invalid method name: '\"+msg.name+\"'\");" << endl
;
1639 indent(f_service_
) << "oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" << endl
;
1640 indent(f_service_
) << "x.write(oprot);" << endl
;
1641 indent(f_service_
) << "oprot.writeMessageEnd();" << endl
;
1642 indent(f_service_
) << "oprot.transport.flush();" << endl
;
1643 indent(f_service_
) << "return true;" << endl
;
1644 scope_down(f_service_
);
1645 indent(f_service_
) << "fn(msg.seqid, iprot, oprot);" << endl
;
1646 indent(f_service_
) << "return true;" << endl
;
1647 scope_down(f_service_
, endl2
); // process function
1649 // Generate the process subfunctions
1650 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1651 generate_process_function(tservice
, *f_iter
);
1654 scope_down(f_service_
, endl2
); // class
1658 * Generates a struct and helpers for a function.
1660 * @param tfunction The function
1662 void t_dart_generator::generate_function_helpers(t_function
* tfunction
) {
1663 if (tfunction
->is_oneway()) {
1667 t_struct
result(program_
, get_result_class_name(tfunction
->get_name()));
1668 t_field
success(tfunction
->get_returntype(), "success", 0);
1669 if (!tfunction
->get_returntype()->is_void()) {
1670 result
.append(&success
);
1673 t_struct
* xs
= tfunction
->get_xceptions();
1674 const vector
<t_field
*>& fields
= xs
->get_members();
1675 vector
<t_field
*>::const_iterator f_iter
;
1676 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1677 result
.append(*f_iter
);
1680 generate_dart_struct_definition(f_service_
, &result
, false, true);
1684 * Generates a process function definition.
1686 * @param tfunction The function to write a dispatcher for
1688 void t_dart_generator::generate_process_function(t_service
* tservice
, t_function
* tfunction
) {
1691 bool await_result
= (!tfunction
->is_oneway() && !tfunction
->get_returntype()->is_void());
1693 indent(f_service_
) << get_member_name(tfunction
->get_name()) << "(int seqid, TProtocol iprot, TProtocol oprot)";
1695 f_service_
<< " async";
1697 scope_up(f_service_
);
1699 string argsname
= get_args_class_name(tfunction
->get_name());
1700 string resultname
= get_result_class_name(tfunction
->get_name());
1702 indent(f_service_
) << argsname
<< " args = new " << argsname
<< "();" << endl
;
1703 indent(f_service_
) << "args.read(iprot);" << endl
;
1704 indent(f_service_
) << "iprot.readMessageEnd();" << endl
;
1706 t_struct
* xs
= tfunction
->get_xceptions();
1707 const std::vector
<t_field
*>& xceptions
= xs
->get_members();
1708 vector
<t_field
*>::const_iterator x_iter
;
1710 if (!tfunction
->is_oneway()) {
1711 indent(f_service_
) << resultname
<< " result = new " << resultname
<< "();" << endl
;
1714 if (!tfunction
->is_oneway() && xceptions
.size() > 0) {
1715 indent(f_service_
) << "try";
1716 scope_up(f_service_
);
1719 // Generate the function call
1720 t_struct
* arg_struct
= tfunction
->get_arglist();
1721 const std::vector
<t_field
*>& fields
= arg_struct
->get_members();
1722 vector
<t_field
*>::const_iterator f_iter
;
1724 f_service_
<< indent();
1726 f_service_
<< "result.success = await ";
1728 f_service_
<< "iface_." << get_member_name(tfunction
->get_name()) << "(";
1730 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1736 f_service_
<< "args." << get_member_name((*f_iter
)->get_name());
1738 f_service_
<< ");" << endl
;
1740 if (!tfunction
->is_oneway() && xceptions
.size() > 0) {
1741 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1742 string result_field_name
= get_member_name((*x_iter
)->get_name());
1743 scope_down(f_service_
, "");
1744 f_service_
<< " on " << type_name((*x_iter
)->get_type())
1745 << " catch(" << result_field_name
<< ")";
1746 scope_up(f_service_
);
1747 if (!tfunction
->is_oneway()) {
1748 indent(f_service_
) << "result." << result_field_name
<< " = "
1749 << result_field_name
<< ";" << endl
;
1752 scope_down(f_service_
, " ");
1753 f_service_
<< "catch (th)";
1754 scope_up(f_service_
);
1755 indent(f_service_
) << "// Internal error" << endl
;
1756 indent(f_service_
) << "TApplicationError x = new "
1757 "TApplicationError(TApplicationErrorType.INTERNAL_ERROR, \"Internal error processing "
1758 << tfunction
->get_name() << "\");" << endl
;
1759 indent(f_service_
) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction
->get_name()
1760 << "\", TMessageType.EXCEPTION, seqid));" << endl
;
1761 indent(f_service_
) << "x.write(oprot);" << endl
;
1762 indent(f_service_
) << "oprot.writeMessageEnd();" << endl
;
1763 indent(f_service_
) << "oprot.transport.flush();" << endl
;
1764 indent(f_service_
) << "return;" << endl
;
1765 scope_down(f_service_
);
1768 if (tfunction
->is_oneway()) {
1769 indent(f_service_
) << "return;" << endl
;
1771 indent(f_service_
) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction
->get_name()
1772 << "\", TMessageType.REPLY, seqid));" << endl
;
1773 indent(f_service_
) << "result.write(oprot);" << endl
;
1774 indent(f_service_
) << "oprot.writeMessageEnd();" << endl
;
1775 indent(f_service_
) << "oprot.transport.flush();" << endl
;
1778 scope_down(f_service_
, endl2
);
1782 * Deserializes a field of any type.
1784 * @param tfield The field
1785 * @param prefix The variable name or container for this field
1787 void t_dart_generator::generate_deserialize_field(ostream
& out
, t_field
* tfield
, string prefix
) {
1788 t_type
* type
= get_true_type(tfield
->get_type());
1789 string field_name
= get_member_name(tfield
->get_name());
1791 if (type
->is_void()) {
1792 throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix
+ field_name
;
1795 string name
= prefix
+ field_name
;
1797 if (type
->is_struct() || type
->is_xception()) {
1798 generate_deserialize_struct(out
, (t_struct
*)type
, name
);
1799 } else if (type
->is_container()) {
1800 generate_deserialize_container(out
, type
, name
);
1801 } else if (type
->is_base_type() || type
->is_enum()) {
1803 indent(out
) << name
<< " = iprot.";
1805 if (type
->is_base_type()) {
1806 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1808 case t_base_type::TYPE_VOID
:
1809 throw "compiler error: cannot serialize void field in a struct: " + name
;
1811 case t_base_type::TYPE_STRING
:
1812 if (type
->is_binary()) {
1813 out
<< "readBinary();";
1815 out
<< "readString();";
1818 case t_base_type::TYPE_BOOL
:
1819 out
<< "readBool();";
1821 case t_base_type::TYPE_I8
:
1822 out
<< "readByte();";
1824 case t_base_type::TYPE_I16
:
1825 out
<< "readI16();";
1827 case t_base_type::TYPE_I32
:
1828 out
<< "readI32();";
1830 case t_base_type::TYPE_I64
:
1831 out
<< "readI64();";
1833 case t_base_type::TYPE_DOUBLE
:
1834 out
<< "readDouble();";
1837 throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase
);
1839 } else if (type
->is_enum()) {
1840 out
<< "readI32();";
1844 printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
1846 type_name(type
).c_str());
1851 * Generates an unserializer for a struct, invokes read()
1853 void t_dart_generator::generate_deserialize_struct(ostream
& out
, t_struct
* tstruct
, string prefix
) {
1854 indent(out
) << prefix
<< " = new " << type_name(tstruct
) << "();" << endl
;
1855 indent(out
) << prefix
<< ".read(iprot);" << endl
;
1859 * Deserializes a container by reading its size and then iterating
1861 void t_dart_generator::generate_deserialize_container(ostream
& out
, t_type
* ttype
, string prefix
) {
1867 if (ttype
->is_map()) {
1869 } else if (ttype
->is_set()) {
1871 } else if (ttype
->is_list()) {
1875 // Declare variables, read header
1876 if (ttype
->is_map()) {
1877 indent(out
) << "TMap " << obj
<< " = iprot.readMapBegin();" << endl
;
1878 } else if (ttype
->is_set()) {
1879 indent(out
) << "TSet " << obj
<< " = iprot.readSetBegin();" << endl
;
1880 } else if (ttype
->is_list()) {
1881 indent(out
) << "TList " << obj
<< " = iprot.readListBegin();" << endl
;
1884 indent(out
) << prefix
<< " = new " << type_name(ttype
) << "();" << endl
;
1886 // For loop iterates over elements
1887 string i
= tmp("_i");
1888 indent(out
) << "for (int " << i
<< " = 0; " << i
<< " < " << obj
<< ".length"
1890 << "++" << i
<< ")";
1893 if (ttype
->is_map()) {
1894 generate_deserialize_map_element(out
, (t_map
*)ttype
, prefix
);
1895 } else if (ttype
->is_set()) {
1896 generate_deserialize_set_element(out
, (t_set
*)ttype
, prefix
);
1897 } else if (ttype
->is_list()) {
1898 generate_deserialize_list_element(out
, (t_list
*)ttype
, prefix
);
1903 // Read container end
1904 if (ttype
->is_map()) {
1905 indent(out
) << "iprot.readMapEnd();" << endl
;
1906 } else if (ttype
->is_set()) {
1907 indent(out
) << "iprot.readSetEnd();" << endl
;
1908 } else if (ttype
->is_list()) {
1909 indent(out
) << "iprot.readListEnd();" << endl
;
1916 * Generates code to deserialize a map
1918 void t_dart_generator::generate_deserialize_map_element(ostream
& out
, t_map
* tmap
, string prefix
) {
1919 string key
= tmp("_key");
1920 string val
= tmp("_val");
1921 t_field
fkey(tmap
->get_key_type(), key
);
1922 t_field
fval(tmap
->get_val_type(), val
);
1924 indent(out
) << declare_field(&fkey
) << endl
;
1925 indent(out
) << declare_field(&fval
) << endl
;
1927 generate_deserialize_field(out
, &fkey
);
1928 generate_deserialize_field(out
, &fval
);
1930 indent(out
) << prefix
<< "[" << key
<< "] = " << val
<< ";" << endl
;
1934 * Deserializes a set element
1936 void t_dart_generator::generate_deserialize_set_element(ostream
& out
, t_set
* tset
, string prefix
) {
1937 string elem
= tmp("_elem");
1938 t_field
felem(tset
->get_elem_type(), elem
);
1940 indent(out
) << declare_field(&felem
) << endl
;
1942 generate_deserialize_field(out
, &felem
);
1944 indent(out
) << prefix
<< ".add(" << elem
<< ");" << endl
;
1948 * Deserializes a list element
1950 void t_dart_generator::generate_deserialize_list_element(ostream
& out
,
1953 string elem
= tmp("_elem");
1954 t_field
felem(tlist
->get_elem_type(), elem
);
1956 indent(out
) << declare_field(&felem
) << endl
;
1958 generate_deserialize_field(out
, &felem
);
1960 indent(out
) << prefix
<< ".add(" << elem
<< ");" << endl
;
1964 * Serializes a field of any type.
1966 * @param tfield The field to serialize
1967 * @param prefix Name to prepend to field name
1969 void t_dart_generator::generate_serialize_field(ostream
& out
, t_field
* tfield
, string prefix
) {
1970 t_type
* type
= get_true_type(tfield
->get_type());
1971 string field_name
= get_member_name(tfield
->get_name());
1973 // Do nothing for void types
1974 if (type
->is_void()) {
1975 throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix
+ field_name
;
1978 if (type
->is_struct() || type
->is_xception()) {
1979 generate_serialize_struct(out
, (t_struct
*)type
, prefix
+ field_name
);
1980 } else if (type
->is_container()) {
1981 generate_serialize_container(out
, type
, prefix
+ field_name
);
1982 } else if (type
->is_base_type() || type
->is_enum()) {
1984 string name
= prefix
+ field_name
;
1985 indent(out
) << "oprot.";
1987 if (type
->is_base_type()) {
1988 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1990 case t_base_type::TYPE_VOID
:
1991 throw "compiler error: cannot serialize void field in a struct: " + name
;
1993 case t_base_type::TYPE_STRING
:
1994 if (type
->is_binary()) {
1995 out
<< "writeBinary(" << name
<< ");";
1997 out
<< "writeString(" << name
<< ");";
2000 case t_base_type::TYPE_BOOL
:
2001 out
<< "writeBool(" << name
<< ");";
2003 case t_base_type::TYPE_I8
:
2004 out
<< "writeByte(" << name
<< ");";
2006 case t_base_type::TYPE_I16
:
2007 out
<< "writeI16(" << name
<< ");";
2009 case t_base_type::TYPE_I32
:
2010 out
<< "writeI32(" << name
<< ");";
2012 case t_base_type::TYPE_I64
:
2013 out
<< "writeI64(" << name
<< ");";
2015 case t_base_type::TYPE_DOUBLE
:
2016 out
<< "writeDouble(" << name
<< ");";
2019 throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase
);
2021 } else if (type
->is_enum()) {
2022 out
<< "writeI32(" << name
<< ");";
2026 printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
2029 type_name(type
).c_str());
2034 * Serializes all the members of a struct.
2036 * @param tstruct The struct to serialize
2037 * @param prefix String prefix to attach to all fields
2039 void t_dart_generator::generate_serialize_struct(ostream
& out
, t_struct
* tstruct
, string prefix
) {
2041 indent(out
) << prefix
<< ".write(oprot);" << endl
;
2045 * Serializes a container by writing its size then the elements.
2047 * @param ttype The type of container
2048 * @param prefix String prefix for fields
2050 void t_dart_generator::generate_serialize_container(ostream
& out
, t_type
* ttype
, string prefix
) {
2054 if (ttype
->is_map()) {
2055 string iter
= tmp("_key");
2056 indent(out
) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map
*)ttype
)->get_key_type())
2057 << ", " << type_to_enum(((t_map
*)ttype
)->get_val_type()) << ", " << prefix
<< ".length));"
2059 } else if (ttype
->is_set()) {
2060 indent(out
) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set
*)ttype
)->get_elem_type())
2061 << ", " << prefix
<< ".length));" << endl
;
2062 } else if (ttype
->is_list()) {
2063 indent(out
) << "oprot.writeListBegin(new TList("
2064 << type_to_enum(((t_list
*)ttype
)->get_elem_type()) << ", " << prefix
<< ".length));"
2068 string iter
= tmp("elem");
2069 if (ttype
->is_map()) {
2070 indent(out
) << "for (var " << iter
<< " in " << prefix
<< ".keys)";
2071 } else if (ttype
->is_set() || ttype
->is_list()) {
2072 indent(out
) << "for (var " << iter
<< " in " << prefix
<< ")";
2077 if (ttype
->is_map()) {
2078 generate_serialize_map_element(out
, (t_map
*)ttype
, iter
, prefix
);
2079 } else if (ttype
->is_set()) {
2080 generate_serialize_set_element(out
, (t_set
*)ttype
, iter
);
2081 } else if (ttype
->is_list()) {
2082 generate_serialize_list_element(out
, (t_list
*)ttype
, iter
);
2087 if (ttype
->is_map()) {
2088 indent(out
) << "oprot.writeMapEnd();" << endl
;
2089 } else if (ttype
->is_set()) {
2090 indent(out
) << "oprot.writeSetEnd();" << endl
;
2091 } else if (ttype
->is_list()) {
2092 indent(out
) << "oprot.writeListEnd();" << endl
;
2099 * Serializes the members of a map.
2101 void t_dart_generator::generate_serialize_map_element(ostream
& out
,
2105 t_field
kfield(tmap
->get_key_type(), iter
);
2106 generate_serialize_field(out
, &kfield
, "");
2107 t_field
vfield(tmap
->get_val_type(), map
+ "[" + iter
+ "]");
2108 generate_serialize_field(out
, &vfield
, "");
2112 * Serializes the members of a set.
2114 void t_dart_generator::generate_serialize_set_element(ostream
& out
, t_set
* tset
, string iter
) {
2115 t_field
efield(tset
->get_elem_type(), iter
);
2116 generate_serialize_field(out
, &efield
, "");
2120 * Serializes the members of a list.
2122 void t_dart_generator::generate_serialize_list_element(ostream
& out
, t_list
* tlist
, string iter
) {
2123 t_field
efield(tlist
->get_elem_type(), iter
);
2124 generate_serialize_field(out
, &efield
, "");
2128 * Returns a Dart type name
2130 * @param ttype The type
2131 * @return Dart type name, i.e. Map<Key, Value>
2133 string
t_dart_generator::type_name(t_type
* ttype
) {
2134 ttype
= get_true_type(ttype
);
2136 if (ttype
->is_base_type()) {
2137 return base_type_name((t_base_type
*)ttype
);
2138 } else if (ttype
->is_enum()) {
2140 } else if (ttype
->is_map()) {
2141 t_map
* tmap
= (t_map
*)ttype
;
2142 return "Map<" + type_name(tmap
->get_key_type()) + ", "
2143 + type_name(tmap
->get_val_type()) + ">";
2144 } else if (ttype
->is_set()) {
2145 t_set
* tset
= (t_set
*)ttype
;
2146 return "Set<" + type_name(tset
->get_elem_type()) + ">";
2147 } else if (ttype
->is_list()) {
2148 t_list
* tlist
= (t_list
*)ttype
;
2149 return "List<" + type_name(tlist
->get_elem_type()) + ">";
2152 return get_ttype_class_name(ttype
);
2156 * Returns the Dart type that corresponds to the thrift type.
2158 * @param tbase The base type
2160 string
t_dart_generator::base_type_name(t_base_type
* type
) {
2161 t_base_type::t_base tbase
= type
->get_base();
2164 case t_base_type::TYPE_VOID
:
2166 case t_base_type::TYPE_STRING
:
2167 if (type
->is_binary()) {
2172 case t_base_type::TYPE_BOOL
:
2174 case t_base_type::TYPE_I8
:
2175 case t_base_type::TYPE_I16
:
2176 case t_base_type::TYPE_I32
:
2177 case t_base_type::TYPE_I64
:
2179 case t_base_type::TYPE_DOUBLE
:
2182 throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase
);
2187 * Declares a field, which may include initialization as necessary.
2189 * @param ttype The type
2191 string
t_dart_generator::declare_field(t_field
* tfield
, bool init
) {
2192 string field_name
= get_member_name(tfield
->get_name());
2193 string result
= type_name(tfield
->get_type()) + " " + field_name
;
2195 t_type
* ttype
= get_true_type(tfield
->get_type());
2196 if (ttype
->is_base_type() && tfield
->get_value() != NULL
) {
2197 std:: ofstream dummy
;
2198 result
+= " = " + render_const_value(dummy
, field_name
, ttype
, tfield
->get_value());
2199 } else if (ttype
->is_base_type()) {
2200 t_base_type::t_base tbase
= ((t_base_type
*)ttype
)->get_base();
2202 case t_base_type::TYPE_VOID
:
2203 throw "NO T_VOID CONSTRUCT";
2204 case t_base_type::TYPE_STRING
:
2205 result
+= " = null";
2207 case t_base_type::TYPE_BOOL
:
2208 result
+= " = false";
2210 case t_base_type::TYPE_I8
:
2211 case t_base_type::TYPE_I16
:
2212 case t_base_type::TYPE_I32
:
2213 case t_base_type::TYPE_I64
:
2216 case t_base_type::TYPE_DOUBLE
:
2221 } else if (ttype
->is_enum()) {
2223 } else if (ttype
->is_container()) {
2224 result
+= " = new " + type_name(ttype
) + "()";
2226 result
+= " = new " + type_name(ttype
) + "()";
2230 return result
+ ";";
2234 * Renders a function signature of the form 'type name(args)'
2236 * @param tfunction Function definition
2237 * @return String of rendered function definition
2239 string
t_dart_generator::function_signature(t_function
* tfunction
) {
2240 std::string arguments
= argument_list(tfunction
->get_arglist());
2242 std::string returntype
;
2243 if (tfunction
->get_returntype()->is_void()) {
2244 returntype
= "Future";
2246 returntype
= "Future<" + type_name(tfunction
->get_returntype()) + ">";
2249 std::string result
= returntype
+ " " + get_member_name(tfunction
->get_name()) +
2250 "(" + arguments
+ ")";
2255 * Renders a comma separated field list, with type names
2257 string
t_dart_generator::argument_list(t_struct
* tstruct
) {
2260 const vector
<t_field
*>& fields
= tstruct
->get_members();
2261 vector
<t_field
*>::const_iterator f_iter
;
2263 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
2269 string field_name
= get_member_name((*f_iter
)->get_name());
2270 result
+= type_name((*f_iter
)->get_type()) + " " + field_name
;
2276 * Converts the parse type to a C++ enum string for the given type.
2278 string
t_dart_generator::type_to_enum(t_type
* type
) {
2279 type
= get_true_type(type
);
2281 if (type
->is_base_type()) {
2282 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
2284 case t_base_type::TYPE_VOID
:
2285 throw "NO T_VOID CONSTRUCT";
2286 case t_base_type::TYPE_STRING
:
2287 return "TType.STRING";
2288 case t_base_type::TYPE_BOOL
:
2289 return "TType.BOOL";
2290 case t_base_type::TYPE_I8
:
2291 return "TType.BYTE";
2292 case t_base_type::TYPE_I16
:
2294 case t_base_type::TYPE_I32
:
2296 case t_base_type::TYPE_I64
:
2298 case t_base_type::TYPE_DOUBLE
:
2299 return "TType.DOUBLE";
2301 } else if (type
->is_enum()) {
2303 } else if (type
->is_struct() || type
->is_xception()) {
2304 return "TType.STRUCT";
2305 } else if (type
->is_map()) {
2307 } else if (type
->is_set()) {
2309 } else if (type
->is_list()) {
2310 return "TType.LIST";
2313 throw "INVALID TYPE IN type_to_enum: " + type
->get_name();
2316 std::string
t_dart_generator::init_value(t_field
* field
) {
2317 // Do not initialize optional fields
2318 if (field
->get_req() == t_field::T_OPTIONAL
) {
2322 t_type
* ttype
= field
->get_type();
2324 // Get the actual type for a typedef
2325 if (ttype
->is_typedef()) {
2326 ttype
= ((t_typedef
*)ttype
)->get_type();
2329 // Only consider base types for default initialization
2330 if (!ttype
->is_base_type()) {
2333 t_base_type::t_base tbase
= ((t_base_type
*)ttype
)->get_base();
2335 // Initialize bools, ints, and doubles with sane defaults
2338 case t_base_type::TYPE_BOOL
:
2339 result
= " = false";
2341 case t_base_type::TYPE_I8
:
2342 case t_base_type::TYPE_I16
:
2343 case t_base_type::TYPE_I32
:
2344 case t_base_type::TYPE_I64
:
2347 case t_base_type::TYPE_DOUBLE
:
2350 case t_base_type::TYPE_VOID
:
2351 case t_base_type::TYPE_STRING
:
2359 std::string
t_dart_generator::get_cap_name(std::string name
) {
2360 name
[0] = toupper(name
[0]);
2364 std::string
t_dart_generator::get_member_name(std::string name
) {
2365 name
[0] = tolower(name
[0]);
2369 std::string
t_dart_generator::get_args_class_name(std::string name
) {
2370 return name
+ "_args";
2373 std::string
t_dart_generator::get_result_class_name(std::string name
) {
2374 return name
+ "_result";
2377 std::string
t_dart_generator::get_file_name(std::string name
) {
2378 // e.g. change APIForFileIO to api_for_file_io
2381 const char* tmp
= name
.c_str();
2382 bool is_prev_lc
= true;
2383 bool is_current_lc
= tmp
[0] == tolower(tmp
[0]);
2384 bool is_next_lc
= false;
2386 for (unsigned int i
= 0; i
< name
.length(); i
++) {
2387 char lc
= tolower(tmp
[i
]);
2389 if (i
== name
.length() - 1) {
2392 is_next_lc
= (tmp
[i
+1] == tolower(tmp
[i
+1]));
2395 if (i
!= 0 && !is_current_lc
&& (is_prev_lc
|| is_next_lc
)) {
2400 is_prev_lc
= is_current_lc
;
2401 is_current_lc
= is_next_lc
;
2407 std::string
t_dart_generator::get_constants_class_name(std::string name
) {
2408 // e.g. change my_great_model to MyGreatModelConstants
2410 const char* tmp
= name
.c_str();
2411 bool is_prev_underscore
= true;
2413 for (unsigned int i
= 0; i
< name
.length(); i
++) {
2414 if (tmp
[i
] == '_') {
2415 is_prev_underscore
= true;
2417 if (is_prev_underscore
) {
2418 ret
+= toupper(tmp
[i
]);
2423 is_prev_underscore
= false;
2427 return ret
+ "Constants";
2430 string
t_dart_generator::constant_name(string name
) {
2431 string constant_name
;
2433 bool is_first
= true;
2434 bool was_previous_char_upper
= false;
2435 for (char character
: name
) {
2436 bool is_upper
= isupper(character
);
2438 if (is_upper
&& !is_first
&& !was_previous_char_upper
) {
2439 constant_name
+= '_';
2441 constant_name
+= toupper(character
);
2444 was_previous_char_upper
= is_upper
;
2447 return constant_name
;
2451 * Emits a doc comment if the provided object has a doc in Thrift
2453 void t_dart_generator::generate_dart_doc(ostream
& out
, t_doc
* tdoc
) {
2454 if (tdoc
->has_doc()) {
2455 generate_docstring_comment(out
, "", "/// ", tdoc
->get_doc(), "");
2460 * Emits a doc comment if the provided function object has a doc in Thrift
2462 void t_dart_generator::generate_dart_doc(ostream
& out
, t_function
* tfunction
) {
2463 if (tfunction
->has_doc()) {
2465 ss
<< tfunction
->get_doc();
2466 const vector
<t_field
*>& fields
= tfunction
->get_arglist()->get_members();
2467 vector
<t_field
*>::const_iterator p_iter
;
2468 for (p_iter
= fields
.begin(); p_iter
!= fields
.end(); ++p_iter
) {
2469 t_field
* p
= *p_iter
;
2470 string field_name
= get_member_name(p
->get_name());
2471 ss
<< "\n@param " << field_name
;
2473 ss
<< " " << p
->get_doc();
2476 generate_docstring_comment(out
, "", "/// ", ss
.str(), "");
2480 std::string
t_dart_generator::generate_isset_check(t_field
* field
) {
2481 string field_name
= get_member_name(field
->get_name());
2482 return generate_isset_check(field_name
);
2485 std::string
t_dart_generator::generate_isset_check(std::string field_name
) {
2486 return "is" + get_cap_name("set") + get_cap_name(field_name
) + "()";
2489 void t_dart_generator::generate_isset_set(ostream
& out
, t_field
* field
) {
2490 if (!type_can_be_null(field
->get_type())) {
2491 string field_name
= get_member_name(field
->get_name());
2492 indent(out
) << "this.__isset_" << field_name
<< " = true;" << endl
;
2496 std::string
t_dart_generator::get_ttype_class_name(t_type
* ttype
) {
2497 if (program_
== ttype
->get_program()) {
2498 return ttype
->get_name();
2500 string named_import
= "t_" + find_library_name(ttype
->get_program());
2501 return named_import
+ "." + ttype
->get_name();
2505 THRIFT_REGISTER_GENERATOR(
2508 " library_name: Optional override for library name.\n"
2509 " library_prefix: Generate code that can be used within an existing library.\n"
2510 " Use a dot-separated string, e.g. \"my_parent_lib.src.gen\"\n"
2511 " pubspec_lib: Optional override for thrift lib dependency in pubspec.yaml,\n"
2512 " e.g. \"thrift: 0.x.x\". Use a pipe delimiter to separate lines,\n"
2513 " e.g. \"thrift:| git:| url: git@foo.com\"\n"