Implement c# stub generator (interface part) 83/165583/7
authorJunghoon Park <jh9216.park@samsung.com>
Tue, 2 Jan 2018 08:32:08 +0000 (17:32 +0900)
committerJunghoon Park <jh9216.park@samsung.com>
Wed, 3 Jan 2018 10:07:20 +0000 (19:07 +0900)
Change-Id: I0a472a05ebd8675dd355a06263937775b96db537
Signed-off-by: Junghoon Park <jh9216.park@samsung.com>
idlc/cs_gen/cs_gen_base.cc
idlc/cs_gen/cs_gen_base.h
idlc/cs_gen/cs_proxy_gen.cc
idlc/cs_gen/cs_stub_gen.cc
idlc/cs_gen/cs_stub_gen.h
idlc/generator.cc
idlc/generator.h
unit_tests/cs_gen/cs_proxy_gen_unittest.cc
unit_tests/cs_gen/cs_stub_gen_unittest.cc

index ca703f2..ee59520 100644 (file)
@@ -28,6 +28,18 @@ CsGeneratorBase::CsGeneratorBase(std::shared_ptr<Document> doc)
       {"list", "List"}, {"float","float"}, {"double", "double"},
       {"bundle", "Bundle"}
   };
+
+  parcel_type_map_ = {
+    {"char", "Byte"},
+    {"int", "Int32"},
+    {"short", "Int16"},
+    {"long", "Int64"},
+    {"string", "String"},
+    {"bool", "Bool"},
+    {"float", "Float"},
+    {"double", "Double"},
+    {"bundle", "Bundle"},
+  };
 }
 
 void CsGeneratorBase::GenStructures(std::ofstream& stream) {
@@ -48,8 +60,8 @@ void CsGeneratorBase::GenStructure(std::ofstream& stream, const Structure& st) {
                       "$$" \
                       "        }\n";
 
-  stream << TAB <<"sealed class " << st.GetID() << std::endl;
-  GenBrace(stream, 4, [&]() {
+  stream << Tab(1) <<"public sealed class " << st.GetID() << NLine(1);
+  GenBrace(stream, TAB_SIZE, [&]() {
     for (auto& i : st.GetElements().GetElms()) {
       GenTemplate(property, stream,
         [&]()->std::string {
@@ -90,4 +102,71 @@ std::string CsGeneratorBase::ConvertTypeToString(const BaseType& type) {
   return type_map_[type.ToString()];
 }
 
+std::string CsGeneratorBase::ConvertTypeToParcelType(const std::string& key) {
+  return parcel_type_map_[key];
+}
+
+std::string CsGeneratorBase::ConvertTypeToDeserializer(
+    const ParameterType& type, std::string id) {
+  if (type.GetDirection() == ParameterType::Direction::OUT)
+      return "";
+
+  if (type.GetBaseType().IsUserDefinedType() ||
+      type.GetBaseType().GetMetaType() != nullptr) {
+    std::string n;
+
+    if (type.GetBaseType().GetMetaType() != nullptr)
+      n = ConvertTypeToString(type.GetBaseType());
+    else
+      n = type.GetBaseType().ToString();
+
+    std::string ret = n + " " + id + " = new " + n +"();\n";
+    ret += "Deserialize(p, " + id +");\n";
+    return ret;
+  }
+
+  std::string ret = "Interop.LibRPCPort.Parcel.Read" +
+                    parcel_type_map_[type.GetBaseType().ToString()] +
+                    "(p, out " +
+                    ConvertTypeToString(type.GetBaseType()) + " " +
+                    id + ");\n";
+
+  return ret;
+}
+
+std::string CsGeneratorBase::ConvertTypeToSerializer(
+    const BaseType& type, std::string id) {
+
+  if (type.IsUserDefinedType() ||
+      type.GetMetaType() != nullptr) {
+    return "Serialize(result, " + id + ");\n";
+  }
+
+  std::string ret = "Interop.LibRPCPort.Parcel.Write" +
+                    parcel_type_map_[type.ToString()] +
+                    "(result, " + id + ");\n";
+
+  return ret;
+}
+
+std::string CsGeneratorBase::Tab(int cnt) {
+  std::string t;
+
+  for (int i = 0; i < cnt; i++) {
+    t += "    ";
+  }
+
+  return t;
+}
+
+std::string CsGeneratorBase::NLine(int cnt) {
+  std::string t;
+
+  for (int i = 0; i < cnt; i++) {
+    t += "\n";
+  }
+
+  return t;
+}
+
 }  // namespace tidl
index 0e9ffd6..e6fa30a 100644 (file)
@@ -35,11 +35,19 @@ class CsGeneratorBase : public Generator {
   void GenStructures(std::ofstream& stream);
   void GenStructure(std::ofstream& stream, const Structure& st);
   std::string ConvertTypeToString(const BaseType& type);
+  std::string ConvertTypeToDeserializer(const ParameterType& type,
+                                        std::string id);
+  std::string ConvertTypeToSerializer(const BaseType& type,
+                                      std::string id);
+  std::string ConvertTypeToParcelType(const std::string& key);
+  std::string Tab(int cnt);
+  std::string NLine(int cnt);
 
  protected:
-  const std::string TAB = "    ";
+  const int TAB_SIZE = 4;
  private:
   std::map<std::string, std::string> type_map_;
+  std::map<std::string, std::string> parcel_type_map_;
 };
 
 }  // namespace tidl
index 4a72377..0e38727 100644 (file)
@@ -23,11 +23,11 @@ CsProxyGen::CsProxyGen(std::shared_ptr<Document> doc)
 
 void CsProxyGen::OnInitGen(std::ofstream& stream) {
   GenCodeBlock("copyright.cb");
-  stream << std::endl;
-  stream << "using System;" << std::endl
-         << "using System.Collections.Generic;" << std::endl
-         << "using System.Runtime.InteropServices;" << std::endl
-         << "using Tizen.Applications;" << std::endl << std::endl;
+  stream << NLine(1);
+  stream << "using System;" << NLine(1)
+         << "using System.Collections.Generic;" << NLine(1)
+         << "using System.Runtime.InteropServices;" << NLine(1)
+         << "using Tizen.Applications;" << NLine(2);
   GenInterop(stream);
   GenNamespace(stream);
 }
@@ -36,7 +36,7 @@ void CsProxyGen::OnFiniGen(std::ofstream& stream) {
 }
 
 void CsProxyGen::GenNamespace(std::ofstream& stream) {
-  stream << "namespace RPCPort" << std::endl;
+  stream << "namespace RPCPort" << NLine(1);
   GenBrace(stream, 0, [&]() {
     GenStructures(stream);
   });
index b2569a1..47619bc 100644 (file)
@@ -23,12 +23,13 @@ CsStubGen::CsStubGen(std::shared_ptr<Document> doc)
 
 void CsStubGen::OnInitGen(std::ofstream& stream) {
   GenCodeBlock("copyright.cb");
-  stream << std::endl;
-  stream << "using System;" << std::endl
-         << "using System.Collections.Generic;" << std::endl
-         << "using System.Runtime.InteropServices;" << std::endl
-         << "using Tizen.Applications;" << std::endl << std::endl;
+  stream << NLine(1);
+  stream << "using System;" << NLine(1)
+         << "using System.Collections.Generic;" << NLine(1)
+         << "using System.Runtime.InteropServices;" << NLine(1)
+         << "using Tizen.Applications;" << NLine(2);
   GenInterop(stream);
+  stream << NLine(1);
   GenNamespace(stream);
 }
 
@@ -41,10 +42,463 @@ void CsStubGen::GenInterop(std::ofstream& stream) {
 }
 
 void CsStubGen::GenNamespace(std::ofstream& stream) {
-  stream << "namespace RPCPort" << std::endl;
+  stream << "namespace RPCPort" << NLine(1);
   GenBrace(stream, 0, [&]() {
     GenStructures(stream);
+    stream << Tab(1) << "namespace Stub" << NLine(1);
+    GenBrace(stream, TAB_SIZE, [&]() {
+      GenInterfaces(stream);
+    });
   });
 }
 
+void CsStubGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+    Interface& iface = static_cast<Interface&>(*i);
+    GenInterface(stream, iface);
+    stream << std::endl;
+  }
+}
+
+void CsStubGen::GenInterface(std::ofstream& stream, const Interface& iface) {
+  stream << Tab(2) << "public sealed class " << iface.GetID() << NLine(1);
+  GenBrace(stream, TAB_SIZE * 2, [&]() {
+    GenServiceBase(stream, iface);
+    stream << Tab(3)
+           << "private IntPtr _stub;" << NLine(2);
+    stream << Tab(3)
+           << "private List<ServiceBase> _services = new List<ServiceBase>();"
+           << NLine(2);
+    stream << Tab(3)
+           << "private Type _serviceType;" << NLine(2);
+    GenMethodId(stream, iface);
+    GenSerializer(stream);
+    GenListSerializer(stream);
+    GenReceivedEvent(stream, iface);
+    GenConnectedEvent(stream);
+    GenDisconnectedEvent(stream);
+    GenCtor(stream, iface);
+    GenCommonMethods(stream);
+  });
+}
+
+void CsStubGen::GenServiceBase(std::ofstream& stream, const Interface& iface) {
+  const char cls[] =
+            "public abstract class ServiceBase\n" \
+            "{\n" \
+            "    public string Sender\n" \
+            "    {\n" \
+            "        get; internal set;\n" \
+            "    }\n" \
+            "\n" \
+            "    protected ServiceBase()\n" \
+            "    {\n" \
+            "    }\n" \
+            "\n";
+
+  stream << AddIndent(TAB_SIZE * 3, cls);
+  GenDeclarations(stream, iface.GetDeclarations());
+  stream << NLine(1);
+  stream << AddIndent(TAB_SIZE * 3, "}\n");
+  stream << NLine(1);
+}
+
+void CsStubGen::GenDeclarations(std::ofstream& stream,
+                                const Declarations& decls) {
+  for (auto& i : decls.GetDecls()) {
+    stream << Tab(4) << "public abstract ";
+    GenDeclaration(stream, *i);
+    stream << NLine(1);
+  }
+}
+
+void CsStubGen::GenDeclaration(std::ofstream& stream, const Declaration& decl) {
+  stream << ConvertTypeToString(decl.GetType()) << " "
+         << decl.GetID() << "(";
+  GenParameters(stream, decl.GetParameters());
+  stream << ");";
+}
+
+void CsStubGen::GenParameters(std::ofstream& stream, const Parameters& ps) {
+  bool first = true;
+  for (auto& i : ps.GetParams()) {
+    if (!first) {
+      stream << ", ";
+    }
+
+    auto dir = i->GetParameterType().GetDirection();
+    if (dir == ParameterType::Direction::OUT) {
+      stream << "out ";
+    } else if (dir == ParameterType::Direction::REF) {
+      stream << "ref ";
+    }
+
+    stream << ConvertTypeToString(i->GetParameterType().GetBaseType()) << " "
+           << i->GetID();
+    first = false;
+  }
+}
+
+void CsStubGen::GenMethodId(std::ofstream& stream, const Interface& iface) {
+  stream << Tab(3) << "private enum MethodId : int" << NLine(1);
+  GenBrace(stream, TAB_SIZE * 3, [&]() {
+    int cnt = 1;
+    for (auto& i : iface.GetDeclarations().GetDecls()) {
+        stream << Tab(4)
+               << i->GetID() << " = " << cnt++ << "," << NLine(1);
+    }
+  });
+  stream << NLine(1);
+}
+
+void CsStubGen::GenWriteBundle(std::ofstream& stream, const std::string& id) {
+  const char block[] =
+      "if (param.$$ != null)\n" \
+      "{\n" \
+      "    Interop.LibRPCPort.Parcel.WriteBundle(h, param.$$.SafeBundleHandle.DangerousGetHandle());\n" \
+      "}\n" \
+      "else\n" \
+      "{\n" \
+      "    Interop.LibRPCPort.Parcel.WriteBundle(h, new Bundle().SafeBundleHandle.DangerousGetHandle());\n" \
+      "}\n";
+
+  GenTemplate(AddIndent(TAB_SIZE * 4, block), stream,
+    [&]()->std::string {
+      return id;
+    },
+    [&]()->std::string {
+      return id;
+    }
+  );
+}
+
+void CsStubGen::GenSerializer(std::ofstream& stream, const Structure& st) {
+  stream << Tab(3) << "private static void Serialize(IntPtr h, "
+                   << st.GetID() << " param)" << NLine(1);
+  GenBrace(stream, TAB_SIZE * 3, [&]() {
+    for (auto& i : st.GetElements().GetElms()) {
+      auto& t = i->GetType();
+      if (!t.IsUserDefinedType() && t.GetMetaType() == nullptr) {
+        if (t.ToString() == "bundle") {
+          GenWriteBundle(stream, i->GetID());
+        } else {
+          stream << Tab(4) << "Interop.LibRPCPort.Parcel.Write"
+                           << ConvertTypeToParcelType(t.ToString())
+                           << "(h, param."
+                           << i->GetID()
+                           << ");" << NLine(1);
+        }
+      } else {
+        stream << Tab(4) << "Serialize(h, param." << i->GetID()
+                         << ");" << NLine(1);
+      }
+    }
+  });
+  stream << NLine(1);
+
+  stream << Tab(3) << "private static void Deserialize(IntPtr h, "
+                   << st.GetID() << " param)" << NLine(1);
+  GenBrace(stream, TAB_SIZE * 3, [&]() {
+    for (auto& i : st.GetElements().GetElms()) {
+      auto& t = i->GetType();
+      if (!t.IsUserDefinedType() && t.GetMetaType() == nullptr) {
+        stream << Tab(4) << "Interop.LibRPCPort.Parcel.Read"
+                         << ConvertTypeToParcelType(t.ToString())
+                         << "(h, out var "
+                         << i->GetID()
+                         << ");" << NLine(1);
+        if (t.ToString() == "bundle") {
+          stream << Tab(4) << "param." << i->GetID()
+                 << " = new Bundle(new SafeBundleHandle(" << i->GetID()
+                 << ", true));" << NLine(1);
+        } else {
+          stream << Tab(4) << "param." << i->GetID() << " = " << i->GetID()
+                 << ";" << NLine(1);
+        }
+      } else {
+        stream << Tab(4) << "param." << i->GetID() << " = new "
+                         << ConvertTypeToString(t)
+                         << "();" << NLine(1);
+        stream << Tab(4) << "Deserialize(h, param." << i->GetID()
+                         << ");" << NLine(1);
+      }
+
+    }
+  });
+  stream << NLine(1);
+}
+
+void CsStubGen::GenSerializer(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() == Block::TYPE_STRUCTURE) {
+      const Structure& st = static_cast<const Structure&>(*i);
+      GenSerializer(stream, st);
+    }
+  }
+}
+
+void CsStubGen::AddSerializerList(const BaseType& type) {
+  if (type.GetMetaType() != nullptr) {
+    serializer_list_[ConvertTypeToString(type)] = &type;
+    AddSerializerList(*type.GetMetaType());
+  }
+}
+
+void CsStubGen::GenListSerializer(std::ofstream& stream, const BaseType& type) {
+  stream << Tab(3) << "private static void Serialize(IntPtr h, "
+                   << ConvertTypeToString(type) << " param)" << NLine(1);
+  GenBrace(stream, TAB_SIZE * 3, [&]() {
+    stream << Tab(4)
+           << "Interop.LibRPCPort.Parcel.WriteArrayCount(h, param.Count);"
+           << NLine(1);
+    stream << Tab(4) << "foreach (var i in param)" << NLine(1);
+    GenBrace(stream, TAB_SIZE * 4, [&]() {
+      auto& mt = *type.GetMetaType();
+      if (!mt.IsUserDefinedType() && mt.GetMetaType() == nullptr) {
+        stream << Tab(5) << "Interop.LibRPCPort.Parcel.Write"
+                         << ConvertTypeToParcelType(mt.ToString())
+                         << "(h, i);" << NLine(1);
+      } else {
+        stream << Tab(5) << "Serialize(h, i);" << NLine(1);
+      }
+    });
+  });
+  stream << NLine(1);
+
+  stream << Tab(3) << "private static void Deserialize(IntPtr h, "
+                   << ConvertTypeToString(type) << " param)" << NLine(1);
+  GenBrace(stream, TAB_SIZE * 3, [&]() {
+    stream << Tab(4)
+           << "Interop.LibRPCPort.Parcel.ReadArrayCount(h, out int l);"
+           << NLine(1);
+    stream << Tab(4) << "for (int i = 0; i < l; i++)" << NLine(1);
+    GenBrace(stream, TAB_SIZE * 4, [&]() {
+      auto& mt = *type.GetMetaType();
+      if (!mt.IsUserDefinedType() && mt.GetMetaType() == nullptr) {
+        stream << Tab(5) << "Interop.LibRPCPort.Parcel.Read"
+                         << ConvertTypeToParcelType(mt.ToString())
+                         << "(h, out var v);" << NLine(1);
+      } else {
+        stream << Tab(5) << "var v = new " << ConvertTypeToString(mt)
+               << "();" << NLine(1);
+        stream << Tab(5) << "Deserialize(h, v);" << NLine(1);
+      }
+      stream << Tab(5) << "param.Add(v);" << NLine(1);
+    });
+  });
+  stream << NLine(1);
+}
+
+void CsStubGen::GenListSerializer(std::ofstream& stream) {
+  serializer_list_.clear();
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() == Block::TYPE_STRUCTURE) {
+      const Structure& st = static_cast<const Structure&>(*i);
+      for (auto& j : st.GetElements().GetElms()) {
+        auto& t = j->GetType();
+        AddSerializerList(t);
+      }
+    } else if (i->GetType() == Block::TYPE_INTERFACE) {
+      const Interface& iface = static_cast<const Interface&>(*i);
+      for (auto& j : iface.GetDeclarations().GetDecls()) {
+        auto& t = j->GetType();
+        AddSerializerList(t);
+        for (auto& k : j->GetParameters().GetParams()) {
+          auto& t1 = k->GetParameterType().GetBaseType();
+          AddSerializerList(t1);
+        }
+      }
+    }
+  }
+
+  for (auto& p : serializer_list_) {
+    const BaseType* t = p.second;
+    GenListSerializer(stream, *t);
+  }
+}
+
+void CsStubGen::GenReceivedEvent(std::ofstream& stream, const Interface& iface) {
+  const char method_front[] =
+    "private int OnReceivedEvent(string sender, IntPtr port, IntPtr data)\n" \
+    "{\n" \
+    "    int ret = Interop.LibRPCPort.Parcel.CreateFromPort(out IntPtr p, port);\n" \
+    "\n" \
+    "    if (ret != 0)\n" \
+    "        return ret;\n" \
+    "\n" \
+    "    Interop.LibRPCPort.Parcel.Create(out IntPtr result);\n" \
+    "    Interop.LibRPCPort.Parcel.ReadInt32(p, out int cmd);\n" \
+    "    ServiceBase b = null;\n" \
+    "\n" \
+    "    foreach (var i in  _services)\n" \
+    "    {\n" \
+    "        if (i.Sender.Equals(sender))\n" \
+    "        {\n" \
+    "            b = i;\n" \
+    "            break;\n" \
+    "        }\n" \
+    "    }\n" \
+    "\n" \
+    "    if (b == null)\n" \
+    "        return -1;\n" \
+    "\n"
+    "    switch ((MethodId)cmd)\n" \
+    "    {\n";
+
+  const char method_back[] =
+    "        default:\n" \
+    "            return -1;\n" \
+    "    }\n" \
+    "\n" \
+    "    Interop.LibRPCPort.Parcel.Destroy(p);\n" \
+    "    Interop.LibRPCPort.Parcel.Destroy(result);\n" \
+    "\n" \
+    "    return 0;\n" \
+    "}\n";
+
+  stream << AddIndent(TAB_SIZE * 3, method_front);
+  for (auto& i : iface.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+    stream << Tab(5) << "case MethodId." << i->GetID() << ":" << NLine(1);
+    GenBrace(stream, TAB_SIZE * 6, [&]() {
+      GenInvocation(stream, *i);
+      stream << Tab(7) << "break;" << NLine(1);
+    });
+  }
+  stream << AddIndent(TAB_SIZE * 3, method_back) << NLine(1);
+}
+
+void CsStubGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
+  int cnt = 1;
+
+  // Deserialize
+  for (auto& i : decl.GetParameters().GetParams()) {
+    std::string v = "param" + std::to_string(cnt);
+    std::string c = ConvertTypeToDeserializer(i->GetParameterType(), v);
+    if (c != "")
+      stream << AddIndent(TAB_SIZE * 7, c);
+    cnt++;
+  }
+
+  // Invoke
+  cnt = 1;
+  std::string m;
+  bool hasRet = false;
+
+  if (decl.GetType().ToString() != "void") {
+    m += "var retVal = ";
+    hasRet = true;
+  }
+
+  m += "b." + decl.GetID() + "(";
+  for (auto& i : decl.GetParameters().GetParams()) {
+    if (cnt != 1) {
+      m += ", ";
+    }
+
+    std::string v = "param" + std::to_string(cnt);
+    auto& pt = i->GetParameterType();
+    if (pt.GetDirection() == ParameterType::Direction::OUT) {
+      m += "out " + ConvertTypeToString(pt.GetBaseType()) + " ";
+    } else if (pt.GetDirection() == ParameterType::Direction::REF) {
+      m += "ref ";
+    }
+    m += v;
+    cnt++;
+  }
+
+  m += ");\n";
+  stream << AddIndent(TAB_SIZE * 7, m);
+
+  // Serialize
+  if (decl.GetMethodType() == Declaration::MethodType::ASYNC)
+    return;
+
+  cnt = 0;
+  m = "";
+  for (auto& i : decl.GetParameters().GetParams()) {
+    auto& pt = i->GetParameterType();
+    cnt++;
+    if (pt.GetDirection() == ParameterType::Direction::IN)
+      continue;
+    m += ConvertTypeToSerializer(pt.GetBaseType(), "param" + std::to_string(cnt));
+  }
+
+  if (hasRet) {
+    m += ConvertTypeToSerializer(decl.GetType(), "retVal");
+  }
+
+  m += "Interop.LibRPCPort.Parcel.Send(result, port);\n";
+  stream << AddIndent(TAB_SIZE * 7, m);
+}
+
+void CsStubGen::GenConnectedEvent(std::ofstream& stream) {
+  const char method[] =
+      "private void OnConnectedEvent(string sender, IntPtr data)\n" \
+      "{\n" \
+      "    ServiceBase s = Activator.CreateInstance(_serviceType) as ServiceBase;\n" \
+      "    s.Sender = sender;\n" \
+      "    _services.Add(s);\n" \
+      "}\n";
+  stream << AddIndent(TAB_SIZE * 3, method) << NLine(1);
+}
+
+void CsStubGen::GenDisconnectedEvent(std::ofstream& stream) {
+  const char method[] =
+      "private void OnDisconnectedEvent(string sender, IntPtr data)\n" \
+      "{\n" \
+      "    foreach (var i in _services)\n" \
+      "    {\n" \
+      "        if (i.Sender.Equals(sender))\n" \
+      "        {\n" \
+      "            _services.Remove(i);\n" \
+      "            break;\n" \
+      "        }\n" \
+      "    }\n" \
+      "}\n";
+  stream << AddIndent(TAB_SIZE * 3, method) << NLine(1);
+}
+
+void CsStubGen::GenCtor(std::ofstream& stream, const Interface& iface) {
+  const char ctor[] =
+      "public $$()\n" \
+      "{\n" \
+      "    Interop.LibRPCPort.Stub.Create(out _stub, \"$$\");\n" \
+      "    Interop.LibRPCPort.Stub.AddReceivedEventCb(_stub, OnReceivedEvent, IntPtr.Zero);\n" \
+      "    Interop.LibRPCPort.Stub.AddConnectedEventCb(_stub, OnConnectedEvent, IntPtr.Zero);\n" \
+      "    Interop.LibRPCPort.Stub.AddDisconnectedEventCb(_stub, OnDisconnectedEvent, IntPtr.Zero);\n" \
+      "}\n";
+
+  GenTemplate(AddIndent(TAB_SIZE * 3, ctor), stream,
+    [&]()->std::string {
+      return iface.GetID();
+    },
+    [&]()->std::string {
+      return iface.GetID();
+    }
+  );
+  stream << NLine(1);
+}
+
+void CsStubGen::GenCommonMethods(std::ofstream& stream) {
+  const char method_listen[] =
+      "public void Listen(Type serviceType)\n" \
+      "{\n" \
+      "    _serviceType = serviceType;\n" \
+      "    Interop.LibRPCPort.Stub.Listen(_stub);\n" \
+      "}\n";
+
+  const char method_get_services[] =
+      "public IEnumerable<ServiceBase> GetServices()\n" \
+      "{\n" \
+      "    return _services;\n" \
+      "}\n";
+
+  stream << AddIndent(TAB_SIZE * 3, method_listen) << NLine(1);
+  stream << AddIndent(TAB_SIZE * 3, method_get_services);
+}
+
 }  // namespace tidl
index 3dcc5c8..74c6993 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <memory>
 #include <string>
+#include <map>
 
 #include "idlc/cs_gen/cs_gen_base.h"
 
@@ -35,6 +36,28 @@ class CsStubGen : public CsGeneratorBase {
  private:
   void GenNamespace(std::ofstream& stream);
   void GenInterop(std::ofstream& stream);
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& iface);
+  void GenMethodId(std::ofstream& stream, const Interface& iface);
+  void GenServiceBase(std::ofstream& stream, const Interface& iface);
+  void GenSerializer(std::ofstream& stream);
+  void GenSerializer(std::ofstream& stream, const Structure& st);
+  void GenListSerializer(std::ofstream& stream);
+  void GenListSerializer(std::ofstream& stream, const BaseType& type);
+  void GenReceivedEvent(std::ofstream& stream, const Interface& iface);
+  void GenConnectedEvent(std::ofstream& stream);
+  void GenDisconnectedEvent(std::ofstream& stream);
+  void GenCtor(std::ofstream& stream, const Interface& iface);
+  void GenCommonMethods(std::ofstream& stream);
+  void GenDeclarations(std::ofstream& stream, const Declarations& decls);
+  void GenDeclaration(std::ofstream& stream, const Declaration& decl);
+  void GenParameters(std::ofstream& stream, const Parameters& ps);
+  void GenInvocation(std::ofstream& stream, const Declaration& decl);
+  void GenWriteBundle(std::ofstream& stream, const std::string& id);
+  void AddSerializerList(const BaseType& type);
+
+ private:
+  std::map<std::string, const BaseType*> serializer_list_;
 };
 
 }  // namespace tidl
index cdcf937..717d2ed 100644 (file)
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <sstream>
+
 #include "idlc/generator.h"
 #include "idlc/block.h"
 #include "idlc/interface.h"
@@ -34,4 +36,26 @@ void Generator::Run(const std::string& file_name) {
   out_file_.close();
 }
 
+std::string Generator::AddIndent(int indent, std::string lines, bool space) {
+  std::stringstream ss(lines);
+  std::string result;
+  std::string to;
+
+  while (std::getline(ss, to, '\n')) {
+    if (to.length() > 0) {
+      for (int i = 0; i < indent; i++) {
+        if (space)
+          result += " ";
+        else
+          result += "\t";
+      }
+    }
+
+    result += to;
+    result += "\n";
+  }
+
+  return result;
+}
+
 }  // namespace tidl
index 0788d3a..f364513 100644 (file)
@@ -36,6 +36,7 @@ class Generator {
   virtual ~Generator() = default;
 
   void Run(const std::string& file_name);
+  std::string AddIndent(int indent, std::string lines, bool space = true);
 
   template<typename T = EmptyCallbackType>
   void GenCodeBlock(std::string filename, T cb = CallEmptyCallback) {
index bef1f70..f83561c 100644 (file)
@@ -61,8 +61,8 @@ TEST_F(CsProxyGenTest, CsProxyGen_Run) {
 
   ASSERT_TRUE(FindStringFromFile("test.cs", "namespace RPCPort"));
   ASSERT_TRUE(FindStringFromFile("test.cs", "        internal static partial class Proxy"));
-  ASSERT_TRUE(FindStringFromFile("test.cs", "    sealed class Student"));
+  ASSERT_TRUE(FindStringFromFile("test.cs", "    public sealed class Student"));
   ASSERT_TRUE(FindStringFromFile("test.cs", "        public string name { get; set; }"));
-  ASSERT_TRUE(FindStringFromFile("test.cs", "    sealed class Class"));
+  ASSERT_TRUE(FindStringFromFile("test.cs", "    public sealed class Class"));
   ASSERT_TRUE(FindStringFromFile("test.cs", "        public List<Student> students { get; set; }"));
 }
index 8d4def5..3a7bebf 100644 (file)
@@ -61,8 +61,8 @@ TEST_F(CsStubGenTest, CsStubGen_Run) {
 
   ASSERT_TRUE(FindStringFromFile("test_stub.cs", "namespace RPCPort"));
   ASSERT_TRUE(FindStringFromFile("test_stub.cs", "        internal static partial class Stub"));
-  ASSERT_TRUE(FindStringFromFile("test_stub.cs", "    sealed class Student"));
+  ASSERT_TRUE(FindStringFromFile("test_stub.cs", "    public sealed class Student"));
   ASSERT_TRUE(FindStringFromFile("test_stub.cs", "        public string name { get; set; }"));
-  ASSERT_TRUE(FindStringFromFile("test_stub.cs", "    sealed class Class"));
+  ASSERT_TRUE(FindStringFromFile("test_stub.cs", "    public sealed class Class"));
   ASSERT_TRUE(FindStringFromFile("test_stub.cs", "        public List<Student> students { get; set; }"));
 }