THRIFT-3582 Erlang libraries should have service metadata
Client: Erlang
Patch: Steve Cohen <steve@pinterest.com>
diff --git a/compiler/cpp/src/generate/t_erl_generator.cc b/compiler/cpp/src/generate/t_erl_generator.cc
index 60fecd4..78d757e 100644
--- a/compiler/cpp/src/generate/t_erl_generator.cc
+++ b/compiler/cpp/src/generate/t_erl_generator.cc
@@ -101,12 +101,16 @@
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);
+ void generate_type_metadata(std::string function_name, vector<string> names);
+ void generate_enum_info(t_enum* tenum);
+ void generate_enum_metadata();
/**
* Service-level generation functions
*/
void generate_service_helpers(t_service* tservice);
+ void generate_service_metadata(t_service* tservice);
void generate_service_interface(t_service* tservice);
void generate_function_info(t_service* tservice, t_function* tfunction);
@@ -204,6 +208,13 @@
std::ostringstream f_service_;
std::ofstream f_service_file_;
std::ofstream f_service_hrl_;
+
+ /**
+ * Metadata containers
+ */
+ std::vector<std::string> v_struct_names_;
+ std::vector<std::string> v_enum_names_;
+ std::vector<t_enum*> v_enums_;
};
/**
@@ -312,6 +323,10 @@
export_types_string("struct_info", 1);
export_types_string("struct_info_ext", 1);
+ export_types_string("enum_info", 1);
+ export_types_string("enum_names", 0);
+ export_types_string("struct_names", 0);
+
f_types_file_ << "-export([" << export_types_lines_.str() << "])." << endl << endl;
f_types_file_ << f_info_.str();
@@ -320,6 +335,10 @@
f_types_file_ << f_info_ext_.str();
f_types_file_ << "struct_info_ext(_) -> erlang:error(function_clause)." << endl << endl;
+ generate_type_metadata("struct_names", v_struct_names_);
+ generate_enum_metadata();
+ generate_type_metadata("enum_names", v_enum_names_);
+
hrl_footer(f_types_hrl_file_, string("BOGUS"));
f_types_file_.close();
@@ -327,6 +346,27 @@
f_consts_.close();
}
+void t_erl_generator::generate_type_metadata(std::string function_name, vector<string> names) {
+ vector<string>::iterator s_iter;
+ size_t num_structs = names.size();
+
+ indent(f_types_file_) << function_name << "() ->\n";
+ indent_up();
+ indent(f_types_file_) << "[";
+
+
+ for(size_t i=0; i < num_structs; i++) {
+ f_types_file_ << atomify(names.at(i));
+
+ if (i < num_structs - 1) {
+ f_types_file_ << ", ";
+ }
+ }
+
+ f_types_file_ << "].\n\n";
+ indent_down();
+}
+
/**
* Generates a typedef. no op
*
@@ -346,6 +386,9 @@
vector<t_enum_value*> constants = tenum->get_constants();
vector<t_enum_value*>::iterator c_iter;
+ v_enums_.push_back(tenum);
+ v_enum_names_.push_back(tenum->get_name());
+
for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
int value = (*c_iter)->get_value();
string name = (*c_iter)->get_name();
@@ -357,6 +400,40 @@
f_types_hrl_file_ << endl;
}
+void t_erl_generator::generate_enum_info(t_enum* tenum){
+ vector<t_enum_value*> constants = tenum->get_constants();
+ size_t num_constants = constants.size();
+
+ indent(f_types_file_) << "enum_info(" << atomify(tenum->get_name()) << ") ->\n";
+ indent_up();
+ indent(f_types_file_) << "[\n";
+
+ for(size_t i=0; i < num_constants; i++) {
+ indent_up();
+ t_enum_value* value = constants.at(i);
+ indent(f_types_file_) << "{" << atomify(value->get_name()) << ", " << value->get_value() << "}";
+
+ if (i < num_constants - 1) {
+ f_types_file_ << ",\n";
+ }
+ indent_down();
+ }
+ f_types_file_ << "\n";
+ indent(f_types_file_) << "];\n\n";
+ indent_down();
+}
+
+void t_erl_generator::generate_enum_metadata() {
+ size_t enum_count = v_enums_.size();
+
+ for(size_t i=0; i < enum_count; i++) {
+ t_enum* tenum = v_enums_.at(i);
+ generate_enum_info(tenum);
+ }
+
+ indent(f_types_file_) << "enum_info(_) -> erlang:error(function_clause).\n\n";
+}
+
/**
* Generate a constant value
*/
@@ -567,6 +644,7 @@
* Generates a struct
*/
void t_erl_generator::generate_struct(t_struct* tstruct) {
+ v_struct_names_.push_back(tstruct->get_name());
generate_erl_struct(tstruct, false);
}
@@ -705,6 +783,8 @@
generate_service_interface(tservice);
+ generate_service_metadata(tservice);
+
// indent_down();
f_service_file_ << erl_autogen_comment() << endl << "-module(" << service_name_ << "_thrift)."
@@ -724,6 +804,28 @@
f_service_hrl_.close();
}
+void t_erl_generator::generate_service_metadata(t_service* tservice) {
+ export_string("function_names", 0);
+ vector<t_function*> functions = tservice->get_functions();
+ vector<t_function*>::iterator f_iter;
+ size_t num_functions = functions.size();
+
+ indent(f_service_) << "function_names() -> " << endl;
+ indent_up();
+ indent(f_service_) << "[";
+
+ for (size_t i=0; i < num_functions; i++) {
+ t_function* current = functions.at(i);
+ f_service_ << atomify(current->get_name());
+ if (i < num_functions - 1) {
+ f_service_ << ", ";
+ }
+ }
+
+ f_service_ << "].\n\n";
+ indent_down();
+}
+
/**
* Generates helper functions for a service.
*