THRIFT-2449 Enhance typedef structure to distinguish between forwards and real typedefs
Client: General Compiler, Delphi
Patch: Jens Geyer
diff --git a/compiler/cpp/src/generate/t_delphi_generator.cc b/compiler/cpp/src/generate/t_delphi_generator.cc
index 1a51e83..4ecc269 100644
--- a/compiler/cpp/src/generate/t_delphi_generator.cc
+++ b/compiler/cpp/src/generate/t_delphi_generator.cc
@@ -85,6 +85,7 @@
 
     void generate_typedef (t_typedef* ttypedef);
     void generate_enum (t_enum* tenum);
+    void generate_forward_declaration(t_struct* tstruct);
     void generate_struct (t_struct* tstruct);
     void generate_xception (t_struct* txception);
     void generate_service (t_service* tservice);
@@ -187,7 +188,7 @@
     string replace_all( string contents, string search, string replace);
     string xml_encode( string contents);
     string xmldoc_encode( string contents);
-	string xmlattrib_encode( string contents);
+    string xmlattrib_encode( string contents);
     void generate_delphi_doc (std::ostream& out, t_field*    field);
     void generate_delphi_doc (std::ostream& out, t_doc*      tdoc);
     void generate_delphi_doc (std::ostream& out, t_function* tdoc);
@@ -215,6 +216,7 @@
     std::ostringstream s_service_impl;
     std::ostringstream s_type_factory_registration;
     std::ostringstream s_type_factory_funcs;
+    bool has_forward;
     bool has_enum;
     bool has_const;
     std::string namespace_dir_;
@@ -237,7 +239,7 @@
     bool register_types_;
     bool constprefix_;
     bool events_;
-	bool xmldoc_;
+    bool xmldoc_;
     void indent_up_impl(){
       ++indent_impl_;
     };
@@ -268,7 +270,7 @@
     size_t found = str.find(search);
     while( (found != string::npos) && (found < str.length())) {
       str.replace( found, slen, repl);
-	  found = str.find(search, found+incr);
+      found = str.find(search, found+incr);
     }
   }
   
@@ -324,7 +326,7 @@
   if( xmldoc_) {
     if (field->get_type()->is_enum()) {
       string combined_message = xmldoc_encode( field->get_doc()) 
-	                          + "\n<seealso cref=\"" 
+                              + "\n<seealso cref=\"" 
                               + xmldoc_encode( type_name(field->get_type()))
                               + "\"/>";
       generate_delphi_docstring_comment(out, combined_message);
@@ -553,6 +555,7 @@
 void t_delphi_generator::init_generator() {
   indent_impl_ = 0;
   namespace_name_ = program_->get_namespace("delphi");
+  has_forward = false;
   has_enum = false;
   has_const = false;
   create_keywords();
@@ -641,8 +644,11 @@
   indent(f_all)  << "c" << tmp_unit << "_Option_XmlDoc         = " << ( xmldoc_         ? "True" : "False") << ";" << endl;
   indent_down();
 
+  f_all  << endl;
   f_all  << "type"  << endl;
-  f_all  << s_forward_decr.str();
+  if(has_forward) {
+    f_all  << s_forward_decr.str() << endl;
+  }
   if (has_enum) {
     indent(f_all) << endl;
     indent(f_all) << "{$SCOPEDENUMS ON}" << endl << endl;
@@ -709,6 +715,21 @@
   indent_down();
 }
 
+void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) {
+  // Forward declare struct def
+  has_forward = true;
+  pverbose("forward declaration of %s\n", type_name(tstruct).c_str());
+  
+  string what = tstruct->is_xception() ? "class" : "interface";
+
+  indent_up();
+  indent(s_forward_decr) << 
+    type_name(tstruct,tstruct->is_xception(),true) << " = " << what << ";" << endl;
+  indent_down();
+  
+  add_defined_type(tstruct);
+}
+
 void t_delphi_generator::generate_typedef(t_typedef* ttypedef) {
   t_type* type = ttypedef->get_type();
 
@@ -718,7 +739,7 @@
     typedefs_pending.push_back( ttypedef); 
     return;
   }
-  
+
   indent_up();
   generate_delphi_doc(s_struct, ttypedef);
   indent(s_struct) << 
@@ -821,7 +842,7 @@
       s_enum << ",";
       s_enum << endl;
     }
-	generate_delphi_doc(s_enum, *c_iter);
+    generate_delphi_doc(s_enum, *c_iter);
     indent(s_enum) << normalize_name((*c_iter)->get_name()) << " = " << value;
   }
   s_enum << endl;
@@ -1568,7 +1589,7 @@
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter)
   {
     generate_delphi_doc(s_service, *f_iter);
-	indent(s_service) <<
+    indent(s_service) <<
       function_signature(*f_iter) << endl;
   }
   indent_down();
@@ -2541,9 +2562,18 @@
 }
 
 string t_delphi_generator::type_name( t_type* ttype, bool b_cls, bool b_no_postfix, bool b_exception_factory, bool b_full_exception_factory) {
-  
-  if (ttype->is_typedef()) {
-    return normalize_name( "T"+((t_typedef*)ttype)->get_symbolic());
+
+  if (ttype->is_typedef()) {    
+    t_typedef* tdef = (t_typedef*)ttype;
+    if( tdef->is_forward_typedef()) {  // forward types according to THRIFT-2421 
+      if( tdef->get_type() != NULL)  {
+        return type_name( tdef->get_type(), b_cls, b_no_postfix, b_exception_factory, b_full_exception_factory);
+      } else {
+        throw "unresolved forward declaration: " + tdef->get_symbolic();
+      }
+    } else {
+      return normalize_name( "T"+tdef->get_symbolic());
+    }
   }
   
   string typ_nm;
diff --git a/compiler/cpp/src/parse/t_typedef.h b/compiler/cpp/src/parse/t_typedef.h
index 1bea4c9..52a7567 100644
--- a/compiler/cpp/src/parse/t_typedef.h
+++ b/compiler/cpp/src/parse/t_typedef.h
@@ -36,6 +36,7 @@
     t_type(program, symbolic),
     type_(type),
     symbolic_(symbolic),
+    forward_(false),
     seen_(false) {}
 
   /**
@@ -43,10 +44,11 @@
    * resolved at a later time, like for forward declarations or
    * recursive types.
    */
-  t_typedef(t_program* program, const std::string& symbolic) :
+  t_typedef(t_program* program, const std::string& symbolic, bool forward) :
     t_type(program, symbolic),
     type_(NULL),
     symbolic_(symbolic),
+    forward_(forward),
     seen_(false) {}
 
   ~t_typedef() {}
@@ -57,6 +59,10 @@
     return symbolic_;
   }
 
+  bool is_forward_typedef() const {
+    return forward_;
+  }
+
   bool is_typedef() const {
     return true;
   }
@@ -81,6 +87,7 @@
  private:
   t_type* type_;
   std::string symbolic_;
+  bool forward_;
   mutable bool seen_;
 };
 
diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy
index e2467df..edb05f9 100644
--- a/compiler/cpp/src/thrifty.yy
+++ b/compiler/cpp/src/thrifty.yy
@@ -1092,7 +1092,7 @@
              declared.  Either way allow it and we'll figure it out
              during generation.
            */
-          $$ = new t_typedef(g_program, $1);
+          $$ = new t_typedef(g_program, $1, true);
         }
       }
     }