gen_proxy_ts.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. #include "code_generator.h"
  17. #define INVOKE_RETURN(protocol, prefix, params) \
  18. str << TAB << "return this._worker." << TC_Common::lower(protocol) << "_invoke(\"" << oPtr->getId() << "\", "; \
  19. str << prefix << "." << TC_Common::lower(protocol) << "Encoder"; \
  20. str << "(" << sParams << params << "), options, " << prefix << ").then("; \
  21. str << prefix << "." << TC_Common::lower(protocol) << "Decoder, "; \
  22. str << prefix << ".errorResponser);" << endl;
  23. #define PROTOCOL_PARAMS (sParams.empty() ? "" : ", ") << "version"
  24. struct SortOperation
  25. {
  26. bool operator()(const OperationPtr &o1, const OperationPtr &o2)
  27. {
  28. return o1->getId() < o2->getId();
  29. }
  30. };
  31. string CodeGenerator::generateTSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr)
  32. {
  33. ostringstream str;
  34. vector<ParamDeclPtr> & vParamDecl = oPtr->getAllParamDeclPtr();
  35. bool bHasParamOut = false;
  36. string sParams = "";
  37. string sParamsWithType = "";
  38. for (size_t i = 0; i < vParamDecl.size(); i++)
  39. {
  40. if (vParamDecl[i]->isOut())
  41. {
  42. continue;
  43. }
  44. sParams += (sParams.empty() ? "" : ", ")
  45. + vParamDecl[i]->getTypeIdPtr()->getId();
  46. sParamsWithType += (sParamsWithType.empty() ? "" : ", ")
  47. + vParamDecl[i]->getTypeIdPtr()->getId()
  48. + ": "
  49. + getTsType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
  50. }
  51. // generate function metadata (SharedFunctionInfo)
  52. str << TAB << "static " << oPtr->getId() << " = _castFunctionInfo({" << endl;
  53. INC_TAB;
  54. str << TAB << "name: \"" << oPtr->getId() << "\"," << endl;
  55. str << TAB << "return: \"" << getClassName(oPtr->getReturnPtr()->getTypePtr()) << "\"," << endl;
  56. str << TAB << "arguments: [";
  57. for (size_t i = 0; i < vParamDecl.size(); i++)
  58. {
  59. str << (i > 0 ? ", {" : "{") << endl;
  60. INC_TAB;
  61. str << TAB << "name: \"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"," << endl;
  62. str << TAB << "class: \"" << getClassName(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << "\"," << endl;
  63. if (vParamDecl[i]->isOut())
  64. {
  65. bHasParamOut = true;
  66. str << TAB << "direction: \"out\"" << endl;
  67. }
  68. else
  69. {
  70. str << TAB << "direction: \"in\"" << endl;
  71. }
  72. DEL_TAB;
  73. str << TAB << "}";
  74. }
  75. str << "]," << endl;
  76. // generate IDL Encoder ($IE)
  77. str << TAB << TC_Common::lower(IDL_NAMESPACE_STR) << "Encoder(" << sParamsWithType << ") {" << endl;
  78. INC_TAB;
  79. str << TAB << "const os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl;
  80. for (size_t i = 0; i < vParamDecl.size(); i++)
  81. {
  82. if (vParamDecl[i]->isOut()) continue;
  83. str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "("
  84. << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId()
  85. << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl;
  86. // push the symbol into dependent list
  87. getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
  88. }
  89. str << TAB << "return os.getBinBuffer();" << endl;
  90. DEL_TAB;
  91. str << TAB << "}," << endl;
  92. // generate IDL Decoder ($ID)
  93. str << TAB << TC_Common::lower(IDL_NAMESPACE_STR) << "Decoder(data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse) {" << endl;
  94. INC_TAB;
  95. str << TAB << "try {" << endl;
  96. INC_TAB;
  97. if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut)
  98. {
  99. str << TAB << "var is = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream(data.response.sBuffer);" << endl;
  100. }
  101. str << TAB << "return {" << endl;
  102. INC_TAB;
  103. str << TAB << "request: data.request," << endl;
  104. str << TAB << "response: {" << endl;
  105. INC_TAB;
  106. str << TAB << "costtime: data.request.costtime," << endl;
  107. str << TAB << "return: ";
  108. if (oPtr->getReturnPtr()->getTypePtr())
  109. {
  110. str << "is." << toFunctionName(oPtr->getReturnPtr(), "read") << "(0, true, ";
  111. if (isSimple(oPtr->getReturnPtr()->getTypePtr()))
  112. {
  113. str << getDefault(oPtr->getReturnPtr(), oPtr->getReturnPtr()->def(), nPtr->getId(), true, true)
  114. << representArgument(oPtr->getReturnPtr()->getTypePtr());
  115. }
  116. else
  117. {
  118. str << getDataType(oPtr->getReturnPtr()->getTypePtr(), true);
  119. }
  120. str << ")," << endl;
  121. }
  122. else
  123. {
  124. str << "undefined as undefined," << endl;
  125. }
  126. str << TAB << "arguments: ";
  127. if (bHasParamOut)
  128. {
  129. str << "{" << endl;
  130. INC_TAB;
  131. for (size_t i = 0; i < vParamDecl.size(); i++)
  132. {
  133. if (!vParamDecl[i]->isOut()) continue;
  134. str << TAB << vParamDecl[i]->getTypeIdPtr()->getId()
  135. << ": is." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") << "(" << (i + 1) << ", true, ";
  136. if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()))
  137. {
  138. str << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId(), true, true)
  139. << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
  140. }
  141. else
  142. {
  143. str << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr(), true);
  144. }
  145. str << ")";
  146. if (i == vParamDecl.size() - 1)
  147. {
  148. str << endl;
  149. }
  150. else
  151. {
  152. str << "," << endl;
  153. }
  154. }
  155. DEL_TAB;
  156. str << TAB << "}" << endl;
  157. }
  158. else
  159. {
  160. str << "undefined as undefined" << endl;
  161. }
  162. DEL_TAB;
  163. str << TAB << "}" << endl;
  164. DEL_TAB;
  165. str << TAB << "};" << endl;
  166. DEL_TAB;
  167. str << TAB << "} catch (e) {" << endl;
  168. INC_TAB;
  169. str << TAB << "throw _makeError(data, e.message, " << IDL_NAMESPACE_STR << "Rpc.error.CLIENT.DECODE_ERROR);" << endl;
  170. DEL_TAB;
  171. str << TAB << "}" << endl;
  172. DEL_TAB;
  173. str << TAB << "}," << endl;
  174. // generate Protocol Encoder ($PE)
  175. str << TAB << TC_Common::lower(PROTOCOL_VAR) << "Encoder(" << sParamsWithType << (sParamsWithType.empty() ? "" : ", ") << "__$PROTOCOL$VERSION: number) {" << endl;
  176. INC_TAB;
  177. str << TAB << "const " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl;
  178. str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = __$PROTOCOL$VERSION;" << endl;
  179. for (size_t i = 0; i < vParamDecl.size(); i++)
  180. {
  181. if (vParamDecl[i]->isOut()) continue;
  182. str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\""
  183. << vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId()
  184. << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl;
  185. // push the symbol into dependent list
  186. getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
  187. }
  188. str << TAB << "return " << PROTOCOL_VAR << ";" << endl;
  189. DEL_TAB;
  190. str << TAB << "}," << endl;
  191. // generate Protocol Decoder ($PD)
  192. str << TAB << TC_Common::lower(PROTOCOL_VAR) << "Decoder(data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse) {" << endl;
  193. INC_TAB;
  194. str << TAB << "try {" << endl;
  195. INC_TAB;
  196. if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut) {
  197. str << TAB << "const " << PROTOCOL_VAR << ": " << IDL_NAMESPACE_STR << "Stream.UniAttribute = (data.response as any)." << PROTOCOL_VAR << ";" << endl;
  198. }
  199. str << TAB << "return {" << endl;
  200. INC_TAB;
  201. str << TAB << "request: data.request," << endl;
  202. str << TAB << "response: {" << endl;
  203. INC_TAB;
  204. str << TAB << "costtime: data.request.costtime," << endl;
  205. str << TAB << "return: ";
  206. if (oPtr->getReturnPtr()->getTypePtr())
  207. {
  208. str << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "read") << "(\"\"";
  209. if (!isSimple(oPtr->getReturnPtr()->getTypePtr()) && !isBinBuffer(oPtr->getReturnPtr()->getTypePtr()))
  210. {
  211. str << ", " << getDataType(oPtr->getReturnPtr()->getTypePtr(), true);
  212. }
  213. str << ", " << getDefault(oPtr->getReturnPtr(), "", nPtr->getId(), true, true)
  214. << representArgument(oPtr->getReturnPtr()->getTypePtr());
  215. str << ")," << endl;
  216. }
  217. else
  218. {
  219. str << "undefined as undefined," << endl;
  220. }
  221. str << TAB << "arguments: ";
  222. if (bHasParamOut)
  223. {
  224. str << "{" << endl;
  225. INC_TAB;
  226. for (size_t i = 0; i < vParamDecl.size(); i++)
  227. {
  228. if (!vParamDecl[i]->isOut()) continue;
  229. str << TAB << vParamDecl[i]->getTypeIdPtr()->getId() << ": "
  230. << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read")
  231. << "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"";
  232. if (!isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) && !isBinBuffer(vParamDecl[i]->getTypeIdPtr()->getTypePtr()))
  233. {
  234. str << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr(), true);
  235. }
  236. str << ")";
  237. if (i == vParamDecl.size() - 1)
  238. {
  239. str << endl;
  240. }
  241. else
  242. {
  243. str << "," << endl;
  244. }
  245. }
  246. DEL_TAB;
  247. str << TAB << "}" << endl;
  248. }
  249. else
  250. {
  251. str << "undefined as undefined" << endl;
  252. }
  253. DEL_TAB;
  254. str << TAB << "}" << endl;
  255. DEL_TAB;
  256. str << TAB << "};" << endl;
  257. DEL_TAB;
  258. str << TAB << "} catch (e) {" << endl;
  259. INC_TAB;
  260. str << TAB << "throw _makeError(data, e.message, " << IDL_NAMESPACE_STR << "Rpc.error.CLIENT.DECODE_ERROR);" << endl;
  261. DEL_TAB;
  262. str << TAB << "}" << endl;
  263. DEL_TAB;
  264. str << TAB << "}," << endl;
  265. // generate error handler ($ER)
  266. str << TAB << "errorResponser(data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse) {" << endl;
  267. INC_TAB;
  268. str << TAB << "throw _makeError(data, \"Call " << pPtr->getId() << "::" << oPtr->getId() << " failed\");" << endl;
  269. DEL_TAB;
  270. str << TAB << "}" << endl;
  271. DEL_TAB;
  272. str << TAB << "})" << endl << endl; // end of metadata
  273. // generate function body
  274. str << TAB << oPtr->getId() << "(" << sParamsWithType << (sParamsWithType.empty() ? "" : ", ") << "options?: " << IDL_NAMESPACE_STR << "Rpc.InvokeProperty) {" << endl;
  275. INC_TAB;
  276. string sFuncFullName = pPtr->getId() + "Proxy." + oPtr->getId();
  277. str << TAB << "const version = this._worker.version;" << endl;
  278. str << TAB << "if (version === " << PROTOCOL_SIMPLE << " || version === " << PROTOCOL_COMPLEX << ") {" << endl;
  279. INC_TAB;
  280. INVOKE_RETURN(PROTOCOL_VAR, sFuncFullName, PROTOCOL_PARAMS);
  281. DEL_TAB;
  282. str << TAB << "} else {" << endl;
  283. INC_TAB;
  284. INVOKE_RETURN(IDL_NAMESPACE_STR, sFuncFullName, "");
  285. DEL_TAB;
  286. str << TAB << "}" << endl;
  287. DEL_TAB;
  288. str << TAB << "}" << endl << endl;
  289. return str.str();
  290. }
  291. string CodeGenerator::generateTSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr)
  292. {
  293. ostringstream str;
  294. vector<OperationPtr> & vOperation = pPtr->getAllOperationPtr();
  295. sort(vOperation.begin(), vOperation.end(), SortOperation());
  296. for (size_t i = 0; i < vOperation.size(); i++)
  297. {
  298. str << generateTSProxy(nPtr, pPtr, vOperation[i]);
  299. }
  300. return str.str();
  301. }
  302. string CodeGenerator::generateTSProxy(const NamespacePtr &nPtr, bool &bNeedStream, bool &bNeedRpc)
  303. {
  304. ostringstream str;
  305. vector<InterfacePtr> &is = nPtr->getAllInterfacePtr();
  306. if (is.size() > 0)
  307. {
  308. bNeedStream = true;
  309. bNeedRpc = true;
  310. }
  311. for (size_t i = 0; i < is.size(); i++)
  312. {
  313. str << TAB << "export class " << is[i]->getId() << "Proxy {" << endl;
  314. INC_TAB;
  315. str << TAB << "protected _name!: string" << endl;
  316. str << TAB << "protected _worker!: " << IDL_NAMESPACE_STR << "Rpc.ObjectProxy" << endl << endl;
  317. str << TAB << "setTimeout (iTimeout: number) { this._worker.timeout = iTimeout; }" << endl;
  318. str << TAB << "getTimeout () { return this._worker.timeout; }" << endl;
  319. str << TAB << "setVersion (iVersion: number) { this._worker.version = iVersion; }" << endl;
  320. str << TAB << "getVersion () { return this._worker.version; }" << endl << endl;
  321. str << generateTSProxy(nPtr, is[i]) << endl;
  322. DEL_TAB;
  323. str << TAB << "}" << endl << endl;
  324. }
  325. return str.str();
  326. }
  327. bool CodeGenerator::generateTSProxy(const ContextPtr &cPtr)
  328. {
  329. vector<NamespacePtr> namespaces = cPtr->getNamespaces();
  330. // generate proxy classes with encoders and decoders
  331. ostringstream estr;
  332. bool bNeedStream = false;
  333. bool bNeedRpc = false;
  334. bool bNeedAssert = false;
  335. bool bQuickFunc = false;
  336. for(size_t i = 0; i < namespaces.size(); i++)
  337. {
  338. ostringstream kstr;
  339. kstr << generateTS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc);
  340. INC_TAB;
  341. kstr << generateTSProxy(namespaces[i], bNeedStream, bNeedRpc);
  342. DEL_TAB;
  343. estr << generateTS(namespaces[i], kstr.str());
  344. }
  345. if (estr.str().empty())
  346. {
  347. return false;
  348. }
  349. // generate module imports
  350. ostringstream sstr;
  351. sstr << printHeaderRemark("Client");
  352. sstr << DISABLE_TSLINT << endl;
  353. sstr << DISABLE_ESLINT << endl;
  354. sstr << endl;
  355. sstr << "/// <reference types=\"node\" />" << endl;
  356. if (bNeedAssert)
  357. {
  358. sstr << TAB << "import assert = require(\"assert\");" << endl;
  359. }
  360. if (bNeedStream)
  361. {
  362. sstr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl;
  363. }
  364. if (bNeedRpc)
  365. {
  366. sstr << "import * as " << IDL_NAMESPACE_STR << "Rpc from \"" << _sRpcPath << "\";" << endl;
  367. }
  368. for (map<string, ImportFile>::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++)
  369. {
  370. if (it->second.sModule.empty()) continue;
  371. if (estr.str().find(it->second.sModule + ".") == string::npos) continue;
  372. sstr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl;
  373. }
  374. // generate helper functions
  375. if (bQuickFunc || bNeedRpc)
  376. {
  377. sstr << endl;
  378. }
  379. if (bQuickFunc)
  380. {
  381. sstr << "const _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl;
  382. }
  383. if (bNeedRpc)
  384. {
  385. sstr << TAB << "function _castFunctionInfo<Ret, Arg>(data: SharedFunctionInfo<Ret, Arg>) { return data; }" << endl;
  386. sstr << TAB << "function _makeError(data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse, message: string, type?: number): " << IDL_NAMESPACE_STR << "Rpc.RpcError {" << endl;
  387. INC_TAB;
  388. sstr << TAB << "var error: any = new Error(message || \"\");" << endl;
  389. sstr << TAB << "error.request = data.request;" << endl;
  390. sstr << TAB << "error.response = {" << endl;
  391. INC_TAB;
  392. sstr << TAB << "costtime: data.request.costtime" << endl;
  393. DEL_TAB;
  394. sstr << TAB << "};" << endl;
  395. sstr << TAB << "if (type === " << IDL_NAMESPACE_STR << "Rpc.error.CLIENT.DECODE_ERROR) {" << endl;
  396. INC_TAB;
  397. sstr << TAB << "error.name = \"DECODE_ERROR\";" << endl;
  398. sstr << TAB << "error.response.error = {" << endl;
  399. INC_TAB;
  400. sstr << TAB << "code: type," << endl;
  401. sstr << TAB << "message: message" << endl;
  402. DEL_TAB;
  403. sstr << TAB << "};" << endl;
  404. DEL_TAB;
  405. sstr << TAB << "} else {" << endl;
  406. INC_TAB;
  407. sstr << TAB << "error.name = \"RPC_ERROR\";" << endl;
  408. sstr << TAB << "error.response.error = data.error;" << endl;
  409. DEL_TAB;
  410. sstr << TAB << "}" << endl;
  411. sstr << TAB << "return error;" << endl;
  412. DEL_TAB;
  413. sstr << TAB << "}" << endl << endl;
  414. sstr << "export interface SharedFunctionInfo<Ret = any, Arg = any> extends " << IDL_NAMESPACE_STR << "Rpc.SharedFunctionInfo {" << endl;
  415. INC_TAB;
  416. sstr << TAB << TC_Common::lower(IDL_NAMESPACE_STR) << "Encoder (...args: any[]): " << IDL_NAMESPACE_STR << "Stream.BinBuffer," << endl;
  417. sstr << TAB << TC_Common::lower(IDL_NAMESPACE_STR) << "Decoder (data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse): " << IDL_NAMESPACE_STR << "Rpc.ProxyResponse<Ret, Arg>," << endl;
  418. sstr << TAB << TC_Common::lower(PROTOCOL_VAR) << "Encoder (...args: any[]): " << IDL_NAMESPACE_STR << "Stream.UniAttribute," << endl;
  419. sstr << TAB << TC_Common::lower(PROTOCOL_VAR) << "Decoder (data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse): " << IDL_NAMESPACE_STR << "Rpc.ProxyResponse<Ret, Arg>," << endl;
  420. sstr << TAB << "errorResponser (data: " << IDL_NAMESPACE_STR << "Rpc.RpcResponse): never" << endl;
  421. DEL_TAB;
  422. sstr << TAB << "}" << endl << endl;
  423. }
  424. sstr << estr.str() << endl;
  425. string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(cPtr->getFileName())) + "Proxy.ts";
  426. TC_File::makeDirRecursive(_sToPath);
  427. makeUTF8File(sFileName, sstr.str());
  428. return true;
  429. }