From cd7a2aa0985b01a4aeeb6e55bb8c6397c53a662a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Mon, 17 Oct 2022 14:21:18 +0200 Subject: THRIFT-5656 Escape Delphi keywords with '&' prefix instead of '_' suffix Client: Delphi Patch: Jens Geyer --- .../cpp/src/thrift/generate/t_delphi_generator.cc | 155 ++++++++++++--------- 1 file changed, 89 insertions(+), 66 deletions(-) (limited to 'compiler') diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc index 8c37c6534..de7e46a00 100644 --- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc @@ -70,6 +70,7 @@ public: ansistr_binary_ = false; register_types_ = false; constprefix_ = false; + old_names_ = false; events_ = false; xmldoc_ = false; async_ = false; @@ -79,6 +80,8 @@ public: ansistr_binary_ = true; } else if( iter->first.compare("register_types") == 0) { register_types_ = true; + } else if( iter->first.compare("old_names") == 0) { + old_names_ = true; } else if( iter->first.compare("constprefix") == 0) { constprefix_ = true; } else if( iter->first.compare("events") == 0) { @@ -353,8 +356,8 @@ public: 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 prop_name(t_field* tfield, bool is_xception = false, std::string prefix = ""); + std::string prop_name(std::string name, bool is_xception = false, std::string prefix = ""); std::string constructor_param_name(string name); void write_enum(std::string line); @@ -402,7 +405,8 @@ private: bool has_enum; bool has_const; std::string namespace_dir_; - std::map delphi_keywords; + std::map delphi_keywords; // TODO: put all into one map, value=flags tells what it is + std::map delphi_reserved_names; std::map delphi_reserved_method; std::map delphi_reserved_method_exception; std::map types_known; @@ -412,7 +416,8 @@ private: bool find_keyword(std::map& keyword_map, std::string name); std::string normalize_name(std::string name, bool b_method = false, - bool b_exception_method = false); + bool b_exception_method = false, + bool b_force_underscore = false); std::string empty_value(t_type* type); bool is_fully_defined_type(t_type* ttype); void add_defined_type(t_type* ttype); @@ -422,6 +427,7 @@ private: bool ansistr_binary_; bool register_types_; bool constprefix_; + bool old_names_; bool events_; bool xmldoc_; bool async_; @@ -566,24 +572,35 @@ bool t_delphi_generator::find_keyword(std::map& keyword_map, s std::string t_delphi_generator::normalize_name(std::string name, bool b_method, - bool b_exception_method) { + bool b_exception_method, + bool b_force_underscore) { string tmp(name); std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast(std::tolower)); - bool b_found = false; + bool b_reserved = false; + bool b_keyword = false; if (find_keyword(delphi_keywords, tmp)) { - b_found = true; + b_keyword = true; + } else if (find_keyword(delphi_reserved_names, tmp)) { + b_reserved = true; } else if (b_method && find_keyword(delphi_reserved_method, tmp)) { - b_found = true; + b_reserved = true; } else if (b_exception_method && find_keyword(delphi_reserved_method_exception, tmp)) { - b_found = true; + b_reserved = true; } - if (b_found) { + // neither reserved nor keyword? + if (!(b_reserved || b_keyword)) { + return name; + } + + // apply the rule: old style '_' postfix or more modern '&' prefix? + // underscore always on non-keywords or when explicitly asked via arg + if( (!b_keyword) || old_names_ || b_force_underscore) { return name + "_"; } else { - return name; + return "&" + name; } } @@ -661,15 +678,7 @@ void t_delphi_generator::create_keywords() { delphi_keywords["at"] = 1; delphi_keywords["on"] = 1; - // reserved/predefined variables and types (lowercase!) - delphi_keywords["result"] = 1; - delphi_keywords["system"] = 1; - delphi_keywords["sysutils"] = 1; - delphi_keywords["thrift"] = 1; - delphi_keywords["tbytes"] = 1; - delphi_keywords["tobject"] = 1; - delphi_keywords["tclass"] = 1; - delphi_keywords["tinterfacedobject"] = 1; + // predefined types (lowercase!) delphi_keywords["ansistring"] = 1; delphi_keywords["string"] = 1; delphi_keywords["boolean"] = 1; @@ -679,6 +688,17 @@ void t_delphi_generator::create_keywords() { delphi_keywords["int64"] = 1; delphi_keywords["double"] = 1; + // reserved variables and types (lowercase!) + delphi_reserved_names["result"] = 1; + delphi_reserved_names["system"] = 1; + delphi_reserved_names["sysutils"] = 1; + delphi_reserved_names["thrift"] = 1; + delphi_reserved_names["tbytes"] = 1; + delphi_reserved_names["tobject"] = 1; + delphi_reserved_names["tclass"] = 1; + delphi_reserved_names["tinterfacedobject"] = 1; + + // reserved method names (lowercase!) delphi_reserved_method["create"] = 1; delphi_reserved_method["free"] = 1; delphi_reserved_method["initinstance"] = 1; @@ -782,7 +802,7 @@ void t_delphi_generator::init_generator() { unitname = include->get_name(); nsname = include->get_namespace("delphi"); if ("" != nsname) { - unitname = normalize_name(nsname); + unitname = normalize_name(nsname,false,false,true/*force underscore*/); } add_delphi_uses_list(unitname); } @@ -802,7 +822,7 @@ void t_delphi_generator::close_generator() { } } - unitname = normalize_name(unitname); + unitname = normalize_name(unitname,false,false,true/*force underscore*/); std::string f_name = get_out_dir() + "/" + unitname + ".pas"; ofstream_with_content_based_conditional_update f_all; @@ -850,6 +870,7 @@ void t_delphi_generator::close_generator() { indent(f_all) << "c" << tmp_unit << "_Option_XmlDoc = " << (xmldoc_ ? "True" : "False") << ";" << endl; indent(f_all) << "c" << tmp_unit << "_Option_Async = " << (async_ ? "True" : "False") << ";" << endl; indent(f_all) << "c" << tmp_unit << "_Option_COM_types = " << (com_types_ ? "True" : "False") << ";" << endl; + indent(f_all) << "c" << tmp_unit << "_Option_Old_Names = " << (old_names_ ? "True" : "False") << ";" << endl; indent_down(); f_all << endl; @@ -927,7 +948,7 @@ void t_delphi_generator::delphi_type_usings(ostream& out) { void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) { // Forward declare struct def has_forward = true; - pverbose("forward declaration of %s\n", type_name(tstruct).c_str()); + pdebug("forward declaration of %s\n", type_name(tstruct).c_str()); string what = tstruct->is_xception() ? "class" : "interface"; @@ -1164,7 +1185,7 @@ void t_delphi_generator::generate_consts(std::vector consts) { for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { initialize_field(vars, code, - "F" + prop_name((*c_iter)->get_name()), + prop_name((*c_iter)->get_name(), false, "F"), (*c_iter)->get_type(), (*c_iter)->get_value()); } @@ -1208,7 +1229,7 @@ void t_delphi_generator::generate_consts(std::vector consts) { if (const_needs_var((*c_iter)->get_type())) { initialize_field(vars, code, - constants_class + ".F" + prop_name((*c_iter)->get_name()), + constants_class + "." + prop_name((*c_iter)->get_name(), false, "F"), (*c_iter)->get_type(), (*c_iter)->get_value()); } @@ -1504,11 +1525,11 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out, if ((*m_iter)->get_value() != nullptr) { initialize_field(vars, code, - "F" + prop_name((*m_iter)->get_name(), is_exception), + prop_name((*m_iter)->get_name(), is_exception, ""), t, (*m_iter)->get_value()); if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - indent_impl(code) << "F__isset_" << prop_name((*m_iter), is_exception) << " := True;" + indent_impl(code) << prop_name((*m_iter), is_exception, "F__isset_") << " := True;" << endl; } } @@ -1788,7 +1809,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - isset_name = "__isset_" + prop_name(*m_iter, is_exception); + isset_name = prop_name(*m_iter, is_exception, "__isset_"); indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";" << endl; } @@ -1837,7 +1858,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, indent(out) << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - isset_name = "F__isset_" + prop_name(*m_iter, is_exception); + isset_name = prop_name(*m_iter, is_exception, "F__isset_"); indent(out) << isset_name << ": System.Boolean;" << endl; } } @@ -1860,7 +1881,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - isset_name = "__isset_" + prop_name(*m_iter, is_exception); + isset_name = prop_name(*m_iter, is_exception, "__isset_"); indent(out) << "function Get" << isset_name << ": System.Boolean;" << endl; indent(out) << "procedure Set" << isset_name << "( const value : System.Boolean);" << endl; } @@ -1925,7 +1946,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, indent(out) << "// isset" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { - isset_name = "__isset_" + prop_name(*m_iter, is_exception); + isset_name = prop_name(*m_iter, is_exception, "__isset_"); indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";" << endl; } @@ -2283,7 +2304,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - indent_impl(s_service_impl) << "if (" << retvar << ".__isset_" << prop_name(*x_iter) + indent_impl(s_service_impl) << "if (" << retvar << "." << prop_name(*x_iter, false, "__isset_") << ") then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter) @@ -3078,26 +3099,26 @@ void t_delphi_generator::generate_delphi_property(ostream& out, 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 " - << fieldPrefix + prop_name(tfield, struct_is_xception) << " write Set" - << prop_name(tfield, struct_is_xception) << ";" << endl; + << type_name(ftype, false, true, is_xception, true) + << " read " << prop_name(tfield, struct_is_xception, fieldPrefix) + << " write " << prop_name(tfield, struct_is_xception, "Set") + << ";" << endl; } -std::string t_delphi_generator::prop_name(t_field* tfield, bool is_xception) { - return prop_name(tfield->get_name(), is_xception); +std::string t_delphi_generator::prop_name(t_field* tfield, bool is_xception, std::string prefix) { + return prop_name(tfield->get_name(), is_xception, prefix); } -std::string t_delphi_generator::prop_name(string name, bool is_xception) { +std::string t_delphi_generator::prop_name(string name, bool is_xception, std::string prefix) { string ret = name; ret[0] = toupper(ret[0]); - return normalize_name(ret, true, is_xception); + return normalize_name(prefix + 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); + return normalize_name("a" + ret, false, false); } string t_delphi_generator::normalize_clsnm(string clsnm, string prefix, bool b_no_check_keyword) { @@ -3288,7 +3309,7 @@ string t_delphi_generator::declare_field(t_field* tfield, t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); - string result = prefix + prop_name(tfield, is_xception_class) + ": " + string result = prop_name(tfield, is_xception_class, prefix) + ": " + type_name(ftype, false, true, is_xception, true) + ";"; return result; } @@ -3510,7 +3531,7 @@ void t_delphi_generator::generate_delphi_property_writer_definition(ostream& out t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); - indent(out) << "procedure Set" << prop_name(tfield, is_xception_class) + indent(out) << "procedure " << prop_name(tfield, is_xception_class, "Set") << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");" << endl; } @@ -3521,15 +3542,15 @@ void t_delphi_generator::generate_delphi_property_reader_definition(ostream& out t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); - indent(out) << "function Get" << prop_name(tfield, is_xception_class) << ": " + indent(out) << "function " << prop_name(tfield, is_xception_class, "Get") << ": " << type_name(ftype, false, true, is_xception, true) << ";" << endl; } void t_delphi_generator::generate_delphi_isset_reader_writer_definition(ostream& out, t_field* tfield, bool is_xception) { - indent(out) << "function Get__isset_" << prop_name(tfield, is_xception) << ": System.Boolean;" << endl; - indent(out) << "procedure Set__isset_" << prop_name(tfield, is_xception) << "( const value : System.Boolean);" << endl; + indent(out) << "function " << prop_name(tfield, is_xception,"Get__isset_") << ": System.Boolean;" << endl; + indent(out) << "procedure " << prop_name(tfield, is_xception, "Set__isset_") << "( const value : System.Boolean);" << endl; } void t_delphi_generator::generate_delphi_clear_union_value(ostream& out, @@ -3552,11 +3573,11 @@ void t_delphi_generator::generate_delphi_clear_union_value(ostream& out, t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); - indent_impl(out) << "if F__isset_" << prop_name(tfield, is_xception_class) << " then begin" + indent_impl(out) << "if " << prop_name(tfield, is_xception_class,"F__isset_") << " then begin" << endl; indent_up_impl(); - indent_impl(out) << "F__isset_" << prop_name(tfield, is_xception_class) << " := False;" << endl; - indent_impl(out) << fieldPrefix << prop_name(tfield, is_xception_class) << " := " + indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := False;" << endl; + indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := " << "Default( " << type_name(ftype, false, true, is_xception, true) << ");" << endl; indent_down_impl(); @@ -3579,7 +3600,7 @@ void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out, bool is_xception = ftype->is_xception(); indent_impl(out) << "procedure " << cls_prefix << name << "." - << "Set" << prop_name(tfield, is_xception_class) + << prop_name(tfield, is_xception_class,"Set") << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");" << endl; indent_impl(out) << "begin" << endl; @@ -3588,9 +3609,9 @@ void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out, indent_impl(out) << "ClearUnionValues;" << endl; } if (tfield->get_req() != t_field::T_REQUIRED) { - indent_impl(out) << "F__isset_" << prop_name(tfield, is_xception_class) << " := True;" << endl; + indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := True;" << endl; } - indent_impl(out) << fieldPrefix << prop_name(tfield, is_xception_class) << " := Value;" << endl; + indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := Value;" << endl; if (is_xception_class && (!is_xception_factory)) { indent_impl(out) << xception_factory_name << "." << prop_name(tfield, is_xception_class) @@ -3614,11 +3635,11 @@ void t_delphi_generator::generate_delphi_property_reader_impl(ostream& out, bool is_xception = ftype->is_xception(); indent_impl(out) << "function " << cls_prefix << name << "." - << "Get" << prop_name(tfield, is_xception_class) << ": " + << prop_name(tfield, is_xception_class,"Get") << ": " << type_name(ftype, false, true, is_xception, true) << ";" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); - indent_impl(out) << "Result := " << fieldPrefix << prop_name(tfield, is_xception_class) << ";" + indent_impl(out) << "Result := " << prop_name(tfield, is_xception_class,fieldPrefix) << ";" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; @@ -3633,7 +3654,7 @@ void t_delphi_generator::generate_delphi_isset_reader_writer_impl(ostream& out, bool is_xception) { (void)type; - string isset_name = "__isset_" + prop_name(tfield, is_xception); + string isset_name = prop_name(tfield, is_xception, "__isset_"); indent_impl(out) << "function " << cls_prefix << name << "." << "Get" << isset_name << ": System.Boolean;" << endl; @@ -3679,7 +3700,7 @@ void t_delphi_generator::generate_delphi_create_exception_impl(ostream& out, 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 __isset_" << propname << " then begin" << endl; + indent_impl(out) << "if " << prop_name(*f_iter, is_exception,"__isset_") << " then begin" << endl; indent_up_impl(); } indent_impl(out) << "Result." << propname << " := " << propname << ";" << endl; @@ -3716,9 +3737,9 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, // local bools for required fields for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { - indent_impl(local_vars) << "_req_isset_" << prop_name(*f_iter, is_exception) << " : System.Boolean;" + indent_impl(local_vars) << prop_name(*f_iter, is_exception,"_req_isset_") << " : System.Boolean;" << endl; - indent_impl(code_block) << "_req_isset_" << prop_name(*f_iter, is_exception) << " := FALSE;" + indent_impl(code_block) << prop_name(*f_iter, is_exception,"_req_isset_") << " := FALSE;" << endl; } } @@ -3760,7 +3781,7 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, // required field? if ((*f_iter)->get_req() == t_field::T_REQUIRED) { - indent_impl(code_block) << "_req_isset_" << prop_name(*f_iter, is_exception) << " := TRUE;" + indent_impl(code_block) << prop_name(*f_iter, is_exception,"_req_isset_") << " := TRUE;" << endl; } @@ -3810,7 +3831,7 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, code_block << endl; first = false; } - indent_impl(code_block) << "if not _req_isset_" << prop_name(*f_iter, is_exception) << endl; + indent_impl(code_block) << "if not " << prop_name(*f_iter, is_exception,"_req_isset_") << endl; indent_impl(code_block) << "then raise TProtocolExceptionInvalidData.Create(" << "'required field " << prop_name(*f_iter, is_exception) << " not set');" @@ -3865,7 +3886,7 @@ void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out, if (fields.size() > 0) { indent_impl(code_block) << "Thrift.Protocol.Init( field_);" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - indent_impl(code_block) << "if (__isset_" << prop_name(*f_iter, is_exception) << ") then" + indent_impl(code_block) << "if (" << prop_name(*f_iter, is_exception,"__isset_") << ") then" << endl; indent_impl(code_block) << "begin" << endl; indent_up_impl(); @@ -3933,6 +3954,7 @@ void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out, for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { string fieldname = prop_name((*f_iter), is_exception); + string isset_name = prop_name((*f_iter), is_exception, "__isset_"); bool null_allowed = type_can_be_null((*f_iter)->get_type()); bool is_required = ((*f_iter)->get_req() == t_field::T_REQUIRED); bool has_isset = (!is_required); @@ -3946,13 +3968,13 @@ void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out, if (null_allowed) { indent_impl(code_block) << "if (Self." << fieldname << " <> nil)"; if (has_isset) { - code_block << " and __isset_" << fieldname; + code_block << " and " << isset_name; } code_block << " then begin" << endl; indent_up_impl(); } else { if (has_isset) { - indent_impl(code_block) << "if (__isset_" << fieldname << ") then begin" << endl; + indent_impl(code_block) << "if (" << isset_name << ") then begin" << endl; indent_up_impl(); } } @@ -4045,13 +4067,13 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, if (null_allowed) { indent_impl(out) << "if (Self." << prop_name((*f_iter), is_exception) << " <> nil)"; if (is_optional) { - out << " and __isset_" << prop_name(*f_iter, is_exception); + out << " and " << prop_name(*f_iter, is_exception,"__isset_"); } out << " then begin" << endl; indent_up_impl(); } else { if (is_optional) { - indent_impl(out) << "if (__isset_" << prop_name(*f_iter, is_exception) << ") then begin" + indent_impl(out) << "if (" << prop_name(*f_iter, is_exception, "__isset_") << ") then begin" << endl; indent_up_impl(); } @@ -4147,4 +4169,5 @@ THRIFT_REGISTER_GENERATOR( " events: Enable and use processing events in the generated code.\n" " xmldoc: Enable XMLDoc comments for Help Insight etc.\n" " async: Generate IAsync interface to use Parallel Programming Library (XE7+ only).\n" - " com_types: Use COM-compatible data types (e.g. WideString).\n") + " com_types: Use COM-compatible data types (e.g. WideString).\n" + " old_names: Compatibility: generate \"reserved\" identifiers with '_' postfix instead of '&' prefix.\n") -- cgit v1.2.1