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};