Repository: thrift
Updated Branches:
  refs/heads/master 83cd3e8d4 -> 1f6e380c5


THRIFT-727 - C++: what() method of generated exceptions will provide more 
information

Patch: Anna Dymek <[email protected]>
Client: C++

This closes #469


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/3b115dfa
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/3b115dfa
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/3b115dfa

Branch: refs/heads/master
Commit: 3b115dfa614cfac7af86d81d99f69b381508b75e
Parents: 83cd3e8
Author: Konrad Grochowski <[email protected]>
Authored: Mon May 18 17:58:36 2015 +0200
Committer: Konrad Grochowski <[email protected]>
Committed: Mon May 18 19:47:23 2015 +0200

----------------------------------------------------------------------
 compiler/cpp/src/generate/t_cpp_generator.cc | 58 ++++++++++++++++++++++-
 lib/cpp/test/processor/ProcessorTest.cpp     |  3 ++
 tutorial/c_glib/c_glib_server.c              |  4 +-
 tutorial/cpp/CppClient.cpp                   |  1 +
 tutorial/cpp/CppServer.cpp                   |  4 +-
 tutorial/d/server.d                          |  4 +-
 tutorial/erl/server.erl                      |  4 +-
 tutorial/haxe/src/CalculatorHandler.hx       |  4 +-
 tutorial/hs/HaskellServer.hs                 |  2 +-
 tutorial/java/src/CalculatorHandler.java     |  4 +-
 tutorial/nodejs/NodeServer.js                |  4 +-
 tutorial/nodejs/NodeServerPromise.js         |  4 +-
 tutorial/ocaml/CalcServer.ml                 |  2 +-
 tutorial/perl/PerlServer.pl                  |  4 +-
 tutorial/php/PhpServer.php                   |  4 +-
 tutorial/py.tornado/PythonServer.py          |  4 +-
 tutorial/py.twisted/PythonServer.py          |  4 +-
 tutorial/py/PythonServer.py                  |  4 +-
 tutorial/rb/RubyServer.rb                    |  4 +-
 tutorial/tutorial.thrift                     |  2 +-
 20 files changed, 92 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/compiler/cpp/src/generate/t_cpp_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc 
b/compiler/cpp/src/generate/t_cpp_generator.cc
index 3edd7c8..426434f 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -138,6 +138,7 @@ public:
   void generate_struct_result_writer(std::ofstream& out, t_struct* tstruct, 
bool pointers = false);
   void generate_struct_swap(std::ofstream& out, t_struct* tstruct);
   void generate_struct_ostream_operator(std::ofstream& out, t_struct* tstruct);
+  void generate_exception_what_method(std::ofstream& out, t_struct* tstruct);
 
   /**
    * Service-level generation functions
@@ -239,6 +240,9 @@ public:
                                    bool include_values);
 
   void generate_struct_ostream_operator_decl(std::ofstream& f, t_struct* 
tstruct);
+  void generate_exception_what_method_decl(std::ofstream& f,
+                                           t_struct* tstruct,
+                                           bool external = false);
 
   // These handles checking gen_dense_ and checking for duplicates.
   void generate_local_reflection(std::ofstream& out, t_type* ttype, bool 
is_definition);
@@ -767,6 +771,9 @@ void t_cpp_generator::generate_cpp_struct(t_struct* 
tstruct, bool is_exception)
     generate_move_assignment_operator(f_types_impl_, tstruct);
   }
   generate_struct_ostream_operator(f_types_impl_, tstruct);
+  if (is_exception) {
+    generate_exception_what_method(f_types_impl_, tstruct);
+  }
 }
 
 void t_cpp_generator::generate_copy_constructor(ofstream& out,
@@ -1113,7 +1120,15 @@ void 
t_cpp_generator::generate_struct_declaration(ofstream& out,
   // ostream operator<<
   out << indent() << "friend ";
   generate_struct_ostream_operator_decl(out, tstruct);
-  out << ";" << endl;
+  out << ";" << endl << endl;
+
+  // std::exception::what()
+  if (is_exception) {
+    out << indent() << "mutable std::string thriftTExceptionMessageHolder_;" 
<< endl;
+    out << indent();
+    generate_exception_what_method_decl(out, tstruct, false);
+    out << ";" << endl;
+  }
 
   indent_down();
   indent(out) << "};" << endl << endl;
@@ -1626,6 +1641,16 @@ void 
t_cpp_generator::generate_struct_ostream_operator_decl(std::ofstream& out,
   out << "std::ostream& operator<<(std::ostream& out, const " << 
tstruct->get_name() << "& obj)";
 }
 
+void t_cpp_generator::generate_exception_what_method_decl(std::ofstream& out,
+                                                          t_struct* tstruct,
+                                                          bool external) {
+  out << "const char* ";
+  if (external) {
+    out << tstruct->get_name() << "::";
+  }
+  out << "what() const throw()";
+}
+
 namespace struct_ostream_operator_generator {
 void generate_required_field_value(std::ofstream& out, const t_field* field) {
   out << " << to_string(obj." << field->get_name() << ")";
@@ -1700,6 +1725,37 @@ void 
t_cpp_generator::generate_struct_ostream_operator(std::ofstream& out, t_str
 }
 
 /**
+ * Generates what() method for exceptions
+ */
+void t_cpp_generator::generate_exception_what_method(std::ofstream& out, 
t_struct* tstruct) {
+  out << indent();
+  generate_exception_what_method_decl(out, tstruct, true);
+  out << " {" << endl;
+
+  indent_up();
+  out << indent() << "try {" << endl;
+
+  indent_up();
+  out << indent() << "std::stringstream ss;" << endl;
+  out << indent() << "ss << \"TException - service has thrown: \" << *this;" 
<< endl;
+  out << indent() << "this->thriftTExceptionMessageHolder_ = ss.str();" << 
endl;
+  out << indent() << "return this->thriftTExceptionMessageHolder_.c_str();" << 
endl;
+  indent_down();
+
+  out << indent() << "} catch (const std::exception& e) {" << endl;
+
+  indent_up();
+  out << indent() << "return \"TException - service has thrown: " << 
tstruct->get_name() << "\";"
+      << endl;
+  indent_down();
+
+  out << indent() << "}" << endl;
+
+  indent_down();
+  out << "}" << endl << endl;
+}
+
+/**
  * Generates a thrift service. In C++, this comprises an entirely separate
  * header and source file. The header file defines the methods and includes
  * the data types defined in the main header file, and the implementation

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/lib/cpp/test/processor/ProcessorTest.cpp
----------------------------------------------------------------------
diff --git a/lib/cpp/test/processor/ProcessorTest.cpp 
b/lib/cpp/test/processor/ProcessorTest.cpp
index 655f481..40d926e 100644
--- a/lib/cpp/test/processor/ProcessorTest.cpp
+++ b/lib/cpp/test/processor/ProcessorTest.cpp
@@ -765,6 +765,9 @@ void testExpectedError() {
     BOOST_FAIL("expected MyError to be thrown");
   } catch (const MyError& e) {
     BOOST_CHECK_EQUAL(message, e.message);
+    // Check if std::exception::what() is handled properly
+    size_t message_pos = std::string(e.what()).find("TException - service has 
thrown: MyError");
+    BOOST_CHECK_NE(message_pos, std::string::npos);
   }
 
   // Now we should see the events for a normal call finish

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/c_glib/c_glib_server.c
----------------------------------------------------------------------
diff --git a/tutorial/c_glib/c_glib_server.c b/tutorial/c_glib/c_glib_server.c
index a20ab54..000d97c 100644
--- a/tutorial/c_glib/c_glib_server.c
+++ b/tutorial/c_glib/c_glib_server.c
@@ -231,7 +231,7 @@ tutorial_calculator_handler_calculate (CalculatorIf      
*iface,
          setting the corresponding output parameter to a new instance
          of its type and returning FALSE. */
       *ouch = g_object_new (TYPE_INVALID_OPERATION,
-                            "what", op,
+                            "whatOp", op,
                             "why",  g_strdup ("Cannot divide by 0"),
                             NULL);
       result = FALSE;
@@ -249,7 +249,7 @@ tutorial_calculator_handler_calculate (CalculatorIf      
*iface,
 
   default:
     *ouch = g_object_new (TYPE_INVALID_OPERATION,
-                          "what", op,
+                          "whatOp", op,
                           "why",  g_strdup ("Invalid Operation"),
                           NULL);
     result = FALSE;

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/cpp/CppClient.cpp
----------------------------------------------------------------------
diff --git a/tutorial/cpp/CppClient.cpp b/tutorial/cpp/CppClient.cpp
index 258cbd6..2763fee 100644
--- a/tutorial/cpp/CppClient.cpp
+++ b/tutorial/cpp/CppClient.cpp
@@ -58,6 +58,7 @@ int main() {
     } catch (InvalidOperation& io) {
       cout << "InvalidOperation: " << io.why << endl;
       // or using generated operator<<: cout << io << endl;
+      // or by using std::exception native method what(): cout << io.what() << 
endl;
     }
 
     work.op = Operation::SUBTRACT;

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/cpp/CppServer.cpp
----------------------------------------------------------------------
diff --git a/tutorial/cpp/CppServer.cpp b/tutorial/cpp/CppServer.cpp
index 84b79d4..6b22193 100644
--- a/tutorial/cpp/CppServer.cpp
+++ b/tutorial/cpp/CppServer.cpp
@@ -71,7 +71,7 @@ public:
     case Operation::DIVIDE:
       if (work.num2 == 0) {
         InvalidOperation io;
-        io.what = work.op;
+        io.whatOp = work.op;
         io.why = "Cannot divide by 0";
         throw io;
       }
@@ -79,7 +79,7 @@ public:
       break;
     default:
       InvalidOperation io;
-      io.what = work.op;
+      io.whatOp = work.op;
       io.why = "Invalid Operation";
       throw io;
     }

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/d/server.d
----------------------------------------------------------------------
diff --git a/tutorial/d/server.d b/tutorial/d/server.d
index d32b937..cbcedcc 100644
--- a/tutorial/d/server.d
+++ b/tutorial/d/server.d
@@ -62,7 +62,7 @@ class CalculatorHandler : Calculator {
     case Operation.DIVIDE:
       if (work.num2 == 0) {
         auto io = new InvalidOperation();
-        io.what = work.op;
+        io.whatOp = work.op;
         io.why = "Cannot divide by 0";
         throw io;
       }
@@ -70,7 +70,7 @@ class CalculatorHandler : Calculator {
       break;
     default:
       auto io = new InvalidOperation();
-      io.what = work.op;
+      io.whatOp = work.op;
       io.why = "Invalid Operation";
       throw io;
     }

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/erl/server.erl
----------------------------------------------------------------------
diff --git a/tutorial/erl/server.erl b/tutorial/erl/server.erl
index 4915606..f1e7357 100644
--- a/tutorial/erl/server.erl
+++ b/tutorial/erl/server.erl
@@ -44,12 +44,12 @@ calculate(Logid, Work) ->
         ?tutorial_Operation_MULTIPLY -> Num1 * Num2;
 
         ?tutorial_Operation_DIVIDE when Num2 == 0 ->
-          throw(#invalidOperation{what=Op, why="Cannot divide by 0"});
+          throw(#invalidOperation{whatOp=Op, why="Cannot divide by 0"});
         ?tutorial_Operation_DIVIDE ->
           Num1 div Num2;
 
         _Else ->
-          throw(#invalidOperation{what=Op, why="Invalid operation"})
+          throw(#invalidOperation{whatOp=Op, why="Invalid operation"})
     end.
 
 getStruct(Key) ->

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/haxe/src/CalculatorHandler.hx
----------------------------------------------------------------------
diff --git a/tutorial/haxe/src/CalculatorHandler.hx 
b/tutorial/haxe/src/CalculatorHandler.hx
index 3376fb6..e9752db 100644
--- a/tutorial/haxe/src/CalculatorHandler.hx
+++ b/tutorial/haxe/src/CalculatorHandler.hx
@@ -67,7 +67,7 @@ class CalculatorHandler implements Calculator {
                 if (work.num2 == 0)
                 {
                     var io = new InvalidOperation();
-                    io.what = work.op;
+                    io.whatOp = work.op;
                     io.why = "Cannot divide by 0";
                     throw io;
                 }
@@ -75,7 +75,7 @@ class CalculatorHandler implements Calculator {
 
             default:
                 var io = new InvalidOperation();
-                io.what = work.op;
+                io.whatOp = work.op;
                 io.why = "Unknown operation";
                 throw io;
         }

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/hs/HaskellServer.hs
----------------------------------------------------------------------
diff --git a/tutorial/hs/HaskellServer.hs b/tutorial/hs/HaskellServer.hs
index 77f1679..cfe1344 100644
--- a/tutorial/hs/HaskellServer.hs
+++ b/tutorial/hs/HaskellServer.hs
@@ -74,7 +74,7 @@ instance Calculator_Iface CalculatorHandler where
                     if num2 work == 0 then
                         throw $
                               InvalidOperation {
-                                 invalidOperation_what = fromIntegral $ 
fromEnum $ op work,
+                                 invalidOperation_whatOp = fromIntegral $ 
fromEnum $ op work,
                                  invalidOperation_why = "Cannot divide by 0"
                                             }
                     else

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/java/src/CalculatorHandler.java
----------------------------------------------------------------------
diff --git a/tutorial/java/src/CalculatorHandler.java 
b/tutorial/java/src/CalculatorHandler.java
index 4216be5..92944b0 100644
--- a/tutorial/java/src/CalculatorHandler.java
+++ b/tutorial/java/src/CalculatorHandler.java
@@ -58,7 +58,7 @@ public class CalculatorHandler implements Calculator.Iface {
     case DIVIDE:
       if (work.num2 == 0) {
         InvalidOperation io = new InvalidOperation();
-        io.what = work.op.getValue();
+        io.whatOp = work.op.getValue();
         io.why = "Cannot divide by 0";
         throw io;
       }
@@ -66,7 +66,7 @@ public class CalculatorHandler implements Calculator.Iface {
       break;
     default:
       InvalidOperation io = new InvalidOperation();
-      io.what = work.op.getValue();
+      io.whatOp = work.op.getValue();
       io.why = "Unknown operation";
       throw io;
     }

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/nodejs/NodeServer.js
----------------------------------------------------------------------
diff --git a/tutorial/nodejs/NodeServer.js b/tutorial/nodejs/NodeServer.js
index ba36105..55d3817 100644
--- a/tutorial/nodejs/NodeServer.js
+++ b/tutorial/nodejs/NodeServer.js
@@ -48,7 +48,7 @@ var server = thrift.createServer(Calculator, {
     } else if (work.op === ttypes.Operation.DIVIDE) {
       if (work.num2 === 0) {
         var x = new ttypes.InvalidOperation();
-        x.what = work.op;
+        x.whatOp = work.op;
         x.why = 'Cannot divide by 0';
         result(x);
         return;
@@ -56,7 +56,7 @@ var server = thrift.createServer(Calculator, {
       val = work.num1 / work.num2;
     } else {
       var x = new ttypes.InvalidOperation();
-      x.what = work.op;
+      x.whatOp = work.op;
       x.why = 'Invalid operation';
       result(x);
       return;

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/nodejs/NodeServerPromise.js
----------------------------------------------------------------------
diff --git a/tutorial/nodejs/NodeServerPromise.js 
b/tutorial/nodejs/NodeServerPromise.js
index 4fd0a35..bff287b 100644
--- a/tutorial/nodejs/NodeServerPromise.js
+++ b/tutorial/nodejs/NodeServerPromise.js
@@ -47,14 +47,14 @@ var server = thrift.createServer(Calculator, {
     } else if (work.op === ttypes.Operation.DIVIDE) {
       if (work.num2 === 0) {
         var x = new ttypes.InvalidOperation();
-        x.what = work.op;
+        x.whatOp = work.op;
         x.why = 'Cannot divide by 0';
                throw x;
       }
       val = work.num1 / work.num2;
     } else {
       var x = new ttypes.InvalidOperation();
-      x.what = work.op;
+      x.whatOp = work.op;
       x.why = 'Invalid operation';
       throw x;
     }

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/ocaml/CalcServer.ml
----------------------------------------------------------------------
diff --git a/tutorial/ocaml/CalcServer.ml b/tutorial/ocaml/CalcServer.ml
index 24d7d03..b5facb7 100755
--- a/tutorial/ocaml/CalcServer.ml
+++ b/tutorial/ocaml/CalcServer.ml
@@ -49,7 +49,7 @@ object (self)
        | Operation.DIVIDE ->
            if w#grab_num2 = Int32.zero then
              let io = new invalidOperation in
-               io#set_what (Operation.to_i w#grab_op) ;
+               io#set_whatOp (Operation.to_i w#grab_op) ;
                io#set_why "Cannot divide by 0" ;
                raise (InvalidOperation io)
            else

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/perl/PerlServer.pl
----------------------------------------------------------------------
diff --git a/tutorial/perl/PerlServer.pl b/tutorial/perl/PerlServer.pl
index a40ec69..adec978 100644
--- a/tutorial/perl/PerlServer.pl
+++ b/tutorial/perl/PerlServer.pl
@@ -68,14 +68,14 @@ sub calculate
     if ($num2 == 0)
     {
       my $x = new tutorial::InvalidOperation;
-      $x->what($op);
+      $x->whatOp($op);
       $x->why('Cannot divide by 0');
       die $x;
     }
     $val = $num1 / $num2;
   } else {
     my $x = new tutorial::InvalidOperation;
-    $x->what($op);
+    $x->whatOp($op);
     $x->why('Invalid operation');
     die $x;
   }

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/php/PhpServer.php
----------------------------------------------------------------------
diff --git a/tutorial/php/PhpServer.php b/tutorial/php/PhpServer.php
index 4af70a4..22ae43e 100755
--- a/tutorial/php/PhpServer.php
+++ b/tutorial/php/PhpServer.php
@@ -79,7 +79,7 @@ class CalculatorHandler implements \tutorial\CalculatorIf {
       case \tutorial\Operation::DIVIDE:
         if ($w->num2 == 0) {
           $io = new \tutorial\InvalidOperation();
-          $io->what = $w->op;
+          $io->whatOp = $w->op;
           $io->why = "Cannot divide by 0";
           throw $io;
         }
@@ -87,7 +87,7 @@ class CalculatorHandler implements \tutorial\CalculatorIf {
         break;
       default:
         $io = new \tutorial\InvalidOperation();
-        $io->what = $w->op;
+        $io->whatOp = $w->op;
         $io->why = "Invalid Operation";
         throw $io;
     }

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/py.tornado/PythonServer.py
----------------------------------------------------------------------
diff --git a/tutorial/py.tornado/PythonServer.py 
b/tutorial/py.tornado/PythonServer.py
index 52932ff..7a34107 100755
--- a/tutorial/py.tornado/PythonServer.py
+++ b/tutorial/py.tornado/PythonServer.py
@@ -62,13 +62,13 @@ class CalculatorHandler(object):
         elif work.op == Operation.DIVIDE:
             if work.num2 == 0:
                 x = InvalidOperation()
-                x.what = work.op
+                x.whatOp = work.op
                 x.why = "Cannot divide by 0"
                 raise x
             val = work.num1 / work.num2
         else:
             x = InvalidOperation()
-            x.what = work.op
+            x.whatOp = work.op
             x.why = "Invalid operation"
             raise x
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/py.twisted/PythonServer.py
----------------------------------------------------------------------
diff --git a/tutorial/py.twisted/PythonServer.py 
b/tutorial/py.twisted/PythonServer.py
index f023cac..227f6d4 100755
--- a/tutorial/py.twisted/PythonServer.py
+++ b/tutorial/py.twisted/PythonServer.py
@@ -59,13 +59,13 @@ class CalculatorHandler:
     elif work.op == Operation.DIVIDE:
       if work.num2 == 0:
         x = InvalidOperation()
-        x.what = work.op
+        x.whatOp = work.op
         x.why = 'Cannot divide by 0'
         raise x
       val = work.num1 / work.num2
     else:
       x = InvalidOperation()
-      x.what = work.op
+      x.whatOp = work.op
       x.why = 'Invalid operation'
       raise x
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/py/PythonServer.py
----------------------------------------------------------------------
diff --git a/tutorial/py/PythonServer.py b/tutorial/py/PythonServer.py
index 014a12e..533b0ea 100755
--- a/tutorial/py/PythonServer.py
+++ b/tutorial/py/PythonServer.py
@@ -56,13 +56,13 @@ class CalculatorHandler:
     elif work.op == Operation.DIVIDE:
       if work.num2 == 0:
         x = InvalidOperation()
-        x.what = work.op
+        x.whatOp = work.op
         x.why = 'Cannot divide by 0'
         raise x
       val = work.num1 / work.num2
     else:
       x = InvalidOperation()
-      x.what = work.op
+      x.whatOp = work.op
       x.why = 'Invalid operation'
       raise x
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/rb/RubyServer.rb
----------------------------------------------------------------------
diff --git a/tutorial/rb/RubyServer.rb b/tutorial/rb/RubyServer.rb
index 22cec31..1d707d7 100755
--- a/tutorial/rb/RubyServer.rb
+++ b/tutorial/rb/RubyServer.rb
@@ -52,14 +52,14 @@ class CalculatorHandler
     elsif work.op == Operation::DIVIDE
       if work.num2 == 0
         x = InvalidOperation.new()
-        x.what = work.op
+        x.whatOp = work.op
         x.why = "Cannot divide by 0"
         raise x
       end
       val = work.num1 / work.num2
     else
       x = InvalidOperation.new()
-      x.what = work.op
+      x.whatOp = work.op
       x.why = "Invalid operation"
       raise x
     end

http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/tutorial.thrift
----------------------------------------------------------------------
diff --git a/tutorial/tutorial.thrift b/tutorial/tutorial.thrift
index c8710d4..571ab8e 100644
--- a/tutorial/tutorial.thrift
+++ b/tutorial/tutorial.thrift
@@ -113,7 +113,7 @@ struct Work {
  * Structs can also be exceptions, if they are nasty.
  */
 exception InvalidOperation {
-  1: i32 what,
+  1: i32 whatOp,
   2: string why
 }
 

Reply via email to