• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
2/*
3* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16const { NapiLog } = require("../tools/NapiLog");
17const { replaceAll, getTab } = require("../tools/tool");
18const re = require("../tools/re");
19const { iServiceHTemplate, proxyHTemplate, stubHTemplate, serviceHTemplate, proxyCppTemplate,
20    proxyFuncTemplate, stubCppTemplate, stubInnerFuncTemplate, serviceCppTemplate, serviceFuncImplTemplate,
21    clientCppTemplate, buildGnTemplate, bundleJsonTemplate, profileGnTemplate, profileXmlTemplate, serviceCfgTemplate,
22    serviceCfgGnTemplate } = require("./fileTemplate");
23const { DATA_WRITE_MAP, DATA_READ_MAP, getParcelType } = require("../tools/common");
24
25let fileContent = {
26    "iServiceHFile": {},
27    "proxyHFile": {},
28    "stubHFile": {},
29    "serviceHFile": {},
30    "proxyCppFile": {},
31    "stubCppFile": {},
32    "serviceCppFile": {},
33    "clientCppFile": {},
34    "buildGnFile": {},
35    "bundleJsonFile": {},
36    "profileGnFile": {},
37    "profileXmlFile": {},
38    "serviceCfgFile": {},
39    "serviceCfgGnFile": {}
40};
41
42function getIncludeStr(includeList) {
43    let includeStr = "";
44    for (let i = 0; i < includeList.length; ++i) {
45        includeStr += "#include " + includeList[i] + "\n";
46    }
47    return includeStr;
48}
49
50function getFuncParamStr(params) {
51    let paramStr = "";
52    for (let i = 0; i < params.length; ++i) {
53        paramStr += (i == 0) ? "" : ", ";
54        paramStr += params[i].type + " " + params[i].name;
55    }
56    return paramStr;
57}
58
59/**
60 * 生成c参数写入remote消息buffer(parcel data)的代码段
61 * @param {} srcName 待写入的c变量名
62 * @param {*} destName 写入目标(parcel data)变量的名称
63 * @param {*} vType c变量类型
64 * @returns 生成的代码段
65 */
66function genWriteString(srcName, destName, vType) {
67    let matchs = re.match("(std::)?vector<([\x21-\x7e]+)>", vType);
68    if (matchs) { // write data of std::vector
69        let rowType = re.getReg(vType, matchs.regs[2]);
70        let parcelType = getParcelType(rowType);
71        let wFunc = DATA_WRITE_MAP.get(parcelType);
72        if (!wFunc) {
73            NapiLog.logError("Unsupport writing with type: " + vType);
74            return "";
75        }
76        // use function Parcel::WriteVector(const std::vector<T1> &val, bool (Parcel::*Write)(T2))
77        return "%s.WriteVector(%s, &(%s.%s));".format(destName, srcName, destName, wFunc);
78    }
79
80    let parcelType = getParcelType(vType);
81    let wFunc = DATA_WRITE_MAP.get(parcelType);
82    if (!wFunc) {
83        NapiLog.logError("Unsupport writing with type: " + vType);
84        return "";
85    }
86    return "%s.%s(%s);".format(destName, wFunc, srcName);
87}
88
89/**
90 * 生成从remote消息buffer(parcel data)读取c参数的代码段
91 * @param {*} srcName 待读取的parcel data变量名称
92 * @param {*} destName 读取出的内容写入的c变量名称
93 * @param {*} vType c变量类型
94 * @returns 生成的代码段
95 */
96function genReadString(srcName, destName, vType) {
97    let matchs = re.match("(std::)?vector<([\x21-\x7e]+)>", vType);
98    if (matchs) { // write data of std::vector
99        let rowType = re.getReg(vType, matchs.regs[2]);
100        let parcelType = getParcelType(rowType);
101        let rFunc = DATA_READ_MAP.get(parcelType);
102        if (!rFunc) {
103            NapiLog.logError("Unsupport reading with type: " + vType);
104            return "";
105        }
106        // use function Parcel::ReadVector(std::vector<T> *val, bool (Parcel::*Read)(T &))
107        return "%s.ReadVector(&(%s), &(%s.%s));".format(srcName, destName, srcName, rFunc);
108    }
109
110    let parcelType = getParcelType(vType);
111    let rFunc = DATA_READ_MAP.get(parcelType);
112    if (!rFunc) {
113        NapiLog.logError("Unsupport reading with type: " + vType);
114        return "";
115    }
116    return "%s = %s.%s();".format(destName, srcName, rFunc);
117}
118
119function genProxyFunc(funcInfo, className, paramStr) {
120    let proxyFunc = replaceAll(proxyFuncTemplate, "[className]", className);
121    proxyFunc = replaceAll(proxyFunc, "[funcName]", funcInfo.name);
122    proxyFunc = replaceAll(proxyFunc, "[params]", paramStr);
123    proxyFunc = replaceAll(proxyFunc, "[retType]", funcInfo.retType);
124    proxyFunc = replaceAll(proxyFunc, "[funcEnum]", funcInfo.funcEnum);
125
126    // 入参处理
127    let writeDataStr = "";
128    let tab = getTab(1);
129    for (let i = 0; i < funcInfo.params.length; ++i) {
130        let param = funcInfo.params[i];
131        writeDataStr += (i == 0) ? "" : "\n" + tab;
132        writeDataStr += genWriteString(param.name, "data", param.type);
133    }
134    proxyFunc = replaceAll(proxyFunc, "[writeData]", writeDataStr);
135
136    // 返回值处理
137    let readReplyStr = "";
138    if (funcInfo.retType != "void") {
139        readReplyStr = "%s result;".format(funcInfo.retType);
140        readReplyStr += "\n" + tab + genReadString("reply", "result", funcInfo.retType);
141        readReplyStr += "\n" + tab + "return result;";
142    }
143    proxyFunc = replaceAll(proxyFunc, "[readReply]", readReplyStr);
144
145    return proxyFunc;
146}
147
148function genStubInnerFunc(funcInfo, className) {
149    let innerFunc = replaceAll(stubInnerFuncTemplate, "[className]", className);
150    innerFunc = replaceAll(innerFunc, "[funcName]", funcInfo.name);
151
152    // 入参处理
153    let readDataStr = ""; // 生成服务端读取客户端传参的代码段
154    let tab = getTab(1);
155    let innerParamStr = ""; // 调用业务方法时传入的入参列表
156    for (let i = 0; i < funcInfo.params.length; ++i) {
157        let param = funcInfo.params[i];
158        let innerParamName = param.name + "Val";
159        if (i > 0) {
160            readDataStr += "\n" + tab;
161            innerParamStr += " ,";
162        }
163
164        //将remote请求中的参数值读取到内部参数变量中
165        readDataStr += "%s %s;".format(param.type, innerParamName); // 定义内部参数变量
166        readDataStr += "\n" + tab + genReadString("data", param.name + "Val", param.type);
167        innerParamStr += innerParamName;
168    }
169    innerFunc = replaceAll(innerFunc, "[readData]", readDataStr);
170
171    // 调用service的实际业务逻辑实现方法
172    let writeReplyStr = ""; // 生成调用服务端实现并返回结果的代码段
173    if (funcInfo.retType === "void") {
174        writeReplyStr += "%s(%s); // call business implementation".format(funcInfo.name, innerParamStr);
175        writeReplyStr += "\n" + tab + "reply.WriteInt32(retCode);";
176    } else {
177        writeReplyStr += "%s retVal = %s(%s);  // call business implementation".format(
178            funcInfo.retType, funcInfo.name, innerParamStr);
179        writeReplyStr += "\n" + tab + "reply.WriteInt32(retCode);";
180        writeReplyStr += "\n" + tab + genWriteString("retVal", "reply", funcInfo.retType);
181    }
182    innerFunc = replaceAll(innerFunc, "[writeReply]", writeReplyStr);
183    return innerFunc;
184}
185
186function genServiceFunc(funcInfo, className, paramStr) {
187    let serviceFunc = replaceAll(serviceFuncImplTemplate, "[retType]", funcInfo.retType);
188    serviceFunc = replaceAll(serviceFunc, "[className]", className);
189    serviceFunc = replaceAll(serviceFunc, "[funcName]", funcInfo.name);
190    serviceFunc = replaceAll(serviceFunc, "[params]", paramStr);
191    return serviceFunc;
192}
193
194function genFunctions(classInfo, files) {
195    let res = genFunctionCode(classInfo);
196    files.iServiceH = replaceAll(files.iServiceH, "[funcEnum]", res.funcEnumStr);
197    files.iServiceH = replaceAll(files.iServiceH, "[functions]", res.iServiceFuncH);
198    files.proxyH = replaceAll(files.proxyH, "[functions]", res.proxyFuncH);
199    files.stubH = replaceAll(files.stubH, "[innerFuncDef]", res.stubInnerFuncH);
200    files.serviceH = replaceAll(files.serviceH, "[functions]", res.proxyFuncH);
201    files.proxyCpp = replaceAll(files.proxyCpp, "[remoteFuncImpl]", res.proxyFuncCpp);
202    files.stubCpp = replaceAll(files.stubCpp, "[innerFuncMap]", res.stubInnerFuncMap);
203    files.stubCpp = replaceAll(files.stubCpp, "[innerFuncImpl]", res.stubInnerFuncCpp);
204    files.serviceCpp = replaceAll(files.serviceCpp, "[serviceFuncImpl]", res.serviceFuncCpp);
205    files.clientCpp = replaceAll(files.clientCpp, "[clientFuncInvoke]", res.clientFuncCpp);
206}
207
208function genFilesByTemplate(upperServiceName, lowServiceName, rootInfo) {
209    let files = {};
210    // 按模板生成.h和.cpp文件内容框架
211    files.iServiceH = replaceAll(iServiceHTemplate, "[marcoName]", upperServiceName);
212    files.proxyH = replaceAll(proxyHTemplate, "[marcoName]", upperServiceName);
213    files.stubH = replaceAll(stubHTemplate, "[marcoName]", upperServiceName);
214    files.serviceH = replaceAll(serviceHTemplate, "[marcoName]", upperServiceName);
215    files.proxyCpp = proxyCppTemplate;
216    files.stubCpp = stubCppTemplate;
217    files.serviceCpp = replaceAll(serviceCppTemplate, "[marcoName]", upperServiceName);
218    files.clientCpp = replaceAll(clientCppTemplate, "[marcoName]", upperServiceName);
219
220    // 按模板生成资源配置文件内容框架
221    files.buildGn = replaceAll(buildGnTemplate, "[lowServiceName]", lowServiceName);
222    files.buildGn = replaceAll(files.buildGn, "[stubCppFile]", fileContent.stubCppFile.name);
223    files.buildGn = replaceAll(files.buildGn, "[serviceCppFile]", fileContent.serviceCppFile.name);
224    files.buildGn = replaceAll(files.buildGn, "[proxyCppFile]", fileContent.proxyCppFile.name);
225    files.buildGn = replaceAll(files.buildGn, "[clientCppFile]", fileContent.clientCppFile.name);
226    files.bundleJson = replaceAll(bundleJsonTemplate, "[lowServiceName]", lowServiceName);
227    files.profileGn = replaceAll(profileGnTemplate, "[lowServiceName]", lowServiceName);
228    files.profileGn = replaceAll(files.profileGn, "[serviceId]", rootInfo.serviceId);
229    files.profileXml = replaceAll(profileXmlTemplate, "[lowServiceName]", lowServiceName);
230    files.profileXml = replaceAll(files.profileXml, "[serviceId]", rootInfo.serviceId);
231    files.serviceCfg = replaceAll(serviceCfgTemplate, "[lowServiceName]", lowServiceName);
232    files.serviceGnCfg = replaceAll(serviceCfgGnTemplate, "[lowServiceName]", lowServiceName);
233    return files;
234}
235
236function replaceClassName(files, classInfo) {
237    files.iServiceH = replaceAll(files.iServiceH, "[className]", classInfo.name);
238    files.proxyH = replaceAll(files.proxyH, "[className]", classInfo.name);
239    files.stubH = replaceAll(files.stubH, "[className]", classInfo.name);
240    files.serviceH = replaceAll(files.serviceH, "[className]", classInfo.name);
241    files.proxyCpp = replaceAll(files.proxyCpp, "[className]", classInfo.name);
242    files.stubCpp = replaceAll(files.stubCpp, "[className]", classInfo.name);
243    files.serviceCpp = replaceAll(files.serviceCpp, "[className]", classInfo.name);
244    files.clientCpp = replaceAll(files.clientCpp, "[className]", classInfo.name);
245}
246
247function replaceServiceName(files, rootInfo) {
248    files.iServiceH = replaceAll(files.iServiceH, "[serviceName]", rootInfo.serviceName);
249    files.proxyH = replaceAll(files.proxyH, "[serviceName]", rootInfo.serviceName);
250    files.stubH = replaceAll(files.stubH, "[serviceName]", rootInfo.serviceName);
251    files.serviceH = replaceAll(files.serviceH, "[serviceName]", rootInfo.serviceName);
252    files.proxyCpp = replaceAll(files.proxyCpp, "[serviceName]", rootInfo.serviceName);
253    files.stubCpp = replaceAll(files.stubCpp, "[serviceName]", rootInfo.serviceName);
254    files.serviceCpp = replaceAll(files.serviceCpp, "[serviceName]", rootInfo.serviceName);
255    files.clientCpp = replaceAll(files.clientCpp, "[serviceName]", rootInfo.serviceName);
256}
257
258function replaceIncludes(files, rootInfo) {
259    files.iServiceH = replaceAll(files.iServiceH, "[includes]", getIncludeStr(rootInfo.includes));
260    files.proxyH = replaceAll(files.proxyH, "[iServiceHInclude]", fileContent.iServiceHFile.name);
261    files.stubH = replaceAll(files.stubH, "[iServiceHInclude]", fileContent.iServiceHFile.name);
262    files.serviceH = replaceAll(files.serviceH, "[stubHInclude]", fileContent.stubHFile.name);
263    files.proxyCpp = replaceAll(files.proxyCpp, "[proxyHInclude]", fileContent.proxyHFile.name);
264    files.stubCpp = replaceAll(files.stubCpp, "[stubHInclude]", fileContent.stubHFile.name);
265    files.serviceCpp = replaceAll(files.serviceCpp, "[serviceHInclude]", fileContent.serviceHFile.name);
266    files.clientCpp = replaceAll(files.clientCpp, "[proxyHInclude]", fileContent.proxyHFile.name);
267}
268
269function genFileNames(lowServiceName, rootInfo) {
270    fileContent.iServiceHFile.name = "i_%s_service.h".format(lowServiceName);
271    fileContent.proxyHFile.name = "%s_service_proxy.h".format(lowServiceName);
272    fileContent.stubHFile.name = "%s_service_stub.h".format(lowServiceName);
273    fileContent.serviceHFile.name = "%s_service.h".format(lowServiceName);
274    fileContent.proxyCppFile.name = "%s_service_proxy.cpp".format(lowServiceName);
275    fileContent.stubCppFile.name = "%s_service_stub.cpp".format(lowServiceName);
276    fileContent.serviceCppFile.name = "%s_service.cpp".format(lowServiceName);
277    fileContent.clientCppFile.name = "%s_client.cpp".format(lowServiceName);
278    fileContent.buildGnFile.name = "BUILD.gn";
279    fileContent.bundleJsonFile.name = "bundle.json";
280    fileContent.profileGnFile.name = "BUILD.gn";
281    fileContent.profileXmlFile.name = rootInfo.serviceId + ".xml";
282    fileContent.serviceCfgFile.name = "%s_service.cfg".format(lowServiceName);
283    fileContent.serviceCfgGnFile.name = "BUILD.gn";
284}
285
286function genFunctionCode(classInfo) {
287    let funcList = classInfo.functions;
288    let genResult = {}
289    genResult.funcEnumStr = "";
290    genResult.iServiceFuncH = ""; //i_service.h 方法定义
291    genResult.proxyFuncH = ""; //proxy.h 方法定义
292    genResult.stubInnerFuncH = ""; // stub.h 的inner方法定义
293    genResult.proxyFuncCpp = ""; //proxy.cpp 方法实现
294    genResult.stubInnerFuncMap = ""; // stub.cpp 的inner方法映射表
295    genResult.stubInnerFuncCpp = ""; // stub.cpp 的inner方法实现
296    genResult.serviceFuncCpp = ""; // service.cpp的方法实现
297    genResult.clientFuncCpp = ""; // client.cpp 的inner方法定义
298
299    let enumTab = getTab(2);
300    let funcTab = getTab(1);
301    for (var i = 0; i < funcList.length; ++i) {
302        funcList[i].funcEnum = funcList[i].name.toUpperCase(); // remote方法的枚举值
303        genResult.funcEnumStr += (i == 0) ? "" : ",\n" + enumTab;
304        genResult.funcEnumStr += funcList[i].funcEnum;
305
306        let paramStr = getFuncParamStr(funcList[i].params);
307        genResult.iServiceFuncH += (i == 0) ? "" : "\n" + funcTab;
308        genResult.iServiceFuncH += "virtual %s %s(%s) = 0;".format(funcList[i].retType, funcList[i].name, paramStr);
309
310        genResult.proxyFuncH += (i == 0) ? "" : "\n" + funcTab;
311        genResult.proxyFuncH += "%s %s(%s) override;".format(funcList[i].retType, funcList[i].name, paramStr);
312
313        genResult.stubInnerFuncH += (i == 0) ? "" : "\n" + funcTab;
314        genResult.stubInnerFuncH +=
315            "ErrCode %sInner(MessageParcel &data, MessageParcel &reply);".format(funcList[i].name);
316
317        genResult.proxyFuncCpp += genProxyFunc(funcList[i], classInfo.name, paramStr);
318
319        genResult.stubInnerFuncMap += (i == 0) ? "" : "\n" + funcTab;
320        genResult.stubInnerFuncMap += "innerFuncs_[%s] = &%sStub::%sInner;".format(
321            funcList[i].funcEnum, classInfo.name, funcList[i].name);
322
323        genResult.stubInnerFuncCpp += genStubInnerFunc(funcList[i], classInfo.name);
324        genResult.serviceFuncCpp += genServiceFunc(funcList[i], classInfo.name, paramStr);
325
326        genResult.clientFuncCpp += (i == 0) ? "" : "\n" + funcTab;
327        genResult.clientFuncCpp += "// proxy->%s(%s);".format(funcList[i].name, paramStr);
328    }
329    return genResult;
330}
331
332function doGenerate(rootInfo) {
333    let lowServiceName = rootInfo.serviceName.toLowerCase();
334    let upperServiceName = rootInfo.serviceName.toUpperCase();
335
336    // 生成文件名
337    genFileNames(lowServiceName, rootInfo);
338
339    // 按模板生成.h和.cpp文件内容框架
340    let files = genFilesByTemplate(upperServiceName, lowServiceName, rootInfo);
341
342    // 替换文件includes
343    replaceIncludes(files, rootInfo);
344
345    // 替换namespace
346    replaceServiceName(files, rootInfo);
347
348    // 替换类名
349    let classInfo = rootInfo.class[0]
350    replaceClassName(files, classInfo);
351
352    // 生成函数定义与实现
353    genFunctions(classInfo, files);
354
355    // 文件内容汇总
356    fileContent.iServiceHFile.content = files.iServiceH;
357    fileContent.proxyHFile.content = files.proxyH;
358    fileContent.stubHFile.content = files.stubH;
359    fileContent.serviceHFile.content = files.serviceH;
360    fileContent.proxyCppFile.content = files.proxyCpp;
361    fileContent.stubCppFile.content = files.stubCpp;
362    fileContent.serviceCppFile.content = files.serviceCpp;
363    fileContent.clientCppFile.content = files.clientCpp;
364    fileContent.buildGnFile.content = files.buildGn;
365    fileContent.bundleJsonFile.content = files.bundleJson;
366    fileContent.profileGnFile.content = files.profileGn;
367    fileContent.profileXmlFile.content = files.profileXml;
368    fileContent.serviceCfgFile.content = files.serviceCfg;
369    fileContent.serviceCfgGnFile.content = files.serviceGnCfg;
370    return fileContent;
371}
372
373module.exports = {
374    doGenerate
375}
376