From d2488da31358bfa872e6a3ff76f58dbce0fe20b8 Mon Sep 17 00:00:00 2001 From: ruanshudong Date: Wed, 18 Mar 2020 17:09:27 +0800 Subject: [PATCH] modify demo CMakeLists.txt close TARS_SSL TARS_HTTP2 default --- servant/script/cmake_demo/CMakeLists.txt | 4 +- servant/script/cmake_http_demo/CMakeLists.txt | 4 +- tools/tars2node/code_generator.cpp | 50 ++- tools/tars2node/code_generator.h | 85 ++++- tools/tars2node/file_util.cpp | 13 +- tools/tars2node/gen_js.cpp | 135 +++++--- tools/tars2node/gen_js_dts.cpp | 82 +++-- tools/tars2node/gen_proxy.cpp | 313 ++++++++++++++---- tools/tars2node/gen_proxy_dts.cpp | 107 +++--- tools/tars2node/gen_server.cpp | 42 ++- tools/tars2node/gen_server_dts.cpp | 37 ++- tools/tars2node/idl_scan.cpp | 15 +- tools/tars2node/idl_util.cpp | 166 +++++++--- tools/tars2node/main.cpp | 63 +++- 14 files changed, 774 insertions(+), 342 deletions(-) diff --git a/servant/script/cmake_demo/CMakeLists.txt b/servant/script/cmake_demo/CMakeLists.txt index 69d40c2..38c1c11 100644 --- a/servant/script/cmake_demo/CMakeLists.txt +++ b/servant/script/cmake_demo/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8) project(Demo-DemoServer) option(TARS_MYSQL "option for mysql" ON) -option(TARS_SSL "option for ssl" ON) -option(TARS_HTTP2 "option for http2" ON) +option(TARS_SSL "option for ssl" OFF) +option(TARS_HTTP2 "option for http2" OFF) if(WIN32) include (c:\\tars\\cpp\\makefile\\tars-tools.cmake) diff --git a/servant/script/cmake_http_demo/CMakeLists.txt b/servant/script/cmake_http_demo/CMakeLists.txt index 69d40c2..38c1c11 100644 --- a/servant/script/cmake_http_demo/CMakeLists.txt +++ b/servant/script/cmake_http_demo/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 2.8) project(Demo-DemoServer) option(TARS_MYSQL "option for mysql" ON) -option(TARS_SSL "option for ssl" ON) -option(TARS_HTTP2 "option for http2" ON) +option(TARS_SSL "option for ssl" OFF) +option(TARS_HTTP2 "option for http2" OFF) if(WIN32) include (c:\\tars\\cpp\\makefile\\tars-tools.cmake) diff --git a/tools/tars2node/code_generator.cpp b/tools/tars2node/code_generator.cpp index 4236b21..5d79567 100644 --- a/tools/tars2node/code_generator.cpp +++ b/tools/tars2node/code_generator.cpp @@ -21,8 +21,8 @@ string CodeGenerator::printHeaderRemark(const string &sTypeName) ostringstream s; s << "// **********************************************************************" << endl; s << "// Parsed By " << IDL_NAMESPACE_STR << "Parser(" << PARSER_VERSION << "), Generated By " << EXECUTE_FILENAME << "(" << GENERATOR_VERSION << ")" << endl; - s << "// " << IDL_NAMESPACE_STR << "Parser Maintained By and " << EXECUTE_FILENAME << " Maintained By " << endl; - s << "// Generated from \"" << TC_File::extractFileName(_sIdlFile) << "\" by " << + s << "// " << IDL_NAMESPACE_STR << "Parser Maintained By <" << TC_Common::upper(IDL_NAMESPACE_STR) << "> and " << EXECUTE_FILENAME << " Maintained By " << endl; + s << "// Generated from \"" << TC_File::extractFileName(_sIdlFile) << "\" by " << (_bEntry ? sTypeName : (_bMinimalMembers ? "Minimal" : "Relation")) << " Mode" << endl; s << "// **********************************************************************" << endl; s << endl; @@ -43,26 +43,47 @@ void CodeGenerator::createFile(const string &file, const bool bEntry) { if (_sIdlFile == contexts[i]->getFileName()) { - scan(_sIdlFile, true); //分析枚举值、结构体所在的文件 + scan(_sIdlFile, true); // collect idl symbols - if (!_bClient && !_bServer) + if (!_bClient && !_bServer) { - generateJS(contexts[i]); //生成当前文件的编解码文件 - if(_bDTS) generateDTS(contexts[i]); //生成 typescript 描述文件 + if (_bTS) + { + generateTS(contexts[i]); // generate .ts + } + else + { + generateJS(contexts[i]); // generate .js + if (_bDTS) generateDTS(contexts[i]); // generate .d.ts + } } - if (_bClient) + if (_bClient) { - if(!generateJSProxy(contexts[i])) return; //生成当前文件的客户端代理类文件 - if(_bDTS) generateDTSProxy(contexts[i]); //生成客户端 typescript 描述文件 + if (_bTS) + { + if (!generateTSProxy(contexts[i])) return; // generate .ts for proxy classes + } + else + { + if (!generateJSProxy(contexts[i])) return; // generate .js for proxy classes + if (_bDTS) generateDTSProxy(contexts[i]); // generate .d.ts for proxy classes + } } if (_bServer) { - if(!generateJSServer(contexts[i])) return; //生成当前文件的服务端代理类文件 - if(_bDTS) generateDTSServer(contexts[i]); //生成服务端 typescript 描述文件 - - generateJSServerImp(contexts[i]); //生成当前文件的服务端实现类文件 + if (_bTS) + { + if (!generateTSServer(contexts[i])) return; // generate .ts for server classes + generateTSServerImp(contexts[i]); // generate .ts for server implementations + } + else + { + if (!generateJSServer(contexts[i])) return; // generate .js for server classes + if (_bDTS) generateDTSServer(contexts[i]); // generate .d.ts for server classes + generateJSServerImp(contexts[i]); // generate .js for server implementations + } } vector files = contexts[i]->getIncludes(); @@ -74,10 +95,11 @@ void CodeGenerator::createFile(const string &file, const bool bEntry) node.setTargetPath(_sToPath); node.setRecursive(_bRecursive); node.setUseSpecialPath(_bUseSpecialPath); - node.setUseStringRepresent(_bUseStringRepresent); + node.setLongType(_iLongType); node.setStringBinaryEncoding(_bStringBinaryEncoding); node.setMinimalMembers(_bMinimalMembers); node.setDependent(_depMembers); + node.setEnableTS(_bTS); node.setEnableDTS(_bDTS); node.createFile(files[ii], false); diff --git a/tools/tars2node/code_generator.h b/tools/tars2node/code_generator.h index b98e8a0..5764270 100644 --- a/tools/tars2node/code_generator.h +++ b/tools/tars2node/code_generator.h @@ -60,6 +60,9 @@ #define PROTOCOL_COMPLEX PROTOCOL_V(IDL_NAMESPACE_STR, PROTOCOL_NAME, "COMPLEX") #define PROTOCOL_VAR TO_LOWER_STRING(PROTOCOL_NAME) +#define DISABLE_ESLINT "/* eslint-disable */" +#define DISABLE_TSLINT "/* tslint:disable */" + using namespace TC_NAMESPACE; class CodeGenerator @@ -74,10 +77,13 @@ public: _bServer(false), _bRecursive(false), _bUseSpecialPath(false), - _bUseStringRepresent(false), + _iLongType(Number), _bStringBinaryEncoding(false), + _bEnumReverseMappings(false), _bMinimalMembers(false), - _bDTS(false) {} + _bTS(false), + _bDTS(false), + _iOptimizeLevel(O0) {} void createFile(const string &file, const bool bEntry = true); @@ -95,16 +101,26 @@ public: void setUseSpecialPath(bool bEnable) { _bUseSpecialPath = bEnable; } - void setUseStringRepresent(bool bEnable) { _bUseStringRepresent = bEnable; } + void setLongType(int iLongType) { _iLongType = iLongType; } void setStringBinaryEncoding(bool bEnable) { _bStringBinaryEncoding = bEnable; } + void setEnumReverseMappings(bool bEnable) { _bEnumReverseMappings = bEnable; } + void setMinimalMembers(bool bEnable) { _bMinimalMembers = bEnable; } - void setDependent(set & deps) { _depMembers = deps; } + void setDependent(set& deps) { _depMembers = deps; } + + void setEnableTS(bool bEnable) { _bTS = bEnable; } void setEnableDTS(bool bEnable) { _bDTS = bEnable; } + void setOptimize(int iLevel) { _iOptimizeLevel = iLevel; } + + enum OPTIMIZE_LEVEL {O0 = 0, Os}; + + enum LONG_TYPE {Number = 0, String, BigInt}; + private: struct ImportFileType { @@ -132,29 +148,43 @@ private: string makeName(); - string findName(const string & sNamespace, const string & sName); + string findName(const string & sNamespace, const string & sName, const bool &bBase = false); private: string toFunctionName(const TypeIdPtr & pPtr, const string &sAction); - string getDataType(const TypePtr & pPtr); + string getDataType(const TypePtr& pPtr, const bool &bCastEnumAsAny = false); - string getDtsType(const TypePtr &pPtr, const bool bStream = true); + string getClassName(const TypePtr& pPtr); - string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace); + string getTsType(const TypePtr &pPtr, const bool bStream = true, const bool bBase = false); - string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace, const bool bGlobal); + string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace, const bool &bGlobal = true, const bool &bCastEnumAsAny = false); - string generateJS(const StructPtr & pPtr, const string &sNamespace, bool &bNeedAssert); +private: + string generateJS(const StructPtr &pPtr, const string &sNamespace, bool &bNeedAssert, bool &bQuickFunc); string generateJS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream); string generateJS(const EnumPtr &pPtr, const string &sNamespace); - string generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert); + string generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert, bool &bQuickFunc); bool generateJS(const ContextPtr &pPtr); +private: + string generateTS(const StructPtr &pPtr, const string &sNamespace, bool &bNeedAssert, bool &bQuickFunc); + + string generateTS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream); + + string generateTS(const EnumPtr &pPtr, const string &sNamespace); + + string generateTS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert, bool &bQuickFunc); + + string generateTS(const NamespacePtr &pPtr, const string &sContent); + + void generateTS(const ContextPtr &cPtr); + private: string generateJSProxy(const NamespacePtr &nPtr, bool &bNeedRpc, bool &bNeedStream); @@ -164,6 +194,15 @@ private: bool generateJSProxy(const ContextPtr &pPtr); +private: + string generateTSProxy(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc); + + string generateTSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr); + + string generateTSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + bool generateTSProxy(const ContextPtr &pPtr); + private: string generateJSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert); @@ -179,6 +218,17 @@ private: bool generateJSServer(const ContextPtr &pPtr); +private: + string generateTSServerAsync(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + string generateTSServerDispatch(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + string generateTSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert); + + string generateTSServer(const InterfacePtr &pPtr, const NamespacePtr &nPtr); + + bool generateTSServer(const ContextPtr &pPtr); + private: string generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); @@ -188,6 +238,9 @@ private: void generateJSServerImp(const ContextPtr &cPtr); +private: + void generateTSServerImp(const ContextPtr &cPtr); + private: string generateDTS(const StructPtr &pPtr, const string &sNamespace); @@ -222,7 +275,7 @@ private: bool isBinBuffer(const TypePtr & pPtr) const; - bool isRawOrString(const TypePtr & pPtr) const; + string representArgument(const TypePtr& pPtr) const; bool isDependent(const string & sNamespace, const string & sName) const; @@ -245,17 +298,23 @@ private: bool _bUseSpecialPath; - bool _bUseStringRepresent; + int _iLongType; bool _bStringBinaryEncoding; + bool _bEnumReverseMappings; + bool _bMinimalMembers; bool _bEntry; string _sIdlFile; + bool _bTS; + bool _bDTS; + + int _iOptimizeLevel; }; #endif \ No newline at end of file diff --git a/tools/tars2node/file_util.cpp b/tools/tars2node/file_util.cpp index cd824a3..607662c 100644 --- a/tools/tars2node/file_util.cpp +++ b/tools/tars2node/file_util.cpp @@ -18,13 +18,14 @@ void CodeGenerator::makeUTF8File(const string& sFileName, const string& sFileContent) { - char header[3] = {(char)(0xef), (char)(0xbb), (char)(0xbf)}; + try { + string sData = TC_Encoder::gbk2utf8(sFileContent); - string sData(header, 3); - - sData += TC_Encoder::gbk2utf8(sFileContent); - - TC_File::save2file(sFileName, sData.c_str()); + TC_File::save2file(sFileName, sData.c_str()); + } catch (...) { + cout << "Convert GBK to UTF8 failed, current encoding is GBK."; + TC_File::save2file(sFileName, sFileContent.c_str()); + } } string CodeGenerator::getRealFileInfo(const string& sPath) diff --git a/tools/tars2node/gen_js.cpp b/tools/tars2node/gen_js.cpp index ae9a12f..1847754 100644 --- a/tools/tars2node/gen_js.cpp +++ b/tools/tars2node/gen_js.cpp @@ -19,33 +19,61 @@ string CodeGenerator::generateJS(const EnumPtr &pPtr, const string &sNamespace) { ostringstream s; - s << TAB << sNamespace << "." << pPtr->getId() << " = {" << endl; - INC_TAB; - - //成员变量 - int nenum = -1; bool bDependent = false; - vector& member = pPtr->getAllMemberPtr(); - for (size_t i = 0; i < member.size(); i++) + + if (_bEnumReverseMappings) { - bDependent |= isDependent(sNamespace, member[i]->getId()); + s << TAB << "(function(" << pPtr->getId() << ") {" << endl; + INC_TAB; - if (member[i]->hasDefault()) - { - nenum = TC_Common::strto(member[i]->def()); - } - else - { - nenum++; - } + int nenum = -1; + vector& member = pPtr->getAllMemberPtr(); + for (size_t i = 0; i < member.size(); i++) + { + bDependent |= isDependent(sNamespace, member[i]->getId()); - s << TAB << "\"" << member[i]->getId() << "\" : " << TC_Common::tostr(nenum) << "," << endl; + if (member[i]->hasDefault()) + { + nenum = TC_Common::strto(member[i]->def()); + } + else + { + nenum++; + } + + s << TAB << pPtr->getId() << "[" << pPtr->getId() << "[\"" << member[i]->getId() << "\"] = " << TC_Common::tostr(nenum) << "] = " + << "\"" << member[i]->getId() << "\";" << endl; + } + DEL_TAB; + s << TAB << "}(" << sNamespace << "." << pPtr->getId() << " = {}));" << endl; } - s << TAB << "\"_classname\" : \"" << sNamespace << "." << pPtr->getId() << "\"" << endl; - DEL_TAB; - s << TAB << "};" << endl; + else + { + s << TAB << sNamespace << "." << pPtr->getId() << " = {" << endl; + INC_TAB; - //函数 + int nenum = -1; + vector& member = pPtr->getAllMemberPtr(); + for (size_t i = 0; i < member.size(); i++) + { + bDependent |= isDependent(sNamespace, member[i]->getId()); + + if (member[i]->hasDefault()) + { + nenum = TC_Common::strto(member[i]->def()); + } + else + { + nenum++; + } + + s << TAB << "\"" << member[i]->getId() << "\" : " << TC_Common::tostr(nenum) << (i < member.size() - 1 ? "," : "") << endl; + } + DEL_TAB; + s << TAB << "};" << endl; + } + + s << TAB << sNamespace << "." << pPtr->getId() << "._classname = \"" << sNamespace << "." << pPtr->getId() << "\";" << endl; s << TAB << sNamespace << "." << pPtr->getId() << "._write = function(os, tag, val) { return os.writeInt32(tag, val); };" << endl; s << TAB << sNamespace << "." << pPtr->getId() << "._read = function(is, tag, def) { return is.readInt32(tag, true, def); };" << endl; @@ -75,7 +103,7 @@ string CodeGenerator::generateJS(const ConstPtr &pPtr, const string &sNamespace, return s.str(); } -string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespace, bool &bNeedAssert) +string CodeGenerator::generateJS(const StructPtr &pPtr, const string &sNamespace, bool &bNeedAssert, bool &bQuickFunc) { if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getId())) { @@ -110,7 +138,7 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac //_readFrom s << TAB << sNamespace << "." << pPtr->getId() << "._readFrom = function (is) {" << endl; INC_TAB; - s << TAB << "var tmp = new " << sNamespace << "." << pPtr->getId() << "();" << endl; + s << TAB << "var tmp = new " << sNamespace << "." << pPtr->getId() << ";" << endl; for (size_t i = 0; i < member.size(); i++) { string sFuncName = toFunctionName(member[i], "read"); @@ -120,7 +148,7 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac if (isSimple(member[i]->getTypePtr())) { s << getDefault(member[i], member[i]->def(), sNamespace) - << (isRawOrString(member[i]->getTypePtr()) ? ", 1" : ""); + << representArgument(member[i]->getTypePtr()); } else { @@ -142,11 +170,21 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac string sFuncName = toFunctionName(member[i], "write"); s << TAB << "os." << sFuncName << "(" << member[i]->getTag() << ", this." << member[i]->getId() - << (isRawOrString(member[i]->getTypePtr()) ? ", 1" : "") << ");" << endl; + << representArgument(member[i]->getTypePtr()) << ");" << endl; } DEL_TAB; s << TAB << "};" << endl; + /* + * Size Optimize: + * Remove support. + * Remove toBinBuffer, readFromObject, toObject, new, create members. + */ + if (_iOptimizeLevel == Os) + { + return s.str(); + } + //_equal vector key = pPtr->getKey(); @@ -233,19 +271,22 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac DEL_TAB; s << TAB << "};" << endl; - //readFromJson + //readFromObject s << TAB << sNamespace << "." << pPtr->getId() << ".prototype.readFromObject = function(json) { "<< endl; INC_TAB; for (size_t i = 0; i < member.size(); i++) { if (isSimple(member[i]->getTypePtr())) { - s << TAB << "json.hasOwnProperty(\"" << member[i]->getId() << "\") && (this." << member[i]->getId() << " = json." << member[i]->getId() << ");" << endl; + s << TAB << "_hasOwnProperty.call(json, \"" << member[i]->getId() << "\") && (this." << member[i]->getId() << " = json." << member[i]->getId() << ");" << endl; } else { - s << TAB << "json.hasOwnProperty(\"" << member[i]->getId() << "\") && (this." << member[i]->getId() << ".readFromObject(json." << member[i]->getId() << "));" << endl; + s << TAB << "_hasOwnProperty.call(json, \"" << member[i]->getId() << "\") && (this." << member[i]->getId() << ".readFromObject(json." << member[i]->getId() << "));" << endl; } + bQuickFunc = true; } + s << TAB << "return this;" << endl; + DEL_TAB; s << TAB << "};" << endl; @@ -275,7 +316,7 @@ string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespac return s.str(); } -string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert) +string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert, bool &bQuickFunc) { ostringstream sstr; vector ss(pPtr->getAllStructPtr()); @@ -285,7 +326,7 @@ string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bo for (vector::iterator iter=ss.begin(); iter!=ss.end();) { - string str = generateJS(*iter, pPtr->getId(), bNeedAssert); + string str = generateJS(*iter, pPtr->getId(), bNeedAssert, bQuickFunc); if (!str.empty()) { sstr << str << endl; @@ -301,23 +342,31 @@ string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bo vector &cs = pPtr->getAllConstPtr(); for (size_t i = 0; i < cs.size(); i++) { - cstr << generateJS(cs[i], pPtr->getId(), bNeedStream); + string str = generateJS(cs[i], pPtr->getId(), bNeedStream); + + if (!str.empty()) { + cstr << str << endl; + } } ostringstream estr; vector & es = pPtr->getAllEnumPtr(); for (size_t i = 0; i < es.size(); i++) { - estr << generateJS(es[i], pPtr->getId()); + string str = generateJS(es[i], pPtr->getId()); + + if (!str.empty()) { + estr << str << endl; + } } ostringstream str; - if (!estr.str().empty()) str << estr.str() << endl; - if (!cstr.str().empty()) str << cstr.str() << endl; + if (!estr.str().empty()) str << estr.str(); + if (!cstr.str().empty()) str << cstr.str(); if (!sstr.str().empty()) { bNeedStream = true; - str << sstr.str() << endl; + str << sstr.str(); } return str.str(); @@ -340,20 +389,21 @@ bool CodeGenerator::generateJS(const ContextPtr &pPtr) } } - //先生成编解码体 + // generate encoders and decoders ostringstream estr; bool bNeedAssert = false; bool bNeedStream = false; + bool bQuickFunc = false; for(size_t i = 0; i < namespaces.size(); i++) { - estr << generateJS(namespaces[i], bNeedStream, bNeedAssert); + estr << generateJS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc); } if (estr.str().empty()) { return false; } - //再生成导入模块 + // generate module imports ostringstream ostr; for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { @@ -364,9 +414,11 @@ bool CodeGenerator::generateJS(const ContextPtr &pPtr) ostr << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl; } - //生成文件内容 + // concat generated code ostringstream sstr; sstr << printHeaderRemark("Structure"); + sstr << DISABLE_ESLINT << endl; + sstr << endl; sstr << "\"use strict\";" << endl << endl; if (bNeedAssert) { @@ -376,6 +428,11 @@ bool CodeGenerator::generateJS(const ContextPtr &pPtr) { sstr << "var " << IDL_NAMESPACE_STR << "Stream = require(\"" << _sStreamPath << "\");" << endl; } + if (bQuickFunc) + { + sstr << endl; + sstr << "var _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl; + } sstr << ostr.str() << endl; sstr << istr.str(); sstr << estr.str() << endl; diff --git a/tools/tars2node/gen_js_dts.cpp b/tools/tars2node/gen_js_dts.cpp index ee66a0e..d7e99be 100644 --- a/tools/tars2node/gen_js_dts.cpp +++ b/tools/tars2node/gen_js_dts.cpp @@ -21,10 +21,9 @@ string CodeGenerator::generateDTS(const EnumPtr &pPtr, const string &sNamespace) ostringstream s; INC_TAB; - s << TAB << "enum " << pPtr->getId() << " {" << endl; + s << TAB << (_bEnumReverseMappings ? "enum " : "const enum ") << pPtr->getId() << " {" << endl; INC_TAB; - //成员变量 int nenum = -1; bool bDependent = false; vector& member = pPtr->getAllMemberPtr(); @@ -39,7 +38,7 @@ string CodeGenerator::generateDTS(const EnumPtr &pPtr, const string &sNamespace) { nenum++; } - s << TAB << "\"" << member[i]->getId() << "\" = " << TC_Common::tostr(nenum) << ((i < member.size() - 1) ? "," : "") << endl; + s << TAB << member[i]->getId() << " = " << TC_Common::tostr(nenum) << ((i < member.size() - 1) ? "," : "") << endl; } DEL_TAB; @@ -67,8 +66,8 @@ string CodeGenerator::generateDTS(const ConstPtr &pPtr, const string &sNamespace } INC_TAB; - s << TAB << "const " << pPtr->getTypeIdPtr()->getId() << ":" - << getDtsType(pPtr->getTypeIdPtr()->getTypePtr()) << ";" + s << TAB << "const " << pPtr->getTypeIdPtr()->getId() << ":" + << getTsType(pPtr->getTypeIdPtr()->getTypePtr()) << ";" << endl; DEL_TAB; return s.str(); @@ -81,51 +80,61 @@ string CodeGenerator::generateDTS(const StructPtr &pPtr, const string &sNamespac return ""; } - string sStructName = pPtr->getId() + "$OBJ"; vector &member = pPtr->getAllMemberPtr(); - ostringstream s; - INC_TAB; + + + ostringstream s; s << TAB << "class " << pPtr->getId() << " {" << endl; INC_TAB; - + for (size_t i = 0; i < member.size(); i++) { - s << TAB << (member[i]->getId()) << (member[i]->isRequire()?": ":"?: ") << getDtsType(member[i]->getTypePtr()) << ";" << endl; + s << TAB << (member[i]->getId()) << ": " << getTsType(member[i]->getTypePtr()) << ";" << endl; } if (member.size() > 0) { s << endl; } - s << TAB << "toObject(): " << sStructName << ";" << endl; - s << TAB << "readFromObject(json: " << sStructName << "): void;" << endl; - s << TAB << "toBinBuffer(): " << IDL_NAMESPACE_STR << "Stream.BinBuffer;" << endl; - s << TAB << "static new(): " << pPtr->getId() << ";" << endl; - s << TAB << "static create(is: " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream): " << pPtr->getId() << ";" << endl; + /* + * Size Optimize: + * Remove support. + * Remove toBinBuffer, readFromObject, toObject, new, create members. + */ + if (_iOptimizeLevel != Os) + { + s << TAB << "toObject(): " << pPtr->getId() << ".Object;" << endl; + s << TAB << "readFromObject(json: " << pPtr->getId() << ".Object): " << pPtr->getId() << ";" << endl; + s << TAB << "toBinBuffer(): " << IDL_NAMESPACE_STR << "Stream.BinBuffer;" << endl; + s << TAB << "static new(): " << pPtr->getId() << ";" << endl; + s << TAB << "static create(is: " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream): " << pPtr->getId() << ";" << endl; + } DEL_TAB; - s << TAB << "}" << endl; + s << TAB << "}" << endl << endl; - s << TAB << "interface " << sStructName << " {" << endl; + s << TAB << "namespace " << pPtr->getId() << " {" << endl; + INC_TAB; + s << TAB << "interface Object {" << endl; INC_TAB; - for (size_t i = 0; i < member.size(); i++) { - const string &sType = getDtsType(member[i]->getTypePtr(), false); - if (!sType.empty()) - { - s << TAB << (member[i]->getId()) << (member[i]->isRequire()?": ":"?: ") << sType << ";" << endl; - } + const string &sType = getTsType(member[i]->getTypePtr(), false); + s << TAB << (member[i]->getId()) << (member[i]->isRequire() ? ": " : "?: ") << (!sType.empty() ? sType : "never") << ";" << endl; } DEL_TAB; s << TAB << "}" << endl; DEL_TAB; + s << TAB << "}" << endl; + + DEL_TAB; + return s.str(); } string CodeGenerator::generateDTS(const NamespacePtr &pPtr, bool &bNeedStream) { - //结构 + // struct ostringstream sstr; vector ss(pPtr->getAllStructPtr()); for (size_t last = 0; last != ss.size() && ss.size() != 0;) @@ -134,19 +143,19 @@ string CodeGenerator::generateDTS(const NamespacePtr &pPtr, bool &bNeedStream) for (vector::iterator iter=ss.begin(); iter!=ss.end();) { string str = generateDTS(*iter, pPtr->getId()); - if (!str.empty()) + if (!str.empty()) { sstr << str << endl; iter = ss.erase(iter); - } - else + } + else { iter++; } } } - //常量 + // const ostringstream cstr; vector &cs = pPtr->getAllConstPtr(); for (size_t i = 0; i < cs.size(); i++) @@ -154,7 +163,7 @@ string CodeGenerator::generateDTS(const NamespacePtr &pPtr, bool &bNeedStream) cstr << generateDTS(cs[i], pPtr->getId(), bNeedStream); } - //枚举 + // enum ostringstream estr; vector &es = pPtr->getAllEnumPtr(); for (size_t i = 0; i < es.size(); i++) @@ -179,7 +188,7 @@ string CodeGenerator::generateDTS(const NamespacePtr &pPtr, const string &sConte ostringstream str; if (!sContent.empty()) { - str << "export declare namespace " << pPtr->getId() << " {" << endl; + str << "export namespace " << pPtr->getId() << " {" << endl; str << sContent; str << "}" << endl << endl; } @@ -189,8 +198,8 @@ string CodeGenerator::generateDTS(const NamespacePtr &pPtr, const string &sConte void CodeGenerator::generateDTS(const ContextPtr &pPtr) { vector namespaces = pPtr->getNamespaces(); - - //先生成编解码体 + + // generate encoders and decoders ostringstream estr; bool bNeedStream = false; for (size_t i = 0; i < namespaces.size(); i++) @@ -202,7 +211,7 @@ void CodeGenerator::generateDTS(const ContextPtr &pPtr) return; } - //再生成导入模块 + // generate module imports ostringstream ostr; if (bNeedStream) { @@ -212,15 +221,18 @@ void CodeGenerator::generateDTS(const ContextPtr &pPtr) for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { if (it->second.sModule.empty()) continue; - + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; } - //生成文件内容 + // concat generated code ostringstream sstr; sstr << printHeaderRemark("Structure"); + sstr << DISABLE_TSLINT << endl; + sstr << DISABLE_ESLINT << endl; + sstr << endl; sstr << ostr.str() << endl; sstr << estr.str() << endl; diff --git a/tools/tars2node/gen_proxy.cpp b/tools/tars2node/gen_proxy.cpp index 4db4860..0f01287 100644 --- a/tools/tars2node/gen_proxy.cpp +++ b/tools/tars2node/gen_proxy.cpp @@ -16,6 +16,15 @@ #include "code_generator.h" +#define INVOKE_RETURN(protocol, prefix, params) \ + str << TAB << "return this._worker." << TC_Common::lower(protocol) << "_invoke(\"" << oPtr->getId() << "\", "; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$" << prefix << "E"; \ + str << "(" << sParams << params << "), arguments[arguments.length - 1], "; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF" << ").then("; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$" << prefix << "D, "; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER);" << endl; +#define PROTOCOL_PARAMS (sParams.empty() ? "" : ", ") << "version" + struct SortOperation { bool operator()(const OperationPtr &o1, const OperationPtr &o2) @@ -28,9 +37,10 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP { ostringstream str; - //SETP01 生成编码接口 - str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$EN = function ("; vector & vParamDecl = oPtr->getAllParamDeclPtr(); + bool bHasParamOut = false; + string sParams = ""; + for (size_t i = 0; i < vParamDecl.size(); i++) { if (vParamDecl[i]->isOut()) @@ -38,9 +48,48 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP continue; } - str << (i == 0?"":", ") << vParamDecl[i]->getTypeIdPtr()->getId(); + sParams += (sParams.empty()?"":", ") + vParamDecl[i]->getTypeIdPtr()->getId(); } - str << ") {" << endl; + + // generate function metadata (SharedFunctionInfo) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF = {" << endl; + + INC_TAB; + + str << TAB << "\"name\" : \"" << oPtr->getId() << "\"," << endl; + str << TAB << "\"return\" : \"" << getClassName(oPtr->getReturnPtr()->getTypePtr()) << "\"," << endl; + str << TAB << "\"arguments\" : ["; + for (size_t i = 0; i < vParamDecl.size(); i++) + { + str << (i > 0 ? ", {" : "{") << endl; + + INC_TAB; + + str << TAB << "\"name\" : \"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"," << endl; + str << TAB << "\"class\" : \"" << getClassName(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << "\"," << endl; + + if (vParamDecl[i]->isOut()) + { + bHasParamOut = true; + str << TAB << "\"direction\" : \"out\"" << endl; + } + else + { + str << TAB << "\"direction\" : \"in\"" << endl; + } + + DEL_TAB; + + str << TAB << "}"; + } + str << "]" << endl; + + DEL_TAB; + + str << TAB << "};" << endl << endl; + + // generate IDL Encoder ($IE) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IE = function (" << sParams << ") {" << endl; INC_TAB; @@ -51,10 +100,10 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP if (vParamDecl[i]->isOut()) continue; str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(" - << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; - // 写入 Dependent 列表 + // push the symbol into dependent list getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); } @@ -64,9 +113,8 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP str << TAB << "};" << endl << endl; - - //STEP02 生成解码函数 - str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$DE = function (data) {" << endl; + // generate IDL Decoder ($ID) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ID = function (data) {" << endl; INC_TAB; str << TAB << "try {" << endl; INC_TAB; @@ -104,7 +152,7 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP if (isSimple(oPtr->getReturnPtr()->getTypePtr())) { str << getDefault(oPtr->getReturnPtr(), oPtr->getReturnPtr()->def(), nPtr->getId()) - << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : ""); + << representArgument(oPtr->getReturnPtr()->getTypePtr()); } else { @@ -130,8 +178,8 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) { - str << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId()) - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : ""); + str << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId()) + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); } else { @@ -163,80 +211,155 @@ string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfaceP DEL_TAB; str << TAB << "} catch (e) {" << endl; INC_TAB; - str << TAB << "throw {" << endl; + str << TAB << "throw _makeError(data, e.message, " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR);" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + // generate Protocol Encoder ($PE) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$PE = function (" + << sParams << (sParams.empty() ? "" : ", ") << "__$PROTOCOL$VERSION) {" << endl; + + INC_TAB; + + str << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; + + str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = __$PROTOCOL$VERSION;" << endl; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (vParamDecl[i]->isOut()) continue; + + str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\"" + << vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId() + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; + + // push the symbol into dependent list + getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << TAB << "return " << PROTOCOL_VAR << ";" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + // generate Protocol Decoder ($PD) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$PD = function (data) {" << endl; + INC_TAB; + str << TAB << "try {" << endl; + INC_TAB; + if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut) { + str << TAB << "var " << PROTOCOL_VAR << " = data.response." << PROTOCOL_VAR << ";" << endl; + } + str << TAB << "return {" << endl; INC_TAB; str << TAB << "\"request\" : data.request," << endl; str << TAB << "\"response\" : {" << endl; INC_TAB; - str << TAB << "\"costtime\" : data.request.costtime," << endl; - str << TAB << "\"error\" : {" << endl; - INC_TAB; - str << TAB << "\"code\" : " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR," << endl; - str << TAB << "\"message\" : e.message" << endl; - DEL_TAB; - str << TAB << "}" << endl; + str << TAB << "\"costtime\" : data.request.costtime"; + + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << "," << endl; + str << TAB << "\"return\" : " << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "read") << "(\"\""; + + if (!isSimple(oPtr->getReturnPtr()->getTypePtr()) && !isBinBuffer(oPtr->getReturnPtr()->getTypePtr())) + { + str << ", " << getDataType(oPtr->getReturnPtr()->getTypePtr()); + } + + str << ", " << getDefault(oPtr->getReturnPtr(), "", nPtr->getId(), true) + << representArgument(oPtr->getReturnPtr()->getTypePtr()); + + str << ")"; + } + + if (bHasParamOut) + { + str << "," << endl; + str << TAB << "\"arguments\" : {" << endl; + + INC_TAB; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << "\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\" : " + << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") + << "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\""; + + if (!isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) && !isBinBuffer(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + str << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << ")"; + + if (i == vParamDecl.size() - 1) + { + str << endl; + } + else + { + str << "," << endl; + } + + } + + DEL_TAB; + str << TAB << "}"; + } + + str << endl; DEL_TAB; str << TAB << "}" << endl; DEL_TAB; str << TAB << "};" << endl; DEL_TAB; + str << TAB << "} catch (e) {" << endl; + INC_TAB; + str << TAB << "throw _makeError(data, e.message, " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR);" << endl; + DEL_TAB; str << TAB << "}" << endl; DEL_TAB; str << TAB << "};" << endl << endl; - //STEP03 生成框架调用错误处理函数 + // generate error handler ($ER) str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER = function (data) {" << endl; INC_TAB; - str << TAB << "throw {" << endl; - INC_TAB; - str << TAB << "\"request\" : data.request," << endl; - str << TAB << "\"response\" : {" << endl; - INC_TAB; - str << TAB << "\"costtime\" : data.request.costtime," << endl; - str << TAB << "\"error\" : data.error" << endl; - DEL_TAB; - str << TAB << "}" << endl; - DEL_TAB; - str << TAB << "}" << endl; + str << TAB << "throw _makeError(data, \"Call " << pPtr->getId() << "::" << oPtr->getId() << " failed\");" << endl; DEL_TAB; str << TAB << "};" << endl << endl; - //SETP04 生成函数接口 - str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy.prototype." << oPtr->getId() << " = function ("; - for (size_t i = 0; i < vParamDecl.size(); i++) - { - if (vParamDecl[i]->isOut()) - { - continue; - } - - str << (i == 0?"":", ") << vParamDecl[i]->getTypeIdPtr()->getId(); - } - str << ") {" << endl; + // generate function body + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy.prototype." << oPtr->getId() << " = function (" + << sParams << ") {" << endl; INC_TAB; - str << TAB << "return this._worker." << TC_Common::lower(IDL_NAMESPACE_STR) << "_invoke(\"" << oPtr->getId() << "\", "; - str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$EN("; - for (size_t i = 0; i < vParamDecl.size(); i++) - { - if (vParamDecl[i]->isOut()) - { - continue; - } + str << TAB << "var version = this._worker.version;" << endl; - str << (i == 0?"":", ") << vParamDecl[i]->getTypeIdPtr()->getId(); - } - str << "), arguments[arguments.length - 1]).then("; - str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$DE, "; - str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER);" << endl; + str << TAB << "if (version === " << PROTOCOL_SIMPLE << " || version === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + INVOKE_RETURN(PROTOCOL_VAR, "P", PROTOCOL_PARAMS); + DEL_TAB; + str << TAB << "} else {" << endl; + INC_TAB; + INVOKE_RETURN(IDL_NAMESPACE_STR, "I", ""); + DEL_TAB; + str << TAB << "}" << endl; DEL_TAB; str << TAB << "};" << endl; + // add the function into the prototype of the proxy class + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy." << oPtr->getId() << " = " + << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF;" << endl; + return str.str(); } @@ -303,8 +426,8 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy = function () {" << endl; INC_TAB; - istr << TAB << "this._name = undefined;" << endl; - istr << TAB << "this._worker = undefined;" << endl; + istr << TAB << "this._name = undefined;" << endl; + istr << TAB << "this._worker = undefined;" << endl; DEL_TAB; istr << TAB << "};" << endl << endl; @@ -319,16 +442,29 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) istr << TAB << "return this._worker.timeout;" << endl; DEL_TAB; istr << TAB << "};" << endl << endl; + + istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.setVersion = function (iVersion) {" << endl; + INC_TAB; + istr << TAB << "this._worker.version = iVersion;" << endl; + DEL_TAB; + istr << TAB << "};" << endl << endl; + + istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.getVersion = function () {" << endl; + INC_TAB; + istr << TAB << "return this._worker.version;" << endl; + DEL_TAB; + istr << TAB << "};" << endl; } } - //先生成编解码 + 代理类 + // generate proxy classes with encoders and decoders ostringstream estr; bool bNeedAssert = false; bool bNeedStream = false; + bool bQuickFunc = false; for(size_t i = 0; i < namespaces.size(); i++) { - estr << generateJS(namespaces[i], bNeedStream, bNeedAssert); + estr << generateJS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc); } bool bNeedRpc = false; @@ -342,7 +478,7 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) return false; } - //再生成导入模块 + // generate module imports ostringstream ostr; for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { @@ -353,9 +489,11 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) ostr << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl; } - //生成文件内容 + // concat generated code ostringstream sstr; sstr << printHeaderRemark("Client"); + sstr << DISABLE_ESLINT << endl; + sstr << endl; sstr << "\"use strict\";" << endl << endl; if (bNeedAssert) { @@ -371,6 +509,48 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) } sstr << ostr.str() << endl; + + // generate helper functions + if (bQuickFunc) + { + sstr << "var _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl; + } + if (bNeedRpc) + { + sstr << TAB << "var _makeError = function (data, message, type) {" << endl; + INC_TAB; + sstr << TAB << "var error = new Error(message || \"\");" << endl; + sstr << TAB << "error.request = data.request;" << endl; + sstr << TAB << "error.response = {" << endl; + INC_TAB; + sstr << TAB << "\"costtime\" : data.request.costtime" << endl; + DEL_TAB; + sstr << TAB << "};" << endl; + sstr << TAB << "if (type === " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR) {" << endl; + INC_TAB; + sstr << TAB << "error.name = \"DECODE_ERROR\";" << endl; + sstr << TAB << "error.response.error = {" << endl; + INC_TAB; + sstr << TAB << "\"code\" : type," << endl; + sstr << TAB << "\"message\" : message" << endl; + DEL_TAB; + sstr << TAB << "};" << endl; + DEL_TAB; + sstr << TAB << "} else {" << endl; + INC_TAB; + sstr << TAB << "error.name = \"RPC_ERROR\";" << endl; + sstr << TAB << "error.response.error = data.error;" << endl; + DEL_TAB; + sstr << TAB << "}" << endl; + sstr << TAB << "return error;" << endl; + DEL_TAB; + sstr << TAB << "};" << endl; + } + if (bQuickFunc || bNeedRpc) + { + sstr << endl; + } + sstr << istr.str() << endl; sstr << estr.str() << endl; @@ -380,4 +560,7 @@ bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) makeUTF8File(sFileName, sstr.str()); return true; -} \ No newline at end of file +} + +#undef INVOKE_RETURN +#undef PROTOCOL_PARAMS \ No newline at end of file diff --git a/tools/tars2node/gen_proxy_dts.cpp b/tools/tars2node/gen_proxy_dts.cpp index f1c05ce..560de51 100644 --- a/tools/tars2node/gen_proxy_dts.cpp +++ b/tools/tars2node/gen_proxy_dts.cpp @@ -25,79 +25,55 @@ string CodeGenerator::generateDTSProxy(const InterfacePtr &pPtr) INC_TAB; str << TAB << "class " << pPtr->getId() << "Proxy {" << endl; INC_TAB; - str << TAB << "setTimeout(timeout: number): void;" << endl; + str << TAB << "setTimeout(iTimeout: number): void;" << endl; str << TAB << "getTimeout(): number;" << endl; + str << TAB << "setVersion(iVersion: number): void;" << endl; + str << TAB << "getVersion(): number;" << endl; for (size_t i = 0; i < vOperation.size(); i++) { OperationPtr &oPtr = vOperation[i]; + string funcReturnGeneric = "<"; + if (oPtr->getReturnPtr()->getTypePtr()) + { + funcReturnGeneric += getTsType(oPtr->getReturnPtr()->getTypePtr()) + ", "; + } + else + { + funcReturnGeneric += "undefined, "; + } + str << TAB << oPtr->getId() << "("; + string argType = ""; vector &vParamDecl = oPtr->getAllParamDeclPtr(); - for (size_t j = 0; j < vParamDecl.size(); j++) + for (size_t j = 0; j < vParamDecl.size(); j++) { - if(vParamDecl[j]->isOut()) + if(vParamDecl[j]->isOut()) { + argType += (argType.empty() ? "" : ", ") + vParamDecl[j]->getTypeIdPtr()->getId() + ": " + getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); continue; } - str << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); + str << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); str << ", "; } - str << "property?: " << IDL_NAMESPACE_STR << "Rpc.InvokeProperty): Promise<" << pPtr->getId() << "$" << oPtr->getId() << "$DE>;" << endl; + + if (!argType.empty()) + { + funcReturnGeneric += "{ " + argType + " }>"; + } + else + { + funcReturnGeneric += "undefined>"; + } + + str << "options?: " << IDL_NAMESPACE_STR << "Rpc.InvokeProperty): Promise<" << IDL_NAMESPACE_STR << "Rpc.ProxyResponse" << funcReturnGeneric << ">;" << endl; + + str << TAB << "static " << oPtr->getId() << ": " << IDL_NAMESPACE_STR << "Rpc.SharedFunctionInfo" << ";" << endl; } DEL_TAB; str << TAB << "}" << endl; - //interface - for (size_t i = 0; i < vOperation.size(); i++) - { - OperationPtr &oPtr = vOperation[i]; - - str << TAB << "interface " << pPtr->getId() << "$" << oPtr->getId() << "$DE {" << endl; - INC_TAB; - str << TAB << "request: object;" << endl; - str << TAB << "response: {" << endl; - INC_TAB; - str << TAB << "costtime: number;" << endl; - if (oPtr->getReturnPtr()->getTypePtr()) - { - str << TAB << "return: " << getDtsType(oPtr->getReturnPtr()->getTypePtr()) << ";" << endl; - } - else - { - str << TAB << "return: void;" << endl; - } - - vector &vParamDecl = oPtr->getAllParamDeclPtr(); - bool hasArgs = false; - for (size_t j = 0; j < vParamDecl.size(); j++) - { - if(vParamDecl[j]->isOut()) { - hasArgs = true; - break; - } - } - - if(hasArgs) - { - str << TAB << "arguments: {" << endl; - INC_TAB; - for (size_t j = 0; j < vParamDecl.size(); j++) - { - if(!vParamDecl[j]->isOut()) { - continue; - } - str << TAB << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) << ";" << endl; - } - DEL_TAB; - str << TAB << "}" << endl; - } - - DEL_TAB; - str << TAB << "}" << endl; - DEL_TAB; - str << TAB << "}" << endl; - } DEL_TAB; return str.str(); @@ -107,15 +83,15 @@ string CodeGenerator::generateDTSProxy(const NamespacePtr &nPtr, bool &bNeedStre { ostringstream str; vector &is = nPtr->getAllInterfacePtr(); - for (size_t i = 0; i < is.size(); i++) - { - str << generateDTSProxy(is[i]) << endl; - } - if (is.size() != 0) + if (is.size() > 0) { bNeedStream = true; bNeedRpc = true; } + for (size_t i = 0; i < is.size(); i++) + { + str << generateDTSProxy(is[i]) << endl; + } return str.str(); } @@ -123,7 +99,7 @@ void CodeGenerator::generateDTSProxy(const ContextPtr &cPtr) { vector namespaces = cPtr->getNamespaces(); - //先生成编解码 + 代理类 + // generate proxy classes with encoders and decoders ostringstream estr; bool bNeedStream = false; bool bNeedRpc = false; @@ -141,20 +117,23 @@ void CodeGenerator::generateDTSProxy(const ContextPtr &cPtr) return; } - //再生成导入模块 + // generate module imports ostringstream ostr; for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { if (it->second.sModule.empty()) continue; - + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; } - //生成文件内容 + // concat generated code ostringstream sstr; sstr << printHeaderRemark("Client"); + sstr << DISABLE_TSLINT << endl; + sstr << DISABLE_ESLINT << endl; + sstr << endl; if (bNeedStream) { sstr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl; diff --git a/tools/tars2node/gen_server.cpp b/tools/tars2node/gen_server.cpp index ffe241f..6825787 100644 --- a/tools/tars2node/gen_server.cpp +++ b/tools/tars2node/gen_server.cpp @@ -58,7 +58,7 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr { sParams += "_ret"; - // 写入 Dependent 列表 + // push the symbol into dependent list getDataType(oPtr->getReturnPtr()->getTypePtr()); } @@ -89,8 +89,8 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = this.getRequestVersion();" << endl; if (oPtr->getReturnPtr()->getTypePtr()) { - str << TAB << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "write") << "(\"\", _ret" - << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + str << TAB << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "write") << "(\"\", _ret" + << representArgument(oPtr->getReturnPtr()->getTypePtr()) << ");" << endl; } for (size_t i = 0; i < vParamDecl.size(); i++) { @@ -98,7 +98,7 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId() - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; } str << endl; str << TAB << "this.doResponse(" << PROTOCOL_VAR << ".encode());" << endl; @@ -109,8 +109,8 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr str << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; if (oPtr->getReturnPtr()->getTypePtr()) { - str << TAB << "os." << toFunctionName(oPtr->getReturnPtr(), "write") << "(0, _ret" - << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + str << TAB << "os." << toFunctionName(oPtr->getReturnPtr(), "write") << "(0, _ret" + << representArgument(oPtr->getReturnPtr()->getTypePtr()) << ");" << endl; } for (size_t i = 0; i < vParamDecl.size(); i++) { @@ -118,7 +118,7 @@ string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(" << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl; } str << endl; str << TAB << "this.doResponse(os.getBinBuffer());" << endl; @@ -172,7 +172,7 @@ string CodeGenerator::generateDispatch(const NamespacePtr &nPtr, const Interface if (vParamDecl[i]->isOut()) { dstr << ", " << getDefault(vParamDecl[i]->getTypeIdPtr(), "", nPtr->getId(), true) - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : ""); + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); } dstr << ");" << endl; @@ -194,7 +194,7 @@ string CodeGenerator::generateDispatch(const NamespacePtr &nPtr, const Interface if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) { dstr << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId()) - << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : ""); + << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); } else { @@ -243,7 +243,7 @@ string CodeGenerator::generateJSServer(const InterfacePtr &pPtr, const Namespace ostringstream str; vector & vOperation = pPtr->getAllOperationPtr(); - //生成类 + // generate the implementation class str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp = function () { " << endl; INC_TAB; str << TAB << "this._name = undefined;" << endl; @@ -251,10 +251,10 @@ string CodeGenerator::generateJSServer(const InterfacePtr &pPtr, const Namespace DEL_TAB; str << TAB << "};" << endl << endl; - //生成初始化函数 + // generate the initialize function str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.initialize = function () {};" << endl << endl; - //生成分发函数 + // generate the dispatch function str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.onDispatch = function (current, funcName, binBuffer) { " << endl; INC_TAB; str << TAB << "if (\"__\" + funcName in this) {" << endl; @@ -269,10 +269,10 @@ string CodeGenerator::generateJSServer(const InterfacePtr &pPtr, const Namespace DEL_TAB; str << TAB << "};" << endl << endl; - //生成 PING 方法 + // generate the ping function str << generatePing(nPtr, pPtr) << endl; - //生成接口函数 + // generate functions for (size_t i = 0; i < vOperation.size(); i++) { str << generateJSServer(nPtr, pPtr, vOperation[i]) << endl; @@ -321,13 +321,14 @@ bool CodeGenerator::generateJSServer(const ContextPtr &pPtr) } } - //生成编解码 + 服务类 + // generate server classes with encoders and decoders ostringstream estr; bool bNeedAssert = false; bool bNeedStream = false; + bool bQuickFunc = false; for(size_t i = 0; i < namespaces.size(); i++) { - estr << generateJS(namespaces[i], bNeedStream, bNeedAssert); + estr << generateJS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc); } bool bNeedRpc = false; @@ -341,7 +342,7 @@ bool CodeGenerator::generateJSServer(const ContextPtr &pPtr) return false; } - //再生成导入模块 + // generate module imports ostringstream ostr; if (bNeedAssert) { @@ -363,10 +364,17 @@ bool CodeGenerator::generateJSServer(const ContextPtr &pPtr) ostr << TAB << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl; } + if (bQuickFunc) + { + ostr << endl; + ostr << TAB << "var _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl; + } ostringstream str; str << printHeaderRemark("Server"); + str << DISABLE_ESLINT << endl; + str << endl; str << "\"use strict\";" << endl << endl; str << ostr.str() << endl; str << istr.str(); diff --git a/tools/tars2node/gen_server_dts.cpp b/tools/tars2node/gen_server_dts.cpp index 064713f..07c1698 100644 --- a/tools/tars2node/gen_server_dts.cpp +++ b/tools/tars2node/gen_server_dts.cpp @@ -25,34 +25,37 @@ string CodeGenerator::generateDTSServer(const NamespacePtr &nPtr, const Interfac INC_TAB; str << TAB << "class " << pPtr->getId() << "Imp {" << endl; INC_TAB; - str << TAB << "initialize(): Promise | void;" << endl; + str << TAB << "initialize(): PromiseLike | void;" << endl; str << TAB << "protected onDispatch(current: " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current, funcName: string, binBuffer: " << IDL_NAMESPACE_STR << "Stream.BinBuffer): number" << endl; for (size_t i = 0; i < vOperation.size(); i++) { OperationPtr &oPtr = vOperation[i]; - str << TAB << oPtr->getId() << "(current: " << pPtr->getId() << "$" << oPtr->getId() << "$CUR"; + str << TAB << oPtr->getId() << "(current: " << pPtr->getId() << "Imp." << oPtr->getId() << "Current"; vector &vParamDecl = oPtr->getAllParamDeclPtr(); - for (size_t j = 0; j < vParamDecl.size(); j++) + for (size_t j = 0; j < vParamDecl.size(); j++) { - str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); + str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); } - str << "): void;" << endl; + str << "): any;" << endl; } DEL_TAB; str << TAB << "}" << endl; - //interface + // Additional namespace + str << TAB << "namespace " << pPtr->getId() << "Imp {" << endl; + INC_TAB; + for (size_t i = 0; i < vOperation.size(); i++) { OperationPtr &oPtr = vOperation[i]; - str << TAB << "interface " << pPtr->getId() << "$" << oPtr->getId() << "$CUR extends " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current {" <getId() << "Current extends " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current {" <getReturnPtr()->getTypePtr()) { - str << "sendResponse(ret: " << getDtsType(oPtr->getReturnPtr()->getTypePtr()); + str << "sendResponse(ret: " << getTsType(oPtr->getReturnPtr()->getTypePtr()); vector &vParamDecl = oPtr->getAllParamDeclPtr(); for (size_t j = 0; j < vParamDecl.size(); j++) @@ -60,7 +63,7 @@ string CodeGenerator::generateDTSServer(const NamespacePtr &nPtr, const Interfac if(!vParamDecl[j]->isOut()) { continue; } - str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) ; + str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) ; } str << "): void;" << endl; } @@ -72,8 +75,11 @@ string CodeGenerator::generateDTSServer(const NamespacePtr &nPtr, const Interfac DEL_TAB; str << TAB << "}" << endl; } - DEL_TAB; + DEL_TAB; + str << TAB << "}" << endl; + + DEL_TAB; return str.str(); } @@ -100,7 +106,7 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) { vector namespaces = pPtr->getNamespaces(); - //生成编解码 + 服务类 + // generate server classes with encoders and decoders ostringstream estr; bool bNeedStream = false; bool bNeedRpc = false; @@ -110,7 +116,7 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) kstr << generateDTS(namespaces[i], bNeedStream); kstr << generateDTSServer(namespaces[i], bNeedStream, bNeedRpc); - + estr << generateDTS(namespaces[i], kstr.str()); } if(estr.str().empty()) @@ -118,7 +124,7 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) return; } - //再生成导入模块 + // generate module imports ostringstream ostr; if (bNeedStream) { @@ -131,7 +137,7 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) { if (it->second.sModule.empty()) continue; - + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; @@ -139,6 +145,9 @@ void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) ostringstream str; str << printHeaderRemark("Server"); + str << DISABLE_TSLINT << endl; + str << DISABLE_ESLINT << endl; + str << endl; str << ostr.str() << endl; str << estr.str() << endl; diff --git a/tools/tars2node/idl_scan.cpp b/tools/tars2node/idl_scan.cpp index 06984f2..e2d59bb 100644 --- a/tools/tars2node/idl_scan.cpp +++ b/tools/tars2node/idl_scan.cpp @@ -29,7 +29,7 @@ string CodeGenerator::makeName() if (iHigh != 0) { - s << string(1, (char)(iHigh + 65)) << string(1, (char)(iLow + 65)); + s << string(1, (char)(iHigh + 65)) << string(1, (char)(iLow + 65)); } else { @@ -46,7 +46,7 @@ bool CodeGenerator::isDependent(const string& sNamespace, const string& sName) c return _depMembers.find(sNamespace + "::" + sName) != _depMembers.end(); } -string CodeGenerator::findName(const string& sNamespace, const string& sName) +string CodeGenerator::findName(const string& sNamespace, const string& sName, const bool &bBase) { #ifdef DUMP_FIND_NAME cout << "FINDNAME BEGIN:" << sNamespace << "|" << sName << endl; @@ -71,17 +71,24 @@ string CodeGenerator::findName(const string& sNamespace, const string& sName) cout << "DEPMEMBER:" << it->first << "|" << inIter->second.sNamespace << "::" << inIter->second.sName << endl; #endif _depMembers.insert(inIter->second.sNamespace + "::" + inIter->second.sName); + string prefix; + + if (bBase && it->second.sModule.empty()) { + prefix = "base."; + } else if (!it->second.sModule.empty()) { + prefix = it->second.sModule + "."; + } switch (inIter->second.iType) { case ImportFileType::EN_ENUM : // [[fallthrough]] case ImportFileType::EN_STRUCT : { - return it->second.sModule + (it->second.sModule.empty()?"":".") + inIter->second.sNamespace + "." + inIter->second.sName; + return prefix + inIter->second.sNamespace + "." + inIter->second.sName; } case ImportFileType::EN_ENUM_VALUE : { - return it->second.sModule + (it->second.sModule.empty()?"":".") + inIter->second.sNamespace + "." + inIter->second.sTypeName + "." + inIter->second.sName; + return prefix + inIter->second.sNamespace + "." + inIter->second.sTypeName + "." + inIter->second.sName; } default : { diff --git a/tools/tars2node/idl_util.cpp b/tools/tars2node/idl_util.cpp index c7b4d3c..28c9ec9 100644 --- a/tools/tars2node/idl_util.cpp +++ b/tools/tars2node/idl_util.cpp @@ -68,26 +68,77 @@ string CodeGenerator::toFunctionName(const TypeIdPtr& pPtr, const string& sActio return ""; } -bool CodeGenerator::isRawOrString(const TypePtr& pPtr) const +string CodeGenerator::representArgument(const TypePtr& pPtr) const { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) { - if (_bUseStringRepresent && bPtr->kind() == Builtin::KindLong) + if (bPtr->kind() == Builtin::KindLong && _iLongType != CodeGenerator::Number) { - return true; + stringstream str; + str << ", " << _iLongType; + return str.str(); } if (_bStringBinaryEncoding && bPtr->kind() == Builtin::KindString) { - return true; + return ", 1"; } } - return false; + return ""; } -string CodeGenerator::getDataType(const TypePtr & pPtr) +string CodeGenerator::getClassName(const TypePtr& pPtr) +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) + { + switch (bPtr->kind()) + { + case Builtin::KindBool : return "bool"; + case Builtin::KindString : return "string"; + case Builtin::KindByte : return "char"; + case Builtin::KindShort : return "short"; + case Builtin::KindInt : return "int32"; + case Builtin::KindLong : return "int64"; + case Builtin::KindFloat : return "float"; + case Builtin::KindDouble : return "double"; + default : assert(false); + } + } + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) + { + return "list(" + getClassName(vPtr->getTypePtr()) + ")"; + } + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) + { + vector vecNames = TC_Common::sepstr(sPtr->getSid(), "::"); + assert(vecNames.size() == 2); + + return vecNames[0] + "." + vecNames[1]; + } + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) + { + return "map(" + getClassName(mPtr->getLeftTypePtr()) + ", " + getClassName(mPtr->getRightTypePtr()) + ")"; + } + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) + { + return "int32"; + } + + return "void"; +} + +string CodeGenerator::getDataType(const TypePtr& pPtr, const bool &bCastEnumAsAny) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) @@ -114,8 +165,7 @@ string CodeGenerator::getDataType(const TypePtr & pPtr) { return IDL_NAMESPACE_STR + "Stream.BinBuffer"; } - - return IDL_NAMESPACE_STR + "Stream.List(" + getDataType(vPtr->getTypePtr()) + (isRawOrString(vPtr->getTypePtr()) ? ", 1" : "") + ")"; + return IDL_NAMESPACE_STR + "Stream.List(" + getDataType(vPtr->getTypePtr(), bCastEnumAsAny) + representArgument(vPtr->getTypePtr()) + ")"; } StructPtr sPtr = StructPtr::dynamicCast(pPtr); @@ -130,20 +180,16 @@ string CodeGenerator::getDataType(const TypePtr & pPtr) MapPtr mPtr = MapPtr::dynamicCast(pPtr); if (mPtr) { - bool bLeft = isRawOrString(mPtr->getLeftTypePtr()); - bool bRight = isRawOrString(mPtr->getRightTypePtr()); + string sLeft = representArgument(mPtr->getLeftTypePtr()); + string sRight = representArgument(mPtr->getRightTypePtr()); - if (!bRight && !bLeft) { - return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ")"; - } else if (bRight && bLeft) { - return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 1, 1)"; - } else if (bRight) { - return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 0, 1)"; - } else if (bLeft) { - return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 1)"; - } else { - assert(false); + if (sLeft.empty() && !sRight.empty()) + { + sLeft = ", 0"; } + + return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr(), bCastEnumAsAny) + ", " + + getDataType(mPtr->getRightTypePtr(), bCastEnumAsAny) + sLeft + sRight + ")"; } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); @@ -151,15 +197,16 @@ string CodeGenerator::getDataType(const TypePtr & pPtr) { vector vecNames = TC_Common::sepstr(ePtr->getSid(), "::"); assert(vecNames.size() == 2); + string suffix = bCastEnumAsAny ? " as any" : ""; - return findName(vecNames[0], vecNames[1]); + return findName(vecNames[0], vecNames[1]) + suffix; } assert(false); return ""; } -string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) +string CodeGenerator::getTsType(const TypePtr &pPtr, const bool bStream, const bool bBase) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) @@ -167,13 +214,22 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) switch (bPtr->kind()) { case Builtin::KindBool : return "boolean"; - case Builtin::KindString : return _bStringBinaryEncoding ? (bStream ? (IDL_NAMESPACE_STR + "Stream.BinBuffer") : "Buffer") : "string"; + case Builtin::KindString : return _bStringBinaryEncoding ? "Buffer" : "string"; case Builtin::KindByte : return "number"; case Builtin::KindShort : return "number"; case Builtin::KindInt : return "number"; - case Builtin::KindLong : return _bUseStringRepresent ? "string" : "number"; case Builtin::KindFloat : return "number"; case Builtin::KindDouble : return "number"; + case Builtin::KindLong : + { + switch (_iLongType) + { + case CodeGenerator::Number : return "number"; + case CodeGenerator::String : return "string"; + case CodeGenerator::BigInt : return "bigint"; + default : assert(false); + } + } default : assert(false); } } @@ -186,7 +242,7 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) { return bStream ? (IDL_NAMESPACE_STR + "Stream.BinBuffer") : "Buffer"; } - return (bStream ? (IDL_NAMESPACE_STR + "Stream.List") : "Array") + string("<") + getDtsType(vPtr->getTypePtr(), bStream) + string(">"); + return (bStream ? (IDL_NAMESPACE_STR + "Stream.List") : "Array") + string("<") + getTsType(vPtr->getTypePtr(), bStream, bBase) + string(">"); } StructPtr sPtr = StructPtr::dynamicCast(pPtr); @@ -195,7 +251,7 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) vector vecNames = TC_Common::sepstr(sPtr->getSid(), "::"); assert(vecNames.size() == 2); - return findName(vecNames[0], vecNames[1]) + (bStream ? "" : "$OBJ"); + return findName(vecNames[0], vecNames[1], bBase) + (bStream ? "" : ".Object"); } MapPtr mPtr = MapPtr::dynamicCast(pPtr); @@ -203,20 +259,24 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) { if (bStream) { - return IDL_NAMESPACE_STR + "Stream.Map<" + getDtsType(mPtr->getLeftTypePtr(), bStream) + ", " + getDtsType(mPtr->getRightTypePtr(), bStream) + ">"; + // In current version (20190311) of the streaming library, + // TypeScript cannot infer enum type over conditional type correctly. + // So use `HeroMap` instead of `Map` to solve this problem. + EnumPtr keyTypePtr = EnumPtr::dynamicCast(mPtr->getLeftTypePtr()); + string mapName = keyTypePtr ? "HeroMap" : "Map"; + + return IDL_NAMESPACE_STR + "Stream." + mapName + "<" + getTsType(mPtr->getLeftTypePtr(), bStream) + ", " + getTsType(mPtr->getRightTypePtr(), bStream, bBase) + ">"; } else { - const string& sLeftType = getDtsType(mPtr->getLeftTypePtr(), bStream); - if (sLeftType == "number" || sLeftType == "string") + const string& sLeftType = getTsType(mPtr->getLeftTypePtr(), bStream, bBase); + const string& sRightType = getTsType(mPtr->getRightTypePtr(), bStream, bBase); + if (isSimple(mPtr->getLeftTypePtr())) { - return "{[key: " + getDtsType(mPtr->getLeftTypePtr(), bStream) + "]: " + getDtsType(mPtr->getRightTypePtr(), bStream) + "}"; + const string& recordKeyType = sLeftType == "number" ? "number" : "string"; + return "Record<" + recordKeyType + ", " + sRightType + ">"; } - else if (isSimple(mPtr->getLeftTypePtr()) && sLeftType != "Buffer") - { - return "object"; - } - else + else { return ""; } @@ -229,7 +289,7 @@ string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) vector vecNames = TC_Common::sepstr(ePtr->getSid(), "::"); assert(vecNames.size() == 2); - return findName(vecNames[0], vecNames[1]); + return findName(vecNames[0], vecNames[1], bBase); } assert(false); @@ -269,21 +329,16 @@ bool CodeGenerator::isBinBuffer(const TypePtr & pPtr) const return false; } -string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace) -{ - return getDefault(pPtr, sDefault, sNamespace, true); -} - -string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace, const bool bGlobal) +string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace, const bool &bGlobal, const bool &bCastEnumAsAny) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); if (bPtr) { switch (bPtr->kind()) { - case Builtin::KindBool : + case Builtin::KindBool : return sDefault.empty() ? "false" : sDefault; - case Builtin::KindString : + case Builtin::KindString : { if (_bStringBinaryEncoding) { @@ -308,13 +363,13 @@ string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, { if (TC_Common::tostr(TC_Common::strto(sTemp)) != sTemp) { - //有可能是枚举值,在枚举值中查找 + // lookup in the enum when it is a enum vector vecNames = TC_Common::sepstr(sDefault, "::"); if (vecNames.size() == 2) { sTemp = findName(vecNames[0], vecNames[1]); } - else + else { sTemp = findName(sNamespace, sDefault); } @@ -326,18 +381,27 @@ string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, sTemp = "0"; } - if (_bUseStringRepresent) + if (bPtr->kind() == Builtin::KindLong) { - if (bPtr->kind() == Builtin::KindLong) + switch (_iLongType) { - sTemp = "\"" + sTemp + "\""; + case CodeGenerator::String: + { + sTemp = "\"" + sTemp + "\""; + break; + } + case CodeGenerator::BigInt: + { + sTemp = sTemp + "n"; + break; + } } } return sTemp; } case Builtin::KindFloat : // [[fallthrough]] - case Builtin::KindDouble : + case Builtin::KindDouble : return sDefault.empty()?"0.0":sDefault; default : assert(false); @@ -384,7 +448,7 @@ string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, if (bGlobal) { - return "new " + getDataType(pPtr->getTypePtr()); + return "new " + getDataType(pPtr->getTypePtr(), bCastEnumAsAny); } return sDefault; diff --git a/tools/tars2node/main.cpp b/tools/tars2node/main.cpp index da808e8..55f4f00 100644 --- a/tools/tars2node/main.cpp +++ b/tools/tars2node/main.cpp @@ -26,21 +26,24 @@ void usage() { cout << "Version : " << GENERATOR_VERSION << endl; cout << "Usage : " << EXECUTE_FILENAME << " [OPTION] " << "*." << TC_Common::lower(IDL_TYPE) << " file" << endl; - cout << " --version print " << EXECUTE_FILENAME << " version" << endl; - cout << " --rpc-path=DIRECTORY specify the path of rpc module." << endl; - cout << " --stream-path=DIRECTORY specify the path of stream module." << endl; - cout << " --allow-reserved-namespace allow you to use reserved word as a namespace." << endl; - cout << " --dir=DIRECTORY generate source file to DIRECTORY." << endl; - cout << " --relative use current path." << endl; - cout << " --base=DIRECTORY where to search " << IDL_TYPE << " files." << endl; - cout << " --r generate source all " << IDL_TYPE << " files." << endl; - cout << " --r-minimal minimize the dependent members." << endl; - cout << " --r-reserved list of names(split by \",\") that should be keeped." << endl; - cout << " --client just for client side source file." << endl; - cout << " --server just for server side source file." << endl; - cout << " --dts generate d.ts file." << endl; - cout << " --use-string-represent use string represent long type." << endl; - cout << " --string-binary-encoding get string raw bytes ." << endl; + cout << " --version print " << EXECUTE_FILENAME << " version" << endl; + cout << " --rpc-path=[DIRECTORY] specify the path of rpc module." << endl; + cout << " --stream-path=[DIRECTORY] specify the path of stream module." << endl; + cout << " --allow-reserved-namespace allow you to use reserved word as a namespace." << endl; + cout << " --dir=DIRECTORY generate source file to DIRECTORY." << endl; + cout << " --relative use current path." << endl; + cout << " --base=DIRECTORY where to search " << IDL_TYPE << " files." << endl; + cout << " --r generate source all " << IDL_TYPE << " files." << endl; + cout << " --r-minimal minimize the dependent members." << endl; + cout << " --r-reserved list of names(split by \",\") that should be keeped." << endl; + cout << " --client just for client side source file." << endl; + cout << " --server just for server side source file." << endl; + cout << " --ts generate typescript file." << endl; + cout << " --dts generate d.ts file." << endl; + cout << " --long-type=[number|string|bigint] use represent type, default is ." << endl; + cout << " --string-binary-encoding get string raw bytes ." << endl; + cout << " --enum-reverse-mappings reverse mapping from enum values to enum names." << endl; + cout << " --optimize=[0|s] support \"s\" to reduce code size, default is 0." << endl; cout << endl; cout << EXECUTE_FILENAME << " support type: boolean char short int long float double list map" << endl; @@ -128,10 +131,38 @@ int main(int argc, char* argv[]) generator.setEnableServer(option.hasParam("server")); generator.setTargetPath(option.hasParam("dir")?option.getValue("dir"):"./"); generator.setUseSpecialPath(option.hasParam("relative")); - generator.setUseStringRepresent(option.hasParam("use-string-represent")); generator.setStringBinaryEncoding(option.hasParam("string-binary-encoding")); + generator.setEnumReverseMappings(option.hasParam("enum-reverse-mappings")); + generator.setEnableTS(option.hasParam("ts")); generator.setEnableDTS(option.hasParam("dts")); + if (option.hasParam("long-type")) + { + string longType = TC_Common::lower(option.getValue("long-type")); + if (longType == "string") + { + generator.setLongType(CodeGenerator::String); + } + else if (longType == "bigint") + { + generator.setLongType(CodeGenerator::BigInt); + } + + } + + if (option.hasParam("optimize")) + { + string level = TC_Common::lower(option.getValue("optimize")); + if (level == "s") + { + generator.setOptimize(CodeGenerator::Os); + } + else + { + generator.setOptimize(CodeGenerator::O0); + } + } + bool _bRecursive = option.hasParam("r"); bool _bMinimalMembers = option.hasParam("r-minimal");