18c339a94Sopenharmony_ci/* 28c339a94Sopenharmony_ci* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 38c339a94Sopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License"); 48c339a94Sopenharmony_ci* you may not use this file except in compliance with the License. 58c339a94Sopenharmony_ci* You may obtain a copy of the License at 68c339a94Sopenharmony_ci* 78c339a94Sopenharmony_ci* http://www.apache.org/licenses/LICENSE-2.0 88c339a94Sopenharmony_ci* 98c339a94Sopenharmony_ci* Unless required by applicable law or agreed to in writing, software 108c339a94Sopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS, 118c339a94Sopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128c339a94Sopenharmony_ci* See the License for the specific language governing permissions and 138c339a94Sopenharmony_ci* limitations under the License. 148c339a94Sopenharmony_ci*/ 158c339a94Sopenharmony_ciconst { generateFunctionDirect } = require('./function_direct'); 168c339a94Sopenharmony_ciconst { generateFunctionSync } = require('./function_sync'); 178c339a94Sopenharmony_ciconst { generateFunctionAsync } = require('./function_async'); 188c339a94Sopenharmony_ciconst { generateInterface } = require('./interface'); 198c339a94Sopenharmony_ciconst { generateClass } = require('./class'); 208c339a94Sopenharmony_ciconst { generateType } = require('./type'); 218c339a94Sopenharmony_ciconst { FuncType, InterfaceList, EnumList, TypeList, CallFunctionList, isOnOffRegisterFunc, isCreateThreadsafeFunc } = 228c339a94Sopenharmony_cirequire('../tools/common'); 238c339a94Sopenharmony_ciconst { generateEnum } = require('./enum'); 248c339a94Sopenharmony_ciconst { generateFunctionOnOff } = require('./function_onoff'); 258c339a94Sopenharmony_ciconst { generateThreadsafeFunc } = require('./function_threadsafe'); 268c339a94Sopenharmony_ci 278c339a94Sopenharmony_ciconst { NapiLog } = require('../tools/NapiLog'); 288c339a94Sopenharmony_ciconst { addUniqFunc2List, addUniqObj2List } = require('../tools/tool'); 298c339a94Sopenharmony_ci 308c339a94Sopenharmony_cifunction findParentByName(parentName, data) { 318c339a94Sopenharmony_ci for (let i in data.interface) { 328c339a94Sopenharmony_ci if (parentName === data.interface[i].name) { 338c339a94Sopenharmony_ci return data.interface[i]; 348c339a94Sopenharmony_ci } 358c339a94Sopenharmony_ci } 368c339a94Sopenharmony_ci 378c339a94Sopenharmony_ci for (let i in data.class) { 388c339a94Sopenharmony_ci if (parentName === data.class[i].name) { 398c339a94Sopenharmony_ci return data.class[i]; 408c339a94Sopenharmony_ci } 418c339a94Sopenharmony_ci } 428c339a94Sopenharmony_ci return null; 438c339a94Sopenharmony_ci} 448c339a94Sopenharmony_ci 458c339a94Sopenharmony_ci/** 468c339a94Sopenharmony_ci * 生成父类的成员变量和方法 478c339a94Sopenharmony_ci * @param currentObj 当前类 488c339a94Sopenharmony_ci * @param data 全局数据上下文 498c339a94Sopenharmony_ci * @param parentBody 输出参数,保存父类的成员变量和方法 508c339a94Sopenharmony_ci * @returns void 518c339a94Sopenharmony_ci */ 528c339a94Sopenharmony_cifunction genParentPropties(currentObj, data, parentBody) { 538c339a94Sopenharmony_ci for (let i in currentObj.body.parentNameList) { 548c339a94Sopenharmony_ci let parentName = currentObj.body.parentNameList[i]; 558c339a94Sopenharmony_ci let parentObj = findParentByName(parentName, data); 568c339a94Sopenharmony_ci if (!parentObj) { 578c339a94Sopenharmony_ci NapiLog.logError("Failed to find %s's parent by name [%s]".format(currentObj.body.name, parentName)); 588c339a94Sopenharmony_ci return; 598c339a94Sopenharmony_ci } 608c339a94Sopenharmony_ci 618c339a94Sopenharmony_ci // 为父类添加子类的对象信息 628c339a94Sopenharmony_ci addUniqObj2List(currentObj, parentObj.body.childList); 638c339a94Sopenharmony_ci 648c339a94Sopenharmony_ci // 为当前类添加父类对象信息 658c339a94Sopenharmony_ci addUniqObj2List(parentObj, currentObj.body.parentList); 668c339a94Sopenharmony_ci 678c339a94Sopenharmony_ci for (let i in parentObj.body.value) { 688c339a94Sopenharmony_ci // 添加父类的所有成员属性到parentBody 698c339a94Sopenharmony_ci addUniqObj2List(parentObj.body.value[i], parentBody.value); 708c339a94Sopenharmony_ci } 718c339a94Sopenharmony_ci for (let i in parentObj.body.function) { 728c339a94Sopenharmony_ci // 添加父类的所有成员方法到parentBody 738c339a94Sopenharmony_ci addUniqFunc2List(parentObj.body.function[i], parentBody.function); 748c339a94Sopenharmony_ci } 758c339a94Sopenharmony_ci if (parentObj.body.parentNameList.length > 0) { 768c339a94Sopenharmony_ci // 递归查找父类的父类 778c339a94Sopenharmony_ci genParentPropties(parentObj, data, parentBody); 788c339a94Sopenharmony_ci } 798c339a94Sopenharmony_ci } 808c339a94Sopenharmony_ci} 818c339a94Sopenharmony_ci 828c339a94Sopenharmony_ci// 为有继承关系的interface和class类型建立父子类关系信息 838c339a94Sopenharmony_cifunction genExtendsRelation(data) { 848c339a94Sopenharmony_ci for (let i in data.interface) { 858c339a94Sopenharmony_ci let ifObj = data.interface[i]; 868c339a94Sopenharmony_ci if (ifObj && ifObj.body.parentNameList && ifObj.body.parentNameList.length > 0) { 878c339a94Sopenharmony_ci ifObj.body.parentBody = {value:[], function:[]}; 888c339a94Sopenharmony_ci genParentPropties(ifObj, data, ifObj.body.parentBody); 898c339a94Sopenharmony_ci } 908c339a94Sopenharmony_ci } 918c339a94Sopenharmony_ci 928c339a94Sopenharmony_ci for (let i in data.class) { 938c339a94Sopenharmony_ci let classObj = data.class[i]; 948c339a94Sopenharmony_ci if (classObj.body.parentName) { 958c339a94Sopenharmony_ci classObj.body.parentBody = {value:[], function:[]}; 968c339a94Sopenharmony_ci genParentPropties(classObj, data, classObj.body.parentBody); 978c339a94Sopenharmony_ci } 988c339a94Sopenharmony_ci } 998c339a94Sopenharmony_ci} 1008c339a94Sopenharmony_ci 1018c339a94Sopenharmony_ci//生成module_middle.cpp、module.h、module.cpp 1028c339a94Sopenharmony_cifunction generateNamespace(name, data, inNamespace = '') { 1038c339a94Sopenharmony_ci let namespaceResult = { implH: '', implCpp: '', middleFunc: '', middleInit: '', declarationH: '', middleH: '', middleInitEnumDef: '' }; 1048c339a94Sopenharmony_ci namespaceResult.middleInit += formatMiddleInit(inNamespace, name); 1058c339a94Sopenharmony_ci genExtendsRelation(data); 1068c339a94Sopenharmony_ci InterfaceList.push(data.interface); 1078c339a94Sopenharmony_ci TypeList.push(data.type); 1088c339a94Sopenharmony_ci EnumList.push(data.enum); 1098c339a94Sopenharmony_ci CallFunctionList.push(data.callFunction); 1108c339a94Sopenharmony_ci let toolNamespace = getToolNamespaceFunc(inNamespace, name); 1118c339a94Sopenharmony_ci enumNamespaceFunction(data, namespaceResult, inNamespace, name, toolNamespace); 1128c339a94Sopenharmony_ci for (let i in data.type) { 1138c339a94Sopenharmony_ci let ii = data.type[i]; 1148c339a94Sopenharmony_ci let result = generateType(ii.name, ii.body, inNamespace + name + '::', inNamespace, name, toolNamespace); 1158c339a94Sopenharmony_ci namespaceResult = getNamespaceResult(result, namespaceResult); 1168c339a94Sopenharmony_ci } 1178c339a94Sopenharmony_ci for (let i in data.interface) { 1188c339a94Sopenharmony_ci let ii = data.interface[i]; 1198c339a94Sopenharmony_ci let result = generateInterface(ii.name, ii.body, inNamespace + name + '::'); 1208c339a94Sopenharmony_ci namespaceResult = getNamespaceResult(result, namespaceResult); 1218c339a94Sopenharmony_ci } 1228c339a94Sopenharmony_ci for (let i in data.class) { 1238c339a94Sopenharmony_ci let ii = data.class[i]; 1248c339a94Sopenharmony_ci let result = generateClass(ii.name, ii.body, inNamespace + name + '::', ii.functiontType); 1258c339a94Sopenharmony_ci namespaceResult = getNamespaceResult(result, namespaceResult); 1268c339a94Sopenharmony_ci } 1278c339a94Sopenharmony_ci namespaceResult.implH = namespaceResult.declarationH + namespaceResult.implH; 1288c339a94Sopenharmony_ci for (let i in data.function) { 1298c339a94Sopenharmony_ci genNamespaceFunc(data, i, namespaceResult, inNamespace, name); 1308c339a94Sopenharmony_ci } 1318c339a94Sopenharmony_ci let flag = true; 1328c339a94Sopenharmony_ci if (data.namespace.length !== 0) { 1338c339a94Sopenharmony_ci flag = false; 1348c339a94Sopenharmony_ci } 1358c339a94Sopenharmony_ci for (let i in data.namespace) { 1368c339a94Sopenharmony_ci let ns = data.namespace[i]; 1378c339a94Sopenharmony_ci let result = generateNamespace(ns.name, ns.body, inNamespace + name + '::'); 1388c339a94Sopenharmony_ci namespaceResult = getNamespaceResult(result, namespaceResult); 1398c339a94Sopenharmony_ci } 1408c339a94Sopenharmony_ci InterfaceList.pop(); 1418c339a94Sopenharmony_ci TypeList.pop(); 1428c339a94Sopenharmony_ci EnumList.pop(); 1438c339a94Sopenharmony_ci CallFunctionList.pop(); 1448c339a94Sopenharmony_ci if (inNamespace.length > 0) { 1458c339a94Sopenharmony_ci namespaceResult.middleInit += '}'; 1468c339a94Sopenharmony_ci flag = true; 1478c339a94Sopenharmony_ci } 1488c339a94Sopenharmony_ci return generateResult(name, namespaceResult.implH, namespaceResult.implCpp, namespaceResult.middleFunc, 1498c339a94Sopenharmony_ci namespaceResult.middleInit, namespaceResult.middleH, namespaceResult.middleInitEnumDef, flag); 1508c339a94Sopenharmony_ci} 1518c339a94Sopenharmony_ci 1528c339a94Sopenharmony_cifunction genNamespaceFunc(data, i, namespaceResult, inNamespace, name) { 1538c339a94Sopenharmony_ci let func = data.function[i]; 1548c339a94Sopenharmony_ci let tmp = generateFunction(func, data, namespaceResult.implH); 1558c339a94Sopenharmony_ci namespaceResult.middleFunc += tmp[0]; 1568c339a94Sopenharmony_ci namespaceResult.implH += tmp[1]; 1578c339a94Sopenharmony_ci namespaceResult.implCpp += tmp[2]; 1588c339a94Sopenharmony_ci namespaceResult.middleH += tmp[3]; 1598c339a94Sopenharmony_ci let toolNamespace = getToolNamespaceFunc(inNamespace, name); 1608c339a94Sopenharmony_ci let middleTmp = ' pxt->DefineFunction("%s", %s%s::%s%s_middle%s);\n' 1618c339a94Sopenharmony_ci .format(func.name, inNamespace, name, toolNamespace, func.name, inNamespace.length > 0 ? ', ' + name : ''); 1628c339a94Sopenharmony_ci if (namespaceResult.middleInit.indexOf(middleTmp) < 0) { // on方法不需要重复定义 1638c339a94Sopenharmony_ci namespaceResult.middleInit += middleTmp; 1648c339a94Sopenharmony_ci } 1658c339a94Sopenharmony_ci} 1668c339a94Sopenharmony_ci 1678c339a94Sopenharmony_cifunction getToolNamespaceFunc(inNamespace, name) { 1688c339a94Sopenharmony_ci let toolNamespace; 1698c339a94Sopenharmony_ci if (inNamespace !== '') { 1708c339a94Sopenharmony_ci let index = inNamespace.lastIndexOf('::'); 1718c339a94Sopenharmony_ci let bodyTmp = inNamespace.substring(0, index); 1728c339a94Sopenharmony_ci let index2 = bodyTmp.lastIndexOf('::'); 1738c339a94Sopenharmony_ci if (index2 > 0 && index2 < index) { 1748c339a94Sopenharmony_ci toolNamespace = inNamespace.substring(index2 + 2, index) + '_interface::'; 1758c339a94Sopenharmony_ci } else { 1768c339a94Sopenharmony_ci toolNamespace = name + '_interface::'; 1778c339a94Sopenharmony_ci } 1788c339a94Sopenharmony_ci } else { 1798c339a94Sopenharmony_ci toolNamespace = name + '_interface::'; 1808c339a94Sopenharmony_ci } 1818c339a94Sopenharmony_ci return toolNamespace; 1828c339a94Sopenharmony_ci} 1838c339a94Sopenharmony_ci 1848c339a94Sopenharmony_cifunction enumNamespaceFunction(data, namespaceResult, inNamespace, nameSpaceName, toolNamespace) { 1858c339a94Sopenharmony_ci let result = generateEnumResult(data, inNamespace, nameSpaceName, toolNamespace); 1868c339a94Sopenharmony_ci namespaceResult.implH += result.implH; 1878c339a94Sopenharmony_ci namespaceResult.implCpp += result.implCpp; 1888c339a94Sopenharmony_ci namespaceResult.middleInit += result.middleInit; 1898c339a94Sopenharmony_ci namespaceResult.middleInitEnumDef += result.midInitEnumDefine; 1908c339a94Sopenharmony_ci} 1918c339a94Sopenharmony_ci 1928c339a94Sopenharmony_cifunction getNamespaceResult(subResult, returnResult) { 1938c339a94Sopenharmony_ci returnResult.middleFunc += subResult.middleBody; 1948c339a94Sopenharmony_ci returnResult.implH += subResult.implH; 1958c339a94Sopenharmony_ci returnResult.implCpp += subResult.implCpp; 1968c339a94Sopenharmony_ci returnResult.middleInit += subResult.middleInit; 1978c339a94Sopenharmony_ci returnResult.declarationH += subResult.declarationH; 1988c339a94Sopenharmony_ci returnResult.middleH += subResult.middleH; 1998c339a94Sopenharmony_ci 2008c339a94Sopenharmony_ci if (subResult.midInitEnumDefine !== undefined) { 2018c339a94Sopenharmony_ci returnResult.middleInitEnumDef += subResult.midInitEnumDefine; 2028c339a94Sopenharmony_ci } 2038c339a94Sopenharmony_ci 2048c339a94Sopenharmony_ci return returnResult; 2058c339a94Sopenharmony_ci} 2068c339a94Sopenharmony_ci 2078c339a94Sopenharmony_ci function generateEnumResult(data, inNamespace, nameSpaceName, toolNamespace) { 2088c339a94Sopenharmony_ci let resultEnum = { 2098c339a94Sopenharmony_ci implH: '', 2108c339a94Sopenharmony_ci implCpp: '', 2118c339a94Sopenharmony_ci middleInit: '', 2128c339a94Sopenharmony_ci midInitEnumDefine: '' 2138c339a94Sopenharmony_ci }; 2148c339a94Sopenharmony_ci 2158c339a94Sopenharmony_ci for (let i in data.enum) { 2168c339a94Sopenharmony_ci let enumm = data.enum[i]; 2178c339a94Sopenharmony_ci let result = generateEnum(enumm.name, enumm.body, inNamespace, nameSpaceName, toolNamespace); 2188c339a94Sopenharmony_ci resultEnum.implH += result.implH; 2198c339a94Sopenharmony_ci resultEnum.implCpp += result.implCpp; 2208c339a94Sopenharmony_ci resultEnum.middleInit += result.midInitEnum; 2218c339a94Sopenharmony_ci resultEnum.midInitEnumDefine += result.midInitEnumDefine; 2228c339a94Sopenharmony_ci } 2238c339a94Sopenharmony_ci return resultEnum; 2248c339a94Sopenharmony_ci} 2258c339a94Sopenharmony_ci 2268c339a94Sopenharmony_cifunction generateResult(name, implH, implCpp, middleFunc, middleInit, middleH, middleInitEnumDef, flag) { 2278c339a94Sopenharmony_ci let result; 2288c339a94Sopenharmony_ci let middleEnumDefine = middleInitEnumDef.indexOf('undefined') >= 0 ? '' : middleInitEnumDef; 2298c339a94Sopenharmony_ci if (flag) { 2308c339a94Sopenharmony_ci result = { 2318c339a94Sopenharmony_ci implH: `\nnamespace %s {\nnamespace %s_interface {%s\n}\n}`.format(name, name, implH), 2328c339a94Sopenharmony_ci implCpp: `\nnamespace %s {\nnamespace %s_interface {%s\n}\n}`.format(name, name, implCpp), 2338c339a94Sopenharmony_ci middleBody: `\nnamespace %s {\nnamespace %s_interface {\n%s%s\n}\n}`.format(name, name, middleEnumDefine, middleFunc), 2348c339a94Sopenharmony_ci middleInit: middleInit, 2358c339a94Sopenharmony_ci middleH: `\nnamespace %s {\nnamespace %s_interface {%s\n}\n}`.format(name, name, middleH) 2368c339a94Sopenharmony_ci }; 2378c339a94Sopenharmony_ci } else { 2388c339a94Sopenharmony_ci result = { 2398c339a94Sopenharmony_ci implH: `\nnamespace %s {%s\n}`.format(name, implH), 2408c339a94Sopenharmony_ci implCpp: `\nnamespace %s {%s}`.format(name, implCpp), 2418c339a94Sopenharmony_ci middleBody: `\nnamespace %s {\n%s%s}`.format(name, middleEnumDefine, middleFunc), 2428c339a94Sopenharmony_ci middleInit: middleInit, 2438c339a94Sopenharmony_ci middleH: `\nnamespace %s {%s\n}`.format(name, middleH) 2448c339a94Sopenharmony_ci }; 2458c339a94Sopenharmony_ci } 2468c339a94Sopenharmony_ci return result; 2478c339a94Sopenharmony_ci} 2488c339a94Sopenharmony_ci 2498c339a94Sopenharmony_cifunction generateFunction(func, data, implH = null) { 2508c339a94Sopenharmony_ci let tmp; 2518c339a94Sopenharmony_ci let className; 2528c339a94Sopenharmony_ci if (isOnOffRegisterFunc(func.name)) { 2538c339a94Sopenharmony_ci return generateFunctionOnOff(func, data); 2548c339a94Sopenharmony_ci } else if (isCreateThreadsafeFunc(func.name)) { 2558c339a94Sopenharmony_ci return generateThreadsafeFunc(func, data); 2568c339a94Sopenharmony_ci } 2578c339a94Sopenharmony_ci switch (func.type) { 2588c339a94Sopenharmony_ci case FuncType.DIRECT: 2598c339a94Sopenharmony_ci tmp = generateFunctionDirect(func, data); 2608c339a94Sopenharmony_ci break; 2618c339a94Sopenharmony_ci case FuncType.SYNC: 2628c339a94Sopenharmony_ci tmp = generateFunctionSync(func, data); 2638c339a94Sopenharmony_ci break; 2648c339a94Sopenharmony_ci case FuncType.ASYNC: 2658c339a94Sopenharmony_ci case FuncType.PROMISE: 2668c339a94Sopenharmony_ci tmp = generateFunctionAsync(func, data, className, implH); 2678c339a94Sopenharmony_ci break; 2688c339a94Sopenharmony_ci default: 2698c339a94Sopenharmony_ci break; 2708c339a94Sopenharmony_ci } 2718c339a94Sopenharmony_ci return tmp; 2728c339a94Sopenharmony_ci} 2738c339a94Sopenharmony_ci 2748c339a94Sopenharmony_cifunction formatMiddleInit(inNamespace, name) { 2758c339a94Sopenharmony_ci let middleInit = ''; 2768c339a94Sopenharmony_ci if (inNamespace.length > 0) { 2778c339a94Sopenharmony_ci let nsl = inNamespace.split('::'); 2788c339a94Sopenharmony_ci nsl.pop(); 2798c339a94Sopenharmony_ci let parentNs = nsl[nsl.length - 1]; 2808c339a94Sopenharmony_ci middleInit = `{\nnapi_value %s = pxt->CreateSubObject(%s, "%s");\n` 2818c339a94Sopenharmony_ci .format(name, nsl.length === 1 ? 'exports' : parentNs, name); 2828c339a94Sopenharmony_ci } 2838c339a94Sopenharmony_ci return middleInit; 2848c339a94Sopenharmony_ci} 2858c339a94Sopenharmony_ci 2868c339a94Sopenharmony_cimodule.exports = { 2878c339a94Sopenharmony_ci generateNamespace, 2888c339a94Sopenharmony_ci getNamespaceResult, 2898c339a94Sopenharmony_ci generateEnumResult, 2908c339a94Sopenharmony_ci generateResult, 2918c339a94Sopenharmony_ci generateFunction, 2928c339a94Sopenharmony_ci formatMiddleInit 2938c339a94Sopenharmony_ci}; 294