Thrift-1441: Generate constructor with parameters for exception class to let it update message property automatically.
Client:delphi
Patch: Kenjiro Fukumitsu
Add the function to delphi generator that generates constructor with parameters to initialize members,if the class is exception and have more than zero parameters.
git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1212226 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_delphi_generator.cc b/compiler/cpp/src/generate/t_delphi_generator.cc
index 4b602e5..bb00ea7 100644
--- a/compiler/cpp/src/generate/t_delphi_generator.cc
+++ b/compiler/cpp/src/generate/t_delphi_generator.cc
@@ -136,9 +136,11 @@
std::string declare_field(t_field* tfield, bool init=false, std::string prefix="", bool is_xception_class = false);
std::string function_signature(t_function* tfunction, std::string full_cls="", bool is_xception = false);
std::string argument_list(t_struct* tstruct);
+ std::string constructor_argument_list(t_struct* tstruct, std::string current_indent);
std::string type_to_enum(t_type* ttype);
std::string prop_name(t_field* tfield, bool is_xception = false);
std::string prop_name(std::string name, bool is_xception = false);
+ std::string constructor_param_name(string name);
void write_enum(std::string line);
void write_forward_decr(std::string line);
@@ -664,7 +666,7 @@
throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
}
string val = render_const_value( vars, out, name, field_type, v_iter->second);
- indent_impl(out) << cls_prefix << normalize_name(name) << "." << normalize_name( v_iter->first->get_string()) << " := " << val << ";" << endl;
+ indent_impl(out) << cls_prefix << normalize_name(name) << "." << prop_name( v_iter->first->get_string(), type->is_xception()) << " := " << val << ";" << endl;
}
} else if (type->is_map()) {
t_type* ktype = ((t_map*)type)->get_key_type();
@@ -716,11 +718,10 @@
indent_impl(out) << name << " := " << type_name(type) << "(" << value->get_integer() << ");" << endl;
} else {
string typname;
- typname = type_name(type,!type->is_xception());
+ typname = type_name( type, true, false, type->is_xception(), type->is_xception());
indent_impl(out) << name << " := " << typname << ".Create;" << endl;
print_const_def_value( vars, out, name, type, value);
}
-
}
void t_delphi_generator::initialize_field(std::ostream& vars, std::ostream& out, string name, t_type* type, t_const_value* value) {
@@ -843,10 +844,10 @@
}
indent_down_impl();
-
indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." << "Create;" << endl;
if ( ! vars.str().empty()) {
+ out << "var" << endl;
out << vars.str();
}
@@ -866,6 +867,21 @@
indent_down_impl();
indent_impl(out) << "end;" << endl << endl;
+ if ((members.size() > 0) && is_exception && (!is_x_factory)) {
+ indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." << "Create(" << constructor_argument_list( tstruct, indent_impl()) << ");" << endl;
+ indent_impl(out) << "begin" << endl;
+ indent_up_impl();
+ indent_impl(out) << "Create;" << endl;
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ string propname = prop_name((*m_iter)->get_name(), is_exception);
+ string param_name = constructor_param_name( (*m_iter)->get_name());
+ indent_impl(out) << propname << " := " << param_name << ";" << endl;
+ }
+ indent_impl(out) << "UpdateMessageProperty;" << endl;
+ indent_down_impl();
+ indent_impl(out) << "end;" << endl << endl;
+ }
+
indent_impl(out) << "destructor " << cls_prefix << cls_nm << "." << "Destroy;" << endl;
indent_impl(out) << "begin" << endl;
indent_up_impl();
@@ -1035,7 +1051,13 @@
indent(out) << "public" << endl;
indent_up();
- indent(out) << "constructor Create;" << endl;
+ if ((members.size() > 0) && is_exception && (! is_x_factory)) {
+ indent(out) << "constructor Create; overload;" << endl;
+ indent(out) << "constructor Create(" << constructor_argument_list( tstruct, indent()) << "); overload;" << endl;
+ } else {
+ indent(out) << "constructor Create;" << endl;
+ }
+
indent(out) << "destructor Destroy; override;" << endl;
out << endl;
@@ -1078,9 +1100,7 @@
}
indent_down();
- indent(out) << "end;" << endl;
-
- indent(out) << endl;
+ indent(out) << "end;" << endl << endl;
}
void t_delphi_generator::generate_service(t_service* tservice) {
@@ -1998,6 +2018,13 @@
return normalize_name( ret, true, is_xception);
}
+std::string t_delphi_generator::constructor_param_name(string name) {
+ string ret = name;
+ ret[0] = toupper(ret[0]);
+ ret = "A" + ret;
+ return normalize_name( ret, false, false);
+}
+
string t_delphi_generator::normalize_clsnm(string clsnm, string prefix, bool b_no_check_keyword) {
if (clsnm.size() > 0) {
clsnm[0] = toupper(clsnm[0]);
@@ -2154,6 +2181,54 @@
return result;
}
+string t_delphi_generator::constructor_argument_list(t_struct* tstruct, string current_indent) {
+ ostringstream result;
+ const vector<t_field*>& fields = tstruct->get_members();
+ vector<t_field*>::const_iterator f_iter;
+ bool first = true;
+ t_type* tt;
+ string line = "";
+ string newline_indent = current_indent + " ";
+
+ bool firstline = true;
+
+ for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+ if (first) {
+ first = false;
+ } else {
+ line += ";";
+ }
+
+ if (line.size() > 80) {
+ if ( firstline ) {
+ result << endl << newline_indent;
+ firstline = false;
+ }
+ result << line << endl;
+ line = newline_indent;
+ } else if ( line.size() > 0) {
+ line += " ";
+ }
+
+ tt = (*f_iter)->get_type();
+ line += constructor_param_name((*f_iter)->get_name()) + ": " + type_name( tt, false, true, tt->is_xception(), true);
+ }
+
+ if ( line.size() > 0) {
+ result << line;
+ }
+
+ string result_str;
+
+ if (firstline) {
+ result_str = " " + result.str();
+ } else {
+ result_str = result.str();
+ }
+
+ return result_str;
+}
+
string t_delphi_generator::type_to_enum(t_type* type) {
while (type->is_typedef()) {
type = ((t_typedef*)type)->get_type();
diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas
index 26d49d2..8f890da 100644
--- a/lib/delphi/test/TestServer.pas
+++ b/lib/delphi/test/TestServer.pas
@@ -106,17 +106,11 @@
end;
procedure TTestServer.TTestHandlerImpl.testException(arg: string);
-var
- x : TXception;
begin
Console.WriteLine('testException(' + arg + ')');
if ( arg = 'Xception') then
begin
- x := TXception.Create;
- x.ErrorCode := 1001;
- x.Message_ := 'This is an Xception';
- x.UpdateMessageProperty;
- raise x;
+ raise TXception.Create( 1001, 'This is an Xception');
end;
end;
@@ -272,21 +266,16 @@
function TTestServer.TTestHandlerImpl.testMultiException(arg0,
arg1: string): IXtruct;
var
- x : TXception;
x2 : TXception2;
begin
Console.WriteLine('testMultiException(' + arg0 + ', ' + arg1 + ')');
if ( arg0 = 'Xception') then
begin
- x := TXception.Create;
- x.ErrorCode := 1001;
- x.Message_ := 'This is an Xception';
- x.UpdateMessageProperty;
- raise x;
+ raise TXception.Create( 1001, 'This is an Xception'); // test the new rich CTOR
end else
if ( arg0 = 'Xception2') then
begin
- x2 := TXception2.Create;
+ x2 := TXception2.Create; // the old way still works too?
x2.ErrorCode := 2002;
x2.Struct_thing := TXtructImpl.Create;
x2.Struct_thing.String_thing := 'This is an Xception2';