THRIFT-1126 - extended struct info + minor fixes
git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1087585 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_erl_generator.cc b/compiler/cpp/src/generate/t_erl_generator.cc
index fec56bc..69c6335 100644
--- a/compiler/cpp/src/generate/t_erl_generator.cc
+++ b/compiler/cpp/src/generate/t_erl_generator.cc
@@ -71,18 +71,23 @@
void generate_member_type(std::ostream & out, t_type* type);
void generate_member_value(std::ostream & out, t_type* type, t_const_value* value);
- std::string render_member_type(t_type* type);
+ std::string render_member_type(t_field * field);
+ std::string render_member_value(t_field * field);
+ std::string render_member_requiredness(t_field * field);
+
std::string render_default_value(t_type* type);
std::string render_const_value(t_type* type, t_const_value* value);
+ std::string render_type_term(t_type* ttype, bool expand_structs, bool extended_info = false);
/**
* Struct generation code
*/
void generate_erl_struct(t_struct* tstruct, bool is_exception);
- void generate_erl_struct_definition(std::ostream& out, std::ostream& hrl_out, t_struct* tstruct, bool is_xception=false, bool is_result=false);
+ void generate_erl_struct_definition(std::ostream& out, t_struct* tstruct);
void generate_erl_struct_member(std::ostream& out, t_field * tmember);
void generate_erl_struct_info(std::ostream& out, t_struct* tstruct);
+ void generate_erl_extended_struct_info(std::ostream& out, t_struct* tstruct);
void generate_erl_function_helpers(t_function* tfunction);
/**
@@ -107,7 +112,6 @@
std::string argument_list(t_struct* tstruct);
std::string type_to_enum(t_type* ttype);
- std::string generate_type_term(t_type* ttype, bool expand_structs);
std::string type_module(t_type* ttype);
std::string capitalize(std::string in) {
@@ -155,7 +159,9 @@
* File streams
*/
- std::ostringstream f_types_;
+ std::ostringstream f_info_;
+ std::ostringstream f_info_ext_;
+
std::ofstream f_types_file_;
std::ofstream f_types_hrl_file_;
@@ -278,12 +284,16 @@
* Closes the type files
*/
void t_erl_generator::close_generator() {
- // Close types file
- export_types_string("struct_info", 1);
- f_types_file_ << "-export([" << export_types_lines_.str() << "])." << endl;
- f_types_file_ << f_types_.str();
- f_types_file_ << "struct_info('i am a dummy struct') -> undefined." << endl;
+ export_types_string("struct_info", 1);
+ export_types_string("struct_info_ext", 1);
+ f_types_file_ << "-export([" << export_types_lines_.str() << "])." << endl << endl;
+
+ f_types_file_ << f_info_.str();
+ f_types_file_ << "struct_info('i am a dummy struct') -> undefined." << endl << endl;
+
+ f_types_file_ << f_info_ext_.str();
+ f_types_file_ << "struct_info_ext('i am a dummy struct') -> undefined." << endl << endl;
hrl_footer(f_types_hrl_file_, string("BOGUS"));
@@ -404,36 +414,28 @@
t_type* ktype = ((t_map*)type)->get_key_type();
t_type* vtype = ((t_map*)type)->get_val_type();
- if ( value->get_map().empty() ) {
- out << "dict:new()";
- } else {
- out << "dict:from_list([";
- map<t_const_value*, t_const_value*>::const_iterator i, end = value->get_map().end();
- for (i = value->get_map().begin(); i != end;) {
- out << "("
- << render_const_value(ktype, i->first) << ","
- << render_const_value(vtype, i->second) << ")";
- if ( ++i != end ) {
- out << ",";
- }
+ out << "dict:from_list([";
+ map<t_const_value*, t_const_value*>::const_iterator i, end = value->get_map().end();
+ for (i = value->get_map().begin(); i != end;) {
+ out << "{"
+ << render_const_value(ktype, i->first) << ","
+ << render_const_value(vtype, i->second) << "}";
+ if ( ++i != end ) {
+ out << ",";
}
- out << "])";
}
+ out << "])";
} else if (type->is_set()) {
t_type* etype = ((t_set*)type)->get_elem_type();
- if ( value->get_list().empty() ) {
- out << "sets:new()";
- } else {
- out << "sets:from_list([";
- vector<t_const_value*>::const_iterator i, end = value->get_list().end();
- for( i = value->get_list().begin(); i != end; ) {
- out << "(" << render_const_value(etype, *i) << ",true)";
- if ( ++i != end ) {
- out << ",";
- }
+ out << "sets:from_list([";
+ vector<t_const_value*>::const_iterator i, end = value->get_list().end();
+ for( i = value->get_list().begin(); i != end; ) {
+ out << render_const_value(etype, *i) ;
+ if ( ++i != end ) {
+ out << ",";
}
- out << "])";
}
+ out << "])";
} else if (type->is_list()) {
t_type* etype;
etype = ((t_list*)type)->get_elem_type();
@@ -457,6 +459,7 @@
return out.str();
}
+
string t_erl_generator::render_default_value(t_type* type) {
if (type->is_struct() || type->is_xception()) {
return "#" + uncapitalize(type->get_name()) + "{}";
@@ -467,13 +470,12 @@
} else if (type->is_list()) {
return "[]";
} else {
- return "";
+ return "undefined";
}
}
-
-string t_erl_generator::render_member_type(t_type* type) {
- type = get_true_type(type);
+string t_erl_generator::render_member_type(t_field * field) {
+ t_type * type = get_true_type(field->get_type());
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
switch (tbase) {
@@ -494,14 +496,24 @@
} else if (type->is_enum()) {
return "integer()";
} else if (type->is_struct() || type->is_xception()) {
+ return "#" + uncapitalize(type->get_name()) + "{}";
} else if (type->is_map()) {
+ return "dict()";
} else if (type->is_set()) {
+ return "set()";
} else if (type->is_list()) {
return "list()";
} else {
throw "compiler error: unsupported type " + type->get_name();
}
- return "";
+}
+
+string t_erl_generator::render_member_requiredness(t_field * field) {
+ switch(field->get_req()) {
+ case t_field::T_REQUIRED: return "required";
+ case t_field::T_OPTIONAL: return "optional";
+ default: return "undefined";
+ }
}
/**
@@ -524,9 +536,11 @@
/**
* Generates a struct
*/
-void t_erl_generator::generate_erl_struct(t_struct* tstruct,
- bool is_exception) {
- generate_erl_struct_definition(f_types_, f_types_hrl_file_, tstruct, is_exception);
+void t_erl_generator::generate_erl_struct(t_struct* tstruct, bool is_exception) {
+ (void) is_exception;
+ generate_erl_struct_definition(f_types_hrl_file_, tstruct);
+ generate_erl_struct_info(f_info_, tstruct);
+ generate_erl_extended_struct_info(f_info_ext_, tstruct);
}
/**
@@ -534,15 +548,8 @@
*
* @param tstruct The struct definition
*/
-void t_erl_generator::generate_erl_struct_definition(ostream& out,
- ostream& hrl_out,
- t_struct* tstruct,
- bool is_exception,
- bool is_result)
+void t_erl_generator::generate_erl_struct_definition(ostream& out, t_struct* tstruct)
{
- (void) is_result;
- (void) is_exception;
-
indent(out) << "%% struct " << type_name(tstruct) << endl << endl;
std::stringstream buf;
@@ -558,10 +565,7 @@
}
buf << "}).";
- hrl_out << buf.str() << endl << endl;
- out << comment(buf.str()) << endl << endl;
-
- generate_erl_struct_info(out, tstruct);
+ out << buf.str() << endl << endl;
}
/**
@@ -571,42 +575,38 @@
void t_erl_generator::generate_erl_struct_member(ostream & out, t_field * tmember)
{
out << uncapitalize(tmember->get_name());
- generate_member_value(out, tmember->get_type(), tmember->get_value());
- generate_member_type(out, tmember->get_type());
+ out << " = " << render_member_value(tmember);
+ out << " :: " << render_member_type(tmember);
}
-void t_erl_generator::generate_member_type(ostream & out, t_type* type) {
- string member_type = render_member_type(type);
- if ( !member_type.empty() ) {
- out << " :: " << member_type;
+string t_erl_generator::render_member_value(t_field * field) {
+ if (!field->get_value()) {
+ return render_default_value(field->get_type());
+ } else {
+ return render_const_value(field->get_type(), field->get_value());
}
}
-void t_erl_generator::generate_member_value(ostream & out, t_type* type, t_const_value* value) {
- string member_value = value ? render_const_value(type, value)
- : render_default_value(type);
- if ( !member_value.empty() ) {
- out << " = " << member_value;
- }
-}
/**
* Generates the read method for a struct
*/
-void t_erl_generator::generate_erl_struct_info(ostream& out,
- t_struct* tstruct) {
- string name = type_name(tstruct);
-
- indent(out) << "struct_info('" << name << "') ->" << endl;
+void t_erl_generator::generate_erl_struct_info(ostream& out, t_struct* tstruct) {
+ indent(out) << "struct_info('" << type_name(tstruct) << "') ->" << endl;
indent_up();
-
- out << indent() << generate_type_term(tstruct, true) << ";" << endl;
-
+ out << indent() << render_type_term(tstruct, true) << ";" << endl;
indent_down();
out << endl;
}
+void t_erl_generator::generate_erl_extended_struct_info(ostream& out, t_struct* tstruct) {
+ indent(out) << "struct_info_ext('" << type_name(tstruct) << "') ->" << endl;
+ indent_up();
+ out << indent() << render_type_term(tstruct, true, true) << ";" << endl;
+ indent_down();
+ out << endl;
+}
/**
* Generates a thrift service.
@@ -748,7 +748,7 @@
"function_info(" << name_atom << ", params_type) ->" << endl;
indent_up();
- indent(f_service_) << generate_type_term(arg_struct, true) << ";" << endl;
+ indent(f_service_) << render_type_term(arg_struct, true) << ";" << endl;
indent_down();
@@ -759,7 +759,7 @@
if (!tfunction->get_returntype()->is_void())
indent(f_service_) <<
- generate_type_term(tfunction->get_returntype(), false) << ";" << endl;
+ render_type_term(tfunction->get_returntype(), false) << ";" << endl;
else if (tfunction->is_oneway())
indent(f_service_) << "oneway_void;" << endl;
else
@@ -770,7 +770,7 @@
indent(f_service_) <<
"function_info(" << name_atom << ", exceptions) ->" << endl;
indent_up();
- indent(f_service_) << generate_type_term(xs, true) << ";" << endl;
+ indent(f_service_) << render_type_term(xs, true) << ";" << endl;
indent_down();
}
@@ -904,11 +904,9 @@
/**
* Generate an Erlang term which represents a thrift type
*/
-std::string t_erl_generator::generate_type_term(t_type* type,
- bool expand_structs) {
+std::string t_erl_generator::render_type_term(t_type* type, bool expand_structs, bool extended_info) {
type = get_true_type(type);
-
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
switch (tbase) {
@@ -933,28 +931,36 @@
return "i32";
} else if (type->is_struct() || type->is_xception()) {
if (expand_structs) {
- // Convert to format: {struct, [{Fid, TypeTerm}, {Fid, TypeTerm}...]}
- std::stringstream ret;
+ std::stringstream buf;
+ buf << "{struct, [";
- ret << "{struct, [";
+ t_struct::members_type const& fields = static_cast<t_struct*>(type)->get_members();
+ t_struct::members_type::const_iterator i, end = fields.end();
+ for( i = fields.begin(); i != end; )
+ {
+ t_struct::members_type::value_type member = *i;
+ int32_t key = member->get_key();
+ string type = render_type_term(member->get_type(), false, false); // recursive call
- int first = true;
- const vector<t_field*>& fields = ((t_struct*)type)->get_members();
- vector<t_field*>::const_iterator f_iter;
+ if ( !extended_info ) {
+ // Convert to format: {struct, [{Fid, Type}|...]}
+ buf << "{" << key << ", " << type << "}";
+ } else {
+ // Convert to format: {struct, [{Fid, Req, Type, Name, Def}|...]}
+ string name = uncapitalize(member->get_name());
+ string value = render_member_value(member);
+ string requiredness = render_member_requiredness(member);
+ buf << "{" << key << ", " << requiredness << ", " << type << ", '" << name << "'"<< ", " << value << "}";
+ }
- for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
- // Comma separate the tuples
- if (!first) ret << "," << endl << indent();
- first = false;
-
- ret << "{" << (*f_iter)->get_key() << ", " <<
- generate_type_term((*f_iter)->get_type(), false) << "}";
+ if ( ++i != end ) {
+ buf << ", ";
+ }
}
- ret << "]}" << endl;
-
- return ret.str();
+ buf << "]}" << endl;
+ return buf.str();
} else {
return "{struct, {'" + type_module(type) + "', '" + type_name(type) + "'}}";
}
@@ -963,18 +969,18 @@
t_type *key_type = ((t_map*)type)->get_key_type();
t_type *val_type = ((t_map*)type)->get_val_type();
- return "{map, " + generate_type_term(key_type, false) + ", " +
- generate_type_term(val_type, false) + "}";
+ return "{map, " + render_type_term(key_type, false) + ", " +
+ render_type_term(val_type, false) + "}";
} else if (type->is_set()) {
t_type *elem_type = ((t_set*)type)->get_elem_type();
- return "{set, " + generate_type_term(elem_type, false) + "}";
+ return "{set, " + render_type_term(elem_type, false) + "}";
} else if (type->is_list()) {
t_type *elem_type = ((t_list*)type)->get_elem_type();
- return "{list, " + generate_type_term(elem_type, false) + "}";
+ return "{list, " + render_type_term(elem_type, false) + "}";
}
throw "INVALID TYPE IN type_to_enum: " + type->get_name();