Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

THRIFT-5781 implement full deprecation support #2966

Merged
merged 1 commit into from Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
114 changes: 106 additions & 8 deletions compiler/cpp/src/thrift/generate/t_netstd_generator.cc
Expand Up @@ -219,13 +219,97 @@ void t_netstd_generator::pragmas_and_directives(ostream& out)
out << "#pragma warning disable IDE1006 // parts of the code use IDL spelling" << '\n';
out << "#pragma warning disable CA1822 // empty " << DEEP_COPY_METHOD_NAME << "() methods still non-static" << '\n';

if( any_deprecations()) {
out << "#pragma warning disable CS0618 // silence our own deprecation warnings" << '\n';
}

if( target_net_version < 6) {
out << "#pragma warning disable IDE0083 // pattern matching \"that is not SomeType\" requires net5.0 but we still support earlier versions" << '\n';
}
out << '\n';
}


bool t_netstd_generator::any_deprecations()
{
// enums
vector<t_enum*> enums = program_->get_enums();
vector<t_enum*>::iterator en_iter;
for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) {
if( is_deprecated((*en_iter)->annotations_)) {
return true;
}

// enum values
vector<t_enum_value*> evals = (*en_iter)->get_constants();
vector<t_enum_value*>::iterator ev_iter;
for (ev_iter = evals.begin(); ev_iter != evals.end(); ++ev_iter) {
if( is_deprecated((*ev_iter)->annotations_)) {
return true;
}
}
}

// typedefs
vector<t_typedef*> typedefs = program_->get_typedefs();
vector<t_typedef*>::iterator td_iter;
for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) {
if( is_deprecated((*td_iter)->annotations_)) {
return true;
}
}

// structs, exceptions, unions
vector<t_struct*> objects = program_->get_objects();
vector<t_struct*>::iterator o_iter;
for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) {
if( is_deprecated((*o_iter)->annotations_)) {
return true;
}

// struct members
const vector<t_field*>& members = (*o_iter)->get_members();
vector<t_field*>::const_iterator m_iter;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if( is_deprecated((*m_iter)->annotations_)) {
return true;
}
}
}

/* not yet
// constants
vector<t_const*> consts = program_->get_consts();
vector<t_const*>::iterator c_iter;
for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
if( is_deprecated((*c_iter)->annotations_)) {
return true;
}
}
*/

// services
vector<t_service*> services = program_->get_services();
vector<t_service*>::iterator sv_iter;
for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
if( is_deprecated((*sv_iter)->annotations_)) {
return true;
}

// service methods
vector<t_function*> functions = (*sv_iter)->get_functions();
vector<t_function*>::iterator f_iter;
for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
if( is_deprecated((*f_iter)->annotations_)) {
return true;
}
}
}

return false;
}


void t_netstd_generator::start_netstd_namespace(ostream& out)
{
if (!namespace_name_.empty())
Expand Down Expand Up @@ -315,6 +399,7 @@ void t_netstd_generator::generate_enum(ostream& out, t_enum* tenum)
start_netstd_namespace(out);
generate_netstd_doc(out, tenum);

generate_deprecation_attribute(out, tenum->annotations_);
out << indent() << "public enum " << type_name(tenum,false) << '\n';
scope_up(out);

Expand All @@ -325,6 +410,7 @@ void t_netstd_generator::generate_enum(ostream& out, t_enum* tenum)
{
generate_netstd_doc(out, *c_iter);
int value = (*c_iter)->get_value();
generate_deprecation_attribute(out, (*c_iter)->annotations_);
out << indent() << normalize_name((*c_iter)->get_name()) << " = " << value << "," << '\n';
}

Expand Down Expand Up @@ -850,6 +936,7 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc

string sharp_struct_name = type_name(tstruct, false);

generate_deprecation_attribute(out, tstruct->annotations_);
out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << sharp_struct_name << " : ";

if (is_exception)
Expand Down Expand Up @@ -1055,6 +1142,7 @@ void t_netstd_generator::generate_netstd_wcffault(ostream& out, t_struct* tstruc

bool is_final = tstruct->annotations_.find("final") != tstruct->annotations_.end();

generate_deprecation_attribute(out, tstruct->annotations_);
out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << type_name(tstruct,false) << "Fault" << '\n'
<< indent() << "{" << '\n';
indent_up();
Expand Down Expand Up @@ -1103,7 +1191,7 @@ void t_netstd_generator::generate_netstd_deepcopy_method(ostream& out, t_struct*
out << '\n' << indent() << "{" << '\n';
indent_up();
} else {
out << '\n';
out << ";\n";
}

for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Expand Down Expand Up @@ -1526,6 +1614,7 @@ void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct
// Let's define the class first
start_netstd_namespace(out);

generate_deprecation_attribute(out, tunion->annotations_);
out << indent() << "public abstract partial class " << normalize_name(tunion->get_name()) << " : TUnionBase" << '\n';
out << indent() << "{" << '\n';
indent_up();
Expand Down Expand Up @@ -1979,6 +2068,7 @@ void t_netstd_generator::generate_service_interface(ostream& out, t_service* tse
out << indent() << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << '\n';
}

generate_deprecation_attribute(out, tservice->annotations_);
prepare_member_name_mapping(tservice);
out << indent() << "public interface IAsync" << extends_iface << '\n'
<< indent() << "{" << '\n';
Expand All @@ -2003,18 +2093,24 @@ void t_netstd_generator::generate_service_interface(ostream& out, t_service* tse
}
}

generate_deprecation_attribute(out, *f_iter);
generate_deprecation_attribute(out, (*f_iter)->annotations_);
out << indent() << function_signature_async(*f_iter) << ";" << '\n' << '\n';
}
indent_down();
out << indent() << "}" << '\n' << '\n';
cleanup_member_name_mapping(tservice);
}

void t_netstd_generator::generate_deprecation_attribute(ostream& out, t_function* func)
bool t_netstd_generator::is_deprecated(std::map<std::string, std::vector<std::string>>& annotations)
{
auto iter = annotations.find("deprecated");
return (annotations.end() != iter);
}

void t_netstd_generator::generate_deprecation_attribute(ostream& out, std::map<std::string, std::vector<std::string>>& annotations)
{
auto iter = func->annotations_.find("deprecated");
if( func->annotations_.end() != iter) {
auto iter = annotations.find("deprecated");
if( annotations.end() != iter) {
out << indent() << "[Obsolete";
// empty annotation values end up with "1" somewhere, ignore these as well
if ((iter->second.back().length() > 0) && (iter->second.back() != "1")) {
Expand Down Expand Up @@ -2066,6 +2162,7 @@ void t_netstd_generator::generate_service_client(ostream& out, t_service* tservi
out << '\n';

generate_netstd_doc(out, tservice);
generate_deprecation_attribute(out, tservice->annotations_);
prepare_member_name_mapping(tservice);
out << indent() << "public class Client : " << extends_client << "IAsync" << '\n'
<< indent() << "{" << '\n';
Expand All @@ -2089,7 +2186,7 @@ void t_netstd_generator::generate_service_client(ostream& out, t_service* tservi
string function_name = raw_func_name + (add_async_postfix ? "Async" : "");

// async
generate_deprecation_attribute(out, *functions_iterator);
generate_deprecation_attribute(out, (*functions_iterator)->annotations_);
out << indent() << "public async " << function_signature_async(*functions_iterator, "") << '\n'
<< indent() << "{" << '\n';
indent_up();
Expand All @@ -2107,7 +2204,7 @@ void t_netstd_generator::generate_service_client(ostream& out, t_service* tservi
out << indent() << "}" << '\n' << '\n';

// async send
generate_deprecation_attribute(out, *functions_iterator);
generate_deprecation_attribute(out, (*functions_iterator)->annotations_);
out << indent() << "public async " << function_signature_async(*functions_iterator, "send_", MODE_NO_RETURN) << '\n'
<< indent() << "{" << '\n';
indent_up();
Expand Down Expand Up @@ -2148,7 +2245,7 @@ void t_netstd_generator::generate_service_client(ostream& out, t_service* tservi
if (!(*functions_iterator)->is_oneway())
{
// async recv
generate_deprecation_attribute(out, *functions_iterator);
generate_deprecation_attribute(out, (*functions_iterator)->annotations_);
out << indent() << "public async " << function_signature_async(*functions_iterator, "recv_", MODE_NO_ARGS) << '\n'
<< indent() << "{" << '\n';
indent_up();
Expand Down Expand Up @@ -3022,6 +3119,7 @@ void t_netstd_generator::generate_netstd_property(ostream& out, t_field* tfield,
{
out << indent() << "[DataMember(Order = 0)]" << '\n';
}
generate_deprecation_attribute(out, tfield->annotations_);

out << indent()
<< (isPublic ? "public " : "private ")
Expand Down
4 changes: 3 additions & 1 deletion compiler/cpp/src/thrift/generate/t_netstd_generator.h
Expand Up @@ -104,7 +104,7 @@ class t_netstd_generator : public t_oop_generator
void generate_netstd_union_reader(ostream& out, t_struct* tunion);
void generate_function_helpers(ostream& out, t_function* tfunction);
void generate_service_interface(ostream& out, t_service* tservice);
void generate_deprecation_attribute(ostream& out, t_function* func);
void generate_deprecation_attribute(ostream& out, std::map<std::string, std::vector<std::string>>& annotations);
void generate_service_helpers(ostream& out, t_service* tservice);
void generate_service_client(ostream& out, t_service* tservice);
void generate_service_server(ostream& out, t_service* tservice);
Expand Down Expand Up @@ -218,6 +218,8 @@ class t_netstd_generator : public t_oop_generator
string initialize_field(t_field* tfield);

void pragmas_and_directives(ostream& out);
bool any_deprecations();
bool is_deprecated(std::map<std::string, std::vector<std::string>>& annotations);
bool is_nullable_type(t_type* ttype);
bool force_member_nullable(t_field* tfield); // see there
string nullable_suffix(); // unconditionally
Expand Down