diff --git a/src/vscode_plugin/src/gen/gencpp.ts b/src/vscode_plugin/src/gen/gencpp.ts index 2bafbfb9a2d6e4faa12f15ab6b42c323afc59ebb..ac24ff866a369039c9e213ae934710d5e4529106 100644 --- a/src/vscode_plugin/src/gen/gencpp.ts +++ b/src/vscode_plugin/src/gen/gencpp.ts @@ -13,20 +13,24 @@ * limitations under the License. */ -import { DirTemp, FuncInfo, FuncObj, GenInfo, InterfaceList, TypeList } from "./datatype"; +import { DirTemp, FuncInfo, GenInfo, InterfaceList, TypeList } from "./datatype"; import { getInterfaceBody, getTypeBody } from "./gendts"; import { - boolIn, boolRet, doubleIn, doubleRet, funcGetParamTemplate, int32tIn, int32tRet, int64tIn, int64tRet, - napiFuncCppTemplate, napiFuncHTemplate, napiFuncInitTemplate, napiFuncRetTemplate, objectRet, objectTosetRet, - paramGenTemplate, promiseRet, stringIn, stringRet, - uint32tIn, uint32tRet + boolIn, boolRet, doubleIn, doubleRet, funcGetParamTemplate, int32tIn, + int32tRet, int64tIn, int64tRet, napiFuncCppTemplate, + napiFuncRetTemplate, objectRet, objectTosetRet, paramGenTemplate, stringIn, + stringRet, uint32tIn, uint32tRet } from "../template/func_template"; import { replaceAll } from "../common/tool"; import { cppdir } from "../template/dtscpp/dtscppdir"; import * as path from 'path'; import * as fs from 'fs'; -import { h2NapiInKey, h2NapiOutKey } from "../template/dtscpp/dts2cpp_key"; -import { napiCppTemplate } from "../template/dtscpp/dtscpp_napicpp_template"; +import { genInitCppFile } from "./tools/gennapiinit"; +import { genNapiHFile } from "./tools/gennapih"; +import { genNapiCppFile } from "./tools/gennapicpp"; +import { genCommonHFile } from "./tools/gennapicommonh"; +import { genCommonCppFile } from "./tools/gennapicommoncpp"; +import { genNapiCommonFile } from "./tools/gencommonfile"; interface RetObjInfo { objName: string; @@ -231,222 +235,10 @@ const fileHandlers: { [key: string]: Function } = { '[fileName]napi.cpp': genNapiCppFile, '[fileName]common.h': genCommonHFile, '[fileName]common.cpp': genCommonCppFile, - '[fileName].h': genCommonFile, - 'readme.md': genCommonFile + '[fileName].h': genNapiCommonFile, + 'readme.md': genNapiCommonFile }; -// 通过类型值映射模板,比如:uint32_t返回值 -> uint32tRet -> napi_create_uint32 -export function transCkey2NapiOutkey(key: string) { - // 如果是ts传递的Promise<>类型,并且transTs2C时未转换,那么就返回promiseRet - let tsPromiseReg = /Promise<([^>]+)>/g; - const tsPromiseMatch = tsPromiseReg.exec(key); - if (tsPromiseMatch) { - return promiseRet; - } - - // 数组 map set iterator tuple pair 等都当作objectOut处理 - for (const keyItem of h2NapiOutKey) { - for (const str of keyItem.keys) { - if (key.includes(str)) { - return keyItem.value; - } - } - } - let replaceKeyList = ['enum', 'struct', 'union']; - for (const rkey of replaceKeyList) { - key = key.replace(rkey, '').trim(); - } - // 其他的全部当作object处理, 如typeDef/enum/struct/union/class等,当作objectOut处理,返回objectRet - return objectRet; -} - -// 通过类型值映射模板,比如:uint32_t输入 -> uint32tIn -> napi_get_value_uint32 -export function transCkey2NapiInkey(key: string) { - for (const keyItem of h2NapiInKey) { - for (const str of keyItem.keys) { - if (key.includes(str)) { - return keyItem.value; - } - } - } - let replaceKeyList = ['enum', 'struct', 'union']; - for (const rkey of replaceKeyList) { - key = key.replace(rkey, '').trim(); - } - // 其他的全部当作object处理, 如typeDef/enum/struct/union/class等, 此时不需要做任何处理,因此返回空 - return ''; - -} - -// 把这些东西分成一个个文件,根据文件内容来生成 -export function genCommonFile(rootInfo: GenInfo, filePath: string, - fileContent: string) { - fs.writeFileSync(filePath, fileContent); -} -// 生成Init的文件 - -export function genInitCppFile(rootInfo: GenInfo, filePath: string, - fileContent: string) { - let napiInitContent = ''; - if (rootInfo.parseObj && rootInfo.parseObj.funcs) { - rootInfo.parseObj.funcs.forEach(func => { - let funcName = func.name; - napiInitContent += replaceAll(napiFuncInitTemplate, - '[func_name_replace]', funcName); - }); - } - // 写文件 - fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); - fileContent = replaceAll(fileContent, '[init_replace]', napiInitContent); - fs.writeFileSync(filePath, fileContent); -} - -// 生成common.h文件,这个读模板直接生成 -export function genCommonHFile(rootInfo: GenInfo, filePath: string, - fileContent: string) { - let upperFileName = rootInfo.fileName.toLocaleUpperCase(); - fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); - fileContent = replaceAll(fileContent, '[upper_filename]', upperFileName); - fs.writeFileSync(filePath, fileContent); -} -// 生成common.cpp文件,读模板直接生成 -export function genCommonCppFile(rootInfo: GenInfo, filePath: string, fileContent: string) { - fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); - fs.writeFileSync(filePath, fileContent); -} - -// 生成napi.h文件 -export function genNapiHFile(rootInfo: GenInfo, filePath: string, - fileContent: string) { - let napiHContent = ''; - if (rootInfo.parseObj && rootInfo.parseObj.funcs) { - rootInfo.parseObj.funcs.forEach(func => { - let funcParams = ''; - for (let i = 0; i < func.parameters.length; ++i) { - funcParams += i > 0 ? ', ' : ''; - funcParams += func.parameters[i].name + ': ' + func.parameters[i].type; - } - let rawFileName = path.basename(rootInfo.rawFilePath); - let hContent = replaceAll(napiFuncHTemplate, '[file_introduce_replace]', rawFileName); - hContent = replaceAll(hContent, '[input_introduce_replace]', funcParams === '' ? 'void' : funcParams); - hContent = replaceAll(hContent, '[func_name_replace]', func.name); - hContent = replaceAll(hContent, '[func_param_replace]', funcParams); - hContent = replaceAll(hContent, '[func_return_replace]', - func.returns === '' ? 'void' : func.returns); - napiHContent += hContent; - }); - } - let upperFileName = rootInfo.fileName.toLocaleUpperCase(); - fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); - fileContent = replaceAll(fileContent, '[upper_filename]', upperFileName); - fileContent = replaceAll(fileContent, '[func_declare_replace]', napiHContent); - fs.writeFileSync(filePath, fileContent); -} - -// 生成napi.cpp文件 -export function genNapiCppFile(rootInfo: GenInfo, filePath: string, - fileContent: string) { - let napiCppContent = ''; - if (rootInfo.parseObj && rootInfo.parseObj.funcs) { - rootInfo.parseObj.funcs.forEach(funcInfo => { - // 替换每个方法主体 - let hFileName = path.basename(rootInfo.rawFilePath); - let bodyReplace = replaceAll(napiFuncCppTemplate, '[func_name_replace]', - funcInfo.name); - bodyReplace = replaceAll(bodyReplace, '[get_error_msg_tag]', - funcInfo.name); - bodyReplace = replaceAll(bodyReplace, '[file_introduce_replace]', - hFileName); - // 生成方法注释 - let funcInfoParams = funcInfo.parameters.length > 0 ? '' : 'void'; - let funcInfoParamTemp = '[paramName]: [paramType]; '; - for (let i = 0; i < funcInfo.parameters.length; i++) { - let funcInfoParamReplace = replaceAll(funcInfoParamTemp, '[paramName]', - funcInfo.parameters[i].name); - funcInfoParamReplace = replaceAll(funcInfoParamReplace, '[paramType]', - funcInfo.parameters[i].type); - funcInfoParams += funcInfoParamReplace; - } - bodyReplace = replaceAll(bodyReplace, '[input_introduce_replace]', - funcInfoParams === '' ? 'void' : funcInfoParams); - bodyReplace = replaceAll(bodyReplace, '[output_introduce_replace]', - funcInfo.returns); - // 方法参数的处理,解析参数类型,生成napi的参数处理代码 - let paramGenResult = getCppParamGen(funcInfo); - bodyReplace = replaceAll(bodyReplace, '[func_getParam_replace]', - paramGenResult); - // 方法返回值的处理,解析返回值类型,生成napi的返回值处理代码 - let returnGenResult = genCppReturnGen(funcInfo); - bodyReplace = replaceAll(bodyReplace, '[func_return_replace]', - returnGenResult); - // 组合一个个方法 - napiCppContent += bodyReplace; - }); - - // 生成xxxNapi.cpp文件 - fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); - fileContent = replaceAll(fileContent, '[func_content_replace]', napiCppContent); - fs.writeFileSync(filePath, fileContent); - } - - fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); - fileContent = replaceAll(fileContent, '[func_content_replace]', napiCppContent); - fs.writeFileSync(filePath, fileContent); -} - -// 方法输入参数的处理,只处理基本类型,像数组/map/set/class/struct等都全部当作 -// object,且不做处理 -export function getCppParamGen(funcInfo: FuncObj): string { - // 处理输入的参数,生成napi的参数处理代码 - if (funcInfo.parameters.length === 0) { - return '// no input params'; - } - let paramGenResult = ''; - for (let i = 0; i < funcInfo.parameters.length; ++i) { - let getParamInTemplate = transCkey2NapiInkey(funcInfo.parameters[i].type); - // 如果getParamInTemplate是空,则默认是对象输入,不做任何处理 - if (getParamInTemplate === '') { - paramGenResult += '// Todo: handle object input.\n\n'; - continue; - } - let getParam = replaceAll(getParamInTemplate, '[param_index_replace]', - 'PARAMS' + i); - getParam = replaceAll(getParam, '[param_name_replace]', - funcInfo.parameters[i].name); - let paramGen = replaceAll(paramGenTemplate, '[param_index_replace]', - 'PARAMS' + i); - paramGen = replaceAll(paramGen, '[param_name_replace]', - funcInfo.parameters[i].name); - paramGen = replaceAll(paramGen, '[getParam_replace]', getParam); - paramGenResult += paramGen; - } - let genParamReplace = replaceAll(funcGetParamTemplate, '[param_length]', - 'PARAMS' + funcInfo.parameters.length); - genParamReplace = replaceAll(genParamReplace, '[func_name_replace]', - funcInfo.name); - genParamReplace = replaceAll(genParamReplace, '[getAllParam_replace]', - paramGenResult); - return genParamReplace -} - -// 方法返回值的处理 -export function genCppReturnGen(funcInfo: FuncObj): string { - // 如果函数返回值是空,直接返回NULL - if (funcInfo.returns === 'void') { - return ' return NULL;\n'; - } - let returnName = funcInfo.name; - let funcReturnReplace = replaceAll(napiFuncRetTemplate, '[return_name]', - returnName); - let retGenResult = transCkey2NapiOutkey(funcInfo.returns); - retGenResult = replaceAll(retGenResult, '[return_name_replace]', returnName); - funcReturnReplace = replaceAll(funcReturnReplace, '[func_name_replace]', - funcInfo.name); - funcReturnReplace = replaceAll(funcReturnReplace, '[return_replace]', - retGenResult); - return funcReturnReplace; -} - export function genDir(dirItem: DirTemp, rootInfo: GenInfo, out: string) { let dirPath = path.join(out, dirItem.name); let lowerFileName = rootInfo.fileName.toLocaleLowerCase(); diff --git a/src/vscode_plugin/src/gen/gentest.ts b/src/vscode_plugin/src/gen/gentest.ts index e4e38d43843f356b76a6198aad8c5634773ce671..fedac6e71b2e046f6eae7314ba3960a08e6da620 100644 --- a/src/vscode_plugin/src/gen/gentest.ts +++ b/src/vscode_plugin/src/gen/gentest.ts @@ -15,7 +15,7 @@ import util = require('util'); import { replaceAll } from "../common/tool"; -import { FuncInfo, GenInfo, InterfaceList, ParamObj, TypeList } from "./datatype"; +import { ClassObj, StructObj, FuncInfo, FuncObj, GenInfo, InterfaceList, ParamObj, TypeList } from "./datatype"; import { getInterfaceBody, getTypeBody, transTskey2Ckey } from './gendts'; import { testAbilityFuncTemplate } from "../template/func_template"; import { Logger } from '../common/log'; @@ -208,54 +208,33 @@ export function genAbilitytestFile(rootInfo: GenInfo, out: string) { out = path.dirname(rootInfo.rawFilePath); } let testContent = '' + // 1.遍历所有class + testContent = genClassTestcase(rootInfo, testContent); + + // 1.遍历所有struct + testContent = genStructTestcase(rootInfo, testContent); + + // 2.遍历所有函数 + testContent = genFunctionTestcase(rootInfo, testContent); + + let fileContent = replaceAll(testFirstGenTemplate.content, + '[testAbilityFunctions]', testContent); + // 将文件写入out文件夹 + if (!fs.existsSync(out)) { + fs.mkdirSync(out, { recursive: true }); + } + let lowerFileName = rootInfo.fileName.toLocaleLowerCase(); + let fileName = testFirstGenTemplate.name.replace('[fileName]', + lowerFileName); + fileContent = replaceAll(fileContent, '[fileName]', lowerFileName); + let filePath = path.join(out, fileName); + fs.writeFileSync(filePath, fileContent); +} + +export function genFunctionTestcase(rootInfo: GenInfo, testContent: string) { if (rootInfo.parseObj && rootInfo.parseObj.funcs) { rootInfo.parseObj.funcs.forEach(funcInfo => { - let callFunc = ''; // 调用函数内容 - let hilogContent = ''; // hilog内容 - let funcParamDefine = ''; // 函数参数定义并初始化 - let funcParamUse = ''; // 函数参数使用 - let funcInfoParams = ''; // 注释 - let funcInfoParamTemp = '[paramName]: [paramType]; '; - // 遍历方法参数,给参数赋初始值,生成注释和参数使用内容 - // 1. 先将所有type转换为ts的type - for (let i = 0; i < funcInfo.parameters.length; ++i) { - // 注释 - let funcInfoParamReplace = replaceAll(funcInfoParamTemp, '[paramName]', - funcInfo.parameters[i].name); - funcInfoParamReplace = replaceAll(funcInfoParamReplace, '[paramType]', - funcInfo.parameters[i].type); - funcInfoParams += funcInfoParamReplace; - // 参数定义并初始化 - const param = funcInfo.parameters[i]; - let paramType = transTskey2Ckey(param.type); - let testValue = 'undefined; // Please give an any value.'; // any类型咋赋值? - dts2TestValue.forEach(item => { - if (item.key === paramType) { - testValue = item.value; - } - }) - funcParamDefine += util.format('let %s: %s = %s;\n ', - funcInfo.parameters[i].name, paramType, testValue); - funcParamUse += funcInfo.parameters[i].name + ', '; - // 如果是最后一个参数,去掉最后的逗号和空格 - if (funcInfo.parameters.length === i + 1) { - funcParamUse = funcParamUse.slice(0, -2); // 去掉最后一个逗号和空格 - } - } - // 返回值,如果本来就是ts类型就不用替换了:如Promise,就不用替换了 - let tsPromiseReg = /Promise<([^>]+)>/g; - let returnType = tsPromiseReg.exec(funcInfo.returns)? funcInfo.returns: - transTskey2Ckey(funcInfo.returns); - if (returnType === 'void') { - callFunc = util.format('testNapi.%s(%s)\n ', funcInfo.name, - funcParamUse); - } else { - callFunc = util.format('let result: %s = testNapi.%s(%s)\n ', - returnType, funcInfo.name, funcParamUse); - hilogContent = util.format( - 'hilog.info(0x0000, "testTag", "Test NAPI %s: ", JSON.stringify(result));\n ',funcInfo.name); - } - let funcTestReplace = funcParamDefine + callFunc + hilogContent; + let { funcTestReplace, funcInfoParams } = genMethodTestcase(funcInfo, false, ''); let rawFileName = path.basename(rootInfo.rawFilePath); // 替换test_case_name let funcTestContent = replaceAll(testAbilityFuncTemplate, @@ -264,25 +243,133 @@ export function genAbilitytestFile(rootInfo: GenInfo, out: string) { funcInfo.name); funcTestContent = replaceAll(funcTestContent, '[file_introduce_replace]', rawFileName); - funcTestContent = replaceAll(funcTestContent, '[func_introduce_replace]', - funcInfo.name); - funcTestContent = replaceAll(funcTestContent, + funcTestContent = replaceAll(funcTestContent, '[input_introduce_replace]', funcInfoParams === '' ? 'void' : funcInfoParams); - funcTestContent = replaceAll(funcTestContent, '[func_return_replace]', + funcTestContent = replaceAll(funcTestContent, '[func_return_replace]', funcInfo.returns); testContent += funcTestContent; }); + } + return testContent; +} + +export function genStructTestcase(rootInfo: GenInfo, testContent: string) { + if (rootInfo.parseObj && rootInfo.parseObj.structs) { + // 只测试成员方法,不测试成员变量的get/set函数??? 还是得测试吧? + rootInfo.parseObj.structs.forEach(structItem => { + let structTestContent = util.format('let %sObj = new testNapi.%s();\n ', structItem.name.toLocaleLowerCase(), structItem.name); + // 1.1.遍历所有成员变量 测试set/get函数 + structItem.members.forEach(variable => { + structTestContent = genClassGetSetTestcase(variable, structTestContent, structItem); + }); + + // 1.2.遍历所有成员函数 + structItem.functions.forEach(funcInfo => { + // 无法判断函数是否为静态函数/是否为constructor/析构函数,所以先全部测试一遍 + let { funcTestReplace, funcInfoParams } = genMethodTestcase(funcInfo, true, structItem.name); + structTestContent += funcTestReplace; + }); + let clsTestContent = replaceAll(testAbilityFuncTemplate, '[func_direct_testCase]', structTestContent); + clsTestContent = replaceAll(clsTestContent, '[test_case_name]', structItem.name); + clsTestContent = replaceAll(clsTestContent, '[file_introduce_replace]', path.basename(rootInfo.rawFilePath)); + clsTestContent = replaceAll(clsTestContent, '[input_introduce_replace]', 'this is a test case for class.'); + clsTestContent = replaceAll(clsTestContent, '[func_return_replace]', 'this is a test case for class.'); + + testContent += clsTestContent; + }); + } + return testContent; +} + +export function genClassTestcase(rootInfo: GenInfo, testContent: string) { + if (rootInfo.parseObj && rootInfo.parseObj.classes) { + rootInfo.parseObj.classes.forEach(classItem => { + let classTestContent = util.format('let %sObj = new testNapi.%s();\n ', classItem.name.toLocaleLowerCase(), classItem.name); + // 1.1.遍历所有成员变量 测试set/get函数 + classItem.variableList.forEach(variable => { + classTestContent = genClassGetSetTestcase(variable, classTestContent, classItem); + }); + + // 1.2.遍历所有成员函数 + classItem.functionList.forEach(funcInfo => { + // 无法判断函数是否为静态函数/是否为constructor/析构函数,所以先全部测试一遍 + let { funcTestReplace, funcInfoParams } = genMethodTestcase(funcInfo, true, classItem.name); + classTestContent += funcTestReplace; + }); + let clsTestContent = replaceAll(testAbilityFuncTemplate, '[func_direct_testCase]', classTestContent); + clsTestContent = replaceAll(clsTestContent, '[test_case_name]', classItem.name); + clsTestContent = replaceAll(clsTestContent, '[file_introduce_replace]', path.basename(rootInfo.rawFilePath)); + clsTestContent = replaceAll(clsTestContent, '[input_introduce_replace]', 'this is a test case for class.'); + clsTestContent = replaceAll(clsTestContent, '[func_return_replace]', 'this is a test case for class.'); + + testContent += clsTestContent; + }); + } + return testContent; +} - let fileContent = replaceAll(testFirstGenTemplate.content, - '[testAbilityFunctions]', testContent); - // 将文件写入out文件夹 - if (!fs.existsSync(out)) { - fs.mkdirSync(out, { recursive: true }); +export function genClassGetSetTestcase(variable: ParamObj, classTestContent: string, classItem: ClassObj | StructObj) { + let variableType = transTskey2Ckey(variable.type); + let testValue = 'undefined; // Please give an any value.'; + dts2TestValue.forEach(item => { + if (item.key === variableType) { + testValue = item.value; } - let lowerFileName = rootInfo.fileName.toLocaleLowerCase(); - let fileName = testFirstGenTemplate.name.replace('[fileName]', - lowerFileName); - let filePath = path.join(out, fileName); - fs.writeFileSync(filePath, fileContent); + }); + // 成员变量的set + classTestContent += util.format('%sObj.%s = %s;\n ', classItem.name.toLocaleLowerCase(), variable.name, testValue); + // 成员变量的get //即打印log + classTestContent += util.format('console.log("%sObj.%s = ", %sObj.%s);\n ', classItem.name.toLocaleLowerCase(), + variable.name, classItem.name.toLocaleLowerCase(), variable.name); + return classTestContent; +} + +export function genMethodTestcase(funcInfo: FuncObj, isClassMethod: boolean, className: string = '') { + let callFunc = ''; // 调用函数内容 + let hilogContent = ''; // hilog内容 + let funcParamDefine = ''; // 函数参数定义并初始化 + let funcParamUse = ''; // 函数参数使用 + let funcInfoParams = ''; // 注释 + let funcInfoParamTemp = '[paramName]: [paramType]; '; + // 遍历方法参数,给参数赋初始值,生成注释和参数使用内容 + // 1. 先将所有type转换为ts的type + for (let i = 0; i < funcInfo.parameters.length; ++i) { + // 注释 + let funcInfoParamReplace = replaceAll(funcInfoParamTemp, '[paramName]', + funcInfo.parameters[i].name); + funcInfoParamReplace = replaceAll(funcInfoParamReplace, '[paramType]', + funcInfo.parameters[i].type); + funcInfoParams += funcInfoParamReplace; + // 参数定义并初始化 + const param = funcInfo.parameters[i]; + let paramType = transTskey2Ckey(param.type); + let testValue = 'undefined; // Please give an any value.'; // any类型咋赋值? + dts2TestValue.forEach(item => { + if (item.key === paramType) { + testValue = item.value; + } + }); + funcParamDefine += util.format('let %s: %s = %s;\n ', + funcInfo.parameters[i].name, paramType, testValue); + funcParamUse += funcInfo.parameters[i].name + ', '; + // 如果是最后一个参数,去掉最后的逗号和空格 + if (funcInfo.parameters.length === i + 1) { + funcParamUse = funcParamUse.slice(0, -2); // 去掉最后一个逗号和空格 + } + } + // 返回值,如果本来就是ts类型就不用替换了:如Promise,就不用替换了 + let tsPromiseReg = /Promise<([^>]+)>/g; + let returnType = tsPromiseReg.exec(funcInfo.returns) ? funcInfo.returns : + transTskey2Ckey(funcInfo.returns); + if (returnType === 'void') { + callFunc = util.format('%s%s(%s)\n ', isClassMethod ? className.toLocaleLowerCase() + 'Obj.' : 'testNapi.', + funcInfo.name, funcParamUse); + } else { + callFunc = util.format('let result: %s = %s%s(%s)\n ', returnType, + isClassMethod ? className.toLocaleLowerCase() + 'Obj.' : 'testNapi.', funcInfo.name, funcParamUse); + hilogContent = util.format( + 'hilog.info(0x0000, "testTag", "Test NAPI %s: ", JSON.stringify(result));\n ', funcInfo.name); } + let funcTestReplace = funcParamDefine + callFunc + hilogContent; + return { funcTestReplace, funcInfoParams }; } \ No newline at end of file diff --git a/src/vscode_plugin/src/gen/tools/gencommonfile.ts b/src/vscode_plugin/src/gen/tools/gencommonfile.ts index 219c0f6b27860980bb13e507dd54a8d46ed6bc6b..c3edde0b86fc99827edaf31d26297be8126f8ca8 100644 --- a/src/vscode_plugin/src/gen/tools/gencommonfile.ts +++ b/src/vscode_plugin/src/gen/tools/gencommonfile.ts @@ -14,7 +14,7 @@ */ import * as fs from 'fs'; -import { HdfRootInfo, ServiceRootInfo } from "../datatype"; +import { GenInfo, HdfRootInfo, ServiceRootInfo } from "../datatype"; import { replaceAll } from '../../common/tool'; // 生成sa非特殊处理的文件, 如xxx.cfg @@ -37,3 +37,9 @@ export function genHdfCommonFile(rootInfo: HdfRootInfo, filePath: string, fileCo fs.writeFileSync(filePath, fileContent); } +// 生成napi非特殊处理的文件 +export function genNapiCommonFile(rootInfo: GenInfo, filePath: string, + fileContent: string) { + fs.writeFileSync(filePath, fileContent); +} + diff --git a/src/vscode_plugin/src/gen/tools/gencommonfunc.ts b/src/vscode_plugin/src/gen/tools/gencommonfunc.ts index f2cd0f1192dd5c82e80e69c5e21e56c9bc7558f9..ce68ff66ec1805f3762afe3ba18912b244eb49ff 100644 --- a/src/vscode_plugin/src/gen/tools/gencommonfunc.ts +++ b/src/vscode_plugin/src/gen/tools/gencommonfunc.ts @@ -16,8 +16,11 @@ import { getTab } from '../../common/tool'; import { getReg, match } from '../../common/re'; import { format } from 'util' -import { FuncObj, ParamObj } from '../datatype'; +import { FuncObj, ParamObj, StructObj, ClassObj } from '../datatype'; import { transferMap } from '../../template/functypemap_template' +import { classMethodDeclareTemplate, objectRet, promiseRet } from "../../template/func_template"; +import { replaceAll } from "../../common/tool"; +import { h2NapiInKey, h2NapiOutKey } from "../../template/dtscpp/dts2cpp_key"; export function getFuncParamStr(params: ParamObj[]) { let paramStr = ''; @@ -101,4 +104,78 @@ export function genRead(parcelName: string, destObj: ParamObj) { let parcelType = getParcelType(destObj.type); let rFunc = getTransferContent(parcelType, 1); return format('%s = %s.%s();', destObj.name, parcelName, rFunc); -} \ No newline at end of file +} + +// ------------ gencpp common function -------------- +// 通过类型值映射模板,比如:uint32_t返回值 -> uint32tRet -> napi_create_uint32 +export function transCkey2NapiOutkey(key: string) { + // 如果是ts传递的Promise<>类型,并且transTs2C时未转换,那么就返回promiseRet + let tsPromiseReg = /Promise<([^>]+)>/g; + const tsPromiseMatch = tsPromiseReg.exec(key); + if (tsPromiseMatch) { + return promiseRet; + } + + // 数组 map set iterator tuple pair 等都当作objectOut处理 + for (const keyItem of h2NapiOutKey) { + for (const str of keyItem.keys) { + if (key.includes(str)) { + return keyItem.value; + } + } + } + let replaceKeyList = ['enum', 'struct', 'union']; + for (const rkey of replaceKeyList) { + key = key.replace(rkey, '').trim(); + } + // 其他的全部当作object处理, 如typeDef/enum/struct/union/class等,当作objectOut处理,返回objectRet + return objectRet; +} + +// 通过类型值映射模板,比如:uint32_t输入 -> uint32tIn -> napi_get_value_uint32 +export function transCkey2NapiInkey(key: string) { + for (const keyItem of h2NapiInKey) { + for (const str of keyItem.keys) { + if (key.includes(str)) { + return keyItem.value; + } + } + } + let replaceKeyList = ['enum', 'struct', 'union']; + for (const rkey of replaceKeyList) { + key = key.replace(rkey, '').trim(); + } + // 其他的全部当作object处理, 如typeDef/enum/struct/union/class等, 此时不需要做任何处理,因此返回空 + return ''; +} +// class的成员变量声明,以及成员变量的Get/Set方法的声明 +export function genClsVariableDeclare(cls: ClassObj) { + let clsVariableDeclare = ''; + let clsVariableGetSetDeclare = ''; + for (let i = 0; i < cls.variableList.length; ++i) { + clsVariableDeclare += cls.variableList[i].type + ' ' + cls.variableList[i].name + ';\n '; + let name = cls.variableList[i].name.toLocaleLowerCase(); + name = name.substring(0, 1).toLocaleUpperCase() + name.substring(1); + // 属性Get函数声明 + clsVariableGetSetDeclare += replaceAll(classMethodDeclareTemplate, '[class_method_name_replace]', 'Get' + name); + // 属性Set函数声明 + clsVariableGetSetDeclare += replaceAll(classMethodDeclareTemplate, '[class_method_name_replace]', 'Set' + name); + } + return { clsVariableDeclare, clsVariableGetSetDeclare }; +} + +// struct的成员变量声明,以及成员变量的Get/Set方法的声明 +export function genStructVariableDeclare(struct: StructObj) { + let clsVariableDeclare = ''; + let clsVariableGetSetDeclare = ''; + for (let i = 0; i < struct.members.length; ++i) { + clsVariableDeclare += struct.members[i].type + ' ' + struct.members[i].name + ';\n '; + let name = struct.members[i].name.toLocaleLowerCase(); + name = name.substring(0, 1).toLocaleUpperCase() + name.substring(1); + // 属性Get函数声明 + clsVariableGetSetDeclare += replaceAll(classMethodDeclareTemplate, '[class_method_name_replace]', 'Get' + name); + // 属性Set函数声明 + clsVariableGetSetDeclare += replaceAll(classMethodDeclareTemplate, '[class_method_name_replace]', 'Set' + name); + } + return { clsVariableDeclare, clsVariableGetSetDeclare }; +} diff --git a/src/vscode_plugin/src/gen/tools/gennapicommoncpp.ts b/src/vscode_plugin/src/gen/tools/gennapicommoncpp.ts new file mode 100644 index 0000000000000000000000000000000000000000..288e46c1b453063d288d75815763c4631453c5e8 --- /dev/null +++ b/src/vscode_plugin/src/gen/tools/gennapicommoncpp.ts @@ -0,0 +1,35 @@ + +/* +* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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. +*/ +import { GenInfo } from "../datatype"; +import { replaceAll } from "../../common/tool"; +import * as fs from 'fs'; +import { Logger } from '../../common/log'; + +// 生成common.cpp文件,读模板直接生成 +export function doGenCommonCppFile(rootInfo: GenInfo, fileContent: string) { + try { + fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); + } catch (error) { + let errmsg = 'generate napi common.cpp fileContent error: ' + JSON.stringify(error); + Logger.getInstance().error(errmsg); + } + return fileContent; +} + +export function genCommonCppFile(rootInfo: GenInfo, filePath: string, fileContent: string) { + fileContent = doGenCommonCppFile(rootInfo, fileContent); + fs.writeFileSync(filePath, fileContent); +} \ No newline at end of file diff --git a/src/vscode_plugin/src/gen/tools/gennapicommonh.ts b/src/vscode_plugin/src/gen/tools/gennapicommonh.ts new file mode 100644 index 0000000000000000000000000000000000000000..b68a55dc1d33db03d802ec17b2832dd3218f7902 --- /dev/null +++ b/src/vscode_plugin/src/gen/tools/gennapicommonh.ts @@ -0,0 +1,38 @@ + +/* +* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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. +*/ +import { GenInfo } from "../datatype"; +import { replaceAll } from "../../common/tool"; +import * as fs from 'fs'; +import { Logger } from '../../common/log'; + +// 生成common.h文件,这个读模板直接生成 +export function doGenCommonHFile(rootInfo: GenInfo, fileContent: string) { + try { + let upperFileName = rootInfo.fileName.toLocaleUpperCase(); + fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); + fileContent = replaceAll(fileContent, '[upper_filename]', upperFileName); + } catch (error) { + let errmsg = 'generate napi common.h fileContent error: ' + JSON.stringify(error); + Logger.getInstance().error(errmsg); + } + return fileContent; +} + +export function genCommonHFile(rootInfo: GenInfo, filePath: string, + fileContent: string) { + fileContent = doGenCommonHFile(rootInfo, fileContent); + fs.writeFileSync(filePath, fileContent); +} \ No newline at end of file diff --git a/src/vscode_plugin/src/gen/tools/gennapicpp.ts b/src/vscode_plugin/src/gen/tools/gennapicpp.ts new file mode 100644 index 0000000000000000000000000000000000000000..9dc09cf79559ce789180f9bfcf2a5c154cfa48e4 --- /dev/null +++ b/src/vscode_plugin/src/gen/tools/gennapicpp.ts @@ -0,0 +1,252 @@ + +/* +* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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. +*/ +import { FuncObj, GenInfo, ParamObj } from "../datatype"; +import { classMethodGetParamTemplate, classMethodNoParamTemplate, classMethodTemplate, classPropertyGetTemplate, + classPropertySetTemplate, classTemplate, funcGetParamTemplate, napiFuncCppTemplate, napiFuncRetTemplate, + paramGenTemplate } from "../../template/func_template"; +import { replaceAll } from "../../common/tool"; +import * as path from 'path'; +import * as fs from 'fs'; +import { transCkey2NapiInkey, transCkey2NapiOutkey } from "./gencommonfunc"; + +export function genClassMethodContent(funcInfo: FuncObj, className: string, classMethodContent: string) { + let methodContent = replaceAll(classMethodTemplate, '[class_method_name_replace]', funcInfo.name); + methodContent = replaceAll(methodContent, '[class_name_replace]', className); + if (funcInfo.parameters.length <= 0) { + methodContent = replaceAll(methodContent, '[class_method_param_in]', classMethodNoParamTemplate); + } else { + // 方法入参替换 + let paramGenResult = ''; + let methodParamIn = replaceAll(classMethodGetParamTemplate, '[param_count_replace]', 'PARAMS' + funcInfo.parameters.length); + for (let i = 0; i < funcInfo.parameters.length; ++i) { + // 这里是入参替换 比如输入2个参数 double/int napi_get_double_value/ napi_get_int32_value + let getParamInTemplate = transCkey2NapiInkey(funcInfo.parameters[i].type); + // 如果getParamInTemplate是空,则默认是对象输入,不做任何处理 + if (getParamInTemplate === '') { + paramGenResult += '// Todo: handle object input.\n'; + continue; + } + let getParam = replaceAll(getParamInTemplate, '[param_index_replace]', + 'PARAMS' + i); + getParam = replaceAll(getParam, '[param_name_replace]', + funcInfo.parameters[i].name); + let paramGen = replaceAll(paramGenTemplate, '[param_index_replace]', + 'PARAMS' + i); + paramGen = replaceAll(paramGen, '[param_name_replace]', + funcInfo.parameters[i].name); + paramGen = replaceAll(paramGen, '[getParam_replace]', getParam); + paramGenResult += paramGen; + } + // 替换get param in + methodParamIn = replaceAll(methodParamIn, '[class_method_get_param]', paramGenResult); + methodContent = replaceAll(methodContent, '[class_method_param_in]', methodParamIn); + } + // 方法返回值替换 + let returnGenResult = genCppReturnGen(funcInfo); + methodContent = replaceAll(methodContent, '[class_method_return]', returnGenResult); + // 该class的所有成员方法内容拼接起来 + classMethodContent += methodContent; + return classMethodContent; +} + +export function genClassGetSetContent(variableInfo: ParamObj, className: string, classPropertyGetSetContent: string) { + let name = variableInfo.name.toLocaleLowerCase(); + name = name.substring(0, 1).toLocaleUpperCase() + name.substring(1); + // class的属性get函数生成 + let getPropertyContent = replaceAll(classPropertyGetTemplate, '[class_property_name_replace]', name); + getPropertyContent = replaceAll(getPropertyContent, '[class_name_replace]', className); + let returnGetfuncContent = transCkey2NapiOutkey(variableInfo.type); + returnGetfuncContent = replaceAll(returnGetfuncContent, '[return_name_replace]', variableInfo.name); + getPropertyContent = replaceAll(getPropertyContent, '[class_property_get]', returnGetfuncContent); + classPropertyGetSetContent += getPropertyContent; + // class的属性set函数生成 + let setPropertyContent = replaceAll(classPropertySetTemplate, '[class_property_name_replace]', name); + setPropertyContent = replaceAll(setPropertyContent, '[class_name_replace]', className); + let returnSetfuncContent = transCkey2NapiInkey(variableInfo.type); + returnSetfuncContent = replaceAll(returnSetfuncContent, '[param_index_replace]', 'PARAMS0'); + returnSetfuncContent = replaceAll(returnSetfuncContent, '[param_name_replace]', variableInfo.name); + setPropertyContent = replaceAll(setPropertyContent, '[class_property_set]', returnSetfuncContent); + classPropertyGetSetContent += setPropertyContent; + return classPropertyGetSetContent; +} + +// 方法输入参数的处理,只处理基本类型,像数组/map/set/class/struct等都全部当作 +// object,且不做处理 +export function getCppParamGen(funcInfo: FuncObj): string { + // 处理输入的参数,生成napi的参数处理代码 + if (funcInfo.parameters.length === 0) { + return '// no input params'; + } + + // 下面这段代码是不是可以优化一下,把下面这段代码提取出来,放到一个函数中,class与struct生成成员方法的时候也可以调用 + let paramGenResult = ''; + for (let i = 0; i < funcInfo.parameters.length; ++i) { + let getParamInTemplate = transCkey2NapiInkey(funcInfo.parameters[i].type); + // 如果getParamInTemplate是空,则默认是对象输入,不做任何处理 + if (getParamInTemplate === '') { + paramGenResult += '// Todo: handle object input.\n'; + continue; + } + let getParam = replaceAll(getParamInTemplate, '[param_index_replace]', + 'PARAMS' + i); + getParam = replaceAll(getParam, '[param_name_replace]', + funcInfo.parameters[i].name); + let paramGen = replaceAll(paramGenTemplate, '[param_index_replace]', + 'PARAMS' + i); + paramGen = replaceAll(paramGen, '[param_name_replace]', + funcInfo.parameters[i].name); + paramGen = replaceAll(paramGen, '[getParam_replace]', getParam); + paramGenResult += paramGen; + } + let genParamReplace = replaceAll(funcGetParamTemplate, '[param_length]', + 'PARAMS' + funcInfo.parameters.length); + genParamReplace = replaceAll(genParamReplace, '[func_name_replace]', + funcInfo.name); + genParamReplace = replaceAll(genParamReplace, '[getAllParam_replace]', + paramGenResult); + return genParamReplace +} + +// 方法返回值的处理 +export function genCppReturnGen(funcInfo: FuncObj): string { + // 如果函数返回值是空,直接返回NULL + if (funcInfo.returns === 'void') { + return ' return NULL;\n'; + } + let returnName = funcInfo.name; + let funcReturnReplace = replaceAll(napiFuncRetTemplate, '[return_name]', + returnName); + let retGenResult = transCkey2NapiOutkey(funcInfo.returns); + retGenResult = replaceAll(retGenResult, '[return_name_replace]', returnName); + funcReturnReplace = replaceAll(funcReturnReplace, '[func_name_replace]', + funcInfo.name); + funcReturnReplace = replaceAll(funcReturnReplace, '[return_replace]', + retGenResult); + return funcReturnReplace; +} + +export function doGenNapiCppFile(rootInfo: GenInfo, fileContent: string) { + let napiCppContent = ''; + + // class的实现 + if (rootInfo.parseObj && rootInfo.parseObj.classes) { + let classesContent = ''; + rootInfo.parseObj.classes.forEach(classInfo => { + // 拿到每个class的信息 这里是类的主体 + let className = classInfo.name; // class的名字 + let classInfoContent = replaceAll(classTemplate, '[class_name_replace]', className) + + let classPropertyGetSetContent = ''; + // class中属性的生成 把一个class的所有属性都生成对应的get set函数 + classInfo.variableList.forEach(variableInfo => { + classPropertyGetSetContent = genClassGetSetContent(variableInfo, className, classPropertyGetSetContent); + }); + classInfoContent = replaceAll(classInfoContent, '[class_property_get_set_replace]', + classPropertyGetSetContent) + + let classMethodContent = ''; + // class中方法的生成 把一个class的所有方法都生成对应的函数 + classInfo.functionList.forEach(funcInfo => { + // 替换每个方法主体 生成每个方法的函数 + classMethodContent = genClassMethodContent(funcInfo, className, classMethodContent); + }); + classInfoContent = replaceAll(classInfoContent, '[class_method_content_replace]', + classMethodContent); + // 所有class拼接起来 + classesContent += classInfoContent; + }); + // 将class的生成内容写入cpp文件 + napiCppContent += classesContent; + } + + // struct的实现 + if (rootInfo.parseObj && rootInfo.parseObj.structs) { + // structs的生成内容 + let structsContent = ''; + rootInfo.parseObj.structs.forEach(structInfo => { + let className = structInfo.name; + let structInfoContent = replaceAll(classTemplate, '[class_name_replace]', className) + + let classPropertyGetSetContent = ''; + // struct中属性的生成 把一个struct的所有属性都生成对应的get set函数 + structInfo.members.forEach(variableInfo => { + classPropertyGetSetContent = genClassGetSetContent(variableInfo, className, classPropertyGetSetContent); + }); + structInfoContent = replaceAll(structInfoContent, '[class_property_get_set_replace]', + classPropertyGetSetContent) + + let structMethodContent = ''; + // struct中方法的生成 把一个class的所有方法都生成对应的函数 + structInfo.functions.forEach(funcInfo => { + // 替换每个方法主体 生成每个方法的函数 + structMethodContent = genClassMethodContent(funcInfo, className, structMethodContent); + }); + structInfoContent = replaceAll(structInfoContent, '[class_method_content_replace]', + structMethodContent); + // 所有struct拼接起来 + structsContent += structInfoContent; + }); + // 将struct的生成内容写入cpp文件 + napiCppContent += structsContent; + } + + // funcs的napi实现 + if (rootInfo.parseObj && rootInfo.parseObj.funcs) { + rootInfo.parseObj.funcs.forEach(funcInfo => { + // 替换每个方法主体 + let hFileName = path.basename(rootInfo.rawFilePath); + let bodyReplace = replaceAll(napiFuncCppTemplate, '[func_name_replace]', + funcInfo.name); + bodyReplace = replaceAll(bodyReplace, '[get_error_msg_tag]', + funcInfo.name); + bodyReplace = replaceAll(bodyReplace, '[file_introduce_replace]', + hFileName); + // 生成方法注释 + let funcInfoParams = funcInfo.parameters.length > 0 ? '' : 'void'; + let funcInfoParamTemp = '[paramName]: [paramType]; '; + for (let i = 0; i < funcInfo.parameters.length; i++) { + let funcInfoParamReplace = replaceAll(funcInfoParamTemp, '[paramName]', + funcInfo.parameters[i].name); + funcInfoParamReplace = replaceAll(funcInfoParamReplace, '[paramType]', + funcInfo.parameters[i].type); + funcInfoParams += funcInfoParamReplace; + } + bodyReplace = replaceAll(bodyReplace, '[input_introduce_replace]', + funcInfoParams === '' ? 'void' : funcInfoParams); + bodyReplace = replaceAll(bodyReplace, '[output_introduce_replace]', + funcInfo.returns); + // 方法参数的处理,解析参数类型,生成napi的参数处理代码 + let paramGenResult = getCppParamGen(funcInfo); + bodyReplace = replaceAll(bodyReplace, '[func_getParam_replace]', + paramGenResult); + // 方法返回值的处理,解析返回值类型,生成napi的返回值处理代码 + let returnGenResult = genCppReturnGen(funcInfo); + bodyReplace = replaceAll(bodyReplace, '[func_return_replace]', + returnGenResult); + // 组合一个个方法 + napiCppContent += bodyReplace; + }); + } + + fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); + fileContent = replaceAll(fileContent, '[func_content_replace]', napiCppContent); + return fileContent; +} +export function genNapiCppFile(rootInfo: GenInfo, filePath: string, + fileContent: string) { + fileContent = doGenNapiCppFile(rootInfo, fileContent); + fs.writeFileSync(filePath, fileContent); +} \ No newline at end of file diff --git a/src/vscode_plugin/src/gen/tools/gennapih.ts b/src/vscode_plugin/src/gen/tools/gennapih.ts new file mode 100644 index 0000000000000000000000000000000000000000..769143a43a014db503d52916e90c9fffec6903ed --- /dev/null +++ b/src/vscode_plugin/src/gen/tools/gennapih.ts @@ -0,0 +1,98 @@ + +/* +* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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. +*/ +import { GenInfo } from "../datatype"; +import { classMethodDeclareTemplate, classNapiHTemplate, napiFuncHTemplate } from "../../template/func_template"; +import { replaceAll } from "../../common/tool"; +import * as path from 'path'; +import * as fs from 'fs'; +import { genClsVariableDeclare, genStructVariableDeclare } from "./gencommonfunc"; + +export function doGenNapiHFile(rootInfo: GenInfo, fileContent: string) { + let napiHContent = ''; + + // 实现class的 + if (rootInfo.parseObj && rootInfo.parseObj.classes) { + let classesDeclare = ''; + rootInfo.parseObj.classes.forEach(cls => { + let clsDeclare = replaceAll(classNapiHTemplate, '[class_name_replace]', cls.name) + // 每个成员方法的声明 + let clsMethodDeclare = ''; + for (let i = 0; i < cls.functionList.length; ++i) { + clsMethodDeclare += replaceAll(classMethodDeclareTemplate, '[class_method_name_replace]', cls.functionList[i].name); + } + clsDeclare = replaceAll(clsDeclare, '[class_method_declare]', clsMethodDeclare); + // 每个成员变量的get set方法的声明 + let { clsVariableDeclare, clsVariableGetSetDeclare } = genClsVariableDeclare(cls); + clsDeclare = replaceAll(clsDeclare, '[class_variable_declare]', clsVariableDeclare); + clsDeclare = replaceAll(clsDeclare, '[class_property_get_set_declare]', clsVariableGetSetDeclare); + // 所有class的napi声明 + classesDeclare += clsDeclare; + }); + napiHContent += classesDeclare; + } + + // 实现struct的 + if (rootInfo.parseObj && rootInfo.parseObj.structs) { + let structDeclare = ''; + rootInfo.parseObj.structs.forEach(struct => { + let clsDeclare = replaceAll(classNapiHTemplate, '[class_name_replace]', struct.name) + // 每个成员方法的声明 + let clsMethodDeclare = ''; + for (let i = 0; i < struct.functions.length; ++i) { + clsMethodDeclare += replaceAll(classMethodDeclareTemplate, '[class_method_name_replace]', struct.functions[i].name); + } + clsDeclare = replaceAll(clsDeclare, '[class_method_declare]', clsMethodDeclare); + // 每个成员变量的get set方法的声明 + let { clsVariableDeclare, clsVariableGetSetDeclare } = genStructVariableDeclare(struct); + clsDeclare = replaceAll(clsDeclare, '[class_variable_declare]', clsVariableDeclare); + clsDeclare = replaceAll(clsDeclare, '[class_property_get_set_declare]', clsVariableGetSetDeclare); + // 所有struct的napi声明 + structDeclare += clsDeclare; + }); + napiHContent += structDeclare; + } + + // 实现function的 + if (rootInfo.parseObj && rootInfo.parseObj.funcs) { + rootInfo.parseObj.funcs.forEach(func => { + let funcParams = ''; + for (let i = 0; i < func.parameters.length; ++i) { + funcParams += i > 0 ? ', ' : ''; + funcParams += func.parameters[i].name + ': ' + func.parameters[i].type; + } + let rawFileName = path.basename(rootInfo.rawFilePath); + let hContent = replaceAll(napiFuncHTemplate, '[file_introduce_replace]', rawFileName); + hContent = replaceAll(hContent, '[input_introduce_replace]', funcParams === '' ? 'void' : funcParams); + hContent = replaceAll(hContent, '[func_name_replace]', func.name); + hContent = replaceAll(hContent, '[func_param_replace]', funcParams); + hContent = replaceAll(hContent, '[func_return_replace]', + func.returns === '' ? 'void' : func.returns); + napiHContent += hContent; + }); + } + let upperFileName = rootInfo.fileName.toLocaleUpperCase(); + fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); + fileContent = replaceAll(fileContent, '[upper_filename]', upperFileName); + fileContent = replaceAll(fileContent, '[func_declare_replace]', napiHContent); + return fileContent; +} + +// 生成napi.h文件 +export function genNapiHFile(rootInfo: GenInfo, filePath: string, + fileContent: string) { + fileContent = doGenNapiHFile(rootInfo, fileContent); + fs.writeFileSync(filePath, fileContent); +} \ No newline at end of file diff --git a/src/vscode_plugin/src/gen/tools/gennapiinit.ts b/src/vscode_plugin/src/gen/tools/gennapiinit.ts new file mode 100644 index 0000000000000000000000000000000000000000..43ce3b9fcd3c7b9b85391c398ee5b2b5d45fcf56 --- /dev/null +++ b/src/vscode_plugin/src/gen/tools/gennapiinit.ts @@ -0,0 +1,80 @@ + +/* +* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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. +*/ +import { GenInfo } from "../datatype"; +import { classInitTemplate, classMethodDeclareTemplate, napiFuncInitTemplate } from "../../template/func_template"; +import { replaceAll } from "../../common/tool"; +import * as fs from 'fs'; +import {genClsVariableDeclare, genStructVariableDeclare} from "./gencommonfunc"; + +export function doGenNapiInitFile(rootInfo: GenInfo, fileContent: string) { + let napiInitContent = ''; + + // class 的声明 + let classesInit = ''; + if (rootInfo.parseObj && rootInfo.parseObj.classes) { + let classInit = ''; + rootInfo.parseObj.classes.forEach(classObj => { + classInit = replaceAll(classInitTemplate, '[class_name_replace]', classObj.name); + let clsMethodDeclare = ''; + for (let i = 0; i < classObj.functionList.length; ++i) { + clsMethodDeclare += replaceAll(classMethodDeclareTemplate, '[class_method_name_replace]', classObj.functionList[i].name); + } + classInit = replaceAll(classInit, '[class_method_replace]', clsMethodDeclare); + let { clsVariableDeclare, clsVariableGetSetDeclare } = genClsVariableDeclare(classObj); + classInit = replaceAll(classInit, '[class_property_replace]', clsVariableGetSetDeclare); + }); + classesInit += classInit; + } + + // struct的声明 + let structsInit = ''; + if (rootInfo.parseObj && rootInfo.parseObj.structs) { + let structInit = ''; + rootInfo.parseObj.structs.forEach(classObj => { + structInit = replaceAll(classInitTemplate, '[class_name_replace]', classObj.name); + let clsMethodDeclare = ''; + for (let i = 0; i < classObj.functions.length; ++i) { + clsMethodDeclare += replaceAll(classMethodDeclareTemplate, '[class_method_name_replace]', classObj.functions[i].name); + } + structInit = replaceAll(structInit, '[class_method_replace]', clsMethodDeclare); + let { clsVariableDeclare, clsVariableGetSetDeclare } = genStructVariableDeclare(classObj); + structInit = replaceAll(structInit, '[class_property_replace]', clsVariableGetSetDeclare); + }); + structsInit += structInit; + } + + if (rootInfo.parseObj && rootInfo.parseObj.funcs) { + rootInfo.parseObj.funcs.forEach(func => { + let funcName = func.name; + napiInitContent += replaceAll(napiFuncInitTemplate, + '[func_name_replace]', funcName); + }); + } + // 写文件 + fileContent = replaceAll(fileContent, '[fileName]', rootInfo.fileName); + fileContent = replaceAll(fileContent, '[init_replace]', napiInitContent); + // class 的init 如果class是空的这里会不会替换出错? 后面再测试 + fileContent = replaceAll(fileContent, '[class_init_replace]', classesInit); + fileContent = replaceAll(fileContent, '[struct_init_replace]', structsInit); + return fileContent; +} + +// 生成napiinit.cpp +export function genInitCppFile(rootInfo: GenInfo, filePath: string, + fileContent: string) { + fileContent = doGenNapiInitFile(rootInfo, fileContent); + fs.writeFileSync(filePath, fileContent); +} diff --git a/src/vscode_plugin/src/model/h2dtscppmod.ts b/src/vscode_plugin/src/model/h2dtscppmod.ts index 8fa18ef7ab5811e5090b6524af5c9266b4b1151a..d54be67ce3d1b99ffbbc79686c6db5a9caf42c57 100644 --- a/src/vscode_plugin/src/model/h2dtscppmod.ts +++ b/src/vscode_plugin/src/model/h2dtscppmod.ts @@ -17,7 +17,7 @@ import * as path from 'path'; import { IModel } from "./imodel"; import { parseHeaderFile } from '../parse/parsec'; import { DtscppRootInfo, GenInfo } from '../gen/datatype'; -import { genDtsFile } from '../gen/gendts'; +import { genDtscppFromH } from '../gen/gendtscpp'; import { GEN_COMPLETE, OPEN_IN_EXPLORER, PARSE_COMPLETE } from '../common/constants'; import { Logger } from '../common/log'; import { @@ -74,7 +74,7 @@ export class H2dtscppMod extends IModel { // generator let out = path.dirname(this.uri.fsPath); // genDtsCppFile(rootInfo, out); - gendtscppFromH(rootInfo); + genDtscppFromH(rootInfo); // progress.report({ increment: 100, message: GEN_COMPLETE + out }); this.emmitEventForKey(EVENT_PROGRESS, 100, PARSE_COMPLETE + out); diff --git a/src/vscode_plugin/src/template/dtscpp/dtscpp_napiinit_template.ts b/src/vscode_plugin/src/template/dtscpp/dtscpp_napiinit_template.ts index 4c354fd544526efaad1e6c2170094877d194c684..30123ab98ebb6872d93dd4e7df8000094c94ac01 100644 --- a/src/vscode_plugin/src/template/dtscpp/dtscpp_napiinit_template.ts +++ b/src/vscode_plugin/src/template/dtscpp/dtscpp_napiinit_template.ts @@ -50,6 +50,10 @@ export let napiInitTemplate: FileTemp = { * properties: 指向 napi_property_descriptor 结构体数组的指针,每个结构体描述了一个要定义的属性。 */ napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + + [class_init_replace] + [struct_init_replace] + return exports; } EXTERN_C_END diff --git a/src/vscode_plugin/src/template/func_template.ts b/src/vscode_plugin/src/template/func_template.ts index b2c5c6934fe635c25613779e0b6ee9757df32390..f516d5ace179b0e68b0847fb614665c93b75836a 100644 --- a/src/vscode_plugin/src/template/func_template.ts +++ b/src/vscode_plugin/src/template/func_template.ts @@ -68,7 +68,7 @@ export const [func_name_replace]:([func_param_replace]) => [func_return_replace] // napi方法的初始化 export let napiFuncInitTemplate = `// [NAPI_GEN]:方法注册后,js方法与native方法映射 -{ "[func_name_replace]" , nullptr, [func_name_replace], nullptr, nullptr, nullptr, napi_default, nullptr }, + { "[func_name_replace]" , nullptr, [func_name_replace], nullptr, nullptr, nullptr, napi_default, nullptr }, `; // napi方法定义 @@ -107,328 +107,496 @@ napi_value [func_name_replace](napi_env env, napi_callback_info info) `; // napi方法返回值处理 -export let napiFuncRetTemplate = `// Todo: add business logic. 在这前后代码为框架所生成 +export let napiFuncRetTemplate = ` // Todo: add business logic. 在这前后代码为框架所生成 -/* [NAPI_GEN]: function return value*/ -[return_replace] -OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "[func_name_replace]", "[func_name_replace] get return info ends"); -OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "[func_name_replace]", "[func_name_replace] ends"); -return [return_name]Out; + /* [NAPI_GEN]: function return value*/ + [return_replace] + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "[func_name_replace]", "[func_name_replace] get return info ends"); + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "[func_name_replace]", "[func_name_replace] ends"); + return [return_name]Out; `; // napi方法返回值各种类型模板 -export let uint32tRet = `napi_value [return_name_replace]Out; -/* [NAPI_GEN]: 返回值是uint32_t类型时,napi_create_uint32创建一个包含32位无符号整数(uint32_t)的js数值对象 - * env: 当前环境的句柄 - * value: 要转换成js数值的uint32_t值,这里以传入1为例,用例新增业务代码时可根据自身需求修改 - * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js数值对象 - */ -status = napi_create_uint32(env, 1, &[return_name_replace]Out); -if (status != napi_ok) { - /*错误处理*/ - getErrMessage(status, env, extended_error_info, "napi_create_uint32", tag); - return nullptr; -} +export let uint32tRet = ` napi_value [return_name_replace]Out; + /* [NAPI_GEN]: 返回值是uint32_t类型时,napi_create_uint32创建一个包含32位无符号整数(uint32_t)的js数值对象 + * env: 当前环境的句柄 + * value: 要转换成js数值的uint32_t值,这里以传入1为例,用例新增业务代码时可根据自身需求修改 + * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js数值对象 + */ + status = napi_create_uint32(env, 1, &[return_name_replace]Out); + if (status != napi_ok) { + /*错误处理*/ + getErrMessage(status, env, extended_error_info, "napi_create_uint32", tag); + return nullptr; + } `; -export let stringRet = `napi_value [return_name_replace]Out; -/* [NAPI_GEN]: 返回值是字符串时,napi_create_string_utf8用于在原生代码中创建一个新的js字符串。这个函数会根据提供的UTF-8编码的字符串创建一个等价的js字符串 - * env: 当前环境的句柄 - * str: 指向以null结尾的UTF-8编码的C字符串的指针,这里以"[return_name_replace]"举例,用户可根据需求修改 - * length: 字符串的长度,可以是具体的字节数,或者使用特殊的值NAPI_AUTO_LENGTH来让函数自己计算长度(假定字符串以null结尾) - * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js字符串 - */ -status = napi_create_string_utf8(env, "[return_name_replace]", NAPI_AUTO_LENGTH, &[return_name_replace]Out); -if (status != napi_ok) { - /*错误处理*/ - getErrMessage(status, env, extended_error_info, "napi_create_string_utf8", tag); - return nullptr; -} +export let stringRet = ` napi_value [return_name_replace]Out; + /* [NAPI_GEN]: 返回值是字符串时,napi_create_string_utf8用于在原生代码中创建一个新的js字符串。这个函数会根据提供的UTF-8编码的字符串创建一个等价的js字符串 + * env: 当前环境的句柄 + * str: 指向以null结尾的UTF-8编码的C字符串的指针,这里以"[return_name_replace]"举例,用户可根据需求修改 + * length: 字符串的长度,可以是具体的字节数,或者使用特殊的值NAPI_AUTO_LENGTH来让函数自己计算长度(假定字符串以null结尾) + * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js字符串 + */ + status = napi_create_string_utf8(env, "[return_name_replace]", NAPI_AUTO_LENGTH, &[return_name_replace]Out); + if (status != napi_ok) { + /*错误处理*/ + getErrMessage(status, env, extended_error_info, "napi_create_string_utf8", tag); + return nullptr; + } `; -export let stringRetUtf16 = `napi_value [return_name_replace]Out; -/* [NAPI_GEN]: 返回值是字符串时,napi_create_string_utf16用于在原生代码中创建一个新的js字符串。这个函数会根据提供的UTF-16编码的字符串创建一个等价的js字符串 - * env: 当前环境的句柄 - * str: 指向以null结尾的UTF-8编码的C字符串的指针,这里以"[return_name_replace]"举例,用户可根据需求修改 - * length: 字符串的长度,可以是具体的字节数,或者使用特殊的值NAPI_AUTO_LENGTH来让函数自己计算长度(假定字符串以null结尾) - * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js字符串 - */ -status = napi_create_string_utf16(env, u"[return_name_replace]", NAPI_AUTO_LENGTH, &[return_name_replace]Out); -if (status != napi_ok) { - /*错误处理*/ - getErrMessage(status, env, extended_error_info, "napi_create_string_utf16", tag); - return nullptr; -} +export let stringRetUtf16 = ` napi_value [return_name_replace]Out; + /* [NAPI_GEN]: 返回值是字符串时,napi_create_string_utf16用于在原生代码中创建一个新的js字符串。这个函数会根据提供的UTF-16编码的字符串创建一个等价的js字符串 + * env: 当前环境的句柄 + * str: 指向以null结尾的UTF-8编码的C字符串的指针,这里以"[return_name_replace]"举例,用户可根据需求修改 + * length: 字符串的长度,可以是具体的字节数,或者使用特殊的值NAPI_AUTO_LENGTH来让函数自己计算长度(假定字符串以null结尾) + * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js字符串 + */ + status = napi_create_string_utf16(env, u"[return_name_replace]", NAPI_AUTO_LENGTH, &[return_name_replace]Out); + if (status != napi_ok) { + /*错误处理*/ + getErrMessage(status, env, extended_error_info, "napi_create_string_utf16", tag); + return nullptr; + } `; -export let int64tRet = ` napi_value [return_name_replace]Out; -/* [NAPI_GEN]: 返回值是int64类型时,napi_create_int64创建一个包含64位整数(int64_t)的js数值对象 - * env: 当前环境的句柄 - * value: 要转换成js数值的int64_t值,这里以传入1为例,用例新增业务代码时可根据自身需求修改 - * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js数值对象 - */ -status = napi_create_int64(env, 1, &[return_name_replace]Out); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_create_int64", tag); - return nullptr; -} +export let int64tRet = ` napi_value [return_name_replace]Out; + /* [NAPI_GEN]: 返回值是int64类型时,napi_create_int64创建一个包含64位整数(int64_t)的js数值对象 + * env: 当前环境的句柄 + * value: 要转换成js数值的int64_t值,这里以传入1为例,用例新增业务代码时可根据自身需求修改 + * result: 指向napi_value的指针,函数执行成功后这个指针将指向新创建的js数值对象 + */ + status = napi_create_int64(env, 1, &[return_name_replace]Out); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_create_int64", tag); + return nullptr; + } `; -export let int32tRet = `napi_value [return_name_replace]Out; -/* [NAPI_GEN]: 返回值是int32_t类型时,napi_create_int32 创建一个包含32位整数(int32_t)的js数值(Number)对象 - * env: 当前环境的句柄 - * value: 要准换成js数值的int32_t的值,这里以传入1为例,用例新增业务代码时可根据自身需求修改 - * result: 指向napi_value的指针,这个指针会被设置为新创建的js数值对象 - */ -status = napi_create_int32(env, 1, &[return_name_replace]Out); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_create_int32", tag); - return nullptr; -} +export let int32tRet = ` napi_value [return_name_replace]Out; + /* [NAPI_GEN]: 返回值是int32_t类型时,napi_create_int32 创建一个包含32位整数(int32_t)的js数值(Number)对象 + * env: 当前环境的句柄 + * value: 要准换成js数值的int32_t的值,这里以传入1为例,用例新增业务代码时可根据自身需求修改 + * result: 指向napi_value的指针,这个指针会被设置为新创建的js数值对象 + */ + status = napi_create_int32(env, 1, &[return_name_replace]Out); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_create_int32", tag); + return nullptr; + } `; -export let doubleRet = `napi_value [return_name_replace]Out; -/* [NAPI_GEN]: 返回值是double类型时,napi_create_double 创建一个包含双精度浮点数的js数值(Number)对象 - * env: 当前环境的句柄 - * value: 要传递给js的双精度浮点数值,这里以传入1.0为例,用例新增业务代码时可根据自身需求修改 - * result: 指向napi_value的指针,这个指针会被设置为新创建的js数值对象 - */ -status = napi_create_double(env, 1.0, &[return_name_replace]Out); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_create_double", tag); - return nullptr; -} +export let doubleRet = ` napi_value [return_name_replace]Out; + /* [NAPI_GEN]: 返回值是double类型时,napi_create_double 创建一个包含双精度浮点数的js数值(Number)对象 + * env: 当前环境的句柄 + * value: 要传递给js的双精度浮点数值,这里以传入1.0为例,用例新增业务代码时可根据自身需求修改 + * result: 指向napi_value的指针,这个指针会被设置为新创建的js数值对象 + */ + status = napi_create_double(env, 1.0, &[return_name_replace]Out); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_create_double", tag); + return nullptr; + } `; -export let boolRet = `napi_value [return_name_replace]Out; -/* [NAPI_GEN]: 返回值是bool类型时,napi_get_boolean创建一个表示布尔值的js Boolean对象 - * env: 当前环境的句柄 - * value: 希望表示的布尔值(C中的true或者false),这里以传入true为例,用例新增业务代码时可根据自身需求修改 - * result: 函数返回一个napi_value,它是对应于js Boolean对象的C语言表示 - */ -status = napi_get_boolean(env, true, &[return_name_replace]Out); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_get_boolean", tag); - return nullptr; -} +export let boolRet = ` napi_value [return_name_replace]Out; + /* [NAPI_GEN]: 返回值是bool类型时,napi_get_boolean创建一个表示布尔值的js Boolean对象 + * env: 当前环境的句柄 + * value: 希望表示的布尔值(C中的true或者false),这里以传入true为例,用例新增业务代码时可根据自身需求修改 + * result: 函数返回一个napi_value,它是对应于js Boolean对象的C语言表示 + */ + status = napi_get_boolean(env, true, &[return_name_replace]Out); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_get_boolean", tag); + return nullptr; + } `; -export let objectRet = `napi_value [return_name_replace]Out; -/* [NAPI_GEN]: 返回值是对象时,需要使用napi_create_object创建一个js的对象与js代码交互 - * env: 当前环境的句柄 - * result: 一个napi_value的指针,该指针将被设置为新创建的js对象 - */ -status = napi_create_object(env, &[return_name_replace]Out); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_create_object", tag); - return nullptr; -} +export let objectRet = ` napi_value [return_name_replace]Out; + /* [NAPI_GEN]: 返回值是对象时,需要使用napi_create_object创建一个js的对象与js代码交互 + * env: 当前环境的句柄 + * result: 一个napi_value的指针,该指针将被设置为新创建的js对象 + */ + status = napi_create_object(env, &[return_name_replace]Out); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_create_object", tag); + return nullptr; + } `; -export let objectTosetRet = `/* [NAPI_GEN]: 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,最终将该对象返回js -* env: 当前环境的句柄 -* object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 -* utf8name: 属性的名称,是一个以UTF-8编码的字符串 -* value: 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) -*/ -status = napi_set_named_property(env, [set_objname_replace]Out, "[set_propname_replace]", [set_propvalue_replace]Out); -if (status != napi_ok) { - /* [NAPI_GEN]: 错误处理*/ - getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); - return nullptr; -} +export let objectTosetRet = ` /* [NAPI_GEN]: 返回值是对象时,将native侧的对象的属性和值依次塞入napi_create_object创建出的对象,最终将该对象返回js + * env: 当前环境的句柄 + * object: 要设置属性的js对象,该对象是由上文napi_create_object创建的 + * utf8name: 属性的名称,是一个以UTF-8编码的字符串 + * value: 与属性名称关联的值,这个值可以是任何js类型(如一个数值、字符串、另一个对象等) + */ + status = napi_set_named_property(env, [set_objname_replace]Out, "[set_propname_replace]", [set_propvalue_replace]Out); + if (status != napi_ok) { + /* [NAPI_GEN]: 错误处理*/ + getErrMessage(status, env, extended_error_info, "napi_set_named_property", tag); + return nullptr; + } `; -export let promiseRet = `napi_value [return_name_replace]Out; -napi_deferred [return_name_replace]DeferedOut; -/* [NAPI_GEN]: 创建一个空的promise对象 - * env: N-API环境的句柄,表示当前的上下文 - * promise: 用于接收创建的promise对象的指针 - * deferred: 用于接收deferred对象的指针 -*/ -status = napi_create_promise(env, &[return_name_replace]Out, &[return_name_replace]DeferedOut); -if (status != napi_ok) { - /* [NAPI_GEN]: 错误处理*/ - getErrMessage(status, env, extended_error_info, "napi_create_promise", tag); - return nullptr; -} -// Todo: create async work here. +export let promiseRet = ` napi_value [return_name_replace]Out; + napi_deferred [return_name_replace]DeferedOut; + /* [NAPI_GEN]: 创建一个空的promise对象 + * env: N-API环境的句柄,表示当前的上下文 + * promise: 用于接收创建的promise对象的指针 + * deferred: 用于接收deferred对象的指针 + */ + status = napi_create_promise(env, &[return_name_replace]Out, &[return_name_replace]DeferedOut); + if (status != napi_ok) { + /* [NAPI_GEN]: 错误处理*/ + getErrMessage(status, env, extended_error_info, "napi_create_promise", tag); + return nullptr; + } + // Todo: create async work here. `; // napi func的paramGen template -export let paramGenTemplate = `napi_valuetype valuetype[param_name_replace]; -/* [NAPI_GEN]: 获取入参类型,第[param_index_replace]个入参 - * env: N-API环境的句柄,表示当前的上下文 - * value: 要检查类型的js值 - * result: 是一个指针,指向napi_valuetype枚举的值,函数会将结果存储在这里 - */ -status = napi_typeof(env, args[[param_index_replace]], &valuetype[param_name_replace]); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_typeof", tag); - return nullptr; -} -[getParam_replace] +export let paramGenTemplate = ` napi_valuetype valuetype[param_name_replace]; + /* [NAPI_GEN]: 获取入参类型,第[param_index_replace]个入参 + * env: N-API环境的句柄,表示当前的上下文 + * value: 要检查类型的js值 + * result: 是一个指针,指向napi_valuetype枚举的值,函数会将结果存储在这里 + */ + status = napi_typeof(env, args[[param_index_replace]], &valuetype[param_name_replace]); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_typeof", tag); + return nullptr; + } + [getParam_replace] `; export let funcGetParamTemplate = ` /* [NAPI_GEN]: argc:js传入的参数个数 */ -size_t argc = [param_length]; -/* [NAPI_GEN]: args: 一个数组,保存js传入的参数 */ -napi_value args[[param_length]] = {nullptr}; -/* [NAPI_GEN]: napi_get_cb_info用于获取JS调用该函数时所传递的参数、接收参数的个数以及'this'的值 - * env: 当前环境的句柄,代表当前的Node.js环境 - * info: 回调信息句柄,代表当前回调的上下文 - * argc: 指向size_t的指针,最初应包含可接受的最大参数数量,函数返回时,它将包含实际传递的参数数量 - * args: 一个足够大的数组,用于接收传递给回调函数的所有js参数。数组的大小应至少与argc传入的值一样大。 - * this_arg: 如果不是NULL,则返回js回调中this的值 - * data: 如果不是NULL,则返回与回调函数关联的任何可选数据。通常用于传递在创建函数时指定的静态数据 - */ -status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); -if(status != napi_ok) { - /* [NAPI_GEN]: 错误处理*/ - getErrMessage(status, env,extended_error_info, "napi_get_cb_info", tag); - return nullptr; -} -/* [NAPI_GEN]: 从args数组中获取入参 */ -OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "[func_name_replace]", "[func_name_replace] get param info begins"); -[getAllParam_replace] -OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "[func_name_replace]", "[func_name_replace] get param info ends"); + size_t argc = [param_length]; + /* [NAPI_GEN]: args: 一个数组,保存js传入的参数 */ + napi_value args[[param_length]] = {nullptr}; + /* [NAPI_GEN]: napi_get_cb_info用于获取JS调用该函数时所传递的参数、接收参数的个数以及'this'的值 + * env: 当前环境的句柄,代表当前的Node.js环境 + * info: 回调信息句柄,代表当前回调的上下文 + * argc: 指向size_t的指针,最初应包含可接受的最大参数数量,函数返回时,它将包含实际传递的参数数量 + * args: 一个足够大的数组,用于接收传递给回调函数的所有js参数。数组的大小应至少与argc传入的值一样大。 + * this_arg: 如果不是NULL,则返回js回调中this的值 + * data: 如果不是NULL,则返回与回调函数关联的任何可选数据。通常用于传递在创建函数时指定的静态数据 + */ + status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if(status != napi_ok) { + /* [NAPI_GEN]: 错误处理*/ + getErrMessage(status, env,extended_error_info, "napi_get_cb_info", tag); + return nullptr; + } + /* [NAPI_GEN]: 从args数组中获取入参 */ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "[func_name_replace]", "[func_name_replace] get param info begins"); + [getAllParam_replace] + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "[func_name_replace]", "[func_name_replace] get param info ends"); `; -export let uint32tIn = `uint32_t [param_name_replace]In = 0; -/* [NAPI_GEN]: napi_get_value_uint32将一个napi_value类型的js布尔值转换成一个C语言的uint32_t类型的数值,第[param_index_replace]个入参 - * env: N-API环境的句柄,表示当前的上下文 - * value:要转换的JavaScript值 - * result:指向 uint32_t 类型的指针,在这里函数将存储转换后的无符号整数 - */ -status = napi_get_value_uint32(env, args[[param_index_replace]], &[param_name_replace]In); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_get_value_uint32", tag); - return nullptr; -} +export let uint32tIn = ` uint32_t [param_name_replace]In = 0; + /* [NAPI_GEN]: napi_get_value_uint32将一个napi_value类型的js布尔值转换成一个C语言的uint32_t类型的数值,第[param_index_replace]个入参 + * env: N-API环境的句柄,表示当前的上下文 + * value:要转换的JavaScript值 + * result:指向 uint32_t 类型的指针,在这里函数将存储转换后的无符号整数 + */ + status = napi_get_value_uint32(env, args[[param_index_replace]], &[param_name_replace]In); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_get_value_uint32", tag); + return nullptr; + } `; -export let stringIn = `size_t strSize[param_index_replace] = 0; -/* [NAPI_GEN]: napi_get_value_string_utf8用于将Js字符串转换为UTF-8编码的C字符串 - * env: N-API环境的句柄,表示当前的上下文 - * value: 要转换的JavaScript字符串 - * buf: 用于存储结果的字符数组的指针 - * bufsize: 缓冲区大小,以字节为单位 - * result: 转换后的字符串的字节长度(不包括空终止符)。若干buf是NULL,则返回所需的缓冲区大小(包括空终止符) - */ -/* [NAPI_GEN]: buf参数是NULL时,用于获取所需缓冲区大小*/ -status = napi_get_value_string_utf8(env, args[[param_index_replace]], NULL, 0, &strSize[param_index_replace]); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "get value string", tag); - return nullptr; -} -char *[param_name_replace]In = new char[strSize[param_index_replace] + 1]; -/* [NAPI_GEN]: 用于获取字符串*/ -status = napi_get_value_string_utf8(env, args[[param_index_replace]], [param_name_replace]In, strSize[param_index_replace] + 1, &strSize[param_index_replace]); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "get value string", tag); - delete[] [param_name_replace]In; - return nullptr; -} -// delete[] [param_name_replace]In; // remember to delete memory +export let stringIn = ` size_t strSize[param_index_replace] = 0; + /* [NAPI_GEN]: napi_get_value_string_utf8用于将Js字符串转换为UTF-8编码的C字符串 + * env: N-API环境的句柄,表示当前的上下文 + * value: 要转换的JavaScript字符串 + * buf: 用于存储结果的字符数组的指针 + * bufsize: 缓冲区大小,以字节为单位 + * result: 转换后的字符串的字节长度(不包括空终止符)。若干buf是NULL,则返回所需的缓冲区大小(包括空终止符) + */ + /* [NAPI_GEN]: buf参数是NULL时,用于获取所需缓冲区大小*/ + status = napi_get_value_string_utf8(env, args[[param_index_replace]], NULL, 0, &strSize[param_index_replace]); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "get value string", tag); + return nullptr; + } + char *[param_name_replace]In = new char[strSize[param_index_replace] + 1]; + /* [NAPI_GEN]: 用于获取字符串*/ + status = napi_get_value_string_utf8(env, args[[param_index_replace]], [param_name_replace]In, strSize[param_index_replace] + 1, &strSize[param_index_replace]); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "get value string", tag); + delete[] [param_name_replace]In; + return nullptr; + } + // delete[] [param_name_replace]In; // remember to delete memory `; -export let stringInUtf16 = `size_t strSize[param_index_replace] = 0; -/* [NAPI_GEN]: napi_get_value_string_utf16用于将Js字符串转换为UTF-16编码的C字符串 - * env: N-API环境的句柄,表示当前的上下文 - * value: 要转换的JavaScript字符串 - * buf: 用于存储结果的字符数组的指针 - * bufsize: 缓冲区大小,以字节为单位 - * result: 转换后的字符串的字节长度(不包括空终止符)。若干buf是NULL,则返回所需的缓冲区大小(包括空终止符) - */ -/* [NAPI_GEN]: buf参数是NULL时,用于获取所需缓冲区大小*/ -status = napi_get_value_string_utf16(env, args[[param_index_replace]], NULL, 0, &strSize[param_index_replace]); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "get value string", tag); - return nullptr; -} -char16_t *[param_name_replace]In = new char16_t[strSize[param_index_replace] + 1]; -/* [NAPI_GEN]: 用于获取字符串*/ -status = napi_get_value_string_utf16(env, args[[param_index_replace]], [param_name_replace]In, strSize[param_index_replace] + 1, &strSize[param_index_replace]); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "get value string", tag); - delete[] [param_name_replace]In; - return nullptr; -} -// delete[] [param_name_replace]In; // remember to delete memory +export let stringInUtf16 = ` size_t strSize[param_index_replace] = 0; + /* [NAPI_GEN]: napi_get_value_string_utf16用于将Js字符串转换为UTF-16编码的C字符串 + * env: N-API环境的句柄,表示当前的上下文 + * value: 要转换的JavaScript字符串 + * buf: 用于存储结果的字符数组的指针 + * bufsize: 缓冲区大小,以字节为单位 + * result: 转换后的字符串的字节长度(不包括空终止符)。若干buf是NULL,则返回所需的缓冲区大小(包括空终止符) + */ + /* [NAPI_GEN]: buf参数是NULL时,用于获取所需缓冲区大小*/ + status = napi_get_value_string_utf16(env, args[[param_index_replace]], NULL, 0, &strSize[param_index_replace]); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "get value string", tag); + return nullptr; + } + char16_t *[param_name_replace]In = new char16_t[strSize[param_index_replace] + 1]; + /* [NAPI_GEN]: 用于获取字符串*/ + status = napi_get_value_string_utf16(env, args[[param_index_replace]], [param_name_replace]In, strSize[param_index_replace] + 1, &strSize[param_index_replace]); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "get value string", tag); + delete[] [param_name_replace]In; + return nullptr; + } + // delete[] [param_name_replace]In; // remember to delete memory `; -export let int64tIn = `int64_t [param_name_replace]In = 0; -/* [NAPI_GEN]: napi_get_value_int64将一个 napi_value 类型的 js 布尔值转换成一个 C 语言的 int64_t 类型的数值 - * env: N-API环境的句柄,表示当前的上下文 - * value:要转换的JavaScript值 - * result:指向 int64_t 类型的指针,在这里函数将存储转换后的整数值 - */ -status = napi_get_value_int64(env, args[[param_index_replace]], &[param_name_replace]In); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_get_value_int64", tag); - return nullptr; -} +export let int64tIn = ` int64_t [param_name_replace]In = 0; + /* [NAPI_GEN]: napi_get_value_int64将一个 napi_value 类型的 js 布尔值转换成一个 C 语言的 int64_t 类型的数值 + * env: N-API环境的句柄,表示当前的上下文 + * value:要转换的JavaScript值 + * result:指向 int64_t 类型的指针,在这里函数将存储转换后的整数值 + */ + status = napi_get_value_int64(env, args[[param_index_replace]], &[param_name_replace]In); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_get_value_int64", tag); + return nullptr; + } `; -export let int32tIn = `int32_t [param_name_replace]In = 0; -/* [NAPI_GEN]: napi_get_value_int32将一个 napi_value 类型的 js 数值转换成一个 C 语言的 int32_t 类型的数值 - * env: N-API环境的句柄,表示当前的上下文 - * value:要转换的JavaScript值 - * result:指向 int32_t 类型的指针,在这里函数将存储转换后的整数值 - */ -status = napi_get_value_int32(env, args[[param_index_replace]], &[param_name_replace]In); -if (status != napi_ok) { - /* [NAPI_GEN]: 错误处理*/ - getErrMessage(status, env, extended_error_info, "napi_get_value_int32", tag); - return nullptr; -} +export let int32tIn = ` int32_t [param_name_replace]In = 0; + /* [NAPI_GEN]: napi_get_value_int32将一个 napi_value 类型的 js 数值转换成一个 C 语言的 int32_t 类型的数值 + * env: N-API环境的句柄,表示当前的上下文 + * value:要转换的JavaScript值 + * result:指向 int32_t 类型的指针,在这里函数将存储转换后的整数值 + */ + status = napi_get_value_int32(env, args[[param_index_replace]], &[param_name_replace]In); + if (status != napi_ok) { + /* [NAPI_GEN]: 错误处理*/ + getErrMessage(status, env, extended_error_info, "napi_get_value_int32", tag); + return nullptr; + } +`; + +export let doubleIn = ` double [param_name_replace]In = 0; + /* [NAPI_GEN]: napi_get_value_double将一个 napi_value 类型的 js 数值转换成一个 C 语言的 double 类型的数值 + * env: N-API环境的句柄,表示当前的上下文 + * value:要转换的JavaScript值 + * result:指向 double 类型的指针,在这里函数将存储转换后的双精度浮点数 + */ + status = napi_get_value_double(env, args[[param_index_replace]], &[param_name_replace]In); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_get_value_double", tag); + return nullptr; + } +`; + +export let boolIn = ` bool [param_name_replace]In = 0; + /* [NAPI_GEN]: napi_get_value_bool将一个 napi_value 类型的 js 布尔值转换成一个 C 语言的 bool 类型的数值 + * env: N-API环境的句柄,表示当前的上下文 + * value:要转换的JavaScript值 + * result:指向 bool 类型的指针,在这里函数将存储转换后的布尔值 + */ + status = napi_get_value_bool(env, args[[param_index_replace]], &[param_name_replace]In); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_get_value_bool", tag); + return nullptr; + } `; -export let doubleIn = `double [param_name_replace]In = 0; -/* [NAPI_GEN]: napi_get_value_double将一个 napi_value 类型的 js 数值转换成一个 C 语言的 double 类型的数值 - * env: N-API环境的句柄,表示当前的上下文 - * value:要转换的JavaScript值 - * result:指向 double 类型的指针,在这里函数将存储转换后的双精度浮点数 - */ -status = napi_get_value_double(env, args[[param_index_replace]], &[param_name_replace]In); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_get_value_double", tag); +export let callbackIn = ` + napi_value argv; + // Todo: 创建要传递给回调函数的参数 + napi_value result; + /** + * env: napi_env 类型的环境变量 + * this_arg: 指向 JavaScript 对象的指针,表示回调函数中的 this 值。如果不需要递 this 值,则可以设置为 nullptr。 + * func: 指向 JavaScript 回调函数的指针。 + * argc: 传递给回调函数的参数数量。示例中传递了一个参数。 + * argv: 一个 napi_value 类型的数组,用于存储要传递给回调函数的参数。示例中传递了一个参数。 + + * result: 指向返回值的指针。如果回调函数没有返回值,则可以设置为 nullptr。 + */ + napi_call_function(env, nullptr, args[[param_index_replace]], 1, &argv, result); +`; + +// class与struct模板 class主体 放在xxxnapi.cpp中 +export let classTemplate = ` +// class napi框架主体 +// 这里构造函数都是默认无参构造函数,如果需要自定义构造函数,可以自行添加 +[class_name_replace]::[class_name_replace]() {} +[class_name_replace]::~[class_name_replace]() { napi_delete_reference(env_, wrapper_); } +void [class_name_replace]::Destructor(napi_env env, void* nativeObject, [[maybe_unused]] void* finalize_hint) +{ + reinterpret_cast<[class_name_replace]*>(nativeObject)->~[class_name_replace](); +} +napi_value [class_name_replace]::New(napi_env env, napi_callback_info info) +{ + napi_value newTarget; + napi_status status; + // Check if the constructor was invoked with new. + napi_get_new_target(env, info, &newTarget); + if (newTarget != nullptr) { + // Invoked as the constructor "new [class_name_replace]()". + napi_value jsThis; + // Retrieve the callback's context and arguments. + status = napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_get_cb_info", tag); + return nullptr; + } + // Create the C++ object. 默认调用无参构造函数,如果需要自定义构造函数,可以自行添加 + [class_name_replace]* obj = new [class_name_replace](); + obj->env_ = env; + // Wrap the C++ object obj in the ArkTS object jsThis. + status =napi_wrap(env, jsThis, reinterpret_cast(obj), [class_name_replace]::Destructor, nullptr, &obj->wrapper_); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_wrap", tag); + return nullptr; + } + delete obj; + return jsThis; + } else { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "CLASS", "[class_name_replace] must be invoked as a constructor with 'new'"); return nullptr; + } } -`; +[class_property_get_set_replace] +[class_method_content_replace] +` -export let boolIn = `bool [param_name_replace]In = 0; -/* [NAPI_GEN]: napi_get_value_bool将一个 napi_value 类型的 js 布尔值转换成一个 C 语言的 bool 类型的数值 - * env: N-API环境的句柄,表示当前的上下文 - * value:要转换的JavaScript值 - * result:指向 bool 类型的指针,在这里函数将存储转换后的布尔值 - */ -status = napi_get_value_bool(env, args[[param_index_replace]], &[param_name_replace]In); -if (status != napi_ok) { - getErrMessage(status, env, extended_error_info, "napi_get_value_bool", tag); +// class的声明,放在xxxnapi.h文件中 +export let classNapiHTemplate = ` +class [class_name_replace] { + public: + static napi_value Init(napi_env env, napi_value exports); + static void Destructor(napi_env env, void* nativeObject, void*finalize_hint); + private: + explicit [class_name_replace](); + ~[class_name_replace](); + static napi_value New(napi_env env, napi_callback_info info); + // 属性的get set函数声明 + [class_property_get_set_declare] + // 方法的声明 + [class_method_declare] + // 变量的声明 + [class_variable_declare] + napi_env env_; + napi_ref wrapper_; +}; +` + +// 替换classNapiHTemplate模板中的内容 +export let classMethodDeclareTemplate = ` + static napi_value [class_method_name_replace](napi_env env, napi_callback_info info); +` + +// 成员方法无入参 +export let classMethodNoParamTemplate = ` + napi_value jsThis; + // 注释 + status = napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_get_cb_info", tag); return nullptr; + } +` + +// 成员方法有入参 +export let classMethodGetParamTemplate = ` + napi_value jsThis; + size_t argc = [param_count_replace]; + napi_value args[[param_count_replace]]; + // 注释 + status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr); + if (status != napi_ok) { + getErrMessage(status, env, extended_error_info, "napi_get_cb_info", tag); + return nullptr; + } + [class_method_get_param] +` + +// class的成员方法Napi实现 放在xxxnapi.cpp文件中 +export let classMethodTemplate = ` +// [NAPI_GEN]:class成员函数的实现方法 +napi_value [class_name_replace]::[class_method_name_replace](napi_env env, napi_callback_info info) +{ + [class_method_param_in] + // Todo: business logic here. + [class_name_replace]* obj; + // 通过napi_unwrap将jsThis之前绑定的C++对象取出,并对其进行操作 + napi_unwrap(env, jsThis, reinterpret_cast(&obj)); + // Todo: you can get value from js and set value to C++. + [class_method_return] } +` +export let classPropertyGetTemplate = ` +// [NAPI_GEN]:class成员变量的get方法 +napi_value [class_name_replace]::Get[class_property_name_replace](napi_env env napi_callback_info info) +{ + napi_value jsThis; + napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); + [class_name_replace]* obj; + // Retrieve obj (the C++ object) previously wrapped in jsThis (the ArkTobject), and perform subsequent operations. + napi_unwrap(env, jsThis, reinterpret_cast(&obj)); + // Todo: get value from C++. + // return value to js... + [class_property_get] +} `; -export let callbackIn = ` -napi_value argv; -// Todo: 创建要传递给回调函数的参数 -napi_value result; -/** -* env: napi_env 类型的环境变量 -* this_arg: 指向 JavaScript 对象的指针,表示回调函数中的 this 值。如果不需要递 this 值,则可以设置为 nullptr。 -* func: 指向 JavaScript 回调函数的指针。 -* argc: 传递给回调函数的参数数量。示例中传递了一个参数。 -* argv: 一个 napi_value 类型的数组,用于存储要传递给回调函数的参数。示例中传递了一个参数。 - -* result: 指向返回值的指针。如果回调函数没有返回值,则可以设置为 nullptr。 -*/ -napi_call_function(env, nullptr, args[[param_index_replace]], 1, &argv, result); +export let classPropertySetTemplate = ` +// [NAPI_GEN]:class成员变量的set方法 +napi_value [class_name_replace]::Set[class_property_name_replace](napi_env env, napi_callback_info info) +{ + napi_value jsThis; + napi_get_cb_info(env, info, nullptr, nullptr, &jsThis, nullptr); + [class_name_replace]* obj; + napi_unwrap(env, jsThis, reinterpret_cast()); + napi_value jsThis; + size_t argc = 1; + napi_value args[1]; + napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr); + [class_name_replace]* obj; + napi_unwrap(env, jsThis, reinterpret_cast(&obj)); + // 例如: napi_get_value_int32(env, args[0], &obj->a); + [class_property_set] + // Todo: set value to C++. + return nullptr; +} +`; + +// 每个类的成员属性都对应一个get和set函数 +export let classPropertyDeclareTemplate = ` + // [NAPI_GEN]:方法注册后,js与native的class属性映射get与set + { [class_property_name_replace], 0, 0, Get[class_property_name_replace], Set[class_property_name_replace], 0, napi_default, 0 }, `; +export let classInitTemplate = ` + // Define properties and methods for a N-API object + napi_property_descriptor [class_name_replace]Properties[] = { + // 成员属性的get与set + [class_property_replace] + // 成员方法的调用 + [class_method_replace] + }; + napi_value cons; + // Define a js class 这里需要介绍class这个参数 + napi_define_class(env, "[class_name_replace]", NAPI_AUTO_LENGTH, New, nullptr, + sizeof([class_name_replace]Properties) / sizeof([class_name_replace]Properties[0]), [class_name_replace]Properties, &cons); + // Set the '[class_name_replace]' class on the exports object. + napi_set_named_property(env, exports, "[class_name_replace]", cons); +` + // napi testAbility需要生成的方法模板 -export let testAbilityFuncTemplate = ` /* [NAPI_GEN]:对应[file_introduce_replace]中:[func_name_replace]方法的dts接口测试用例 +export let testAbilityFuncTemplate = ` /* [NAPI_GEN]:对应[file_introduce_replace]中:[test_case_name]的dts接口测试用例 * 方法输入: [input_introduce_replace] * 方法输出: [func_return_replace] */ diff --git a/src/vscode_plugin/src/test/suite/gen/gendts.test.ts b/src/vscode_plugin/src/test/suite/gen/gendts.test.ts index 09d72a03d62491b8acdd51eaf8bf9e9f3ba8bdf2..094917110b8cb1bbdd6b87dff01f65179c3bf6d2 100644 --- a/src/vscode_plugin/src/test/suite/gen/gendts.test.ts +++ b/src/vscode_plugin/src/test/suite/gen/gendts.test.ts @@ -21,6 +21,7 @@ import * as vscode from 'vscode'; import * as genDts from '../../../gen/gendts' import { ClassObj, EnumObj, FuncObj, GenInfo, ParseObj, StructObj, UnionObj } from '../../../gen/datatype'; import * as fs from 'fs'; +import * as path from 'path'; suite('Gendts_file_Suite', () => { vscode.window.showInformationMessage('Start all tests.'); @@ -39,21 +40,24 @@ suite('Gendts_file_Suite', () => { type: 'int', name: 'v1', arraySize: -1, + arraySizeList: [], } ], }, ], } + let hFilePath = path.join(__dirname, '../../../test/test.h'); //1, 测试一般情况 test('genDtsFile_test_1', () => { let rootInfo: GenInfo = { parseObj: parseObj, - rawFilePath: 'e:\\test.h', + rawFilePath: hFilePath, fileName: 'test', } - let expectedPath = genDts.genDtsFile(rootInfo); - assert.strictEqual(expectedPath, 'e:\\test.d.ts'); + let expectedPath = genDts.genDtsFile(rootInfo, ''); + let genFilePath = path.join(path.dirname(hFilePath), 'test.d.ts'); + assert.strictEqual(expectedPath, genFilePath); // 清理生成的文件 fs.unlinkSync(expectedPath); }); @@ -62,11 +66,12 @@ suite('Gendts_file_Suite', () => { test('genDtsFile_test_2', () => { let rootInfo: GenInfo = { parseObj: parseObj, - rawFilePath: 'e:\\test.h', + rawFilePath: hFilePath, fileName: '', } - let expectedPath = genDts.genDtsFile(rootInfo); - assert.strictEqual(expectedPath, 'e:\\.d.ts'); + let expectedPath = genDts.genDtsFile(rootInfo, ''); + let genFilePath = path.join(path.dirname(hFilePath), '.d.ts'); + assert.strictEqual(expectedPath, genFilePath); // 清理生成的文件 fs.unlinkSync(expectedPath); }); @@ -75,11 +80,11 @@ suite('Gendts_file_Suite', () => { test('genDtsFile_test_3', () => { let rootInfo: GenInfo = { fileName: 'test', - rawFilePath: 'e:\\test.h', + rawFilePath: hFilePath, } let res = true; try { - genDts.genDtsFile(rootInfo); + genDts.genDtsFile(rootInfo, ''); } catch (error) { res = false; } @@ -91,7 +96,7 @@ suite('Gendts_file_Suite', () => { } let res2 = true; try { - genDts.genDtsFile(rootInfo2); + genDts.genDtsFile(rootInfo2, ''); } catch (error) { res2 = false; } @@ -103,14 +108,14 @@ suite('Gendts_file_Suite', () => { test('genDtsFile_test_4', () => { let res = true; try { - genDts.genDtsFile(null); + genDts.genDtsFile(null, ''); } catch (error) { res = false; } assert.strictEqual(res, false); let res2 = true; try { - genDts.genDtsFile(undefined); + genDts.genDtsFile(undefined, ''); } catch (error) { res2 = false; } diff --git a/src/vscode_plugin/src/test/suite/gen/gennapicommoncpp.test.ts b/src/vscode_plugin/src/test/suite/gen/gennapicommoncpp.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..01319ea43876d3093c2183be19f42743443be05c --- /dev/null +++ b/src/vscode_plugin/src/test/suite/gen/gennapicommoncpp.test.ts @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as genNapiCommonCpp from '../../../gen/tools/gennapicommoncpp' +import { GenInfo, ParseObj } from '../../../gen/datatype'; +import * as path from 'path'; +import { napiCommonCppTemplate } from '../../../template/dtscpp/dtscpp_commoncpp_template'; + +suite('Gennapicommoncpp_file_Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + let parseObj: ParseObj = { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: [ + { + type: 'function', + returns: 'int', + name: 'testFunc', + parameters: [ + { + type: 'int', + name: 'v1', + arraySize: -1, + arraySizeList: [], + } + ], + }, + ], + } + let hFilePath = path.join(__dirname, '../../../test/test.h'); + + //1, 测试一般情况 + test('genNapiCommonCppFile_test_1', () => { + let rootInfo: GenInfo = { + parseObj: parseObj, + rawFilePath: hFilePath, + fileName: 'test', + } + let fileContent = genNapiCommonCpp.doGenCommonCppFile(rootInfo, napiCommonCppTemplate.content); + // 判断有没有替换成功,那么直接判断那个替换的字符串是否在fileContent中,若没有,则成功,若有,则失败 + assert.strictEqual(fileContent.indexOf('[filename]') >= 0? 0: -1, -1); + }); + + //2, 测试边界情况 + test('genNapiCommonCppFile_test_2', () => { + let rootInfo: GenInfo = { + parseObj: parseObj, + rawFilePath: hFilePath, + fileName: '', + } + let fileContent = genNapiCommonCpp.doGenCommonCppFile(rootInfo, napiCommonCppTemplate.content); + assert.strictEqual(fileContent.indexOf('[filename]') >= 0? 0: -1, -1); + }); + + //3, 测试异常情况 + test('genNapiCommonCppFile_test_3', () => { + let rootInfo: GenInfo = { + parseObj: parseObj, + rawFilePath: hFilePath, + } + let fileContent = genNapiCommonCpp.doGenCommonCppFile(rootInfo, napiCommonCppTemplate.content); + assert.strictEqual(fileContent.indexOf('[filename]') >= 0? 0: -1, 0); + + }); + + //4, 测试错误情况 + test('genNapiCommonCppFile_test_4', () => { + let fileContent = genNapiCommonCpp.doGenCommonCppFile(undefined, napiCommonCppTemplate.content); + assert.strictEqual(fileContent.indexOf('[filename]') >= 0? 0: -1, -1); + + let fileContent2 = genNapiCommonCpp.doGenCommonCppFile(null, napiCommonCppTemplate.content); + assert.strictEqual(fileContent2.indexOf('[filename]') >= 0? 0: -1, -1); + }); +}); \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/gen/gennapicommonh.test.ts b/src/vscode_plugin/src/test/suite/gen/gennapicommonh.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..1abfea76f6f0eb298669e8deec2b80cbb66a17f5 --- /dev/null +++ b/src/vscode_plugin/src/test/suite/gen/gennapicommonh.test.ts @@ -0,0 +1,98 @@ +/* +* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as genNapiCommonH from '../../../gen/tools/gennapicommonh' +import { GenInfo, ParseObj } from '../../../gen/datatype'; +import * as path from 'path'; +import { napiCommonHTemplate } from '../../../template/dtscpp/dtscpp_commonh_template'; + +suite('Gennapicommonh_file_Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + let parseObj: ParseObj = { + enums: [], + unions: [], + structs: [], + classes: [], + funcs: [ + { + type: 'function', + returns: 'int', + name: 'testFunc', + parameters: [ + { + type: 'int', + name: 'v1', + arraySize: -1, + arraySizeList: [], + } + ], + }, + ], + } + let hFilePath = path.join(__dirname, '../../../test/test.h'); + + //1, 测试一般情况 + test('genNapiCommonHFile_test_1', () => { + let rootInfo: GenInfo = { + parseObj: parseObj, + rawFilePath: hFilePath, + fileName: 'test', + } + let fileContent = genNapiCommonH.doGenCommonHFile(rootInfo, napiCommonHTemplate.content); + // 判断有没有替换成功,那么直接判断那个替换的字符串是否在fileContent中,若没有,则成功,若有,则失败 + assert.strictEqual(fileContent.indexOf('[upper_filename]') >= 0? 0: -1, -1); + assert.strictEqual(fileContent.indexOf('[filename]') >= 0? 0: -1, -1); + }); + + //2, 测试边界情况 + test('genNapiCommonHFile_test_2', () => { + let rootInfo: GenInfo = { + parseObj: parseObj, + rawFilePath: hFilePath, + fileName: '', + } + let fileContent = genNapiCommonH.doGenCommonHFile(rootInfo, napiCommonHTemplate.content); + assert.strictEqual(fileContent.indexOf('[upper_filename]') >= 0? 0: -1, -1); + assert.strictEqual(fileContent.indexOf('[filename]') >= 0? 0: -1, -1); + }); + + //3, 测试异常情况 + test('genNapiCommonHFile_test_3', () => { + let rootInfo: GenInfo = { + parseObj: parseObj, + rawFilePath: hFilePath, + } + let fileContent = genNapiCommonH.doGenCommonHFile(rootInfo, napiCommonHTemplate.content); + assert.strictEqual(fileContent.indexOf('[upper_filename]') >= 0? 0: -1, 0); + assert.strictEqual(fileContent.indexOf('[filename]') >= 0? 0: -1, 0); + + }); + + //4, 测试错误情况 + test('genNapiCommonHFile_test_4', () => { + let fileContent = genNapiCommonH.doGenCommonHFile(undefined, napiCommonHTemplate.content); + assert.strictEqual(fileContent.indexOf('[upper_filename]') >= 0? 0: -1, -1); + assert.strictEqual(fileContent.indexOf('[filename]') >= 0? 0: -1, -1); + + let fileContent2 = genNapiCommonH.doGenCommonHFile(null, napiCommonHTemplate.content); + assert.strictEqual(fileContent2.indexOf('[upper_filename]') >= 0? 0: -1, -1); + assert.strictEqual(fileContent2.indexOf('[filename]') >= 0? 0: -1, -1); + }); +}); \ No newline at end of file