Add PHP namespacing support to Thrift

Summary: "php_namespace Whoa" at the top of your Thrift file, then all your defined class names start with "Whoa_"

Reviewed By: aditya


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664908 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 90d7de8..953bb55 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -102,7 +102,7 @@
  */
 void t_cpp_generator::generate_typedef(t_typedef* ttypedef) {
   f_types_ <<
-    indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " << ttypedef->get_symbolic() << ";" << endl <<
+    indent() << "typedef " << type_name(ttypedef->get_type(), false, true) << " " << ttypedef->get_symbolic() << ";" << endl <<
     endl;
 }
 
@@ -1947,32 +1947,36 @@
  * @param ttype The type
  * @return String of the type name, i.e. std::set<type>
  */
-string t_cpp_generator::type_name(t_type* ttype, bool in_typedef) {
+string t_cpp_generator::type_name(t_type* ttype, bool arg, bool in_typedef) {
   if (ttype->is_base_type()) {
     return base_type_name(((t_base_type*)ttype)->get_base());
   }
   
   // Check for a custom overloaded C++ name
   if (ttype->is_container()) {
+    string cname;
+
     t_container* tcontainer = (t_container*) ttype;
     if (tcontainer->has_cpp_name()) {
-      return tcontainer->get_cpp_name();
+      cname = tcontainer->get_cpp_name();
+    } else if (ttype->is_map()) {
+      t_map* tmap = (t_map*) ttype;
+      cname = "std::map<" +
+        type_name(tmap->get_key_type(), in_typedef) + ", " +
+        type_name(tmap->get_val_type(), in_typedef) + "> ";
+    } else if (ttype->is_set()) {
+      t_set* tset = (t_set*) ttype;
+      cname = "std::set<" + type_name(tset->get_elem_type(), in_typedef) + "> ";
+    } else if (ttype->is_list()) {
+      t_list* tlist = (t_list*) ttype;
+      cname = "std::vector<" + type_name(tlist->get_elem_type(), in_typedef) + "> ";
     }
-  }
-  // Use std:: types for containers
-  if (ttype->is_map()) {
-    t_map* tmap = (t_map*) ttype;
-    return "std::map<" +
-      type_name(tmap->get_key_type(), in_typedef) + ", " +
-      type_name(tmap->get_val_type(), in_typedef) + "> ";
-  }
-  if (ttype->is_set()) {
-    t_set* tset = (t_set*) ttype;
-    return "std::set<" + type_name(tset->get_elem_type(), in_typedef) + "> ";
-  }
-  if (ttype->is_list()) {
-    t_list* tlist = (t_list*) ttype;
-    return "std::vector<" + type_name(tlist->get_elem_type(), in_typedef) + "> ";
+    
+    if (arg) {
+      return "const " + cname + "&";
+    } else {
+      return cname;
+    }
   }
 
   string class_prefix;
@@ -1981,15 +1985,22 @@
   }
 
   // Check if it needs to be namespaced
+  string pname;
   t_program* program = ttype->get_program();
   if (program != NULL && program != program_) {
-    return
+    pname = 
       class_prefix +
       namespace_prefix(program->get_cpp_namespace()) +
       ttype->get_name();
+  } else {
+    pname = class_prefix + ttype->get_name();
   }
 
-  return class_prefix + ttype->get_name();
+  if (arg) {
+    return "const " + pname + "&";
+  } else {
+    return pname;
+  }
 }
 
 /**
diff --git a/compiler/cpp/src/generate/t_cpp_generator.h b/compiler/cpp/src/generate/t_cpp_generator.h
index f0c7ec2..83780ed 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.h
+++ b/compiler/cpp/src/generate/t_cpp_generator.h
@@ -127,7 +127,7 @@
   std::string namespace_prefix(std::string ns);
   std::string namespace_open(std::string ns);
   std::string namespace_close(std::string ns);
-  std::string type_name(t_type* ttype, bool in_typedef=false);
+  std::string type_name(t_type* ttype, bool arg=false, bool in_typedef=false);
   std::string base_type_name(t_base_type::t_base tbase);
   std::string declare_field(t_field* tfield, bool init=false);
   std::string function_signature(t_function* tfunction, std::string prefix="");
diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc
index cb2573c..bc348c4 100644
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ b/compiler/cpp/src/generate/t_php_generator.cc
@@ -71,7 +71,7 @@
  */
 void t_php_generator::generate_enum(t_enum* tenum) {
   f_types_ <<
-    "$GLOBALS['E_" << tenum->get_name() << "'] = array(" << endl;
+    "$GLOBALS['" << php_namespace(tenum->get_program()) << "E_" << tenum->get_name() << "'] = array(" << endl;
   
   vector<t_enum_value*> constants = tenum->get_constants();
   vector<t_enum_value*>::iterator c_iter;
@@ -95,7 +95,7 @@
   // code but you can't do things like an 'extract' on it, which is a bit of
   // a downer.
   f_types_ <<
-    "final class " << tenum->get_name() << " {" << endl;
+    "final class " << php_namespace(tenum->get_program()) << tenum->get_name() << " {" << endl;
   indent_up();
   
   value = -1;
@@ -165,7 +165,7 @@
   } else if (type->is_enum()) {
     indent(f_consts_) << value->get_integer();
   } else if (type->is_struct() || type->is_xception()) {
-    f_consts_ << "new " << type->get_name() << "(array(" << endl;
+    f_consts_ << "new " << php_namespace(type->get_program()) << type->get_name() << "(array(" << endl;
     indent_up();
     const vector<t_field*>& fields = ((t_struct*)type)->get_members();
     vector<t_field*>::const_iterator f_iter;
@@ -268,7 +268,7 @@
   vector<t_field*>::const_iterator m_iter; 
 
   out <<
-    "class " << tstruct->get_name();
+    "class " << php_namespace(tstruct->get_program()) << tstruct->get_name();
   if (is_exception) {
     out << " extends Exception";
   }
@@ -1213,7 +1213,7 @@
                                                   t_struct* tstruct,
                                                   string prefix) {
   out <<
-    indent() << "$" << prefix << " = new " << tstruct->get_name() << "();" << endl <<
+    indent() << "$" << prefix << " = new " << php_namespace(tstruct->get_program()) << tstruct->get_name() << "();" << endl <<
     indent() << "$xfer += $" << prefix << "->read($input);" << endl;
 }
 
@@ -1665,7 +1665,7 @@
       result += " = array()";
     } else if (type->is_struct() || type->is_xception()) {
       if (obj) {
-        result += " = new " + type->get_name() + "()";
+        result += " = new " + php_namespace(type->get_program()) + type->get_name() + "()";
       } else {
         result += " = null";
       }
diff --git a/compiler/cpp/src/generate/t_php_generator.h b/compiler/cpp/src/generate/t_php_generator.h
index e276eb4..ddea1a2 100644
--- a/compiler/cpp/src/generate/t_php_generator.h
+++ b/compiler/cpp/src/generate/t_php_generator.h
@@ -130,6 +130,11 @@
   std::string argument_list(t_struct* tstruct);
   std::string type_to_enum(t_type* ttype);
 
+  std::string php_namespace(t_program* p) {
+    std::string ns = p->get_php_namespace();
+    return ns.size() ? (ns + "_") : "";
+  }
+
  private:
 
   /**
diff --git a/compiler/cpp/src/parse/t_program.h b/compiler/cpp/src/parse/t_program.h
index b0eb60e..9a86621 100644
--- a/compiler/cpp/src/parse/t_program.h
+++ b/compiler/cpp/src/parse/t_program.h
@@ -114,6 +114,14 @@
     return cpp_includes_;
   }
 
+  void set_php_namespace(std::string php_namespace) {
+    php_namespace_ = php_namespace;
+  }
+
+  const std::string& get_php_namespace() const {
+    return php_namespace_;
+  }
+
   void set_java_package(std::string java_package) {
     java_package_ = java_package;
   }
@@ -154,6 +162,9 @@
   // C++ extra includes
   std::vector<std::string> cpp_includes_;
 
+  // PHP namespace
+  std::string php_namespace_;
+
   // Java package
   std::string java_package_;
 
diff --git a/compiler/cpp/src/thrift.l b/compiler/cpp/src/thrift.l
index 44927fa..324c5ea 100644
--- a/compiler/cpp/src/thrift.l
+++ b/compiler/cpp/src/thrift.l
@@ -58,6 +58,7 @@
 "cpp_include"   { return tok_cpp_include;   }
 "cpp_type"      { return tok_cpp_type;      }
 "java_package"  { return tok_java_package;  }
+"php_namespace" { return tok_php_namespace; }
 "include"       { return tok_include;       }
 
 "void"          { return tok_void;          }
diff --git a/compiler/cpp/src/thrift.y b/compiler/cpp/src/thrift.y
index 9dee535..8dbe621 100644
--- a/compiler/cpp/src/thrift.y
+++ b/compiler/cpp/src/thrift.y
@@ -64,6 +64,7 @@
 %token tok_cpp_namespace
 %token tok_cpp_include
 %token tok_cpp_type
+%token tok_php_namespace
 %token tok_java_package
 
 /**
@@ -198,6 +199,13 @@
         g_program->add_cpp_include($2);
       }
     }
+| tok_php_namespace tok_identifier
+    {
+      pdebug("Header -> tok_php_namespace tok_identifier");
+      if (g_parse_mode == PROGRAM) {
+        g_program->set_php_namespace($2);
+      }
+    }
 | tok_java_package tok_identifier
     {
       pdebug("Header -> tok_java_package tok_identifier");