1/* 2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15const re = require('../tools/re'); 16const { checkOutBody, print } = require('../tools/tool'); 17const { FuncType, NumberIncrease, isFuncType, isArrowFunc, isRegisterFunc } = require('../tools/common'); 18const { NapiLog } = require('../tools/NapiLog'); 19 20function isSyncFuncType(type, funcType) { 21 let isSync = false; 22 if (funcType === FuncType.DIRECT && type.indexOf('Callback') >= 0 && type.indexOf('AsyncCallback') < 0 || 23 isFuncType(type) || isArrowFunc(type)) { 24 isSync = true; 25 } 26 return isSync; 27} 28 29/** 30 * on方法中回调方法的解析 31 * @param {*} valueType 回调方法体 32 * @param {*} valueName 参数名 33 * @param {*} rsltCallFunction 解析结果 34 */ 35function analyzeCallbackFunction(valueType, valueName, rsltCallFunction) { 36 37 if (valueType.indexOf('=>') > 0) { 38 valueType = re.replaceAll(valueType, ' ', ''); 39 } 40 let matchs = re.match('\\(([a-zA-Z_0-9:,]+)*\\)=>([a-zA-Z_0-9]+)', valueType); 41 42 if (matchs) { 43 let number = NumberIncrease.getAndIncrease(); 44 let functionTypeName = 'AUTO_CALLFUNCTION_%s_%s'.format(valueName, number); 45 46 let functionRet = re.getReg(valueType, matchs.regs[2]); 47 let functionBody = re.getReg(valueType, matchs.regs[1]); 48 49 let tmp = analyzeParams(functionTypeName, functionBody); 50 let bodyRes = tmp[0]; 51 for (let i in bodyRes) { 52 let hasProperty = Object.prototype.hasOwnProperty.call(bodyRes[i], 'type'); 53 if (hasProperty && bodyRes[i].type === 'number') { 54 bodyRes[i].type = 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease(); 55 } 56 } 57 58 rsltCallFunction.push({ 59 'name': functionTypeName, 60 'body': bodyRes, 61 'ret': functionRet, 62 }); 63 valueType = functionTypeName; 64 } 65 return valueType; 66} 67 68/**函数参数解析 */ 69function analyzeParams(funcName, values) { 70 let result = []; 71 let rsltCallFunction = []; 72 let funcType = FuncType.DIRECT; 73 let optionalParamCount = 0; // 可选参数的个数 74 while (values.length > 0) { 75 let v = checkOutBody(values, 0, ['', ',']); 76 if (v === null) { 77 v = values; 78 } 79 80 values = values.substring(v.length, values.length); 81 let matchs = re.match('([a-zA-Z_0-9\\.]+)(\\?*): *([a-zA-Z<,>|_0-9\\[\\]\\(\\):=\'{}]+)', v); 82 if (matchs === null && (funcName === 'on' || funcName === 'off')) { 83 // on和off的第一个参数的类型可以是一串字符 84 matchs = re.match('([a-zA-Z_0-9\\.]+)(\\?*): *\"([a-zA-Z|_0-9\\[\\]\\(\\):=\'{}]+)\"', v); 85 } 86 if (matchs !== null) { 87 let type = re.getReg(v, matchs.regs[3]); 88 if (type.indexOf('Map') < 0 && !isArrowFunc(type)) { 89 type = type.replace(/,/g, ''); 90 } 91 92 let valueName = re.getReg(v, matchs.regs[1]); 93 type = analyzeCallbackFunction(type, valueName, rsltCallFunction); 94 95 let optionalFlag = re.getReg(v, matchs.regs[2]) === '?' ? true : false; 96 let checkParamOk = true; 97 let retVal = analyzaParamsFunc(optionalFlag, optionalParamCount, v, funcName, checkParamOk, 98 result, matchs, type, funcType); 99 result = retVal[0]; 100 funcType = retVal[1]; 101 } 102 else { 103 NapiLog.logError('Failed to analyse parameter [%s] of function [%s].'.format(v, funcName)); 104 } 105 } 106 return [result, funcType, rsltCallFunction]; 107} 108 109function analyzaParamsFunc(optionalFlag, optionalParamCount, v, funcName, checkParamOk, 110 result, matchs, type, funcType) { 111 if (optionalFlag) { 112 optionalParamCount++; 113 } else if (optionalParamCount > 0) { 114 // 可选参数之后不能再有必选参数,须是可选参数。 115 NapiLog.logError('Invalid parameter [%s] of function [%s],'.format(v, funcName) + 116 ' the required parameter cannot follow an optional parameter.'); 117 checkParamOk = false; 118 } 119 if (checkParamOk) { 120 result.push({ 'name': re.getReg(v, matchs.regs[1]), 'type': type, 'optional': optionalFlag, 'realType': type }); 121 if (type.indexOf('AsyncCallback') >= 0) { 122 funcType = FuncType.ASYNC; 123 } 124 125 if (isSyncFuncType(type, funcType)) { 126 funcType = FuncType.SYNC; 127 } 128 } 129 return [result, funcType]; 130} 131 132module.exports = { 133 analyzeParams, 134}; 135