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 re = require('../tools/re');
168c339a94Sopenharmony_ciconst { checkOutBody, print } = require('../tools/tool');
178c339a94Sopenharmony_ciconst { FuncType, NumberIncrease, isFuncType, isArrowFunc, isRegisterFunc } = require('../tools/common');
188c339a94Sopenharmony_ciconst { NapiLog } = require('../tools/NapiLog');
198c339a94Sopenharmony_ci
208c339a94Sopenharmony_cifunction isSyncFuncType(type, funcType) {
218c339a94Sopenharmony_ci    let isSync = false;
228c339a94Sopenharmony_ci    if (funcType === FuncType.DIRECT && type.indexOf('Callback') >= 0 && type.indexOf('AsyncCallback') < 0 ||
238c339a94Sopenharmony_ci        isFuncType(type) || isArrowFunc(type)) {
248c339a94Sopenharmony_ci        isSync = true;
258c339a94Sopenharmony_ci    }
268c339a94Sopenharmony_ci    return isSync;
278c339a94Sopenharmony_ci}
288c339a94Sopenharmony_ci
298c339a94Sopenharmony_ci/**
308c339a94Sopenharmony_ci * on方法中回调方法的解析
318c339a94Sopenharmony_ci * @param {*} valueType 回调方法体
328c339a94Sopenharmony_ci * @param {*} valueName 参数名
338c339a94Sopenharmony_ci * @param {*} rsltCallFunction 解析结果
348c339a94Sopenharmony_ci */
358c339a94Sopenharmony_cifunction analyzeCallbackFunction(valueType, valueName, rsltCallFunction) {
368c339a94Sopenharmony_ci
378c339a94Sopenharmony_ci    if (valueType.indexOf('=>') > 0) {
388c339a94Sopenharmony_ci        valueType = re.replaceAll(valueType, ' ', '');
398c339a94Sopenharmony_ci    }
408c339a94Sopenharmony_ci    let matchs = re.match('\\(([a-zA-Z_0-9:,]+)*\\)=>([a-zA-Z_0-9]+)', valueType);
418c339a94Sopenharmony_ci
428c339a94Sopenharmony_ci    if (matchs) {
438c339a94Sopenharmony_ci        let number = NumberIncrease.getAndIncrease();
448c339a94Sopenharmony_ci        let functionTypeName = 'AUTO_CALLFUNCTION_%s_%s'.format(valueName, number);
458c339a94Sopenharmony_ci
468c339a94Sopenharmony_ci        let functionRet = re.getReg(valueType, matchs.regs[2]);
478c339a94Sopenharmony_ci        let functionBody = re.getReg(valueType, matchs.regs[1]);
488c339a94Sopenharmony_ci
498c339a94Sopenharmony_ci        let tmp = analyzeParams(functionTypeName, functionBody);
508c339a94Sopenharmony_ci        let bodyRes = tmp[0];
518c339a94Sopenharmony_ci        for (let i in bodyRes) {
528c339a94Sopenharmony_ci            let hasProperty = Object.prototype.hasOwnProperty.call(bodyRes[i], 'type');
538c339a94Sopenharmony_ci            if (hasProperty && bodyRes[i].type === 'number') {
548c339a94Sopenharmony_ci                bodyRes[i].type = 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease();
558c339a94Sopenharmony_ci            }
568c339a94Sopenharmony_ci        }
578c339a94Sopenharmony_ci
588c339a94Sopenharmony_ci        rsltCallFunction.push({
598c339a94Sopenharmony_ci            'name': functionTypeName,
608c339a94Sopenharmony_ci            'body': bodyRes,
618c339a94Sopenharmony_ci            'ret': functionRet,
628c339a94Sopenharmony_ci        });
638c339a94Sopenharmony_ci        valueType = functionTypeName;
648c339a94Sopenharmony_ci    }
658c339a94Sopenharmony_ci    return valueType;
668c339a94Sopenharmony_ci}
678c339a94Sopenharmony_ci
688c339a94Sopenharmony_ci/**函数参数解析 */
698c339a94Sopenharmony_cifunction analyzeParams(funcName, values) {
708c339a94Sopenharmony_ci    let result = [];
718c339a94Sopenharmony_ci    let rsltCallFunction = [];
728c339a94Sopenharmony_ci    let funcType = FuncType.DIRECT;
738c339a94Sopenharmony_ci    let optionalParamCount = 0; // 可选参数的个数
748c339a94Sopenharmony_ci    while (values.length > 0) {
758c339a94Sopenharmony_ci        let v = checkOutBody(values, 0, ['', ',']);
768c339a94Sopenharmony_ci        if (v === null) {
778c339a94Sopenharmony_ci            v = values;
788c339a94Sopenharmony_ci        }
798c339a94Sopenharmony_ci
808c339a94Sopenharmony_ci        values = values.substring(v.length, values.length);
818c339a94Sopenharmony_ci        let matchs = re.match('([a-zA-Z_0-9\\.]+)(\\?*): *([a-zA-Z<,>|_0-9\\[\\]\\(\\):=\'{}]+)', v);
828c339a94Sopenharmony_ci        if (matchs === null && (funcName === 'on' || funcName === 'off')) {
838c339a94Sopenharmony_ci            // on和off的第一个参数的类型可以是一串字符
848c339a94Sopenharmony_ci            matchs = re.match('([a-zA-Z_0-9\\.]+)(\\?*): *\"([a-zA-Z|_0-9\\[\\]\\(\\):=\'{}]+)\"', v);
858c339a94Sopenharmony_ci        }
868c339a94Sopenharmony_ci        if (matchs !== null) {
878c339a94Sopenharmony_ci            let type = re.getReg(v, matchs.regs[3]);
888c339a94Sopenharmony_ci            if (type.indexOf('Map') < 0 && !isArrowFunc(type)) {
898c339a94Sopenharmony_ci                type = type.replace(/,/g, '');
908c339a94Sopenharmony_ci            }
918c339a94Sopenharmony_ci
928c339a94Sopenharmony_ci            let valueName = re.getReg(v, matchs.regs[1]);
938c339a94Sopenharmony_ci            type = analyzeCallbackFunction(type, valueName, rsltCallFunction);
948c339a94Sopenharmony_ci
958c339a94Sopenharmony_ci            let optionalFlag = re.getReg(v, matchs.regs[2]) === '?' ? true : false;
968c339a94Sopenharmony_ci            let checkParamOk = true;
978c339a94Sopenharmony_ci            let retVal = analyzaParamsFunc(optionalFlag, optionalParamCount, v, funcName, checkParamOk,
988c339a94Sopenharmony_ci                result, matchs, type, funcType);
998c339a94Sopenharmony_ci            result = retVal[0];
1008c339a94Sopenharmony_ci            funcType = retVal[1];
1018c339a94Sopenharmony_ci        }
1028c339a94Sopenharmony_ci        else {
1038c339a94Sopenharmony_ci            NapiLog.logError('Failed to analyse parameter [%s] of function [%s].'.format(v, funcName));
1048c339a94Sopenharmony_ci        }
1058c339a94Sopenharmony_ci    }
1068c339a94Sopenharmony_ci    return [result, funcType, rsltCallFunction];
1078c339a94Sopenharmony_ci}
1088c339a94Sopenharmony_ci
1098c339a94Sopenharmony_cifunction analyzaParamsFunc(optionalFlag, optionalParamCount, v, funcName, checkParamOk,
1108c339a94Sopenharmony_ci    result, matchs, type, funcType) {
1118c339a94Sopenharmony_ci    if (optionalFlag) {
1128c339a94Sopenharmony_ci        optionalParamCount++;
1138c339a94Sopenharmony_ci    } else if (optionalParamCount > 0) {
1148c339a94Sopenharmony_ci        // 可选参数之后不能再有必选参数,须是可选参数。
1158c339a94Sopenharmony_ci        NapiLog.logError('Invalid parameter [%s] of function [%s],'.format(v, funcName) +
1168c339a94Sopenharmony_ci            ' the required parameter cannot follow an optional parameter.');
1178c339a94Sopenharmony_ci        checkParamOk = false;
1188c339a94Sopenharmony_ci    }
1198c339a94Sopenharmony_ci    if (checkParamOk) {
1208c339a94Sopenharmony_ci        result.push({ 'name': re.getReg(v, matchs.regs[1]), 'type': type, 'optional': optionalFlag, 'realType': type });
1218c339a94Sopenharmony_ci        if (type.indexOf('AsyncCallback') >= 0) {
1228c339a94Sopenharmony_ci            funcType = FuncType.ASYNC;
1238c339a94Sopenharmony_ci        }
1248c339a94Sopenharmony_ci
1258c339a94Sopenharmony_ci        if (isSyncFuncType(type, funcType)) {
1268c339a94Sopenharmony_ci            funcType = FuncType.SYNC;
1278c339a94Sopenharmony_ci        }
1288c339a94Sopenharmony_ci    }
1298c339a94Sopenharmony_ci    return [result, funcType];
1308c339a94Sopenharmony_ci}
1318c339a94Sopenharmony_ci
1328c339a94Sopenharmony_cimodule.exports = {
1338c339a94Sopenharmony_ci    analyzeParams,
1348c339a94Sopenharmony_ci};
135