123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- /**
- * Tencent is pleased to support the open source community by making Tars available.
- *
- * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
- *
- * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * https://opensource.org/licenses/BSD-3-Clause
- *
- * Unless required by applicable law or agreed to in writing, software distributed
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
- #include "code_generator.h"
- string CodeGenerator::generateTSServerAsync(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr)
- {
- ostringstream str;
- string sParams = "";
- int rspNum = 0;
- if (oPtr->getReturnPtr()->getTypePtr())
- {
- sParams += "_ret: " + getTsType(oPtr->getReturnPtr()->getTypePtr());
- // push the symbol into dependent list
- getDataType(oPtr->getReturnPtr()->getTypePtr());
- ++rspNum;
- }
- vector<ParamDeclPtr> &vParamDecl = oPtr->getAllParamDeclPtr();
- for (size_t i = 0; i < vParamDecl.size(); i++)
- {
- if (!vParamDecl[i]->isOut())
- continue;
- sParams += (sParams.empty() ? "" : ", ") + vParamDecl[i]->getTypeIdPtr()->getId();
- sParams += ": " + getTsType(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
- ++rspNum;
- }
- str << TAB << "protected static __" << oPtr->getId() << "_responser(this: " << IDL_NAMESPACE_STR << "Rpc.TarsCurrent, " << sParams << ") {" << endl;
- INC_TAB;
- if (sParams.empty())
- {
- str << TAB << "this.doResponse(new " << IDL_NAMESPACE_STR << "Stream.BinBuffer());" << endl;
- DEL_TAB;
- str << TAB << "}" << endl;
- return str.str();
- }
- str << TAB << "if (this.getRequestVersion() === " << PROTOCOL_SIMPLE << " || this.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl;
- INC_TAB;
- str << TAB << "const " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl;
- str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = this.getRequestVersion();" << endl;
- if (oPtr->getReturnPtr()->getTypePtr())
- {
- str << TAB << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "write") << "(\"\", _ret"
- << representArgument(oPtr->getReturnPtr()->getTypePtr()) << ");" << 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;
- }
- str << endl;
- str << TAB << "this.doResponse(" << PROTOCOL_VAR << ".encode());" << endl;
- DEL_TAB;
- //// ========= 增加对 JSON_VERSION 支持
- str << TAB << "} else if (this.getRequestVersion() === " << PROTOCOL_JSON << ") {" << endl;
- INC_TAB;
- str << TAB << "const _data_ = {" << endl;
- INC_TAB;
- if (oPtr->getReturnPtr()->getTypePtr())
- {
- str << TAB << "\"tars_ret\": _ret";
- --rspNum;
- if (rspNum > 0)
- {
- str << ", " << endl;
- }
- }
- for (size_t i = 0; i < vParamDecl.size(); i++)
- {
- if (!vParamDecl[i]->isOut())
- continue;
- str << TAB << "\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\": " << toObjectString(vParamDecl[i]->getTypeIdPtr());
- --rspNum;
- if (rspNum > 0)
- {
- str << ", " << endl;
- }
- }
- DEL_TAB;
- str << endl;
- str << TAB << "};" << endl;
- str << endl;
- str << TAB << "this.doResponse(new TarsStream.BinBuffer(Buffer.from(JSON.stringify(_data_))));" << endl;
- DEL_TAB;
- //// =========
-
- str << TAB << "} else {" << endl;
- INC_TAB;
- str << TAB << "const os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl;
- if (oPtr->getReturnPtr()->getTypePtr())
- {
- str << TAB << "os." << toFunctionName(oPtr->getReturnPtr(), "write") << "(0, _ret"
- << representArgument(oPtr->getReturnPtr()->getTypePtr()) << ");" << endl;
- }
- for (size_t i = 0; i < vParamDecl.size(); i++)
- {
- if (!vParamDecl[i]->isOut())
- continue;
- str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "("
- << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId()
- << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ");" << endl;
- }
- str << endl;
- str << TAB << "this.doResponse(os.getBinBuffer());" << endl;
- DEL_TAB;
- str << TAB << "}" << endl;
- DEL_TAB;
- str << TAB << "}" << endl;
- return str.str();
- }
- string CodeGenerator::generateTSServerDispatch(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr)
- {
- ostringstream str;
- vector<ParamDeclPtr> & vParamDecl = oPtr->getAllParamDeclPtr();
- str << TAB << "protected __" << oPtr->getId() << "(current: " << IDL_NAMESPACE_STR << "Rpc.TarsCurrent";
- if (vParamDecl.size() != 0) str << ", binBuffer: " << IDL_NAMESPACE_STR << "Stream.BinBuffer";
- str << ") {" << endl;
- INC_TAB;
- ostringstream dstr;
- for (size_t i = 0; i < vParamDecl.size(); i++)
- {
- dstr << TAB << "let " << vParamDecl[i]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ";" << endl;
- }
- if (vParamDecl.size() != 0)
- {
- dstr << endl;
- }
- dstr << TAB << "if (current.getRequestVersion() === " << PROTOCOL_SIMPLE << " || current.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl;
- INC_TAB;
- dstr << TAB << "const " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl;
- dstr << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = current.getRequestVersion();" << endl;
- dstr << TAB << PROTOCOL_VAR << ".decode(binBuffer);" << endl;
- for (size_t i = 0; i < vParamDecl.size(); i++)
- {
- dstr << 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()))
- {
- dstr << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr(), true);
- }
- if (vParamDecl[i]->isOut())
- {
- dstr << ", " << getDefault(vParamDecl[i]->getTypeIdPtr(), "", nPtr->getId(), true, true)
- << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
- }
- dstr << ");" << endl;
- }
- DEL_TAB;
- //// ========= 增加对 JSON_VERSION 支持
- dstr << TAB << "} else if (current.getRequestVersion() === " << PROTOCOL_JSON << ") {" << endl;
- INC_TAB;
- dstr << TAB << "const _data_ = JSON.parse(binBuffer.toNodeBuffer().toString());" << endl;
- for (size_t i = 0; i < vParamDecl.size(); i++)
- {
- if (vParamDecl[i]->isOut())
- {
- StructPtr sPtr = StructPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
- VectorPtr vPtr = VectorPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
- MapPtr mPtr = MapPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
- if (sPtr || vPtr || mPtr)
- {
- dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId()
- << " = " << getDefault(vParamDecl[i]->getTypeIdPtr(), "", nPtr->getId(), true)
- << ";" << endl;
- dstr << TAB << "_data_." << vParamDecl[i]->getTypeIdPtr()->getId() << " ? " << vParamDecl[i]->getTypeIdPtr()->getId() << ".readFromObject("
- << "_data_." << vParamDecl[i]->getTypeIdPtr()->getId() << ") : " << vParamDecl[i]->getTypeIdPtr()->getId()
- << ";" << endl;
- }
- else
- {
- dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId()
- << " = _data_." << vParamDecl[i]->getTypeIdPtr()->getId() << " || " << getDefault(vParamDecl[i]->getTypeIdPtr(), "", nPtr->getId(), true)
- << ";" << endl;
- }
- }
- else
- {
- StructPtr sPtr = StructPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
- VectorPtr vPtr = VectorPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
- MapPtr mPtr = MapPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
- if (sPtr || vPtr || mPtr)
- {
- dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId()
- << " = " << getDefault(vParamDecl[i]->getTypeIdPtr(), "", nPtr->getId(), true)
- << ";" << endl;
- dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId() << ".readFromObject("
- << "_data_." << vParamDecl[i]->getTypeIdPtr()->getId() << ")"
- << ";" << endl;
- }
- else
- {
- dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId()
- << " = _data_." << vParamDecl[i]->getTypeIdPtr()->getId()
- << ";" << endl;
- }
- }
- }
- DEL_TAB;
- //// =========
- dstr << TAB << "} else {" << endl;
- INC_TAB;
- dstr << TAB << "const is = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream(binBuffer);" << endl;
- string sParams = "";
- for (size_t i = 0; i < vParamDecl.size(); i++)
- {
- sParams += ", " + vParamDecl[i]->getTypeIdPtr()->getId();
- dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId()
- << " = is." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") << "("
- << (i + 1) << ", " << (vParamDecl[i]->isOut() ? "false" : "true") << ", ";
- if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()))
- {
- dstr << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId(), true, true)
- << representArgument(vParamDecl[i]->getTypeIdPtr()->getTypePtr());
- }
- else
- {
- dstr << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr(), true);
- }
- dstr << ");" << endl;
- }
- DEL_TAB;
- dstr << TAB << "}" << endl << endl;
- if (!sParams.empty())
- {
- str << dstr.str();
- }
- str << TAB << "current.sendResponse = " << pPtr->getId() << "Imp.__" << oPtr->getId() << "_responser;" << endl << endl;
- str << TAB << "this." << oPtr->getId() << "(current" << sParams << ");" << endl << endl;
- str << TAB << "return " << IDL_NAMESPACE_STR << "Rpc.error.SUCCESS;" << endl;
- DEL_TAB;
- str << TAB << "}" << endl;
- return str.str();
- }
- string CodeGenerator::generateTSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert)
- {
- ostringstream str;
- vector<InterfacePtr> & is = pPtr->getAllInterfacePtr();
- for (size_t i = 0; i < is.size(); i++)
- {
- str << generateTSServer(is[i], pPtr) << endl;
- }
- if (is.size() != 0)
- {
- bNeedRpc = true;
- bNeedStream = true;
- bNeedAssert = true;
- }
- return str.str();
- }
- string CodeGenerator::generateTSServer(const InterfacePtr &pPtr, const NamespacePtr &nPtr)
- {
- ostringstream str;
- vector<OperationPtr> & vOperation = pPtr->getAllOperationPtr();
- // generate the implementation class
- str << TAB << "export abstract class " << pPtr->getId() << "Imp { " << endl;
- INC_TAB;
- str << TAB << "_name!: string" << endl;
- str << TAB << "_worker!: any" << endl << endl;
- // generate the initialize function
- str << TAB << "initialize(): PromiseLike<any> | void {}" << endl << endl;
- // generate the dispatch function
- str << TAB << "onDispatch(current: " << IDL_NAMESPACE_STR << "Rpc.TarsCurrent, funcName: string, binBuffer: " << IDL_NAMESPACE_STR << "Stream.BinBuffer) { " << endl;
- INC_TAB;
- str << TAB << "if (\"__\" + funcName in this) {" << endl;
- INC_TAB;
- str << TAB << "return (this as any)[\"__\" + funcName](current, binBuffer);" << endl;
- DEL_TAB;
- str << TAB << "} else {" << endl;
- INC_TAB;
- str << TAB << "return " << IDL_NAMESPACE_STR << "Rpc.error.SERVER.FUNC_NOT_FOUND;" << endl;
- DEL_TAB;
- str << TAB << "}" << endl;
- DEL_TAB;
- str << TAB << "}" << endl << endl;
- // generate the ping function
- str << TAB << "__" << TC_Common::lower(IDL_NAMESPACE_STR) << "_ping(current: " << IDL_NAMESPACE_STR << "Rpc.TarsCurrent) { " << endl;
- INC_TAB;
- str << TAB << "const _ret = 0;" << endl;
- str << TAB << "if (current.getRequestVersion() === " << PROTOCOL_SIMPLE << " || current.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl;
- INC_TAB;
- str << TAB << "const " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl;
- str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = current.getRequestVersion();" << endl;
- str << TAB << PROTOCOL_VAR << ".writeInt32(\"\", _ret);" << endl << endl;
- str << TAB << "current.doResponse(" << PROTOCOL_VAR << ".encode());" << endl;
- DEL_TAB;
- str << TAB << "} else {" << endl;
- INC_TAB;
- str << TAB << "const os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl;
- str << TAB << "os.writeInt32(0, _ret);" << endl << endl;
- str << TAB << "current.doResponse(os.getBinBuffer());" << endl;
- DEL_TAB;
- str << TAB << "}" << endl << endl;
- str << TAB << "return " << IDL_NAMESPACE_STR << "Rpc.error.SUCCESS;" << endl;
- DEL_TAB;
- str << TAB << "}" << endl << endl;
- // generate functions
- for (size_t i = 0; i < vOperation.size(); i++)
- {
- const OperationPtr &oPtr = vOperation[i];
- // generate function definition
- str << TAB << oPtr->getId() << "(current: " << pPtr->getId() << "Imp." << oPtr->getId() << "Current";
- vector<ParamDeclPtr> &vParamDecl = oPtr->getAllParamDeclPtr();
- for (size_t j = 0; j < vParamDecl.size(); j++)
- {
- str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr());
- }
- str << "): any { " << endl;
- INC_TAB;
- str << TAB << "assert.fail(\"" << oPtr->getId() << " function not implemented\");" << endl;
- DEL_TAB;
- str << TAB << "}" << endl << endl;
- // generate encoder and decoder
- str << generateTSServerAsync(nPtr, pPtr, vOperation[i]) << endl;
- str << generateTSServerDispatch(nPtr, pPtr, vOperation[i]) << endl;
- }
- DEL_TAB;
- str << TAB << "}" << endl << endl; // end of class
- // generate additional namespaces
- str << TAB << "export namespace " << pPtr->getId() << "Imp {" << endl;
- INC_TAB;
- for (size_t i = 0; i < vOperation.size(); i++)
- {
- OperationPtr &oPtr = vOperation[i];
- str << TAB << "export interface " << oPtr->getId() << "Current extends " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current {" <<endl;
- INC_TAB;
- str << TAB;
- if (oPtr->getReturnPtr()->getTypePtr())
- {
- str << "sendResponse(ret: " << getTsType(oPtr->getReturnPtr()->getTypePtr());
- vector<ParamDeclPtr> &vParamDecl = oPtr->getAllParamDeclPtr();
- for (size_t j = 0; j < vParamDecl.size(); j++)
- {
- if(!vParamDecl[j]->isOut()) {
- continue;
- }
- str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getTsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) ;
- }
- str << "): void;" << endl;
- }
- else
- {
- str << "sendResponse(): void;" << endl;
- }
- DEL_TAB;
- str << TAB << "}" << endl;
- }
- DEL_TAB;
- str << TAB << "}" << endl;
- return str.str();
- }
- bool CodeGenerator::generateTSServer(const ContextPtr &pPtr)
- {
- vector<NamespacePtr> namespaces = pPtr->getNamespaces();
- // generate server classes with encoders and decoders
- ostringstream estr;
- bool bNeedStream = false;
- bool bNeedRpc = false;
- bool bNeedAssert = false;
- bool bQuickFunc = false;
- for(size_t i = 0; i < namespaces.size(); i++)
- {
- ostringstream kstr;
- kstr << generateTS(namespaces[i], bNeedStream, bNeedAssert, bQuickFunc);
- INC_TAB;
- kstr << generateTSServer(namespaces[i], bNeedStream, bNeedRpc, bNeedAssert);
- DEL_TAB;
- estr << generateTS(namespaces[i], kstr.str());
- }
- if (estr.str().empty())
- {
- return false;
- }
- ostringstream str;
- // generate the source file
- str << printHeaderRemark("Server");
- str << DISABLE_TSLINT << endl;
- str << DISABLE_ESLINT << endl;
- str << endl;
- str << "/// <reference types=\"node\" />" << endl;
- if (bNeedAssert)
- {
- str << TAB << "import assert = require(\"assert\");" << endl;
- }
- if (bNeedStream)
- {
- str << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl;
- }
- if (bNeedRpc)
- {
- str << "import * as " << IDL_NAMESPACE_STR << "Rpc from \"" << _sRpcPath << "\";" << endl;
- }
- for (map<string, ImportFile>::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++)
- {
- if (it->second.sModule.empty()) continue;
- if (estr.str().find(it->second.sModule + ".") == string::npos) continue;
- str << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl;
- }
- if (bQuickFunc)
- {
- str << endl;
- str << TAB << "const _hasOwnProperty = Object.prototype.hasOwnProperty;" << endl;
- }
- str << endl << estr.str() << endl;
- string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + ".ts";
- TC_File::makeDirRecursive(_sToPath);
- makeUTF8File(sFileName, str.str());
- return true;
- }
|