diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc index 670383281f7..ca371f74935 100644 --- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc @@ -118,8 +118,7 @@ class t_delphi_generator : public t_oop_generator { void generate_delphi_property(ostream& out, bool struct_is_exception, t_field* tfield, - bool isPublic, - std::string fieldPrefix = ""); + bool isPublic); void generate_delphi_isset_reader_writer_definition(ostream& out, t_field* tfield, bool is_xception); void generate_delphi_property_reader_definition(ostream& out, t_field* tfield, @@ -141,9 +140,7 @@ class t_delphi_generator : public t_oop_generator { t_field* tfield, std::string fieldPrefix, bool is_xception_class, - bool is_union, - bool is_xception_factory, - std::string xception_factory_name); + bool is_union); void generate_delphi_clear_union_value(ostream& out, std::string cls_prefix, std::string name, @@ -151,40 +148,30 @@ class t_delphi_generator : public t_oop_generator { t_field* tfield, std::string fieldPrefix, bool is_xception_class, - bool is_union, - bool is_xception_factory, - std::string xception_factory_name); + bool is_union); void generate_delphi_isset_reader_writer_impl(ostream& out, - std::string cls_prefix, - std::string name, - t_type* type, - t_field* tfield, - std::string fieldPrefix, - bool is_xception); + std::string cls_prefix, + std::string name, + t_type* type, + t_field* tfield, + std::string fieldPrefix, + bool is_xception_class); void generate_delphi_struct_writer_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, - bool is_exception, - bool is_x_factory); - void generate_delphi_struct_result_writer_impl(ostream& out, - std::string cls_prefix, - t_struct* tstruct, - bool is_exception, - bool is_x_factory); + bool is_exception); void generate_delphi_struct_tostring_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, - bool is_exception, - bool is_x_factory); + bool is_exception); void add_delphi_uses_list(string unitname); void generate_delphi_struct_reader_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, - bool is_exception, - bool is_x_factory); + bool is_exception); void generate_delphi_create_exception_impl(ostream& out, string cls_prefix, t_struct* tstruct, @@ -200,12 +187,14 @@ class t_delphi_generator : public t_oop_generator { std::ostream& out, std::string name, t_type* type, - t_const_value* value); + t_const_value* value, + bool is_const_class); void initialize_field(std::ostream& vars, std::ostream& out, std::string name, t_type* type, - t_const_value* value); + t_const_value* value, + bool is_const_class); void finalize_field(std::ostream& out, std::string name, t_type* type, @@ -213,7 +202,6 @@ class t_delphi_generator : public t_oop_generator { std::string cls_nm = ""); std::string render_const_value(std::ostream& local_vars, std::ostream& out, - std::string name, t_type* type, t_const_value* value, bool guidAsLiteral); @@ -225,32 +213,27 @@ class t_delphi_generator : public t_oop_generator { std::string cls_nm = ""); std::string make_constants_classname(); - void generate_delphi_struct(t_struct* tstruct, bool is_exception); + void generate_delphi_struct(t_struct* tstruct); + void generate_delphi_exception(t_struct* tstruct); void generate_delphi_struct_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, - bool is_exception, - bool is_result = false, - bool is_x_factory = false); + bool is_result, + bool is_const_class); + void generate_delphi_exception_impl(ostream& out, + std::string cls_prefix, + t_struct* tstruct); void print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct); void generate_delphi_struct_type_factory(ostream& out, std::string cls_prefix, - t_struct* tstruct, - bool is_exception, - bool is_result = false, - bool is_x_factory = false); + t_struct* tstruct); void generate_delphi_struct_type_factory_registration(ostream& out, std::string cls_prefix, - t_struct* tstruct, - bool is_exception, - bool is_result = false, - bool is_x_factory = false); + t_struct* tstruct); void generate_delphi_struct_definition(std::ostream& out, - t_struct* tstruct, - bool is_xception = false, - bool in_class = false, - bool is_result = false, - bool is_x_factory = false); + t_struct* tstruct); + void generate_delphi_exception_definition(std::ostream& out, + t_struct* tstruct); void generate_function_helpers(t_function* tfunction); void generate_service_interface(t_service* tservice); @@ -327,9 +310,7 @@ class t_delphi_generator : public t_oop_generator { std::string type_name(t_type* ttype, bool b_cls = false, - bool b_no_postfix = false, - bool b_exception_factory = false, - bool b_full_exception_factory = false); + bool b_no_postfix = false); std::string normalize_clsnm(std::string name, std::string prefix, bool b_no_check_keyword = false); @@ -339,7 +320,6 @@ class t_delphi_generator : public t_oop_generator { std::string base_type_name(t_base_type* tbase); 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, @@ -369,10 +349,7 @@ class t_delphi_generator : public t_oop_generator { void generate_delphi_docstring_comment(std::ostream& out, string contents); bool type_can_be_null(t_type* ttype) { - while (ttype->is_typedef()) { - ttype = ((t_typedef*)ttype)->get_type(); - } - + ttype = ttype->get_true_type(); return ttype->is_container() || ttype->is_struct() || ttype->is_xception(); } @@ -426,10 +403,10 @@ class t_delphi_generator : public t_oop_generator { }; // reserved exception class method names (lowercase!) - const std::string DELPHI_RESERVED_METHOD_EXCEPTION[23] = { + const std::string DELPHI_RESERVED_METHOD_EXCEPTION[24] = { "setinnerexception", "setstackinfo", "getstacktrace", "raisingexception", "createfmt", "createres", "createresfmt", "createhelp", "createfmthelp", "createreshelp", "createresfmthelp", "getbaseexception", - "baseexception", "helpcontext", "innerexception", "message", "stacktrace", "stackinfo", + "baseexception", "helpcontext", "innerexception", "exceptiondata", "message", "stacktrace", "stackinfo", "getexceptionstackinfoproc", "getstackinfostringproc", "cleanupstackinfoproc", "raiseouterexception", "throwouterexception" }; @@ -830,11 +807,11 @@ void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) { has_forward = true; pdebug("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 << ";" - << '\n'; + indent(s_forward_decr) << type_name(tstruct, false, true) << " = interface;" << '\n'; + if( tstruct->is_xception()) { + indent(s_forward_decr) << type_name(tstruct, true, true) << " = class;" << '\n'; + } indent_down(); add_defined_type(tstruct); @@ -1070,7 +1047,8 @@ void t_delphi_generator::generate_consts(std::vector consts) { code, prop_name((*c_iter)->get_name(), false, "F"), (*c_iter)->get_type(), - (*c_iter)->get_value()); + (*c_iter)->get_value(), + true); } indent_down_impl(); @@ -1114,7 +1092,8 @@ void t_delphi_generator::generate_consts(std::vector consts) { code, constants_class + "." + prop_name((*c_iter)->get_name(), false, "F"), (*c_iter)->get_type(), - (*c_iter)->get_value()); + (*c_iter)->get_value(), + true); } } indent_down_impl(); @@ -1175,7 +1154,7 @@ void t_delphi_generator::print_const_def_value(std::ostream& vars, if (field_type == nullptr) { 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, false); + string val = render_const_value(vars, out, field_type, v_iter->second, false); indent_impl(out) << cls_prefix << normalize_name(name) << "." << prop_name(v_iter->first->get_string(), type->is_xception()) << " := " << val << ";" << '\n'; @@ -1186,8 +1165,8 @@ void t_delphi_generator::print_const_def_value(std::ostream& vars, const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - string key = render_const_value(vars, out, name, ktype, v_iter->first, false); - string val = render_const_value(vars, out, name, vtype, v_iter->second, false); + string key = render_const_value(vars, out, ktype, v_iter->first, false); + string val = render_const_value(vars, out, vtype, v_iter->second, false); indent_impl(out) << cls_prefix << normalize_name(name) << "[" << key << "]" << " := " << val << ";" << '\n'; } @@ -1202,7 +1181,7 @@ void t_delphi_generator::print_const_def_value(std::ostream& vars, const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - string val = render_const_value(vars, out, name, etype, *v_iter, false); + string val = render_const_value(vars, out, etype, *v_iter, false); indent_impl(out) << cls_prefix << normalize_name(name) << ".Add(" << val << ");" << '\n'; } } @@ -1217,10 +1196,7 @@ void t_delphi_generator::print_private_field(std::ostream& out, } bool t_delphi_generator::const_needs_var(t_type* type) { - t_type* truetype = type; - while (truetype->is_typedef()) { - truetype = ((t_typedef*)truetype)->get_type(); - } + t_type* truetype = type->get_true_type(); if(!truetype->is_base_type()) { return true; @@ -1247,7 +1223,7 @@ void t_delphi_generator::print_const_prop(std::ostream& out, << '\n'; } else { std::ostringstream vars; // dummy - string v2 = render_const_value(vars, out, name, type, value, true); + string v2 = render_const_value(vars, out, type, value, true); indent(out) << "const " << name << " = " << v2 << ";" << '\n'; } } @@ -1256,23 +1232,20 @@ void t_delphi_generator::print_const_value(std::ostream& vars, std::ostream& out, string name, t_type* type, - t_const_value* value) { - t_type* truetype = type; - while (truetype->is_typedef()) { - truetype = ((t_typedef*)truetype)->get_type(); - } + t_const_value* value, + bool is_const_class) { + t_type* truetype = type->get_true_type(); if (truetype->is_base_type()) { - if(const_needs_var(type)) { - string the_value = render_const_value( vars, out, name, type, value, false); + if(const_needs_var(type) || (!is_const_class)) { + string the_value = render_const_value( vars, out, type, value, false); indent_impl(out) << name << " := " << the_value << ";" << '\n'; } } else if (truetype->is_enum()) { indent_impl(out) << name << " := " << type_name(type) << "." << value->get_identifier_name() << ";" << '\n'; } else { - string typname; - typname = type_name(truetype, true, false, type->is_xception(), type->is_xception()); + string typname = type_name(truetype, true, false/*, type->is_xception(), type->is_xception()*/); indent_impl(out) << name << " := " << typname << ".Create;" << '\n'; print_const_def_value(vars, out, name, truetype, value); } @@ -1282,8 +1255,9 @@ void t_delphi_generator::initialize_field(std::ostream& vars, std::ostream& out, string name, t_type* type, - t_const_value* value) { - print_const_value(vars, out, name, type, value); + t_const_value* value, + bool is_const_class) { + print_const_value(vars, out, name, type, value, is_const_class); } void t_delphi_generator::finalize_field(std::ostream& out, @@ -1300,16 +1274,10 @@ void t_delphi_generator::finalize_field(std::ostream& out, string t_delphi_generator::render_const_value(ostream& vars, ostream& out, - string name, t_type* type, t_const_value* value, bool guidAsLiteral) { - (void)name; - - t_type* truetype = type; - while (truetype->is_typedef()) { - truetype = ((t_typedef*)truetype)->get_type(); - } + t_type* truetype = type->get_true_type(); std::ostringstream render; @@ -1360,7 +1328,7 @@ string t_delphi_generator::render_const_value(ostream& vars, } else { string t = tmp("tmp"); vars << " " << t << " : " << type_name(type) << ";" << '\n'; - print_const_value(vars, out, t, type, value); + print_const_value(vars, out, t, type, value, true); render << t; } @@ -1368,54 +1336,53 @@ string t_delphi_generator::render_const_value(ostream& vars, } void t_delphi_generator::generate_struct(t_struct* tstruct) { - generate_delphi_struct(tstruct, false); + generate_delphi_struct(tstruct); } void t_delphi_generator::generate_xception(t_struct* txception) { - generate_delphi_struct(txception, true); + generate_delphi_exception(txception); } -void t_delphi_generator::generate_delphi_struct(t_struct* tstruct, bool is_exception) { +void t_delphi_generator::generate_delphi_struct(t_struct* tstruct) { indent_up(); - generate_delphi_struct_definition(s_struct, tstruct, is_exception); + generate_delphi_struct_definition(s_struct, tstruct); indent_down(); add_defined_type(tstruct); - generate_delphi_struct_impl(s_struct_impl, "", tstruct, is_exception); + generate_delphi_struct_impl(s_struct_impl, "", tstruct, false, false/*?*/); if (register_types_) { - generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct, is_exception); - generate_delphi_struct_type_factory_registration(s_type_factory_registration, - "", - tstruct, - is_exception); + generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct); + generate_delphi_struct_type_factory_registration(s_type_factory_registration, "", tstruct); } } -void t_delphi_generator::generate_delphi_struct_impl(ostream& out, - string cls_prefix, - t_struct* tstruct, - bool is_exception, - bool is_result, - bool is_x_factory) { - - if (is_exception && (!is_x_factory)) { - generate_delphi_struct_impl(out, cls_prefix, tstruct, is_exception, is_result, true); - } +void t_delphi_generator::generate_delphi_exception(t_struct* tstruct) { + // generate exception data class first + generate_delphi_struct(tstruct); - string cls_nm; + indent_up(); + generate_delphi_exception_definition(s_struct, tstruct); + indent_down(); - string exception_factory_name; + add_defined_type(tstruct); - if (is_exception) { - exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory"; + generate_delphi_exception_impl(s_struct_impl, "", tstruct); + /* + if (register_types_) { + generate_delphi_exception_type_factory(s_type_factory_funcs, "", tstruct); + generate_delphi_exception_type_factory_registration(s_type_factory_registration, "", tstruct); } + */ +} - if (is_exception) { - cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true); - } else { - cls_nm = type_name(tstruct, true, false); - } +void t_delphi_generator::generate_delphi_struct_impl(ostream& out, + string cls_prefix, + t_struct* tstruct, + bool is_result, + bool is_const_class) { + + string cls_nm = type_name(tstruct, true, false); std::ostringstream vars, code; @@ -1424,26 +1391,22 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out, indent_up_impl(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = (*m_iter)->get_type(); - while (t->is_typedef()) { - t = ((t_typedef*)t)->get_type(); - } + t_type* truetype = (*m_iter)->get_type()->get_true_type(); if ((*m_iter)->get_value() != nullptr) { initialize_field(vars, code, - prop_name((*m_iter)->get_name(), is_exception, ""), - t, - (*m_iter)->get_value()); + prop_name((*m_iter)->get_name(), false, "F"), + truetype, + (*m_iter)->get_value(), + is_const_class); if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - indent_impl(code) << prop_name((*m_iter), is_exception, "F__isset_") << " := True;" - << '\n'; + indent_impl(code) << prop_name((*m_iter), false, "F__isset_") << " := True;" << '\n'; } } } indent_down_impl(); - indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." - << "Create;" << '\n'; + indent_impl(out) << "constructor " << cls_prefix << cls_nm << ".Create;" << '\n'; if (!vars.str().empty()) { out << "var" << '\n'; @@ -1452,11 +1415,7 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out, indent_impl(out) << "begin" << '\n'; indent_up_impl(); - if (is_exception && (!is_x_factory)) { - indent_impl(out) << "inherited Create('');" << '\n'; - } else { - indent_impl(out) << "inherited;" << '\n'; - } + indent_impl(out) << "inherited;" << '\n'; if (!code.str().empty()) { out << code.str(); @@ -1465,82 +1424,25 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out, indent_down_impl(); indent_impl(out) << "end;" << '\n' << '\n'; - if ((members.size() > 0) && is_exception && (!is_x_factory)) { - indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." - << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");" - << '\n'; - indent_impl(out) << "begin" << '\n'; - indent_up_impl(); - indent_impl(out) << "Create;" << '\n'; - 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 << ";" << '\n'; - } - indent_impl(out) << "UpdateMessageProperty;" << '\n'; - indent_down_impl(); - indent_impl(out) << "end;" << '\n' << '\n'; - } - - indent_impl(out) << "destructor " << cls_prefix << cls_nm << "." - << "Destroy;" << '\n'; + indent_impl(out) << "destructor " << cls_prefix << cls_nm << ".Destroy;" << '\n'; indent_impl(out) << "begin" << '\n'; indent_up_impl(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = (*m_iter)->get_type(); - while (t->is_typedef()) { - t = ((t_typedef*)t)->get_type(); - } - finalize_field(out, prop_name(*m_iter, is_exception), t, (*m_iter)->get_value()); + t_type* t = (*m_iter)->get_type()->get_true_type(); + finalize_field(out, prop_name(*m_iter, false), t, (*m_iter)->get_value()); } indent_impl(out) << "inherited;" << '\n'; indent_down_impl(); indent_impl(out) << "end;" << '\n' << '\n'; - if (is_exception && (!is_x_factory)) { - indent_impl(out) << "function " << cls_prefix << cls_nm << "." << exception_factory_name - << ": I" << exception_factory_name << ";" << '\n'; - indent_impl(out) << "begin" << '\n'; - indent_up_impl(); - indent_impl(out) << "if F" << exception_factory_name << " = nil" << '\n'; - indent_impl(out) << "then F" << exception_factory_name << " := T" << exception_factory_name << "Impl.Create;" << '\n' << '\n'; - indent_impl(out) << "result := F" << exception_factory_name << ";" << '\n'; - indent_down_impl(); - indent_impl(out) << "end;" << '\n' << '\n'; - indent_impl(out) << "function " << cls_prefix << cls_nm << ".QueryInterface(const IID: TGUID; out Obj): HRESULT;" << '\n'; - indent_impl(out) << "begin" << '\n'; - indent_up_impl(); - indent_impl(out) << "if GetInterface(IID, Obj)" << '\n'; - indent_impl(out) << "then result := S_OK" << '\n'; - indent_impl(out) << "else result := E_NOINTERFACE;" << '\n'; - indent_down_impl(); - indent_impl(out) << "end;" << '\n' << '\n'; - indent_impl(out) << "function " << cls_prefix << cls_nm << "._AddRef: Integer;" << '\n'; - indent_impl(out) << "begin" << '\n'; - indent_up_impl(); - indent_impl(out) << "result := -1; // not refcounted" << '\n'; - indent_down_impl(); - indent_impl(out) << "end;" << '\n' << '\n'; - indent_impl(out) << "function " << cls_prefix << cls_nm << "._Release: Integer;" << '\n'; - indent_impl(out) << "begin" << '\n'; - indent_up_impl(); - indent_impl(out) << "result := -1; // not refcounted" << '\n'; - indent_down_impl(); - indent_impl(out) << "end;" << '\n' << '\n'; - } - if (tstruct->is_union()) { - indent_impl(out) << "procedure " << cls_prefix << cls_nm << "." - << "ClearUnionValues;" << '\n'; + indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".ClearUnionValues;" << '\n'; indent_impl(out) << "begin" << '\n'; indent_up_impl(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = (*m_iter)->get_type(); - while (t->is_typedef()) { - t = ((t_typedef*)t)->get_type(); - } + t_type* t = (*m_iter)->get_type()->get_true_type(); generate_delphi_clear_union_value(out, cls_prefix, @@ -1548,47 +1450,138 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out, t, *m_iter, "F", - is_exception, - tstruct->is_union(), - is_x_factory, - exception_factory_name); + false, + tstruct->is_union()); } indent_down_impl(); indent_impl(out) << "end;" << '\n' << '\n'; } for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = (*m_iter)->get_type(); - while (t->is_typedef()) { - t = ((t_typedef*)t)->get_type(); - } - generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception); + t_type* t = (*m_iter)->get_type()->get_true_type(); + generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", false); generate_delphi_property_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", - is_exception, - tstruct->is_union(), - is_x_factory, - exception_factory_name); + false, + tstruct->is_union()); if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception); + generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", false); } } - generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); - if (is_result) { - generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); - } else { - generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); + generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, false); + generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, false); + generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, false); +} + +void t_delphi_generator::generate_delphi_exception_impl(ostream& out, + string cls_prefix, + t_struct* tstruct) { + + string cls_nm = type_name(tstruct, true, true/*, false, true*/); + + const vector& members = tstruct->get_members(); + vector::const_iterator m_iter; + + indent_impl(out) << "constructor " << cls_prefix << cls_nm << ".Create;" << '\n'; + indent_impl(out) << "begin" << '\n'; + indent_up_impl(); + indent_impl(out) << "inherited Create('');" << '\n'; + indent_impl(out) << "FData := " << type_name(tstruct, true, false) << ".Create;" << '\n'; + indent_down_impl(); + indent_impl(out) << "end;" << '\n' << '\n'; + + if (members.size() > 0) { + indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." + << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");" + << '\n'; + indent_impl(out) << "begin" << '\n'; + indent_up_impl(); + indent_impl(out) << "Create;" << '\n'; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + string propname = prop_name((*m_iter)->get_name(), true); + string param_name = constructor_param_name((*m_iter)->get_name()); + indent_impl(out) << propname << " := " << param_name << ";" << '\n'; + } + indent_impl(out) << "UpdateMessageProperty;" << '\n'; + indent_down_impl(); + indent_impl(out) << "end;" << '\n' << '\n'; + } + + indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." + << "Create(const aData: " << type_name(tstruct, false, false) << ");" + << '\n'; + indent_impl(out) << "begin" << '\n'; + indent_up_impl(); + indent_impl(out) << "inherited Create('');" << '\n'; + indent_impl(out) << "if aData <> nil" << '\n'; + indent_impl(out) << "then FData := aData" << '\n'; + indent_impl(out) << "else ASSERT(FALSE,'Invalid argument');" << '\n'; + indent_impl(out) << "UpdateMessageProperty;" << '\n'; + indent_down_impl(); + indent_impl(out) << "end;" << '\n' << '\n'; + + indent_impl(out) << "destructor " << cls_prefix << cls_nm << "." + << "Destroy;" << '\n'; + indent_impl(out) << "begin" << '\n'; + indent_up_impl(); + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = (*m_iter)->get_type()->get_true_type(); + finalize_field(out, prop_name(*m_iter, true), t, (*m_iter)->get_value()); } - generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); - if (is_exception && is_x_factory) { - generate_delphi_create_exception_impl(out, cls_prefix, tstruct, is_exception); + indent_impl(out) << "inherited;" << '\n'; + indent_down_impl(); + indent_impl(out) << "end;" << '\n' << '\n'; + + // non-refcounted IUnknown impl + indent_impl(out) << "function " << cls_prefix << cls_nm << ".QueryInterface(const IID: TGUID; out Obj): HRESULT;" << '\n'; + indent_impl(out) << "begin" << '\n'; + indent_up_impl(); + indent_impl(out) << "if GetInterface(IID, Obj)" << '\n'; + indent_impl(out) << "then result := S_OK" << '\n'; + indent_impl(out) << "else result := E_NOINTERFACE;" << '\n'; + indent_down_impl(); + indent_impl(out) << "end;" << '\n' << '\n'; + indent_impl(out) << "function " << cls_prefix << cls_nm << "._AddRef: Integer;" << '\n'; + indent_impl(out) << "begin" << '\n'; + indent_up_impl(); + indent_impl(out) << "result := -1; // not refcounted" << '\n'; + indent_down_impl(); + indent_impl(out) << "end;" << '\n' << '\n'; + indent_impl(out) << "function " << cls_prefix << cls_nm << "._Release: Integer;" << '\n'; + indent_impl(out) << "begin" << '\n'; + indent_up_impl(); + indent_impl(out) << "result := -1; // not refcounted" << '\n'; + indent_down_impl(); + indent_impl(out) << "end;" << '\n' << '\n'; + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = (*m_iter)->get_type()->get_true_type(); + generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "", true); + generate_delphi_property_writer_impl(out, + cls_prefix, + cls_nm, + t, + *m_iter, + "", + true, + tstruct->is_union()); + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "", true); + } } + + generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, true); + generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, true); + generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, true); + + generate_delphi_create_exception_impl(out, cls_prefix, tstruct, true); } void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct) { @@ -1600,17 +1593,8 @@ void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_s void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out, string cls_prefix, - t_struct* tstruct, - bool is_exception, - bool is_result, - bool is_x_factory) { + t_struct* tstruct) { (void)cls_prefix; - if (is_exception) - return; - if (is_result) - return; - if (is_x_factory) - return; string struct_intf_name = type_name(tstruct); string cls_nm = type_name(tstruct, true, false); @@ -1629,17 +1613,8 @@ void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out, void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostream& out, string cls_prefix, - t_struct* tstruct, - bool is_exception, - bool is_result, - bool is_x_factory) { + t_struct* tstruct) { (void)cls_prefix; - if (is_exception) - return; - if (is_result) - return; - if (is_x_factory) - return; string struct_intf_name = type_name(tstruct); @@ -1649,12 +1624,8 @@ void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostrea out << '\n'; } -void t_delphi_generator::generate_delphi_struct_definition(ostream& out, - t_struct* tstruct, - bool is_exception, - bool in_class, - bool is_result, - bool is_x_factory) { +void t_delphi_generator::generate_delphi_struct_definition(ostream& out, + t_struct* tstruct) { bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); string struct_intf_name; string struct_name; @@ -1662,121 +1633,77 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, const vector& members = tstruct->get_members(); vector::const_iterator m_iter; - string exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory"; - - if (is_exception) { - struct_intf_name = type_name(tstruct, false, false, true); - } else { - struct_intf_name = type_name(tstruct); - } + struct_intf_name = type_name(tstruct, false, false); + struct_name = type_name(tstruct, true); - if (is_exception) { - struct_name = type_name(tstruct, true, (!is_x_factory), is_x_factory); + generate_delphi_doc(out, tstruct); + if(rtti_) { + indent(out) << "{$TYPEINFO ON}" << '\n'; + indent(out) << "{$RTTI EXPLICIT METHODS([vcPublic, vcPublished]) PROPERTIES([vcPublic, vcPublished])}" << '\n'; + indent(out) << struct_intf_name << " = interface(IBaseWithTypeInfo)" << '\n'; } else { - struct_name = type_name(tstruct, true); + indent(out) << struct_intf_name << " = interface(IBase)" << '\n'; } + indent_up(); - if ((!is_exception) || is_x_factory) { - - generate_delphi_doc(out, tstruct); - if(rtti_) { - indent(out) << "{$TYPEINFO ON}" << '\n'; - indent(out) << "{$RTTI EXPLICIT METHODS([vcPublic, vcPublished]) PROPERTIES([vcPublic, vcPublished])}" << '\n'; - indent(out) << struct_intf_name << " = interface(IBaseWithTypeInfo)" << '\n'; - } else { - indent(out) << struct_intf_name << " = interface(IBase)" << '\n'; - } - indent_up(); + generate_guid(out); - generate_guid(out); + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + generate_delphi_property_reader_definition(out, *m_iter, false); + generate_delphi_property_writer_definition(out, *m_iter, false); + } + if (members.size() > 0) { + out << '\n'; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - generate_delphi_property_reader_definition(out, *m_iter, is_exception); - generate_delphi_property_writer_definition(out, *m_iter, is_exception); - } - - if (is_x_factory) { - out << '\n'; - indent(out) << "// Create Exception Object" << '\n'; - indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << '\n'; - } - - if (members.size() > 0) { - out << '\n'; - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - generate_property(out, *m_iter, true, is_exception); - } + generate_property(out, *m_iter, true, false); } - if (members.size() > 0) { - out << '\n'; - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - generate_delphi_isset_reader_writer_definition(out, *m_iter, is_exception); - } + out << '\n'; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + generate_delphi_isset_reader_writer_definition(out, *m_iter, false); } } - if (members.size() > 0) { - out << '\n'; - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - isset_name = prop_name(*m_iter, is_exception, "__isset_"); - indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";" - << '\n'; - } + out << '\n'; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + isset_name = prop_name(*m_iter, false, "__isset_"); + indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";" + << '\n'; } } + } - indent_down(); - indent(out) << "end;" - << render_deprecation_attribute(tstruct->annotations_, " {", "}") - << '\n'; - if(rtti_) { - indent(out) << "{$IFNDEF TYPEINFO_WAS_ON} {$TYPEINFO OFF} {$ENDIF}" << '\n'; - } - indent(out) << '\n'; + indent_down(); + indent(out) << "end;" + << render_deprecation_attribute(tstruct->annotations_, " {", "}") + << '\n'; + if(rtti_) { + indent(out) << "{$IFNDEF TYPEINFO_WAS_ON} {$TYPEINFO OFF} {$ENDIF}" << '\n'; } + indent(out) << '\n'; generate_delphi_doc(out, tstruct); indent(out) << struct_name << " = "; if (is_final) { out << "sealed "; } - out << "class("; - if (is_exception && (!is_x_factory)) { - out << "TException, IInterface, IBase, ISupportsToString"; - } else { - out << "TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name; - } - out << ")" << '\n'; - - if (is_exception && (!is_x_factory)) { - indent(out) << "public" << '\n'; - indent_up(); - indent(out) << "type" << '\n'; - indent_up(); - generate_delphi_struct_definition(out, tstruct, is_exception, in_class, is_result, true); - indent_down(); - indent_down(); - } + out << "class(TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name << ")" << '\n'; indent(out) << "private" << '\n'; indent_up(); - if (is_exception && (!is_x_factory)) { - indent(out) << "F" << exception_factory_name << " :" << struct_intf_name << ";" << '\n' << '\n'; - } - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - indent(out) << declare_field(*m_iter, false, "F", is_exception) << '\n'; + indent(out) << declare_field(*m_iter, "F", false) << '\n'; } if (members.size() > 0) { indent(out) << '\n'; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - isset_name = prop_name(*m_iter, is_exception, "F__isset_"); + isset_name = prop_name(*m_iter, false, "F__isset_"); indent(out) << isset_name << ": System.Boolean;" << '\n'; } } @@ -1785,8 +1712,8 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, indent(out) << '\n'; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - generate_delphi_property_reader_definition(out, *m_iter, is_exception); - generate_delphi_property_writer_definition(out, *m_iter, is_exception); + generate_delphi_property_reader_definition(out, *m_iter, false); + generate_delphi_property_writer_definition(out, *m_iter, false); } if (tstruct->is_union()) { @@ -1799,72 +1726,134 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, out << '\n'; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - isset_name = prop_name(*m_iter, is_exception, "__isset_"); + isset_name = prop_name(*m_iter, false, "__isset_"); indent(out) << "function Get" << isset_name << ": System.Boolean;" << '\n'; indent(out) << "procedure Set" << isset_name << "( const value : System.Boolean);" << '\n'; } } } - if (is_exception && (!is_x_factory)) { + indent_down(); + indent(out) << "public" << '\n'; + indent_up(); + indent(out) << "constructor Create;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n'; + indent(out) << "destructor Destroy; override;" << '\n'; + + out << '\n'; + indent(out) << "function ToString: string; override;" << '\n'; + + out << '\n'; + indent(out) << "// IBase" << '\n'; + indent(out) << "procedure Read( const iprot: IProtocol);" << '\n'; + indent(out) << "procedure Write( const oprot: IProtocol);" << '\n'; + + if (members.size() > 0) { out << '\n'; - indent_down(); - indent(out) << "strict protected" << '\n'; - indent_up(); - indent(out) << "function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;" << '\n'; - indent(out) << "function _AddRef: Integer; stdcall;" << '\n'; - indent(out) << "function _Release: Integer; stdcall;" << '\n'; + indent(out) << "// Properties" << '\n'; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + generate_property(out, *m_iter, true, false); + } + out << '\n'; + indent(out) << "// isset" << '\n'; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + isset_name = prop_name(*m_iter, false, "__isset_"); + indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";" + << '\n'; + } + } } + indent_down(); + indent(out) << "end;" << '\n' << '\n'; +} + +void t_delphi_generator::generate_delphi_exception_definition(ostream& out, + t_struct* tstruct) { + bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); + string struct_intf_name; + string struct_name; + string isset_name; + const vector& members = tstruct->get_members(); + vector::const_iterator m_iter; + + struct_intf_name = type_name(tstruct, false, false); + struct_name = type_name(tstruct, true, true); + + generate_delphi_doc(out, tstruct); + indent(out) << struct_name << " = "; + if (is_final) { + out << "sealed "; + } + out << "class(TException, IInterface, IBase, ISupportsToString)" << '\n'; + + indent(out) << "private" << '\n'; + indent_up(); + indent(out) << "FData : " << struct_intf_name << ';' << '\n'; + indent(out) << '\n'; + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + generate_delphi_property_reader_definition(out, *m_iter, true); + generate_delphi_property_writer_definition(out, *m_iter, true); + } + + if (members.size() > 0) { + out << '\n'; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + isset_name = prop_name(*m_iter, true, "__isset_"); + indent(out) << "function Get" << isset_name << ": System.Boolean;" << '\n'; + indent(out) << "procedure Set" << isset_name << "( const value : System.Boolean);" << '\n'; + } + } + } + + out << '\n'; + indent_down(); + indent(out) << "strict protected" << '\n'; + indent_up(); + indent(out) << "// non-refcounted instance" << '\n'; + indent(out) << "function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;" << '\n'; + indent(out) << "function _AddRef: Integer; stdcall;" << '\n'; + indent(out) << "function _Release: Integer; stdcall;" << '\n'; + out << '\n'; + indent_down(); indent(out) << "public" << '\n'; indent_up(); - if ((members.size() > 0) && is_exception && (!is_x_factory)) { - indent(out) << "constructor Create; overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n'; + indent(out) << "constructor Create; overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n'; + if (members.size() > 0) { indent(out) << "constructor Create(" << constructor_argument_list(tstruct, indent()) << "); overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n'; - } else { - indent(out) << "constructor Create;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n'; } + indent(out) << "constructor Create( const aData: " << struct_intf_name + << "); overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n'; indent(out) << "destructor Destroy; override;" << '\n'; out << '\n'; + indent(out) << "property ExceptionData : " << struct_intf_name << " read FData;" << '\n'; indent(out) << "function ToString: string; override;" << '\n'; - if (is_exception && (!is_x_factory)) { - out << '\n'; - indent(out) << "// Exception Factory" << '\n'; - indent(out) << "function " << exception_factory_name << ": " << struct_intf_name << ";" << '\n'; - } - out << '\n'; indent(out) << "// IBase" << '\n'; indent(out) << "procedure Read( const iprot: IProtocol);" << '\n'; indent(out) << "procedure Write( const oprot: IProtocol);" << '\n'; - if (is_exception && is_x_factory) { - out << '\n'; - indent(out) << "// Create Exception Object" << '\n'; - indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << '\n'; - } - if (members.size() > 0) { out << '\n'; indent(out) << "// Properties" << '\n'; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - generate_property(out, *m_iter, true, is_exception); + generate_property(out, *m_iter, true, true); } - } - if (members.size() > 0) { out << '\n'; indent(out) << "// isset" << '\n'; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - isset_name = prop_name(*m_iter, is_exception, "__isset_"); + isset_name = prop_name(*m_iter, true, "__isset_"); indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";" << '\n'; } @@ -1957,11 +1946,11 @@ void t_delphi_generator::generate_service_helpers(t_service* tservice) { for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); - generate_delphi_struct_definition(s_service, ts, false, true); + generate_delphi_struct_definition(s_service, ts); generate_delphi_struct_impl(s_service_impl, normalize_clsnm(service_name_, "T") + ".", ts, - false); + false, false); generate_function_helpers(*f_iter); } } @@ -2076,7 +2065,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { // Delphi forces us to specify a type with IFuture, so we use Integer=0 for void methods indent_impl(s_service_impl) << "result := TTask.Future(function: System.Integer" << '\n'; } else { - string rettype = type_name(ttype, false, true, false, true); + string rettype = type_name(ttype, false, true/*, false, true*/); indent_impl(s_service_impl) << "result := TTask.Future<" << rettype << ">(function: " << rettype << '\n'; } indent_impl(s_service_impl) << "begin" << '\n'; @@ -2227,8 +2216,10 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { indent_impl(s_service_impl) << "if (" << retvar << "." << prop_name(*x_iter, false, "__isset_") << ") then begin" << '\n'; indent_up_impl(); - indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter) - << ".CreateException;" << '\n'; + indent_impl(s_service_impl) << exceptvar + << " := " << type_name((*x_iter)->get_type(),true,true/*,false,true*/) + << ".Create(" << retvar << "." << prop_name(*x_iter) << ");" + << '\n'; indent_impl(s_service_impl) << "raise " << exceptvar << ";" << '\n'; indent_down_impl(); indent_impl(s_service_impl) << "end;" << '\n'; @@ -2434,18 +2425,21 @@ void t_delphi_generator::generate_function_helpers(t_function* tfunction) { result.append(&success); } + int num_excepts = 0; t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); + ++num_excepts; } + result.set_method_xcepts(num_excepts > 0); - generate_delphi_struct_definition(s_service, &result, false, true, true); + generate_delphi_struct_definition(s_service, &result); generate_delphi_struct_impl(s_service_impl, normalize_clsnm(service_name_, "T") + ".", &result, - false); + true, false); } void t_delphi_generator::generate_process_function(t_service* tservice, t_function* tfunction) { @@ -2543,10 +2537,7 @@ void t_delphi_generator::generate_process_function(t_service* tservice, t_functi << " do begin" << '\n'; indent_up_impl(); if (!tfunction->is_oneway()) { - string factory_name = normalize_clsnm((*x_iter)->get_type()->get_name(), "", true) - + "Factory"; - indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E." << factory_name << ";" - << '\n'; + indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E.ExceptionData;" << '\n'; } indent_down_impl(); indent_impl(s_service_impl) << "end;" << '\n'; @@ -2616,10 +2607,7 @@ void t_delphi_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, ostream& local_vars) { - t_type* type = tfield->get_type(); - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } + t_type* type = tfield->get_type()->get_true_type(); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); @@ -2695,11 +2683,7 @@ void t_delphi_generator::generate_deserialize_struct(ostream& out, string prefix) { string typ_name; - if (tstruct->is_xception()) { - typ_name = type_name(tstruct, true, false, true, true); - } else { - typ_name = type_name(tstruct, true, false); - } + typ_name = type_name(tstruct, true, false); indent_impl(out) << prefix << name << " := " << typ_name << ".Create;" << '\n'; indent_impl(out) << prefix << name << ".Read(iprot);" << '\n'; @@ -2819,10 +2803,7 @@ void t_delphi_generator::generate_serialize_field(ostream& out, ostream& local_vars) { (void)local_vars; - t_type* type = tfield->get_type(); - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } + t_type* type = tfield->get_type()->get_true_type(); string name = prefix + prop_name(tfield, is_xception); @@ -2999,22 +2980,21 @@ void t_delphi_generator::generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception) { - generate_delphi_property(out, is_xception, tfield, isPublic, "Get"); + generate_delphi_property(out, is_xception, tfield, isPublic); } void t_delphi_generator::generate_delphi_property(ostream& out, bool struct_is_xception, t_field* tfield, - bool isPublic, - std::string fieldPrefix) { + bool isPublic) { (void)isPublic; t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); generate_delphi_doc(out, tfield); indent(out) << "property " << prop_name(tfield, struct_is_xception) << ": " - << type_name(ftype, false, true, is_xception, true) - << " read " << prop_name(tfield, struct_is_xception, fieldPrefix) + << type_name(ftype, false, true/*, false, true*/) + << " read " << prop_name(tfield, struct_is_xception, "Get") << " write " << prop_name(tfield, struct_is_xception, "Set") << ";" << render_deprecation_attribute(tfield->annotations_, " {", "}") @@ -3050,9 +3030,7 @@ string t_delphi_generator::normalize_clsnm(string clsnm, string prefix, bool b_n 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) { + bool b_no_postfix) { if (ttype->is_typedef()) { t_typedef* tdef = (t_typedef*)ttype; @@ -3060,9 +3038,7 @@ string t_delphi_generator::type_name(t_type* ttype, if (tdef->get_type() != nullptr) { return type_name(tdef->get_type(), b_cls, - b_no_postfix, - b_exception_factory, - b_full_exception_factory); + b_no_postfix); } else { throw "unresolved forward declaration: " + tdef->get_symbolic(); } @@ -3117,20 +3093,12 @@ string t_delphi_generator::type_name(t_type* ttype, string nm = normalize_clsnm(ttype->get_name(), type_prefix); - if (b_exception_factory) { - nm = normalize_clsnm(ttype->get_name(), type_prefix, true) + "Factory"; - } - if (b_cls) { if (!b_no_postfix) { nm = nm + "Impl"; } } - if (b_exception_factory && b_full_exception_factory) { - return type_name(ttype, true, true, false, false) + "." + nm; - } - return nm; } @@ -3217,16 +3185,14 @@ string t_delphi_generator::base_type_name(t_base_type* tbase) { } string t_delphi_generator::declare_field(t_field* tfield, - bool init, std::string prefix, bool is_xception_class) { - (void)init; - t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); string result = prop_name(tfield, is_xception_class, prefix) + ": " - + type_name(ftype, false, true, is_xception, true) + ";"; + + type_name(ftype, false, true) + ";"; + return result; } @@ -3251,7 +3217,7 @@ string t_delphi_generator::function_signature(t_function* tfunction, } else { signature = "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "Async(" + argument_list(tfunction->get_arglist()) + "): IFuture<" - + type_name(ttype, false, true, is_xception, true) + ">;"; + + type_name(ttype, false, true/*, is_xception, true*/) + ">;"; } } else { if (is_void(ttype)) { @@ -3260,7 +3226,7 @@ string t_delphi_generator::function_signature(t_function* tfunction, } else { signature = "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "(" + argument_list(tfunction->get_arglist()) + "): " - + type_name(ttype, false, true, is_xception, true) + ";"; + + type_name(ttype, false, true/*, is_xception, true*/) + ";"; } } @@ -3289,7 +3255,7 @@ string t_delphi_generator::argument_list(t_struct* tstruct) { tt = (*f_iter)->get_type(); result += input_arg_prefix(tt); // const? result += normalize_name((*f_iter)->get_name()) + ": " - + type_name(tt, false, true, tt->is_xception(), true); + + type_name(tt, false, true/*, tt->is_xception(), true*/); } return result; } @@ -3326,7 +3292,7 @@ string t_delphi_generator::constructor_argument_list(t_struct* tstruct, string c tt = (*f_iter)->get_type(); line += input_arg_prefix(tt); // const? line += constructor_param_name((*f_iter)->get_name()) + ": " - + type_name(tt, false, true, tt->is_xception(), true); + + type_name(tt, false, true/*, tt->is_xception(), true*/); } if (line.size() > 0) { @@ -3345,9 +3311,7 @@ string t_delphi_generator::constructor_argument_list(t_struct* tstruct, string c } string t_delphi_generator::type_to_enum(t_type* type) { - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } + type = type->get_true_type(); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); @@ -3387,9 +3351,7 @@ string t_delphi_generator::type_to_enum(t_type* type) { } string t_delphi_generator::empty_value(t_type* type) { - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } + type = type->get_true_type(); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); @@ -3436,7 +3398,7 @@ void t_delphi_generator::generate_delphi_property_writer_definition(ostream& out bool is_xception = ftype->is_xception(); indent(out) << "procedure " << prop_name(tfield, is_xception_class, "Set") - << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");" + << "( const Value: " << type_name(ftype, false, true/*, false, true*/) << ");" << render_deprecation_attribute(tfield->annotations_, " ", ";") << '\n'; } @@ -3448,7 +3410,7 @@ void t_delphi_generator::generate_delphi_property_reader_definition(ostream& out bool is_xception = ftype->is_xception(); indent(out) << "function " << prop_name(tfield, is_xception_class, "Get") << ": " - << type_name(ftype, false, true, is_xception, true) << ";" + << type_name(ftype, false, true/*, false*/) << ";" << render_deprecation_attribute(tfield->annotations_, " ", ";") << '\n'; } @@ -3456,8 +3418,8 @@ void t_delphi_generator::generate_delphi_property_reader_definition(ostream& out void t_delphi_generator::generate_delphi_isset_reader_writer_definition(ostream& out, t_field* tfield, bool is_xception) { - indent(out) << "function " << prop_name(tfield, is_xception,"Get__isset_") << ": System.Boolean;" << '\n'; - indent(out) << "procedure " << prop_name(tfield, is_xception, "Set__isset_") << "( const value : System.Boolean);" << '\n'; + indent(out) << "function " << prop_name(tfield, false,"Get__isset_") << ": System.Boolean;" << '\n'; + indent(out) << "procedure " << prop_name(tfield, false, "Set__isset_") << "( const value : System.Boolean);" << '\n'; } void t_delphi_generator::generate_delphi_clear_union_value(ostream& out, @@ -3467,25 +3429,20 @@ void t_delphi_generator::generate_delphi_clear_union_value(ostream& out, t_field* tfield, std::string fieldPrefix, bool is_xception_class, - bool is_union, - bool is_xception_factory, - std::string xception_factory_name) { + bool is_union) { (void)cls_prefix; (void)name; (void)type; (void)is_union; - (void)is_xception_factory; - (void)xception_factory_name; t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); - indent_impl(out) << "if " << prop_name(tfield, is_xception_class,"F__isset_") << " then begin" - << '\n'; + indent_impl(out) << "if " << prop_name(tfield, is_xception_class,"F__isset_") << " then begin" << '\n'; indent_up_impl(); indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := False;" << '\n'; indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := " - << "Default( " << type_name(ftype, false, true, is_xception, true) << ");" + << "Default( " << type_name(ftype, false, true/*, is_xception, true*/) << ");" << '\n'; indent_down_impl(); indent_impl(out) << "end;" << '\n'; @@ -3498,9 +3455,7 @@ void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out, t_field* tfield, std::string fieldPrefix, bool is_xception_class, - bool is_union, - bool is_xception_factory, - std::string xception_factory_name) { + bool is_union) { (void)type; t_type* ftype = tfield->get_type(); @@ -3508,21 +3463,20 @@ void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out, indent_impl(out) << "procedure " << cls_prefix << name << "." << prop_name(tfield, is_xception_class,"Set") - << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");" + << "( const Value: " << type_name(ftype, false, true) << ");" << '\n'; indent_impl(out) << "begin" << '\n'; indent_up_impl(); if (is_union) { indent_impl(out) << "ClearUnionValues;" << '\n'; } - if (tfield->get_req() != t_field::T_REQUIRED) { - indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := True;" << '\n'; - } - indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := Value;" << '\n'; - - if (is_xception_class && (!is_xception_factory)) { - indent_impl(out) << xception_factory_name << "." << prop_name(tfield, is_xception_class) - << " := Value;" << '\n'; + if(is_xception_class) { + indent_impl(out) << "FData." << prop_name(tfield, false, fieldPrefix) << " := Value;" << '\n'; + } else { + if (tfield->get_req() != t_field::T_REQUIRED) { + indent_impl(out) << prop_name(tfield, is_xception_class, "F__isset_") << " := True;" << '\n'; + } + indent_impl(out) << prop_name(tfield, is_xception_class, fieldPrefix) << " := Value;" << '\n'; } indent_down_impl(); @@ -3543,11 +3497,14 @@ void t_delphi_generator::generate_delphi_property_reader_impl(ostream& out, indent_impl(out) << "function " << cls_prefix << name << "." << prop_name(tfield, is_xception_class,"Get") << ": " - << type_name(ftype, false, true, is_xception, true) << ";" << '\n'; + << type_name(ftype, false, true) << ";" << '\n'; indent_impl(out) << "begin" << '\n'; indent_up_impl(); - indent_impl(out) << "Result := " << prop_name(tfield, is_xception_class,fieldPrefix) << ";" - << '\n'; + if(is_xception_class) { + indent_impl(out) << "Result := FData." << prop_name(tfield, false, fieldPrefix) << ";" << '\n'; + } else { + indent_impl(out) << "Result := " << prop_name(tfield, is_xception_class, fieldPrefix) << ";" << '\n'; + } indent_down_impl(); indent_impl(out) << "end;" << '\n' << '\n'; } @@ -3558,16 +3515,20 @@ void t_delphi_generator::generate_delphi_isset_reader_writer_impl(ostream& out, t_type* type, t_field* tfield, std::string fieldPrefix, - bool is_xception) { + bool is_xception_class) { (void)type; - string isset_name = prop_name(tfield, is_xception, "__isset_"); + string isset_name = prop_name(tfield, false, "__isset_"); indent_impl(out) << "function " << cls_prefix << name << "." << "Get" << isset_name << ": System.Boolean;" << '\n'; indent_impl(out) << "begin" << '\n'; indent_up_impl(); - indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << '\n'; + if(is_xception_class) { + indent_impl(out) << "Result := FData." << fieldPrefix << isset_name << ";" << '\n'; + } else { + indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << '\n'; + } indent_down_impl(); indent_impl(out) << "end;" << '\n' << '\n'; @@ -3575,7 +3536,11 @@ void t_delphi_generator::generate_delphi_isset_reader_writer_impl(ostream& out, << "Set" << isset_name << "( const value: System.Boolean);" << '\n'; indent_impl(out) << "begin" << '\n'; indent_up_impl(); - indent_impl(out) << fieldPrefix << isset_name << " := value;" << '\n'; + if(is_xception_class) { + indent_impl(out) << "FData." << fieldPrefix << isset_name << " := value;" << '\n'; + } else { + indent_impl(out) << fieldPrefix << isset_name << " := value;" << '\n'; + } indent_down_impl(); indent_impl(out) << "end;" << '\n' << '\n'; } @@ -3587,47 +3552,13 @@ void t_delphi_generator::generate_delphi_create_exception_impl(ostream& out, (void)cls_prefix; string exception_cls_nm = type_name(tstruct, true, true); - string cls_nm = type_name(tstruct, true, false, is_exception, is_exception); - - indent_impl(out) << "function " << cls_nm << ".CreateException: " << exception_cls_nm << ";" - << '\n'; - - indent_impl(out) << "begin" << '\n'; - indent_up_impl(); - - indent_impl(out) << "Result := " << exception_cls_nm << ".Create;" << '\n'; - string factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory"; - indent_impl(out) << "Result.F" << factory_name << " := Self;" << '\n'; - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - string propname; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - propname = prop_name(*f_iter, is_exception); - if ((*f_iter)->get_req() != t_field::T_REQUIRED) { - indent_impl(out) << "if " << prop_name(*f_iter, is_exception,"__isset_") << " then begin" << '\n'; - indent_up_impl(); - } - indent_impl(out) << "Result." << propname << " := " << propname << ";" << '\n'; - if ((*f_iter)->get_req() != t_field::T_REQUIRED) { - indent_down_impl(); - indent_impl(out) << "end;" << '\n'; - } - } - - indent_impl(out) << "Result.UpdateMessageProperty;" << '\n'; - - indent_down_impl(); - indent_impl(out) << "end;" << '\n' << '\n'; + string cls_nm = type_name(tstruct, true, false/*, is_exception, is_exception*/); } void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, string cls_prefix, t_struct* tstruct, - bool is_exception, - bool is_x_factory) { + bool is_exception) { ostringstream local_vars; ostringstream code_block; @@ -3746,7 +3677,7 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, } } - if( is_exception && (!is_x_factory)) { + if( is_exception) { code_block << '\n'; indent_impl(code_block) << "UpdateMessageProperty;" << '\n'; } @@ -3755,10 +3686,9 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, string cls_nm; - cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory); + cls_nm = type_name(tstruct, true, is_exception); - indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);" - << '\n'; + indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);" << '\n'; indent_impl(out) << "var" << '\n'; indent_up_impl(); indent_impl(out) << "field_ : TThriftField;" << '\n'; @@ -3768,76 +3698,10 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, out << code_block.str(); } -void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out, - string cls_prefix, - t_struct* tstruct, - bool is_exception, - bool is_x_factory) { - - ostringstream local_vars; - ostringstream code_block; - - string name = tstruct->get_name(); - const vector& fields = tstruct->get_sorted_members(); - vector::const_iterator f_iter; - - indent_impl(code_block) << "begin" << '\n'; - indent_up_impl(); - - indent_impl(local_vars) << "tracker : IProtocolRecursionTracker;" << '\n'; - indent_impl(code_block) << "tracker := oprot.NextRecursionLevel;" << '\n'; - - indent_impl(code_block) << "Thrift.Protocol.Init( struc, '" << name << "');" << '\n'; - indent_impl(code_block) << "oprot.WriteStructBegin(struc);" << '\n'; - - if (fields.size() > 0) { - indent_impl(code_block) << "Thrift.Protocol.Init( field_);" << '\n'; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - indent_impl(code_block) << "if (" << prop_name(*f_iter, is_exception,"__isset_") << ") then" - << '\n'; - indent_impl(code_block) << "begin" << '\n'; - indent_up_impl(); - indent_impl(code_block) << "field_.Name := '" << (*f_iter)->get_name() << "';" << '\n'; - indent_impl(code_block) << "field_.Type_ := " << type_to_enum((*f_iter)->get_type()) << ";" - << '\n'; - indent_impl(code_block) << "field_.ID := " << (*f_iter)->get_key() << ";" << '\n'; - indent_impl(code_block) << "oprot.WriteFieldBegin(field_);" << '\n'; - generate_serialize_field(code_block, is_exception, *f_iter, "Self.", local_vars); - indent_impl(code_block) << "oprot.WriteFieldEnd();" << '\n'; - indent_down_impl(); - } - } - - indent_impl(code_block) << "oprot.WriteFieldStop();" << '\n'; - indent_impl(code_block) << "oprot.WriteStructEnd();" << '\n'; - - indent_down_impl(); - indent_impl(code_block) << "end;" << '\n' << '\n'; - - string cls_nm; - - cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory); - - indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);" - << '\n'; - indent_impl(out) << "var" << '\n'; - indent_up_impl(); - indent_impl(out) << "struc : TThriftStruct;" << '\n'; - - if (fields.size() > 0) { - indent_impl(out) << "field_ : TThriftField;" << '\n'; - } - - out << local_vars.str(); - indent_down_impl(); - out << code_block.str(); -} - void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out, string cls_prefix, t_struct* tstruct, - bool is_exception, - bool is_x_factory) { + bool is_exception) { ostringstream local_vars; ostringstream code_block; @@ -3906,7 +3770,7 @@ void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out, string cls_nm; - cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory); + cls_nm = type_name(tstruct, true, is_exception); indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);" << '\n'; @@ -3924,8 +3788,7 @@ void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out, void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, string cls_prefix, t_struct* tstruct, - bool is_exception, - bool is_x_factory) { + bool is_exception) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; @@ -3933,7 +3796,7 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, string cls_nm; if (is_exception) { - cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true); + cls_nm = type_name(tstruct, true, true/*, false, true*/); } else { cls_nm = type_name(tstruct, true, false); } @@ -3998,10 +3861,7 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, << '\n'; } - t_type* ttype = (*f_iter)->get_type(); - while (ttype->is_typedef()) { - ttype = ((t_typedef*)ttype)->get_type(); - } + t_type* ttype = (*f_iter)->get_type()->get_true_type(); if (ttype->is_xception() || ttype->is_struct()) { indent_impl(out) << "if (Self." << prop_name((*f_iter), is_exception) << " = nil) then " << tmp_sb @@ -4009,7 +3869,7 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, << prop_name((*f_iter), is_exception) << ".ToString());" << '\n'; } else if (ttype->is_enum()) { indent_impl(out) << tmp_sb << ".Append(EnumUtils<" - << type_name(ttype, false, true, false, false) + << type_name(ttype, false, true) << ">.ToString( System.Ord( Self." << prop_name((*f_iter), is_exception) << ")));" << '\n'; } else if (ttype->is_uuid()) { @@ -4048,9 +3908,7 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, } bool t_delphi_generator::is_void(t_type* type) { - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } + type = type->get_true_type(); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); diff --git a/compiler/cpp/src/thrift/parse/t_function.h b/compiler/cpp/src/thrift/parse/t_function.h index 57cf5ffce37..d2cb19bbc3a 100644 --- a/compiler/cpp/src/thrift/parse/t_function.h +++ b/compiler/cpp/src/thrift/parse/t_function.h @@ -85,17 +85,23 @@ class t_function : public t_doc { void validate() const { get_returntype()->validate(); + +#ifndef ALLOW_EXCEPTIONS_AS_TYPE if (get_returntype()->get_true_type()->is_xception()) { failure("method %s(): exception type \"%s\" cannot be used as function return", get_name().c_str(), get_returntype()->get_name().c_str()); } +#endif std::vector::const_iterator it; std::vector list = get_arglist()->get_members(); for(it=list.begin(); it != list.end(); ++it) { (*it)->get_type()->validate(); + +#ifndef ALLOW_EXCEPTIONS_AS_TYPE if( (*it)->get_type()->get_true_type()->is_xception()) { failure("method %s(): exception type \"%s\" cannot be used as function argument %s", get_name().c_str(), (*it)->get_type()->get_name().c_str(), (*it)->get_name().c_str()); } +#endif } } diff --git a/compiler/cpp/src/thrift/parse/t_list.h b/compiler/cpp/src/thrift/parse/t_list.h index 5daa412bdcf..162281cc088 100644 --- a/compiler/cpp/src/thrift/parse/t_list.h +++ b/compiler/cpp/src/thrift/parse/t_list.h @@ -35,9 +35,11 @@ class t_list : public t_container { bool is_list() const override { return true; } void validate() const { +#ifndef ALLOW_EXCEPTIONS_AS_TYPE if( get_elem_type()->get_true_type()->is_xception()) { failure("exception type \"%s\" cannot be used inside a list", get_elem_type()->get_name().c_str()); } +#endif } private: diff --git a/compiler/cpp/src/thrift/parse/t_map.h b/compiler/cpp/src/thrift/parse/t_map.h index 444fca79800..30a8b06c9b9 100644 --- a/compiler/cpp/src/thrift/parse/t_map.h +++ b/compiler/cpp/src/thrift/parse/t_map.h @@ -38,12 +38,14 @@ class t_map : public t_container { bool is_map() const override { return true; } void validate() const { +#ifndef ALLOW_EXCEPTIONS_AS_TYPE if( get_key_type()->get_true_type()->is_xception()) { failure("exception type \"%s\" cannot be used inside a map", get_key_type()->get_name().c_str()); } if( get_val_type()->get_true_type()->is_xception()) { failure("exception type \"%s\" cannot be used inside a map", get_val_type()->get_name().c_str()); } +#endif } private: diff --git a/compiler/cpp/src/thrift/parse/t_set.h b/compiler/cpp/src/thrift/parse/t_set.h index 4a02dcc08ae..88de93f44c4 100644 --- a/compiler/cpp/src/thrift/parse/t_set.h +++ b/compiler/cpp/src/thrift/parse/t_set.h @@ -37,9 +37,11 @@ class t_set : public t_container { bool is_set() const override { return true; } void validate() const { +#ifndef ALLOW_EXCEPTIONS_AS_TYPE if( get_elem_type()->get_true_type()->is_xception()) { failure("exception type \"%s\" cannot be used inside a set", get_elem_type()->get_name().c_str()); } +#endif } private: diff --git a/compiler/cpp/src/thrift/parse/t_struct.h b/compiler/cpp/src/thrift/parse/t_struct.h index 941712d80ef..3aa67c0e16a 100644 --- a/compiler/cpp/src/thrift/parse/t_struct.h +++ b/compiler/cpp/src/thrift/parse/t_struct.h @@ -112,9 +112,8 @@ class t_struct : public t_type { const members_type& get_sorted_members() const { return members_in_id_order_; } bool is_struct() const override { return !is_xception_; } - bool is_xception() const override { return is_xception_; } - + bool is_method_xcepts() const override { return is_method_xcepts_; } bool is_union() const { return is_union_; } t_field* get_field_by_name(std::string field_name) { @@ -144,11 +143,14 @@ class t_struct : public t_type { std::vector list = get_members(); for(it=list.begin(); it != list.end(); ++it) { (*it)->get_type()->validate(); + +#ifndef ALLOW_EXCEPTIONS_AS_TYPE if (!is_method_xcepts_) { // this is in fact the only legal usage for any exception type if( (*it)->get_type()->get_true_type()->is_xception()) { failure("%s %s: exception type \"%s\" cannot be used as member field type %s", what.c_str(), get_name().c_str(), (*it)->get_type()->get_name().c_str(), (*it)->get_name().c_str()); } } +#endif } } diff --git a/compiler/cpp/src/thrift/parse/t_type.h b/compiler/cpp/src/thrift/parse/t_type.h index f4082426c8e..d087601aeca 100644 --- a/compiler/cpp/src/thrift/parse/t_type.h +++ b/compiler/cpp/src/thrift/parse/t_type.h @@ -26,6 +26,8 @@ #include #include +#define ALLOW_EXCEPTIONS_AS_TYPE + class t_program; /** @@ -54,6 +56,7 @@ class t_type : public t_doc { virtual bool is_enum() const { return false; } virtual bool is_struct() const { return false; } virtual bool is_xception() const { return false; } + virtual bool is_method_xcepts() const { return false; } virtual bool is_container() const { return false; } virtual bool is_list() const { return false; } virtual bool is_set() const { return false; } diff --git a/lib/delphi/test/serializer/SerializerData.dpr b/lib/delphi/test/serializer/SerializerData.dpr index 92ed00b0094..637e4ed9925 100644 --- a/lib/delphi/test/serializer/SerializerData.dpr +++ b/lib/delphi/test/serializer/SerializerData.dpr @@ -40,6 +40,8 @@ uses Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', System_ in 'gen-delphi\System_.pas', SysUtils_ in 'gen-delphi\SysUtils_.pas', + test.ExceptionStruct in 'gen-delphi\test.ExceptionStruct.pas', + test.SimpleException in 'gen-delphi\test.SimpleException.pas', DebugProtoTest in 'gen-delphi\DebugProtoTest.pas', TestSerializer.Data in 'TestSerializer.Data.pas'; @@ -69,11 +71,26 @@ begin end; +function CreateBatchGetResponse : IBatchGetResponse; stdcall; +begin + result := Fixtures.CreateBatchGetResponse; +end; + + +function CreateSimpleException : IError; stdcall; +begin + result := Fixtures.CreateSimpleException; +end; + + exports CreateOneOfEach, CreateNesting, CreateHolyMoley, - CreateCompactProtoTestStruct; + CreateCompactProtoTestStruct, + CreateBatchGetResponse, + CreateSimpleException; + begin IsMultiThread := TRUE; diff --git a/lib/delphi/test/serializer/SerializerData.dproj b/lib/delphi/test/serializer/SerializerData.dproj index cfc27f8781d..cdad3120517 100644 --- a/lib/delphi/test/serializer/SerializerData.dproj +++ b/lib/delphi/test/serializer/SerializerData.dproj @@ -1,22 +1,4 @@ - - + {B523D1D7-2C9A-4B39-A6CF-69EF536D5079} SerializerData.dpr @@ -85,6 +67,8 @@ + + @@ -100,10 +84,12 @@ - + - + Delphi.Personality.12 @@ -140,6 +126,9 @@ thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift]]>

SerializerData.dpr + + bin\Debug\Win32\TestSerializer.exe + True diff --git a/lib/delphi/test/serializer/SimpleException.thrift b/lib/delphi/test/serializer/SimpleException.thrift new file mode 100644 index 00000000000..c13876c8d74 --- /dev/null +++ b/lib/delphi/test/serializer/SimpleException.thrift @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +namespace * test.SimpleException + +exception Error { + 1: i32 ErrorCode = 42 + /** test name collision with Exception class */ + 2: Error InnerException + /** test name collisions with Thrift Delphi implementation details */ + 3: uuid ExceptionData = '00000000-4444-CCCC-ffff-0123456789ab' +} + + + +// EOF diff --git a/lib/delphi/test/serializer/TestSerializer.Data.pas b/lib/delphi/test/serializer/TestSerializer.Data.pas index 24f850d2f61..ddf4ba243eb 100644 --- a/lib/delphi/test/serializer/TestSerializer.Data.pas +++ b/lib/delphi/test/serializer/TestSerializer.Data.pas @@ -27,6 +27,8 @@ interface ComObj, Thrift.Protocol, Thrift.Collections, + test.ExceptionStruct, + test.SimpleException, DebugProtoTest; @@ -37,6 +39,8 @@ Fixtures = class class function CreateNesting : INesting; class function CreateHolyMoley : IHolyMoley; class function CreateCompactProtoTestStruct : ICompactProtoTestStruct; + class function CreateBatchGetResponse : IBatchGetResponse; + class function CreateSimpleException : IError; // These byte arrays are serialized versions of the above structs. // They were serialized in binary protocol using thrift 0.6.x and are used to @@ -359,6 +363,51 @@ class function Fixtures.CreateCompactProtoTestStruct : ICompactProtoTestStruct; end; +class function Fixtures.CreateBatchGetResponse : IBatchGetResponse; +var + data : IGetRequest; + error : ISomeException; +const + REQUEST_ID = '123'; +begin + data := TGetRequestImpl.Create; + data.Id := REQUEST_ID; + data.Data := TThriftBytesImpl.Create( TEncoding.UTF8.GetBytes( #0#1#2#3#4#5#6#7#8)); + + error := TSomeExceptionImpl.Create; + error.Error := TErrorCode.GenericError; + + result := TBatchGetResponseImpl.Create; + result.Responses := TThriftDictionaryImpl.Create; + result.Responses.Add( REQUEST_ID, data); + result.Errors := TThriftDictionaryImpl.Create; + result.Errors.Add( REQUEST_ID, error); +end; + + +class function Fixtures.CreateSimpleException : IError; +var i : Integer; + inner : IError; + guid : TGuid; +const + IDL_GUID_VALUE : TGuid = '{00000000-4444-CCCC-ffff-0123456789ab}'; +begin + result := nil; + for i := 0 to 4 do begin + inner := result; + result := TErrorImpl.Create; + + // validate const values set in IDL + ASSERT( result.ErrorCode = 42); // IDL default value + ASSERT( IsEqualGUID( result.ExceptionData, IDL_GUID_VALUE)); + + // set fresh, but reproducible values + FillChar( guid, SizeOf(guid), i); + result.ErrorCode := i; + result.ExceptionData := guid; + result.InnerException := inner; + end; +end; end. diff --git a/lib/delphi/test/serializer/TestSerializer.Tests.pas b/lib/delphi/test/serializer/TestSerializer.Tests.pas index e6a309e6861..466fb269efc 100644 --- a/lib/delphi/test/serializer/TestSerializer.Tests.pas +++ b/lib/delphi/test/serializer/TestSerializer.Tests.pas @@ -41,6 +41,8 @@ interface Thrift.WinHTTP, Thrift.TypeRegistry, System_, + test.ExceptionStruct, + test.SimpleException, DebugProtoTest; {$TYPEINFO ON} @@ -82,8 +84,11 @@ TTestSerializer = class //extends TestCase { procedure Test_Serializer_Deserializer; procedure Test_COM_Types; procedure Test_ThriftBytesCTORs; - procedure Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); - procedure Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); + + procedure Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); + procedure Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); + procedure Test_ExceptionStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); + procedure Test_SimpleException( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); public constructor Create; @@ -100,6 +105,8 @@ function CreateOneOfEach : IOneOfEach; stdcall; external SERIALIZERDATA_DLL; function CreateNesting : INesting; stdcall; external SERIALIZERDATA_DLL; function CreateHolyMoley : IHolyMoley; stdcall; external SERIALIZERDATA_DLL; function CreateCompactProtoTestStruct : ICompactProtoTestStruct; stdcall; external SERIALIZERDATA_DLL; +function CreateBatchGetResponse : IBatchGetResponse; stdcall; external SERIALIZERDATA_DLL; +function CreateSimpleException : IError; stdcall; external SERIALIZERDATA_DLL; { TTestSerializer } @@ -266,6 +273,105 @@ procedure TTestSerializer.Test_CompactStruct( const method : TMethod; const fact end; +procedure TTestSerializer.Test_ExceptionStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); +var tested, correct : IBatchGetResponse; + bytes : TBytes; + corrDP, testDP : TPair; + corrEP, testEP : TPair; +begin + // write + tested := CreateBatchGetResponse; + case method of + mt_Bytes: bytes := Serialize( tested, factory); + mt_Stream: begin + stream.Size := 0; + Serialize( tested, factory, stream); + end + else + ASSERT( FALSE); + end; + + // init + read + correct := TBatchGetResponseImpl.Create; + case method of + mt_Bytes: Deserialize( bytes, tested, factory); + mt_Stream: begin + stream.Position := 0; + Deserialize( stream, tested, factory); + end + else + ASSERT( FALSE); + end; + + // check + correct := CreateBatchGetResponse; + + // rewrite the following test if not + ASSERT( tested.Responses.Count = 1); + ASSERT( correct.Responses.Count = tested.Responses.Count); + for corrDP in correct.Responses do begin + for testDP in tested.Responses do begin + ASSERT( corrDP.Key = testDP.Key); + ASSERT( corrDP.Value.Id = testDP.Value.Id); + ASSERT( corrDP.Value.Data.Count = testDP.Value.Data.Count); + end; + end; + + // rewrite the following test if not + ASSERT( tested.Errors.Count = 1); + ASSERT( correct.Errors.Count = tested.Errors.Count); + for corrEP in correct.Errors do begin + for testEP in tested.Errors do begin + ASSERT( corrEP.Key = testEP.Key); + ASSERT( corrEP.Value.Error = testEP.Value.Error); + end; + end; +end; + + +procedure TTestSerializer.Test_SimpleException( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); +var tested, correct : IError; + bytes : TBytes; +begin + // write + tested := CreateSimpleException; + case method of + mt_Bytes: bytes := Serialize( tested, factory); + mt_Stream: begin + stream.Size := 0; + Serialize( tested, factory, stream); + end + else + ASSERT( FALSE); + end; + + // init + read + correct := TErrorImpl.Create; + case method of + mt_Bytes: Deserialize( bytes, tested, factory); + mt_Stream: begin + stream.Position := 0; + Deserialize( stream, tested, factory); + end + else + ASSERT( FALSE); + end; + + // check + correct := CreateSimpleException; + while correct <> nil do begin + // validate + ASSERT( correct.ErrorCode = tested.ErrorCode); + ASSERT( IsEqualGUID( correct.ExceptionData, tested.ExceptionData)); + + // iterate + correct := correct.InnerException; + tested := tested.InnerException; + ASSERT( (tested <> nil) xor (correct = nil)); // both or none + end; +end; + + procedure TTestSerializer.Test_Serializer_Deserializer; var factory : TFactoryPair; stream : TFileStream; @@ -279,8 +385,10 @@ procedure TTestSerializer.Test_Serializer_Deserializer; for factory in FProtocols do begin Writeln('- '+UserFriendlyName(factory)); - Test_OneOfEach( method, factory, stream); - Test_CompactStruct( method, factory, stream); + Test_OneOfEach( method, factory, stream); + Test_CompactStruct( method, factory, stream); + Test_ExceptionStruct( method, factory, stream); + Test_SimpleException( method, factory, stream); end; Writeln; diff --git a/lib/delphi/test/serializer/TestSerializer.dpr b/lib/delphi/test/serializer/TestSerializer.dpr index b78c0db05d9..8c2f64d9e10 100644 --- a/lib/delphi/test/serializer/TestSerializer.dpr +++ b/lib/delphi/test/serializer/TestSerializer.dpr @@ -44,6 +44,8 @@ uses System_ in 'gen-delphi\System_.pas', SysUtils_ in 'gen-delphi\SysUtils_.pas', DebugProtoTest in 'gen-delphi\DebugProtoTest.pas', + test.ExceptionStruct in 'gen-delphi\test.ExceptionStruct.pas', + test.SimpleException in 'gen-delphi\test.SimpleException.pas', TestSerializer.Tests in 'TestSerializer.Tests.pas'; diff --git a/lib/delphi/test/serializer/TestSerializer.dproj b/lib/delphi/test/serializer/TestSerializer.dproj index 383e04a9547..5ea2b796adc 100644 --- a/lib/delphi/test/serializer/TestSerializer.dproj +++ b/lib/delphi/test/serializer/TestSerializer.dproj @@ -1,22 +1,4 @@ - - + {9282EDD8-7C12-41B0-8172-61C6BFA6E238} TestSerializer.dpr @@ -85,6 +67,8 @@ + + Cfg_2 @@ -99,10 +83,12 @@ - + +thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift +thrift.exe -r -gen delphi:com_types ..\..\..\..\test\ExceptionStruct.thrift +thrift.exe -r -gen delphi:com_types SimpleException.thrift]]> Delphi.Personality.12 diff --git a/test/ExceptionStruct.thrift b/test/ExceptionStruct.thrift new file mode 100644 index 00000000000..b962209b3d1 --- /dev/null +++ b/test/ExceptionStruct.thrift @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +namespace * test.ExceptionStruct + +enum ErrorCode { + GenericError, + ServerOverload, + InvalidData +} + +struct GetRequest { + 1: string id + 2: binary data // some arbitrary data +} + +struct GetResponse { + 1: i32 job_nr + 2: binary data // some arbitrary data +} + +struct BatchGetRequest { + 1: list requests +} + +struct BatchGetResponse { + 1: map responses, // key is id + 2: map errors, // key is id +} + +exception SomeException { + 2: ErrorCode error +} + +service Foo { + GetResponse get(1: GetRequest request) throws(1: SomeException error); + BatchGetResponse batchGet(1: BatchGetRequest request) throws(1: SomeException error); // may or may not be the same exception type, only throw exception when full request failed +} + +# eof