THRIFT-2330 Generate PHPDoc comments
Patch: Maurus Cuelenaere
diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc
index 833caef..0f48758 100644
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ b/compiler/cpp/src/generate/t_php_generator.cc
@@ -186,6 +186,18 @@
t_list* tlist,
std::string iter);
+ void generate_php_doc (std::ofstream& out,
+ t_doc* tdoc);
+
+ void generate_php_doc (std::ofstream& out,
+ t_field* tfield);
+
+ void generate_php_doc (std::ofstream& out,
+ t_function* tfunction);
+
+ void generate_php_docstring_comment (std::ofstream &out,
+ string contents);
+
/**
* Helper rendering functions
*/
@@ -196,6 +208,7 @@
std::string argument_list(t_struct* tstruct, bool addStructSignature = true);
std::string type_to_cast(t_type* ttype);
std::string type_to_enum(t_type* ttype);
+ std::string type_to_phpdoc(t_type* ttype);
std::string php_namespace_base(const t_program* p) {
std::string ns = p->get_namespace("php");
@@ -440,12 +453,14 @@
// We're also doing it this way to see how it performs. It's more legible
// code but you can't do things like an 'extract' on it, which is a bit of
// a downer.
+ generate_php_doc(f_types_, tenum);
f_types_ <<
"final class " << tenum->get_name() << " {" << endl;
indent_up();
for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
int value = (*c_iter)->get_value();
+ generate_php_doc(f_types_, *c_iter);
indent(f_types_) <<
"const " << (*c_iter)->get_name() << " = " << value << ";" << endl;
}
@@ -472,6 +487,7 @@
string name = tconst->get_name();
t_const_value* value = tconst->get_value();
+ generate_php_doc(f_types_, tconst);
f_types_ << "$GLOBALS['" << program_name_ << "_CONSTANTS']['" << name << "'] = ";
f_types_ << render_const_value(type, value);
f_types_ << ";" << endl << endl;
@@ -690,6 +706,7 @@
const vector<t_field*>& members = tstruct->get_members();
vector<t_field*>::const_iterator m_iter;
+ generate_php_doc(out, tstruct);
out <<
"class " << php_namespace_declaration(tstruct);
if (is_exception) {
@@ -709,6 +726,7 @@
if ((*m_iter)->get_value() != NULL && !(t->is_struct() || t->is_xception())) {
dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value());
}
+ generate_php_doc(out, *m_iter);
indent(out) <<
"public $" << (*m_iter)->get_name() << " = " << dval << ";" << endl;
}
@@ -1304,12 +1322,14 @@
extends = " extends " + php_namespace(tservice->get_extends()->get_program()) + tservice->get_extends()->get_name();
extends_if = " extends " + php_namespace(tservice->get_extends()->get_program()) + tservice->get_extends()->get_name() + "If";
}
+ generate_php_doc(f_service_, tservice);
f_service_ <<
"interface " << php_namespace_declaration(tservice) << "If" << extends_if << " {" << endl;
indent_up();
vector<t_function*> functions = tservice->get_functions();
vector<t_function*>::iterator f_iter;
for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+ generate_php_doc(f_service_, *f_iter);
indent(f_service_) <<
"public function " << function_signature(*f_iter) << ";" << endl;
}
@@ -2205,6 +2225,93 @@
}
/**
+ * Emits a PHPDoc comment for the given contents
+ */
+void t_php_generator::generate_php_docstring_comment(ofstream &out, string contents) {
+ generate_docstring_comment(out,
+ "/**\n",
+ " * ", contents,
+ " */\n");
+}
+
+/**
+ * Emits a PHPDoc comment if the provided object has a doc in Thrift
+ */
+void t_php_generator::generate_php_doc(ofstream &out, t_doc* tdoc) {
+ if (tdoc->has_doc()) {
+ generate_php_docstring_comment(out, tdoc->get_doc());
+ }
+}
+
+/**
+ * Emits a PHPDoc comment for a field
+ */
+void t_php_generator::generate_php_doc(ofstream &out, t_field* field) {
+ stringstream ss;
+
+ // prepend free-style doc if available
+ if (field->has_doc()) {
+ ss << field->get_doc() << endl;
+ }
+
+ // append @var tag
+ t_type* type = get_true_type(field->get_type());
+ ss << "@var " << type_to_phpdoc(type) << endl;
+
+ generate_php_docstring_comment(out, ss.str());
+}
+
+/**
+ * Emits a PHPDoc comment for a function
+ */
+void t_php_generator::generate_php_doc(ofstream &out, t_function* function) {
+ stringstream ss;
+ if (function->has_doc()) {
+ ss << function->get_doc() << endl;
+ }
+
+ // generate parameter types doc
+ const vector<t_field*>& args = function->get_arglist()->get_members();
+ vector<t_field*>::const_iterator a_iter;
+ for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) {
+ t_field* arg = *a_iter;
+ ss << "@param " << type_to_phpdoc(arg->get_type()) << " $" << arg->get_name();
+ if (arg->has_doc()) {
+ ss << " " << arg->get_doc();
+ }
+ ss << endl;
+ }
+
+ // generate return type doc
+ t_type* ret_type = function->get_returntype();
+ if (!ret_type->is_void() || ret_type->has_doc()) {
+ ss << "@return " << type_to_phpdoc(ret_type);
+ if (ret_type->has_doc()) {
+ ss << " " << ret_type->get_doc();
+ }
+ ss << endl;
+ }
+
+ // generate exceptions doc
+ const vector<t_field*>& excs = function->get_xceptions()->get_members();
+ vector<t_field*>::const_iterator e_iter;
+ for (e_iter = excs.begin(); e_iter != excs.end(); ++e_iter) {
+ t_field* exc = *e_iter;
+ ss << "@throws " << type_to_phpdoc(exc->get_type());
+ if (exc->has_doc()) {
+ ss << " " << exc->get_doc();
+ }
+ ss << endl;
+ }
+
+ generate_docstring_comment(out,
+ "/**\n",
+ " * ", ss.str(),
+ " */\n");
+}
+
+
+/**
* Declares a field, which may include initialization as necessary.
*
* @param ttype The type
@@ -2363,6 +2470,59 @@
throw "INVALID TYPE IN type_to_enum: " + type->get_name();
}
+/**
+ * Converts the parse type to a PHPDoc string for the given type.
+ */
+string t_php_generator ::type_to_phpdoc(t_type* type) {
+ type = get_true_type(type);
+
+ if (type->is_base_type()) {
+ t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+ switch (tbase) {
+ case t_base_type::TYPE_VOID:
+ return "void";
+ case t_base_type::TYPE_STRING:
+ return "string";
+ case t_base_type::TYPE_BOOL:
+ return "bool";
+ case t_base_type::TYPE_BYTE:
+ return "int";
+ case t_base_type::TYPE_I16:
+ return "int";
+ case t_base_type::TYPE_I32:
+ return "int";
+ case t_base_type::TYPE_I64:
+ return "int";
+ case t_base_type::TYPE_DOUBLE:
+ return "double";
+ }
+ } else if (type->is_enum()) {
+ return "int";
+ } else if (type->is_struct() || type->is_xception()) {
+ return php_namespace(type->get_program()) + type->get_name();
+ } else if (type->is_map()) {
+ return "array";
+ } else if (type->is_set()) {
+ t_set* tset = static_cast<t_set*>(type);
+ t_type* t_elem = tset->get_elem_type();
+ if (t_elem->is_container()) {
+ return "(" + type_to_phpdoc(t_elem) + ")[]";
+ } else {
+ return type_to_phpdoc(t_elem) + "[]";
+ }
+ } else if (type->is_list()) {
+ t_list* tlist = static_cast<t_list*>(type);
+ t_type* t_elem = tlist->get_elem_type();
+ if (t_elem->is_container()) {
+ return "(" + type_to_phpdoc(t_elem) + ")[]";
+ } else {
+ return type_to_phpdoc(t_elem) + "[]";
+ }
+ }
+
+ throw "INVALID TYPE IN type_to_enum: " + type->get_name();
+}
+
THRIFT_REGISTER_GENERATOR(php, "PHP",
" inlined: Generate PHP inlined files\n"
" server: Generate PHP server stubs\n"