THRIFT-5395 inconsistent treatment of methods ending in "Async"
Client: netstd
Patch: Jens Geyer

This closes #2372
diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc
index ed766ee..8b1c4c4 100644
--- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc
@@ -88,18 +88,6 @@
     out_dir_base_ = "gen-netstd";
 }
 
-static string correct_function_name_for_async(string const& function_name)
-{
-    string const async_end = "Async";
-    size_t i = function_name.find(async_end);
-    if (i != string::npos)
-    {
-        return function_name + async_end;
-    }
-
-    return function_name;
-}
-
 /**
 * \brief Search and replace "_args" substring in struct name if exist (for C# class naming)
 * \param struct_name
@@ -2011,7 +1999,8 @@
 
     for (functions_iterator = functions.begin(); functions_iterator != functions.end(); ++functions_iterator)
     {
-        string function_name = correct_function_name_for_async((*functions_iterator)->get_name());
+        string raw_func_name = (*functions_iterator)->get_name();
+        string function_name = raw_func_name + "Async";
 
         // async
         out << indent() << "public async " << function_signature_async(*functions_iterator, "") << endl
@@ -2020,7 +2009,7 @@
 
         string argsname = (*functions_iterator)->get_name() + "Args";
 
-        out << indent() << "await OutputProtocol.WriteMessageBeginAsync(new TMessage(\"" << function_name
+        out << indent() << "await OutputProtocol.WriteMessageBeginAsync(new TMessage(\"" << raw_func_name
             << "\", TMessageType." << ((*functions_iterator)->is_oneway() ? "Oneway" : "Call") 
             << ", SeqId), cancellationToken);" << endl
             << indent() << endl
@@ -2155,8 +2144,8 @@
     out << indent() << "_logger = logger;" << endl;
     for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter)
     {
-        string function_name = (*f_iter)->get_name();
-        out << indent() << "processMap_[\"" << correct_function_name_for_async(function_name) << "\"] = " << function_name << "_ProcessAsync;" << endl;
+        string raw_func_name = (*f_iter)->get_name();
+        out << indent() << "processMap_[\"" << raw_func_name << "\"] = " << raw_func_name << "_ProcessAsync;" << endl;
     }
 
     indent_down();
@@ -2370,7 +2359,7 @@
     if (!tfunction->is_oneway())
     {
         out << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\""
-                << correct_function_name_for_async(tfunction->get_name()) << "\", TMessageType.Reply, seqid), cancellationToken); " << endl
+                << tfunction->get_name() << "\", TMessageType.Reply, seqid), cancellationToken); " << endl
             << indent() << "await result.WriteAsync(oprot, cancellationToken);" << endl;
     }
     indent_down();
@@ -2404,7 +2393,7 @@
     else
     {
         out << indent() << "var x = new TApplicationException(TApplicationException.ExceptionType.InternalError,\" Internal error.\");" << endl
-            << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" << correct_function_name_for_async(tfunction->get_name())
+            << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" << tfunction->get_name()
             << "\", TMessageType.Exception, seqid), cancellationToken);" << endl
             << indent() << "await x.WriteAsync(oprot, cancellationToken);" << endl;
         indent_down();
diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Impl/Thrift5253/MyService.cs b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Impl/Thrift5253/MyService.cs
index 342dd4a..1b8d99f 100644
--- a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Impl/Thrift5253/MyService.cs
+++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Impl/Thrift5253/MyService.cs
@@ -51,6 +51,16 @@
             return Task.FromResult(new InternalStructs() { Foo = input.Foo });
         }
 
+        public Task TestAsyncAsync(CancellationToken cancellationToken = default)
+        {
+            return Task.CompletedTask;
+        }
+
+        public Task TestXsyncAsync(CancellationToken cancellationToken = default)
+        {
+            return Task.CompletedTask;
+        }
+
         public Task<WorksRslt> WorksAsync(WorksArrrgs input, CancellationToken cancellationToken = default)
         {
             return Task.FromResult(new WorksRslt() { Foo = input.Foo });
diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5253.thrift b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5253.thrift
index ee3df9b..224ac85 100644
--- a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5253.thrift
+++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5253.thrift
@@ -42,5 +42,9 @@
     AsyncProcessor  AsyncProcessor ( 1: AsyncProcessor  foo)
     Client          Client         ( 1: Client  foo)
     IAsync          IAsync         ( 1: IAsync  foo)
+
+    // inconsistent treatment of methods ending in "Async"
+    void TestXsync()
+    void TestAsync()
 }