From c53deaf93886442a49536e3fe75e70a288311c83 Mon Sep 17 00:00:00 2001 From: zhangzhicheng007 Date: Fri, 29 Jul 2022 15:46:39 +0800 Subject: [PATCH] support optional params Signed-off-by: zhangzhicheng007 --- src/gen/analyze/function.js | 4 +- src/gen/analyze/params.js | 34 +++++--- src/gen/generate.js | 7 +- src/gen/generate/function_async.js | 25 ++++-- src/gen/generate/function_direct.js | 14 ++- src/gen/generate/function_onoff.js | 8 +- src/gen/generate/function_sync.js | 34 ++++++-- src/gen/generate/param_generate.js | 130 ++++++++++++++++++---------- src/gen/generate/return_generate.js | 72 +++++++++------ test/unittest/analyze.test.js | 10 +-- test/unittest/generate.test.js | 14 +-- 11 files changed, 233 insertions(+), 119 deletions(-) diff --git a/src/gen/analyze/function.js b/src/gen/analyze/function.js index 408168e9..d24e3664 100644 --- a/src/gen/analyze/function.js +++ b/src/gen/analyze/function.js @@ -85,7 +85,7 @@ function getFuncParaType(v, interfaceName, data) { /**函数解析 */ function analyzeFunction(data, name, values, ret) { values = re.replaceAll(re.replaceAll(values, " ", ""), "\n", "") - let matchs = re.match("([a-zA-Z_0-9]*):{([A-Za-z0-9_]+:[A-Za-z0-9_,]+)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}$", values) + let matchs = re.match("([a-zA-Z_0-9]*)\\?*:{([A-Za-z0-9_]+:[A-Za-z0-9_,]+)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}$", values) let interfaceName = '' if (matchs) { let interfacePara = re.getReg(values, matchs.regs[1]) @@ -99,7 +99,7 @@ function analyzeFunction(data, name, values, ret) { }) } - let tmp = analyzeParams(values) + let tmp = analyzeParams(name, values) values = tmp[0] let funcType = tmp[1] tmp = analyzeReturn(ret) diff --git a/src/gen/analyze/params.js b/src/gen/analyze/params.js index 8bdf3c89..db2d4524 100644 --- a/src/gen/analyze/params.js +++ b/src/gen/analyze/params.js @@ -18,29 +18,43 @@ const { FuncType } = require("../tools/common"); const { NapiLog } = require("../tools/NapiLog"); /**函数参数解析 */ -function analyzeParams(values) { +function analyzeParams(funcName, values) { let result = [] let funcType = FuncType.DIRECT + let optionalParamCount = 0; //可选参数的个数 while (values.length > 0) { let v = checkOutBody(values, 0, ["", ","]) if (v == null) v = values values = values.substring(v.length, values.length) - let matchs = re.match("([a-zA-Z_0-9\\.]+)\\?*: *([a-zA-Z<,>_0-9\\[\\]\\(\\):='{}]+)", v) + let matchs = re.match("([a-zA-Z_0-9\\.]+)(\\?*): *([a-zA-Z<,>_0-9\\[\\]\\(\\):='{}]+)", v) if (matchs != null) { - let type = re.getReg(v, matchs.regs[2]) + let type = re.getReg(v, matchs.regs[3]) if (type.indexOf("Map") < 0) { type = type.replace(/,/g, "") } - result.push({ "name": re.getReg(v, matchs.regs[1]), "type": type }) - if (type.indexOf("AsyncCallback") >= 0) - funcType = FuncType.ASYNC - if (funcType == FuncType.DIRECT && type.indexOf("Callback") >= 0 && type.indexOf("AsyncCallback") < 0) - funcType = FuncType.SYNC + + let optionalFlag = re.getReg(v, matchs.regs[2]) == '?' ? true : false; + let checkParamOk = true; + if (optionalFlag) { + optionalParamCount++; + } else if (optionalParamCount > 0) { + // 可选参数之后不能再有必选参数,必选都是可选参数。 + NapiLog.logError("Invalid parameter [%s] of function [%s],".format(v, funcName) + + " the required parameter cannot follow an optional parameter."); + checkParamOk = false; + } + if (checkParamOk) { + result.push({ "name": re.getReg(v, matchs.regs[1]), "type": type , "optional": optionalFlag}) + if (type.indexOf("AsyncCallback") >= 0) + funcType = FuncType.ASYNC + if (funcType == FuncType.DIRECT && type.indexOf("Callback") >= 0 && type.indexOf("AsyncCallback") < 0) + funcType = FuncType.SYNC + } } else { - NapiLog.logError("参数列表解析失败"); - NapiLog.logError("analyzeParams error params:" + v); + NapiLog.logError("方法[%s]的参数列表[%s]解析失败。".format(funcName, v)); + NapiLog.logError("Failed to analyse parameter [%s] of function [%s].".format(v, funcName)); } } return [result, funcType] diff --git a/src/gen/generate.js b/src/gen/generate.js index 8afc971d..22c964f5 100644 --- a/src/gen/generate.js +++ b/src/gen/generate.js @@ -62,7 +62,12 @@ let moduleCppTmplete = `\ #define BOOLEAN_JS_2_C(napi_v, type, dest){ \\ dest = pxt->SwapC2JsBool(napi_v); \\ -} \\ +} + +#define C_DELETE(p) \\ + if (p) { \\ + delete p; \\ + } static napi_value number_c_to_js(XNapiTool *pxt, const std::type_info &n, void *num) { diff --git a/src/gen/generate/function_async.js b/src/gen/generate/function_async.js index 0cf5dc98..521f8c66 100644 --- a/src/gen/generate/function_async.js +++ b/src/gen/generate/function_async.js @@ -37,6 +37,7 @@ struct [funcName]_value_struct {[valueIn] { [funcName]_value_struct *vio = ([funcName]_value_struct *)data; + napi_value result = nullptr; [valuePackage] { @@ -44,6 +45,7 @@ struct [funcName]_value_struct {[valueIn] pxt->FinishAsync(1, args); } + [optionalParamDestory] delete vio; } @@ -61,6 +63,8 @@ struct [funcName]_value_struct {[valueIn] [valueCheckout] + [optionalCallbackInit] + [start_async] if (pxt->IsFailed()) { @@ -69,6 +73,14 @@ struct [funcName]_value_struct {[valueIn] return result; }` +function getOptionalCallbackInit(param) { + if (!param.callback.optional) { + return "" + } + let cType = param.valueOut.substr(0, param.valueOut.indexOf("*")) + return "vio->out = new %s;".format(cType) +} + function generateFunctionAsync(func, data, className) { let middleFunc = replaceAll(funcAsyncTemplete, "[funcName]", func.name) if (className == null) { @@ -86,25 +98,27 @@ function generateFunctionAsync(func, data, className) { let param = { valueIn: "",//定义输入 valueOut: "",//定义输出 - valueCheckout: "",//解析 valueFill: "",//填充到函数内 valuePackage: "",//输出参数打包 - valueDefine: ""//impl参数定义 + valueDefine: "",//impl参数定义 + optionalParamDestory: ""//可选参数内存释放 } for (let i in func.value) { - let v = func.value[i] - paramGenerate(i, v.name, v.type, param, data) + paramGenerate(i, func.value[i], param, data) } - returnGenerate(param.callback.type, param, data) + returnGenerate(param.callback, param, data) middleFunc = replaceAll(middleFunc, "[valueIn]", param.valueIn)// # 输入参数定义 middleFunc = replaceAll(middleFunc, "[valueOut]", param.valueOut)// # 输出参数定义 middleFunc = replaceAll(middleFunc, "[valueCheckout]", param.valueCheckout)// # 输入参数解析 + let optionalCallback = getOptionalCallbackInit(param) + middleFunc = replaceAll(middleFunc, "[optionalCallbackInit]", optionalCallback)//可选callback参数初始化 + middleFunc = replaceAll(middleFunc, "[start_async]", ` napi_value result = \ pxt->StartAsync(%s_execute, vio, %s_complete, pxt->GetArgc() == %s ? pxt->GetArgv(%d) : nullptr);`.format(func.name, @@ -114,6 +128,7 @@ pxt->StartAsync(%s_execute, vio, %s_complete, pxt->GetArgc() == %s ? pxt->GetArg middleFunc = replaceAll(middleFunc, "[callFunc]", callFunc)//执行 middleFunc = replaceAll(middleFunc, "[valuePackage]", param.valuePackage)//输出参数打包 + middleFunc = replaceAll(middleFunc, "[optionalParamDestory]", param.optionalParamDestory)//可选参数内存释放 let implH = "\nbool %s(%s);".format(func.name, param.valueDefine) let implCpp = ` diff --git a/src/gen/generate/function_direct.js b/src/gen/generate/function_direct.js index 17113988..b4aad5c0 100644 --- a/src/gen/generate/function_direct.js +++ b/src/gen/generate/function_direct.js @@ -41,12 +41,16 @@ struct [funcName]_value_struct {[valueIn] [callFunc] + napi_value result = nullptr; [valuePackage] + [optionalParamDestory] + delete vio; if (pxt->IsFailed()) { result = pxt->GetError(); } + delete pxt; // release return result; }` @@ -68,15 +72,16 @@ function generateFunctionDirect(func, data, className) { valueCheckout: "",//解析 valueFill: "",//填充到函数内 valuePackage: "",//输出参数打包 - valueDefine: ""//impl参数定义 + valueDefine: "",//impl参数定义 + optionalParamDestory: ""//可选参数内存释放 } for (let i in func.value) { - let v = func.value[i] - paramGenerate(i, v.name, v.type, param, data) + paramGenerate(i, func.value[i], param, data) } - returnGenerate(func.ret, param, data) + let returnInfo = {type: func.ret, optional: false} + returnGenerate(returnInfo, param, data) middleFunc = replaceAll(middleFunc, "[valueIn]", param.valueIn)// # 输入参数定义 middleFunc = replaceAll(middleFunc, "[valueOut]", param.valueOut)// # 输出参数定义 @@ -87,6 +92,7 @@ function generateFunctionDirect(func, data, className) { middleFunc = replaceAll(middleFunc, "[callFunc]", callFunc)//执行 middleFunc = replaceAll(middleFunc, "[valuePackage]", param.valuePackage)//输出参数打包 + middleFunc = replaceAll(middleFunc, "[optionalParamDestory]", param.optionalParamDestory)//可选参数内存释放 let implH = "\nbool %s(%s);".format(func.name, param.valueDefine) let implCpp = ` diff --git a/src/gen/generate/function_onoff.js b/src/gen/generate/function_onoff.js index 3459c2fe..22aa36dc 100644 --- a/src/gen/generate/function_onoff.js +++ b/src/gen/generate/function_onoff.js @@ -140,7 +140,7 @@ return true; } function gennerateEventCallback(codeContext, data, param) { - returnGenerate(param.callback.type, param) + returnGenerate(param.callback, param) let paramType = param.valueOut.substring(0, param.valueOut.length - "out;".length) let realParamType = paramType.substring(0, 12) == "NUMBER_TYPE_" ? "uint32_t" : paramType if (!isOnTypeExist(data.onTypeList, realParamType)) { @@ -171,12 +171,12 @@ function generateFunctionOnOff(func, data, className) { valueFill: "",//填充到函数内 valuePackage: "",//输出参数打包 valueDefine: "",//impl参数定义 - eventName:""//注册/去注册事件名称 + eventName:"",//注册/去注册事件名称 + optionalParamDestory: ""//可选参数内存释放 } for (let i in func.value) { - let v = func.value[i] - eventParamGenerate(i, v.name, v.type, param, data) + eventParamGenerate(i, func.value[i], param, data) } let codeContext = { diff --git a/src/gen/generate/function_sync.js b/src/gen/generate/function_sync.js index f1c40749..10fc8c99 100644 --- a/src/gen/generate/function_sync.js +++ b/src/gen/generate/function_sync.js @@ -39,16 +39,21 @@ struct [funcName]_value_struct {[valueIn] [valueCheckout] + [optionalCallbackInit] [callFunc] - [valuePackage] + napi_value result = nullptr; + if (pxt->GetArgc() > [callback_param_offset]) { + [valuePackage] - { - napi_value args[1] = {result}; - pxt->SyncCallBack(pxt->GetArgv([callback_param_offset]), 1, args); + { + napi_value args[1] = {result}; + pxt->SyncCallBack(pxt->GetArgv([callback_param_offset]), 1, args); + } } result = pxt->UndefinedValue(); + [optionalParamDestory] delete vio; if (pxt->IsFailed()) { result = pxt->GetError(); @@ -57,6 +62,14 @@ struct [funcName]_value_struct {[valueIn] return result; }` +function getOptionalCallbackInit(param) { + if (!param.callback.optional) { + return "" + } + let cType = param.valueOut.substr(0, param.valueOut.indexOf("*")) + return "if (pxt->GetArgc() > %s) {\n vio->out = new %s;\n }".format(param.callback.offset, cType) +} + function generateFunctionSync(func, data, className) { let middleFunc = replaceAll(funcSyncTemplete, "[funcName]", func.name) if (className == null) { @@ -71,19 +84,18 @@ function generateFunctionSync(func, data, className) { let param = { valueIn: "",//定义输入 valueOut: "",//定义输出 - valueCheckout: "",//解析 valueFill: "",//填充到函数内 valuePackage: "",//输出参数打包 - valueDefine: ""//impl参数定义 + valueDefine: "",//impl参数定义 + optionalParamDestory: ""//可选参数内存释放 } for (let i in func.value) { - let v = func.value[i] - paramGenerate(i, v.name, v.type, param, data) + paramGenerate(i, func.value[i], param, data) } - returnGenerate(param.callback.type, param) + returnGenerate(param.callback, param) middleFunc = replaceAll(middleFunc, "[valueIn]", param.valueIn)// # 输入参数定义 middleFunc = replaceAll(middleFunc, "[valueOut]", param.valueOut)// # 输出参数定义 @@ -93,7 +105,11 @@ function generateFunctionSync(func, data, className) { let callFunc = "%s%s(%s);".format(className == null ? "" : "pInstance->", func.name, param.valueFill) middleFunc = replaceAll(middleFunc, "[callFunc]", callFunc)//执行 + let optionalCallback = getOptionalCallbackInit(param) + middleFunc = replaceAll(middleFunc, "[optionalCallbackInit]", optionalCallback)//可选callback参数初始化 + middleFunc = replaceAll(middleFunc, "[valuePackage]", param.valuePackage)//输出参数打包 + middleFunc = replaceAll(middleFunc, "[optionalParamDestory]", param.optionalParamDestory)//可选参数内存释放 middleFunc = middleFunc.replaceAll("[callback_param_offset]", param.callback.offset);//呼叫回调 diff --git a/src/gen/generate/param_generate.js b/src/gen/generate/param_generate.js index f2385010..78b79296 100644 --- a/src/gen/generate/param_generate.js +++ b/src/gen/generate/param_generate.js @@ -125,7 +125,7 @@ function arrTemplete(dest, napiVn, type) { [replace_swap] %s.push_back(tt[replace_lt]); - }`.format(napiVn, arrayType == "boolean" ? "bool" : arrayType, dest) + }\n`.format(napiVn, arrayType == "boolean" ? "bool" : arrayType, dest) let arrMapTemplete = `\ uint32_t len[replace_lt]=pxt->GetArrayLength(%s); @@ -144,7 +144,7 @@ function arrTemplete(dest, napiVn, type) { } %s.push_back(tt[replace_lt]); - }`.format(napiVn, arrayType, dest) + }\n`.format(napiVn, arrayType, dest) arrTemplete = arrTemplete.replaceAll("[replace_lt]", lt) let str = "std::mapGetArrayElement(%s,i%d)".format(napiVn, lt), arrayType)) } else if (arrayType == "bool") { arrTemplete = arrTemplete.replaceAll("[replace_swap]", - "pxt->SwapJs2CBool(pxt->GetArrayElement(%s,i%d));".format(napiVn, lt)) + "tt%d = pxt->SwapJs2CBool(pxt->GetArrayElement(%s,i%d));".format(lt, napiVn, lt)) } return arrTemplete } -function paramGenerateArray(p, name, type, param) { +function paramGenerateArray(p, funcValue, param) { + let type = funcValue.type + let name = funcValue.name + let inParamName = funcValue.optional ? "(*vio->in" + p + ")" : "vio->in" + p + let modifiers = funcValue.optional ? "* " : "&" if (type.substring(type.length - 2) == "[]") { let arrayType = getArrayTypeTwo(type) if (arrayType == "string") arrayType = "std::string" if (arrayType == "boolean") arrayType = "bool" - param.valueIn += "\n std::vector<%s> in%d;".format(arrayType, p) - param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) + param.valueIn += funcValue.optional ? "\n std::vector<%s>* in%d = nullptr;".format(arrayType, p) + : "\n std::vector<%s> in%d;".format(arrayType, p) + param.valueCheckout += jsToC(inParamName, "pxt->GetArgv(%d)".format(p), type) param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) - param.valueDefine += "%sstd::vector<%s> &%s".format(param.valueDefine.length > 0 ? ", " : "", arrayType, name) + param.valueDefine += "%sstd::vector<%s> %s%s".format(param.valueDefine.length > 0 ? ", " + : "", arrayType, modifiers, name) } else if (type.substring(0, 6) == "Array<") { let str = "[key:string]:" let strLen = str.length @@ -227,29 +233,39 @@ function paramGenerateArray(p, name, type, param) { } arrayType = "std::map".format(valueTypeOut) } - param.valueIn += "\n std::vector<%s> in%d;".format(arrayType, p) - param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) + param.valueIn += funcValue.optional ? "\n std::vector<%s>* in%d = nullptr;".format(arrayType, p) + : "\n std::vector<%s> in%d;".format(arrayType, p) + let arrValueCheckout = jsToC(inParamName, "pxt->GetArgv(%d)".format(p), type) + if (funcValue.optional) { + arrValueCheckout = "if (pxt->GetArgc() > %s) {\n vio->in%d = new std::vector<%s>;\n" + .format(p, p, arrayType) + arrValueCheckout + " }\n" + param.optionalParamDestory += "C_DELETE(vio->in%d);\n ".format(p) + } + param.valueCheckout += arrValueCheckout param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) - param.valueDefine += "%sstd::vector<%s> &%s".format(param.valueDefine.length > 0 ? ", " : "", arrayType, name) + param.valueDefine += "%sstd::vector<%s> %s%s".format(param.valueDefine.length > 0 ? ", " + : "", arrayType, modifiers, name) } else { NapiLog.logError("The current version do not support to this param to generate :", name, "type :", type); } } -function paramGenerateEnum(data, type, param, name, p) { - let index = enumIndex(type, data) +function paramGenerateEnum(data, funcValue, param, p) { + let index = enumIndex(funcValue.type, data) if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_NUMBER) { - type = "NUMBER_TYPE_" + NumberIncrease.getAndIncrease() + funcValue.type = "NUMBER_TYPE_" + NumberIncrease.getAndIncrease() } else if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_STRING) { - type = "string" + funcValue.type = "string" } else { NapiLog.logError(`paramGenerate is not support`); return } - paramGenerate(p, name, type, param, data) + paramGenerate(p, funcValue, param, data) } -function paramGenerateMap(type, param, p, name) { +function paramGenerateMap(funcValue, param, p) { + let type = funcValue.type + let name = funcValue.name let mapType = getMapType(type) let mapTypeString if (mapType[1] != undefined && mapType[2] == undefined) { @@ -268,11 +284,15 @@ function paramGenerateMap(type, param, p, name) { else if (mapType[3].substring(0, 12) == "NUMBER_TYPE_") { mapTypeString = "std::vector<"+mapType[3]+">" } else if (mapType[3] == "boolean") { mapTypeString = "std::vector" } } - param.valueIn += "\n std::map in%d;".format(mapTypeString, p) - param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) - param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) - param.valueDefine += "%sstd::map &%s" - .format(param.valueDefine.length > 0 ? ", " : "", mapTypeString, name) + let inParamName = funcValue.optional ? "(*vio->in" + p + ")" : "vio->in" + p + let modifiers = funcValue.optional ? "*" : "&" + param.valueIn += funcValue.optional ? "\n std::map* in%d = nullptr;".format(mapTypeString, p) + : "\n std::map in%d;".format(mapTypeString, p) + param.valueCheckout += getValueCheckout(funcValue, param, inParamName, p, + "std::map".format(mapTypeString)) + param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) + param.valueDefine += "%sstd::map%s %s" + .format(param.valueDefine.length > 0 ? ", " : "", mapTypeString, modifiers, name) } function mapTempleteFunc(dest, napiVn, type) { @@ -498,7 +518,8 @@ function mapArray(mapType, napiVn, dest, lt) { return mapTemplete } -function paramGenerateCallBack(data, type, param, p) { +function paramGenerateCallBack(data, funcValue, param, p) { + let type = funcValue.type let arrayType = re.match("(Async)*Callback<(Array<([a-zA-Z_0-9]+)>)>", type) let regType if (arrayType) { @@ -521,7 +542,8 @@ function paramGenerateCallBack(data, type, param, p) { } param.callback = { type: regType, - offset: p + offset: p, + optional: funcValue.optional } } @@ -532,42 +554,53 @@ function isArrayType(type) { return false; } +function getValueCheckout(funcValue, param, inParamName, p, cType) { + let valueCheckout = jsToC(inParamName, "pxt->GetArgv(%d)".format(p), funcValue.type) + "\n " + if (funcValue.optional) { + valueCheckout = "if (pxt->GetArgc() > %d) {\n vio->in%d = new %s;\n ".format(p, p, cType) + + valueCheckout + "}\n " + param.optionalParamDestory += "C_DELETE(vio->in%d);\n ".format(p) + } + return valueCheckout; +} + +function paramGenerateCommon(p, cType, funcValue, param, modifiers, inParamName) { + param.valueIn += funcValue.optional ? "\n %s* in%d = nullptr;".format(cType, p) + : "\n %s in%d;".format(cType, p) + param.valueCheckout += getValueCheckout(funcValue, param, inParamName, p, cType) + param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) + param.valueDefine += "%s%s%s %s".format( + param.valueDefine.length > 0 ? ", " : "", cType, modifiers, funcValue.name) +} + // 函数的参数处理 -function paramGenerate(p, name, type, param, data) { +function paramGenerate(p, funcValue, param, data) { + let type = funcValue.type + let name = funcValue.name + let inParamName = funcValue.optional ? "(*vio->in" + p + ")" : "vio->in" + p + let modifiers = funcValue.optional ? "*" : "&" if (type == "string") { - param.valueIn += "\n std::string in%d;".format(p) - param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) - param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) - param.valueDefine += "%sstd::string &%s".format(param.valueDefine.length > 0 ? ", " : "", name) + paramGenerateCommon(p, "std::string", funcValue, param, modifiers, inParamName) } else if (type.substring(0, 12) == "NUMBER_TYPE_" && type.indexOf("[]") < 0) { - param.valueIn += "\n %s in%d;".format(type, p) - param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) - param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) - param.valueDefine += "%s%s &%s".format(param.valueDefine.length > 0 ? ", " : "", type, name) + paramGenerateCommon(p, funcValue.type, funcValue, param, modifiers, inParamName) } else if (InterfaceList.getValue(type)) { - param.valueIn += "\n %s in%d;".format(type, p) - param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) - param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) - param.valueDefine += "%s%s &%s".format(param.valueDefine.length > 0 ? ", " : "", type, name) + paramGenerateCommon(p, funcValue.type, funcValue, param, modifiers, inParamName) } else if (type.substring(0, 9) == "Callback<" || type.substring(0, 14) == "AsyncCallback<") { - paramGenerateCallBack(data, type, param, p) + paramGenerateCallBack(data, funcValue, param, p) } else if (type == "boolean") { - param.valueIn += "\n bool in%d;".format(p) - param.valueCheckout += jsToC("vio->in" + p, "pxt->GetArgv(%d)".format(p), type) - param.valueFill += "%svio->in%d".format(param.valueFill.length > 0 ? ", " : "", p) - param.valueDefine += "%sbool &%s".format(param.valueDefine.length > 0 ? ", " : "", name) + paramGenerateCommon(p, "bool", funcValue, param, modifiers, inParamName) } else if (isEnum(type, data)) { - paramGenerateEnum(data, type, param, name, p) + paramGenerateEnum(data, funcValue, param, p) } else if (type.substring(0, 4) == "Map<" || type.indexOf("{") == 0) { - paramGenerateMap(type, param, p, name) + paramGenerateMap(funcValue, param, p) } else if (isArrayType(type)) { - paramGenerateArray(p, name, type, param); + paramGenerateArray(p, funcValue, param); } else { NapiLog.logError("function paramGenerate: The current version do not support to this param to generate :" , name, "type :", type); @@ -575,13 +608,15 @@ function paramGenerate(p, name, type, param, data) { } // on/off 接口的event名称参数处理 -function eventParamGenerate(p, name, type, param, data) { +function eventParamGenerate(p, funcValue, param, data) { + let name = funcValue.name; + let type = funcValue.type; let regName = re.match("'([a-zA-Z_0-9]+)'", type) if (regName) { param.eventName = re.getReg(type, regName.regs[1]) param.valueDefine += "%sstd::string &%s".format(param.valueDefine.length > 0 ? ", " : "", name) } else if (type.substring(0, 9) == "Callback<" || type.substring(0, 14) == "AsyncCallback<") { - paramGenerateCallBack(data, type, param, p) + paramGenerateCallBack(data, funcValue, param, p) } else { NapiLog.logError("function eventParamGenerate:The current version do not support to this param to generate :" , name, "type :", type); @@ -595,5 +630,6 @@ module.exports = { paramGenerate, paramGenerateArray, paramGenerateMap, - mapTempleteFunc + mapTempleteFunc, + eventParamGenerate } \ No newline at end of file diff --git a/src/gen/generate/return_generate.js b/src/gen/generate/return_generate.js index 0104f251..bf59c6c2 100644 --- a/src/gen/generate/return_generate.js +++ b/src/gen/generate/return_generate.js @@ -287,7 +287,8 @@ function mapTempleteArray(mapType, tnvdef, lt) { return ret } -function returnGenerateMap(type, param) { +function returnGenerateMap(returnInfo, param) { + let type = returnInfo.type let mapType = getMapType(type) let mapTypeString if (mapType[1] != undefined && mapType[2] == undefined) { @@ -306,36 +307,44 @@ function returnGenerateMap(type, param) { else if (mapType[3].substring(0, 12) == "NUMBER_TYPE_") { mapTypeString = "std::vector<"+mapType[3]+">" } else if (mapType[3] == "boolean") { mapTypeString = "std::vector" } } - param.valueOut = "std::map out;".format(mapTypeString) - param.valueDefine += "%sstd::map &out" - .format(param.valueDefine.length > 0 ? ", " : "", mapTypeString) + let modifiers = returnInfo.optional ? "*" : "&" + param.valueOut = returnInfo.optional ? "std::map* out = nullptr;".format(mapTypeString) + : "std::map out;".format(mapTypeString) + param.valueDefine += "%sstd::map%s out" + .format(param.valueDefine.length > 0 ? ", " : "", mapTypeString, modifiers) } -function returnGenerate(type, param, data) { +function returnGenerate(returnInfo, param, data) { + let type = returnInfo.type param.valueFill += "%svio->out".format(param.valueFill.length > 0 ? ", " : "") + let outParam = returnInfo.optional ? "(*vio->out)" : "vio->out" + let modifiers = returnInfo.optional ? "*" : "&" + if (returnInfo.optional) { + param.optionalParamDestory += "C_DELETE(vio->out);\n " + } if (!isEnum(type, data)) { - param.valuePackage = "napi_value result = nullptr;\n " + cToJs("vio->out", type, "result") + param.valuePackage = cToJs(outParam, type, "result") } if (type == "string") { - param.valueOut = "std::string out;" - param.valueDefine += "%sstd::string &out".format(param.valueDefine.length > 0 ? ", " : "") + param.valueOut = returnInfo.optional ? "std::string* out = nullptr;" : "std::string out;" + param.valueDefine += "%sstd::string%s out".format(param.valueDefine.length > 0 ? ", " : "", modifiers) } else if (type == "void") { NapiLog.logInfo("The current void type don't need generate"); } else if (type == "boolean") { - param.valueOut = "bool out;" - param.valueDefine += "%sbool &out".format(param.valueDefine.length > 0 ? ", " : "") + param.valueOut = returnInfo.optional ? "bool* out = nullptr;" : "bool out;" + param.valueDefine += "%sbool%s out".format(param.valueDefine.length > 0 ? ", " : "", modifiers) } else if (isEnum(type, data)) { - returnGenerateEnum(data, type, param) + returnGenerateEnum(data, returnInfo, param) } else if (type.substring(0, 12) == "NUMBER_TYPE_") { - param.valueOut = type + " out;" - param.valueDefine += "%s%s &out".format(param.valueDefine.length > 0 ? ", " : "", type) + param.valueOut = type + (returnInfo.optional ? "* out = nullptr;" : " out;") + param.valueDefine += "%s%s%s out".format(param.valueDefine.length > 0 ? ", " : "", type, modifiers) } else if(generateType(type)){ - returnGenerate2(type, param, data) + returnGenerate2(returnInfo, param, data) } else { NapiLog.logError("function returnGenerate:The current version do not support this type return %s".format(type)); @@ -360,30 +369,39 @@ function generateType(type){ } } -function returnGenerate2(type, param, data){ +function returnGenerate2(returnInfo, param, data){ + let type = returnInfo.type + let modifiers = returnInfo.optional ? "*" : "&" + if (InterfaceList.getValue(type)) { - param.valueOut = type + " out;" - param.valueDefine += "%s%s &out".format(param.valueDefine.length > 0 ? ", " : "", type) + param.valueOut = type + (returnInfo.optional ? "* out = nullptr;" : " out;") + param.valueDefine += "%s%s%s out".format(param.valueDefine.length > 0 ? ", " : "", type, modifiers) } else if (type.substring(0, 6) == "Array<") { let arrayType = getArrayType(type) if (arrayType == "string") arrayType = "std::string" - param.valueOut = "std::vector<%s> out;".format(arrayType) - param.valueDefine += "%sstd::vector<%s> &out".format(param.valueDefine.length > 0 ? ", " : "", arrayType) + param.valueOut = returnInfo.optional ? "std::vector<%s>* out = nullptr;".format(arrayType) + : "std::vector<%s> out;".format(arrayType) + param.valueDefine += "%sstd::vector<%s>%s out".format( + param.valueDefine.length > 0 ? ", ": "", arrayType, modifiers) } else if (type.substring(type.length - 2) == "[]") { let arrayType = getArrayTypeTwo(type) if (arrayType == "string") arrayType = "std::string" - param.valueOut = "std::vector<%s> out;".format(arrayType) - param.valueDefine += "%sstd::vector<%s> &out".format(param.valueDefine.length > 0 ? ", " : "", arrayType) + param.valueOut = returnInfo.optional ? "std::vector<%s>* out = nullptr;".format(arrayType) + : "std::vector<%s> out;".format(arrayType) + param.valueDefine += "%sstd::vector<%s>%s out".format( + param.valueDefine.length > 0 ? ", " : "", arrayType, modifiers) } else if (type.substring(0, 4) == "Map<" || type.indexOf("{") == 0) { - returnGenerateMap(type, param) + returnGenerateMap(returnInfo, param) } } -function returnGenerateEnum(data, type, param) { +function returnGenerateEnum(data, returnInfo, param) { + let type = returnInfo.type let index = enumIndex(type, data) + let modifiers = returnInfo.optional ? "*" : "&" if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_NUMBER) { type = "NUMBER_TYPE_" + NumberIncrease.getAndIncrease() } else if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_STRING) { @@ -392,14 +410,14 @@ function returnGenerateEnum(data, type, param) { NapiLog.logError(`function returnGenerateEnum:this type is not support %s`.format(type)); return } - param.valuePackage = "napi_value result = nullptr;\n " + cToJs("vio->out", type, "result") + param.valuePackage = cToJs("vio->out", type, "result") if (type == "string") { - param.valueOut = "std::string out;" - param.valueDefine += "%sstd::string &out".format(param.valueDefine.length > 0 ? ", " : "") + param.valueOut = returnInfo.optional ? "std::string* out = nullptr;" : "std::string out;" + param.valueDefine += "%sstd::string%s out".format(param.valueDefine.length > 0 ? ", " : "", modifiers) } else if (type.substring(0, 12) == "NUMBER_TYPE_") { param.valueOut = type + " out;" - param.valueDefine += "%s%s &out".format(param.valueDefine.length > 0 ? ", " : "", type) + param.valueDefine += "%s%s%s out".format(param.valueDefine.length > 0 ? ", " : "", type, modifiers) } } diff --git a/test/unittest/analyze.test.js b/test/unittest/analyze.test.js index c0816b94..b714ab2f 100755 --- a/test/unittest/analyze.test.js +++ b/test/unittest/analyze.test.js @@ -232,34 +232,34 @@ function partOfNamespaceTwo(correctResult){ function partOfParam(correctResult) { it('test gen/analyze/params analyzeDirectParams', function () { - let ret = analyzeParams('v1:string,v2:boolean'); + let ret = analyzeParams('', 'v1:string,v2:boolean'); let retJson = JSON.stringify(ret) assert.strictEqual(retJson, correctResult['Analyze']['analyzeDirectParams']); assert.strictEqual(ret[1], 1); }); it('test gen/analyze/params analyzeAsynctParams', function () { - let ret = analyzeParams('v2:string,cb:AsyncCallback'); + let ret = analyzeParams('', 'v2:string,cb:AsyncCallback'); let retJson = JSON.stringify(ret) assert.strictEqual(retJson, correctResult['Analyze']['analyzeAsynctParams']); assert.strictEqual(ret[1], 4); }); it('test gen/analyze/params analyzeSynctParams', function () { - let ret = analyzeParams('v2:boolean,cb:Callback'); + let ret = analyzeParams('', 'v2:boolean,cb:Callback'); let retJson = JSON.stringify(ret) assert.strictEqual(retJson, correctResult['Analyze']['analyzeSynctParams']); assert.strictEqual(ret[1], 2); }); it('test gen/analyze/params analyzeArrayParams', function () { - let ret = analyzeParams("v1: Array,v2:Map"); + let ret = analyzeParams('', "v1: Array,v2:Map"); let retJson = JSON.stringify(ret) assert.strictEqual(retJson, correctResult['Analyze']['analyzeArrayParams']); }); it('test gen/analyze/params analyzeMapParams', function () { - let ret = analyzeParams("v1: string[],v2:{[key:string]:boolean}"); + let ret = analyzeParams('', "v1: string[],v2:{[key:string]:boolean}"); let retJson = JSON.stringify(ret) assert.strictEqual(retJson, correctResult['Analyze']['analyzeMapParams']); }); diff --git a/test/unittest/generate.test.js b/test/unittest/generate.test.js index 5f599e29..d3fb3f84 100755 --- a/test/unittest/generate.test.js +++ b/test/unittest/generate.test.js @@ -16,6 +16,7 @@ let genDir = "../../src/gen/" const { analyzeFile } = require(genDir + "analyze"); var assert = require("assert"); +const { info } = require("console"); const { JsxEmit } = require("typescript"); const { readFile } = require(genDir + "tools/FileRW"); const { generateEnum } = require(genDir + "generate/enum"); @@ -382,7 +383,8 @@ function partofParamGenerate(correctResult){ valueOut: '', valuePackage: '' } - paramGenerateArray('0','v','Array',param); + let funcValue = {name: 'v', type: 'Array'} + paramGenerateArray('0',funcValue,param); assert.strictEqual(JSON.stringify(param), correctResult['Generate']['paramGenerateArray']); }); @@ -452,10 +454,11 @@ function returnGenerateAndAssert(dataType, structOfTs) { valuePackage: "", valueDefine: "" } + let returnInfo = {type: dataType, optional: false} if (null != structOfTs) { - returnGenerate(dataType, param, structOfTs) + returnGenerate(returnInfo, param, structOfTs) } else { - returnGenerate(dataType, param) + returnGenerate(returnInfo, param) } let result = JSON.stringify(param); return result @@ -503,10 +506,11 @@ function paramGenerateAndAssert(dataType, structOfTs) { valuePackage: "", valueDefine: "" } + let funcValue = {name: "a", type: dataType} if (null != structOfTs) { - paramGenerate(0, "a", dataType, param, structOfTs) + paramGenerate(0, funcValue, param, structOfTs) } else { - paramGenerate(0, "a", dataType, param) + paramGenerate(0, funcValue, param) } let result = JSON.stringify(param); return result -- Gitee