• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15const { replaceAll } = require('../tools/tool');
16const re = require('../tools/re');
17const { eventParamGenerate } = require('./param_generate');
18const { returnGenerate } = require('./return_generate');
19const { cToJs } = require('./return_generate');
20const { jsonCfgList, isRegisterFunc, isUnRegisterFunc, getOnObjCallbackType, isOnObjCallback } =
21require('../tools/common');
22
23let middleHOnOffTemplate = `
24struct [funcName]_value_struct {
25    std::string eventName;
26};
27
28[static_define]napi_value [funcName]_middle(napi_env env, napi_callback_info info);
29`;
30let middleHCallbackTemplate = `
31  void [eventName]CallbackMiddle(std::string &eventName, [callback_param_type]);
32  void [eventName]AsyncOrSyncCallbackMiddle(const std::string &eventName, [callback_param_type]);
33`;
34
35/**
36 * on和off接口生成模板
37 */
38let funcOnOffTemplete = `
39napi_value [middleClassName][funcName]_middle(napi_env env, napi_callback_info info)
40{
41    XNapiTool *pxt = std::make_unique<XNapiTool>(env, info).release();
42    if (pxt->IsFailed()) {
43        napi_value err = pxt->GetError();
44        delete pxt;
45        return err;
46    }
47    struct [funcName]_value_struct *vio = new [funcName]_value_struct();
48    [getEventName]
49    [handleRegist]
50
51    napi_value result = pxt->UndefinedValue();
52    delete vio;
53    delete pxt; // release
54    return result;
55}
56`;
57
58let middleAsyncCallbackTemplate = `
59void [middleClassName][eventNames]AsyncOrSyncCallbackMiddle(const std::string &eventName, [callback_param_type])
60{
61  printf("onSayHelloStartAsyncOrSyncCallbackMiddle callFuncs_.count %u  ",
62  (unsigned int)XNapiTool::callFuncs_.count(eventName));
63	if(XNapiTool::callFuncs_.count(eventName) <= 0) {
64        return;
65    }
66  CallFunc *pAsyncFuncs = &XNapiTool::callFuncs_[eventName];
67	napi_value exports = nullptr;
68	XNapiTool *pxt = std::make_unique<XNapiTool>(pAsyncFuncs->env_, exports).release();
69    napi_value result = nullptr;
70    napi_status status = napi_create_array(pAsyncFuncs->env_, &result);
71    if (status != napi_ok) {
72      return;  // napi数组创建失败
73    }
74    [cb_params_define]
75    [cb_params]
76    [value_set_array]
77  XNapiTool::[call_function_name](pAsyncFuncs, result);
78	delete pxt;
79}
80`;
81
82let fixedTypeMiddleTemplate =
83`if (eventName != "[eventName]") { // on方法注册字段为固定值时,判断ts文件中注册的字段与使用字段是否一样
84        printf("eventName Err !");
85        return;
86    }`;
87
88let middleEventCallbakTemplate = `
89void [middleClassName][eventName]CallbackMiddle(std::string &eventName, [callback_param_type]) {
90    [replace_onTypeMiddle]
91    [middleClassName][eventName]AsyncOrSyncCallbackMiddle(eventName, [callback_param_name]);
92}
93`;
94
95let implHEventCallbakTemplate = `
96//供业务调用的回调接口
97void [eventName]Callback([callback_eventName][callback_param_type]);
98`;
99
100let implCppEventCallbakTemplate = `
101//供业务调用的回调接口
102void [className][eventName]Callback([callback_eventName][callback_param_type])
103{
104  [eventName_is_string]
105  [use_callback_func]
106}
107`;
108
109function isOnTypeExist(onTypeList, newType) {
110    if (!onTypeList) {
111        return false;
112    }
113
114    for (let i in onTypeList) {
115        if (onTypeList[i] === newType) {
116            return true;
117        }
118    }
119    return false;
120}
121
122function addOnTypeToList(data, newType) {
123    if (!data.onTypeList) {
124        data.onTypeList = [];
125    }
126
127    data.onTypeList.push(newType);
128}
129
130function isOnOffFuncExist(data, funcName) {
131    return data.onOffList && data.onOffList.indexOf(funcName) > -1;
132}
133
134function addOnOffFunc(data, funcName) {
135    if (!data.onOffList) {
136        data.onOffList = [];
137    }
138    data.onOffList.push(funcName);
139}
140
141function getregistLine(name) {
142    let registLine = '';
143    if (isRegisterFunc(name)) {
144        registLine = 'pxt->RegistOnOffFunc(vio->eventName, pxt->GetArgv(XNapiTool::ZERO));';
145    } else if (name === 'on') {
146        registLine = 'pxt->RegistOnOffFunc(vio->eventName, pxt->GetArgv(XNapiTool::ONE));';
147    } else if (isOnObjCallback(name)) {
148        // registLine = "pxt->RegistOnOffFunc(vio->eventName, cbFunc);"
149    } else { // off/unRegister处理
150        registLine = 'pxt->UnregistOnOffFunc(vio->eventName);';
151    }
152    return registLine;
153}
154
155function getPrefix(isRegister) {
156    let prefix = '';
157    if (isRegister) {
158        prefix = 'register';
159    } else {
160        prefix = 'unRegister';
161    }
162    return prefix;
163}
164
165function gennerateOnOffContext(codeContext, func, data, className, param) {
166    let isRegister = isRegisterFunc(func.name);
167    let isUnRegister = isUnRegisterFunc(func.name);
168    let getEventName = '';
169    let registLine = getregistLine(func.name);
170    let onObjFlag = isOnObjCallback(func.name);
171
172    if (isRegister || isUnRegister) {
173        let prefix = getPrefix(isRegister);
174        param.eventName = func.name.replaceAll(prefix, ''); // 去掉注册、注销关键字前缀
175        getEventName = 'vio->eventName = "%s";\n'.format(param.eventName);
176    } else if (onObjFlag) {
177        param.eventName = className + '_' + func.name;
178        getEventName = 'vio->eventName = "%s";\n'.format(param.eventName);
179    } else {
180        getEventName = 'pxt->SwapJs2CUtf8(pxt->GetArgv(XNapiTool::ZERO), vio->eventName);\n';
181    }
182    codeContext.middleFunc = replaceAll(funcOnOffTemplete, '[funcName]', func.name);
183
184    if (func.name !== 'constructor') {
185      codeContext.middleH = replaceAll(middleHOnOffTemplate, '[funcName]', func.name);
186    }
187    codeContext.middleFunc = codeContext.middleFunc.replaceAll('[getEventName]', getEventName);
188    let middleClassName = '';
189    if (className === null || className === undefined) {
190        codeContext.middleH = codeContext.middleH.replaceAll('[static_define]', '');
191        codeContext.middleFunc = codeContext.middleFunc.replaceAll('[middleClassName]', '');
192    }
193    else {
194        middleClassName = className + '_middle';
195        codeContext.middleH = codeContext.middleH.replaceAll('[static_define]', 'static ');
196        codeContext.middleFunc = codeContext.middleFunc.replaceAll('[middleClassName]', middleClassName + '::');
197    }
198    let instancePtr = '%s'.format((className === null || className === undefined) ? '' : 'pInstance->');
199    codeContext.middleFunc = replaceAll(codeContext.middleFunc, '[instance]', instancePtr); //执行
200
201    codeContext.middleFunc = replaceAll(codeContext.middleFunc, '[handleRegist]', registLine); //注册/去注册event
202
203    if (isRegister) {
204        codeContext.middleFunc = replaceAll(codeContext.middleFunc, '(vio->eventName)', '()');
205    }
206
207    addOnOffFunc(data, func.name);
208}
209
210function gennerateEventCallback(codeContext, data, param, className = null, isOnFuncFlag = false) {
211    let paramIsAsync = false;
212    let middleClassName = '';
213
214    param.resultDefine = '';
215    param.cbParams = '';
216    param.valueSetArray = '';
217    param.useParams = '';
218    param.params = '';
219
220    returnGenerate(param.callback, param, data, isOnFuncFlag);
221    if (param.params === '') {
222        let paramType = param.valueOut.substring(0, param.valueOut.lastIndexOf(' ') + 1);
223        if (paramType !== null && paramType !== undefined && paramType !== '') {
224            param.params = paramType + '&valueIn';
225        }
226    }
227    if (param.useParams === '' && param.params !== '') {
228        param.useParams = 'valueIn';
229    }
230
231    if (className !== null && className !== undefined) {
232        middleClassName = className + '_middle';
233    }
234
235    let callFunctionName = paramIsAsync ? 'CallAsyncFunc' : 'CallSyncFunc';
236    let callbackFunc = middleAsyncCallbackTemplate;
237    callbackFunc = replaceAll(middleAsyncCallbackTemplate, '[eventNames]', param.eventName);
238    callbackFunc = replaceAll(callbackFunc, '[callback_param_type]', param.params);
239    if (param.params === '') {
240        callbackFunc = replaceAll(callbackFunc, '&eventName, ', '&eventName');
241    }
242
243    // 回调是箭头函数
244    if (param.callback !== null && param.callback !== undefined &&
245        param.callback.isArrowFuncFlag !== undefined && param.callback.isArrowFuncFlag !== null &&
246        param.callback.isArrowFuncFlag) {
247        callbackFunc = getArrowCallbackC2JsParam(callbackFunc, param);
248    } else { // 回调是普通callback
249        callbackFunc = getCallbackC2JsParam(callbackFunc, param);
250    }
251    callbackFunc = replaceAll(callbackFunc, '[call_function_name]', callFunctionName);
252    if (className !== null && className !== undefined) {
253        callbackFunc = replaceAll(callbackFunc, '[middleClassName]', middleClassName + '::');
254    } else {
255        callbackFunc = replaceAll(callbackFunc, '[middleClassName]', '');
256    }
257    codeContext.middleFunc += callbackFunc;
258
259     // 为每个on的event事件生成回调方法
260    genCallbackMiddleMethod(param, className, middleClassName, codeContext);
261
262    // 为每个on的event事件生成回调接口供用户侧使用
263    genCallbackMethodH(param, codeContext);
264
265    // 为每个on的event事件生成回调接口在工具代码中声明
266    genCallbackMethodDeclare(param, codeContext);
267
268    // 为每个on的event事件生成回调接口的实现供用户侧使用
269    genCallbackMethod(param, className, middleClassName, codeContext);
270}
271
272function genCallbackMethodDeclare(param, codeContext) {
273  let middleHCallback = replaceAll(middleHCallbackTemplate, '[eventName]', param.eventName);
274  middleHCallback = replaceAll(middleHCallback, '[callback_param_type]', param.params);
275  if (param.params === '') {
276    middleHCallback = replaceAll(middleHCallback, '&eventName,', '&eventName');
277  }
278  codeContext.middleH += middleHCallback;
279}
280
281function getArrowCallbackC2JsParam(callbackFunc, param) {
282    callbackFunc = replaceAll(callbackFunc, '[cb_params_define]', param.resultDefine);
283    callbackFunc = replaceAll(callbackFunc, '[cb_params]', param.cbParams + '\n');
284    callbackFunc = replaceAll(callbackFunc, '[value_set_array]', param.valueSetArray);
285    return callbackFunc;
286}
287
288function getCallbackC2JsParam(callbackFunc, param) {
289    callbackFunc = replaceAll(callbackFunc, '[cb_params_define]', `napi_value resultTmp = nullptr; `);
290    callbackFunc = replaceAll(callbackFunc, '[cb_params]', param.valuePackage);
291    callbackFunc = replaceAll(callbackFunc, '[value_set_array]',
292      `napi_set_element(pAsyncFuncs->env_, result, 0, resultTmp);`);
293    return callbackFunc;
294}
295
296function genCallbackMiddleMethod(param, className, middleClassName, codeContext) {
297    let middleEventCallBack = replaceAll(middleEventCallbakTemplate, '[eventName]', param.eventName);
298    middleEventCallBack = replaceAll(middleEventCallBack, '[callback_param_type]', param.params);
299    middleEventCallBack = replaceAll(middleEventCallBack, '[callback_param_name]', param.useParams);
300    if (className !== null && className !== undefined) {
301        middleEventCallBack = replaceAll(middleEventCallBack, '[middleClassName]', middleClassName + '::');
302    } else {
303        middleEventCallBack = replaceAll(middleEventCallBack, '[middleClassName]', '');
304    }
305    let middleEventTypeTemplate = replaceAll(fixedTypeMiddleTemplate, '[eventName]', param.eventName);
306    if (param.eventNameIsStr) {
307        middleEventCallBack = replaceAll(middleEventCallBack, '[replace_onTypeMiddle]', '');
308    } else {
309        middleEventCallBack = replaceAll(middleEventCallBack, '[replace_onTypeMiddle]', middleEventTypeTemplate);
310    }
311    if (param.params === '') {
312        middleEventCallBack = replaceAll(middleEventCallBack, 'eventName, ', 'eventName');
313    }
314    codeContext.middleFunc += middleEventCallBack;
315}
316
317function genCallbackMethodH(param, codeContext) {
318    let eventNameDefine = param.eventNameIsStr ? 'std::string &eventName, ' : '';
319    if (param.params === '' && eventNameDefine !== '') {
320        eventNameDefine = 'std::string &eventName';
321    }
322    let implHCallBack = replaceAll(implHEventCallbakTemplate, '[eventName]', param.eventName);
323    implHCallBack = replaceAll(implHCallBack, '[callback_param_type]', param.params);
324    implHCallBack = replaceAll(implHCallBack, '[callback_eventName]', eventNameDefine);
325    codeContext.implH += implHCallBack;
326}
327
328function genCallbackMethod(param, className, middleClassName, codeContext) {
329    let isStrType = param.eventNameIsStr ? '' : `std::string eventName = "[fixed_eventName]";`;
330    isStrType = replaceAll(isStrType, '[fixed_eventName]', param.eventName);
331    let implCppCallBack = replaceAll(implCppEventCallbakTemplate, '[eventName]', param.eventName);
332    implCppCallBack = replaceAll(implCppCallBack, '[callback_param_type]', param.params);
333    implCppCallBack = replaceAll(implCppCallBack, '[eventName_is_string]', isStrType);
334    let eventNameDefine = param.eventNameIsStr ? 'std::string &eventName, ' : '';
335    if (param.params === '' && eventNameDefine !== '') {
336        eventNameDefine = replaceAll(eventNameDefine, '&eventName,', '&eventName');
337    }
338
339    implCppCallBack = replaceAll(implCppCallBack, '[callback_eventName]', eventNameDefine);
340
341    let callbackNoClass = `[eventName]CallbackMiddle(eventName, [callback_param_name]);`;
342    let callbackClass = `  [middleClassName] *ptr = new [middleClassName]();
343        ptr->[eventName]CallbackMiddle(eventName, [callback_param_name]);
344        delete ptr;`;
345
346    if (className === null) {
347      let callbackNoClassRes = replaceAll(callbackNoClass, '[eventName]', param.eventName);
348      callbackNoClassRes = replaceAll(callbackNoClassRes, '[callback_param_name]', param.useParams);
349      if (param.useParams === '') {
350        callbackNoClassRes = replaceAll(callbackNoClassRes, 'eventName, ', 'eventName');
351      }
352      implCppCallBack = replaceAll(implCppCallBack, '[use_callback_func]', callbackNoClassRes);
353      implCppCallBack = replaceAll(implCppCallBack, '[className]', '');
354    } else {
355      let callbackClassRes = replaceAll(callbackClass, '[eventName]', param.eventName);
356      callbackClassRes = replaceAll(callbackClassRes, '[callback_param_name]', param.useParams);
357      callbackClassRes = replaceAll(callbackClassRes, '[middleClassName]', middleClassName);
358      if (param.useParams === '') {
359        callbackClassRes = replaceAll(callbackClassRes, 'eventName, ', 'eventName');
360      }
361      implCppCallBack = replaceAll(implCppCallBack, '[use_callback_func]', callbackClassRes);
362      implCppCallBack = replaceAll(implCppCallBack, '[className]', className + '::');
363    }
364
365    codeContext.implCpp += implCppCallBack;
366}
367
368function generateFunctionOnOff(func, data, className) {
369    let param = {
370        valueIn: '', // 定义输入
371        valueOut: '', // 定义输出
372        valueCheckout: '', // 解析
373        valueFill: '', // 填充到函数内
374        valuePackage: '', // 输出参数打包
375        valueDefine: '', // impl参数定义
376        eventName:'', // 注册/去注册事件名称
377        eventNameIsStr:false, // 注册/去注册事件名称是否在ts中为string类型
378        optionalParamDestory: '' // 可选参数内存释放
379    };
380
381    let isRegister = isRegisterFunc(func.name);
382    let onObjFlag = isOnObjCallback(func.name);
383    if (onObjFlag) {
384        let cbType = getOnObjCallbackType(func.name, className);
385        let funcValue = {
386            type: cbType,
387            optional: false
388        };
389        eventParamGenerate(0, funcValue, param, data);
390
391    } else {
392        for (let i in func.value) {
393            eventParamGenerate(i, func.value[i], param, data);
394        }
395    }
396
397    let codeContext = {
398        middleFunc: '',
399        implH: '',
400        implCpp: '',
401        middleH: ''
402    };
403    if (!isOnOffFuncExist(data, func.name)) {
404        // 同一个ts文件中所有的on和off 接口只需要生成一份公共的native方法
405        gennerateOnOffContext(codeContext, func, data, className, param);
406    }
407
408    if (func.name === 'on' || isRegister || onObjFlag) {
409        // 为每个on接口同步生成eventCallback方法供用户回调使用
410        let isOnFuncFlag = true;
411        gennerateEventCallback(codeContext, data, param, className, isOnFuncFlag);
412    }
413
414    return [codeContext.middleFunc, codeContext.implH, codeContext.implCpp, codeContext.middleH];
415}
416
417module.exports = {
418    generateFunctionOnOff
419};