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 { FuncType, NumberIncrease, isEnum, EnumValueType, enumIndex, isType, typeIndex, isOnObjCallback,
178c339a94Sopenharmony_ci    getOnObjCallbackType, getLogErrInfo } = require('../tools/common');
188c339a94Sopenharmony_ciconst { analyzeParams } = require('./params');
198c339a94Sopenharmony_ciconst { analyzeReturn } = require('./return');
208c339a94Sopenharmony_ciconst { NapiLog } = require('../tools/NapiLog');
218c339a94Sopenharmony_ciconst { randomInt } = require('crypto');
228c339a94Sopenharmony_ciconst { print } = require('../tools/tool');
238c339a94Sopenharmony_ci
248c339a94Sopenharmony_cifunction analyzeSubInterface(data) {
258c339a94Sopenharmony_ci    let body = re.replaceAll(data, '\n', '').split(';'); //  # replace(' ', '').
268c339a94Sopenharmony_ci    let result = {
278c339a94Sopenharmony_ci        value: [],
288c339a94Sopenharmony_ci        function: [],
298c339a94Sopenharmony_ci        parentNameList: [],
308c339a94Sopenharmony_ci        childList: [],
318c339a94Sopenharmony_ci        parentList: [],
328c339a94Sopenharmony_ci    };
338c339a94Sopenharmony_ci    for (let i in body) {
348c339a94Sopenharmony_ci        let t = body[i];
358c339a94Sopenharmony_ci        while (t.length > 0 && t[0] === ' ') {
368c339a94Sopenharmony_ci            t = t.substring(1, t.length);
378c339a94Sopenharmony_ci        }
388c339a94Sopenharmony_ci        while (t.length > 0 && t[-1] === ' ') {
398c339a94Sopenharmony_ci            t = t.substring(0, t.length - 1);
408c339a94Sopenharmony_ci        }
418c339a94Sopenharmony_ci        if (t === '') {
428c339a94Sopenharmony_ci            break;
438c339a94Sopenharmony_ci        }
448c339a94Sopenharmony_ci        let tt = re.match(' *([a-zA-Z0-9_]+) *: *([a-zA-Z_0-9<>,:{}[\\] ]+)', t);
458c339a94Sopenharmony_ci        if (tt) { // 变量
468c339a94Sopenharmony_ci            analyzeSubInterfaceVariable(t, tt, result);
478c339a94Sopenharmony_ci        }
488c339a94Sopenharmony_ci    }
498c339a94Sopenharmony_ci    return result;
508c339a94Sopenharmony_ci}
518c339a94Sopenharmony_ci
528c339a94Sopenharmony_cifunction analyzeSubInterfaceVariable(t, tt, result) {
538c339a94Sopenharmony_ci    let valueName = re.getReg(t, tt.regs[1]);
548c339a94Sopenharmony_ci    let valueType = re.getReg(t, tt.regs[2]);
558c339a94Sopenharmony_ci    let index = valueType.indexOf('number');
568c339a94Sopenharmony_ci    while (index !== -1) {
578c339a94Sopenharmony_ci        valueType = valueType.replace('number', 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
588c339a94Sopenharmony_ci        index = valueType.indexOf('number');
598c339a94Sopenharmony_ci    }
608c339a94Sopenharmony_ci    result.value.push({
618c339a94Sopenharmony_ci        name: valueName,
628c339a94Sopenharmony_ci        type: valueType,
638c339a94Sopenharmony_ci    });
648c339a94Sopenharmony_ci}
658c339a94Sopenharmony_ci
668c339a94Sopenharmony_cifunction getFuncParaType(v, interfaceName, data, results) {
678c339a94Sopenharmony_ci    let arrayType = re.match('(Async)*Callback<(Array<([a-zA-Z_0-9]+)>)>', v.type);
688c339a94Sopenharmony_ci    let parameter = v.type;
698c339a94Sopenharmony_ci    if (arrayType) {
708c339a94Sopenharmony_ci        parameter = re.getReg(v.type, arrayType.regs[2]);
718c339a94Sopenharmony_ci    }
728c339a94Sopenharmony_ci    if (isEnum(parameter, data)) {
738c339a94Sopenharmony_ci        let index = enumIndex(parameter, data);
748c339a94Sopenharmony_ci        if (data.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_NUMBER) {
758c339a94Sopenharmony_ci            v.type = v.type.replace(parameter, 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
768c339a94Sopenharmony_ci        } else if (data.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_STRING) {
778c339a94Sopenharmony_ci            v.type = v.type.replace(parameter, 'string');
788c339a94Sopenharmony_ci        } else {
798c339a94Sopenharmony_ci            NapiLog.logError('analyzeFunction getFuncParaType is not support this type %s.'
808c339a94Sopenharmony_ci                .format(data.enum[index].body.enumValueType), getLogErrInfo);
818c339a94Sopenharmony_ci            return null;
828c339a94Sopenharmony_ci        }
838c339a94Sopenharmony_ci    }
848c339a94Sopenharmony_ci    // interface & class中的方法参数类型是enum的情况
858c339a94Sopenharmony_ci    else if (isEnum(parameter, results)) {
868c339a94Sopenharmony_ci        let index = enumIndex(parameter, results);
878c339a94Sopenharmony_ci        if (results.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_NUMBER) {
888c339a94Sopenharmony_ci            v.type = v.type.replace(parameter, 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
898c339a94Sopenharmony_ci        } else if (results.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_STRING) {
908c339a94Sopenharmony_ci            v.type = v.type.replace(parameter, 'string');
918c339a94Sopenharmony_ci        } else {
928c339a94Sopenharmony_ci            NapiLog.logError('analyzeFunction getFuncParaType is not support this type %s.'
938c339a94Sopenharmony_ci                .format(results.enum[index].body.enumValueType), getLogErrInfo());
948c339a94Sopenharmony_ci            return null;
958c339a94Sopenharmony_ci        }
968c339a94Sopenharmony_ci    }
978c339a94Sopenharmony_ci
988c339a94Sopenharmony_ci    let interfaceType = re.match('{([A-Za-z0-9_]+:[A-Za-z0-9_,]+)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}$', v.type);
998c339a94Sopenharmony_ci    if (interfaceType) {
1008c339a94Sopenharmony_ci        v.type = interfaceName;
1018c339a94Sopenharmony_ci    }
1028c339a94Sopenharmony_ci
1038c339a94Sopenharmony_ci    if (parameter.indexOf('number') >= 0) {
1048c339a94Sopenharmony_ci        v.type = v.type.replace('number', 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
1058c339a94Sopenharmony_ci    }
1068c339a94Sopenharmony_ci
1078c339a94Sopenharmony_ci    // type的处理
1088c339a94Sopenharmony_ci    if (isType(parameter, data)) {
1098c339a94Sopenharmony_ci        let index = typeIndex(parameter, data);
1108c339a94Sopenharmony_ci        if (data.type[index].isEnum) {
1118c339a94Sopenharmony_ci            v.type = v.type.replace(parameter, 'string');
1128c339a94Sopenharmony_ci        }
1138c339a94Sopenharmony_ci    }
1148c339a94Sopenharmony_ci    return v;
1158c339a94Sopenharmony_ci}
1168c339a94Sopenharmony_ci
1178c339a94Sopenharmony_cifunction analyzeFuncNoNameInterface(data, values, results) {
1188c339a94Sopenharmony_ci    values = re.replaceAll(re.replaceAll(values, ' ', ''), '\n', '');
1198c339a94Sopenharmony_ci    let interfaceName = '';
1208c339a94Sopenharmony_ci    let matchNoName = '([:{<}>,;a-zA-Z_0-9]*)\\?*(:[A-Za-z0-9_,;]*)?:((Async)*Callback<)?{(([A-Za-z0-9_]+:' +
1218c339a94Sopenharmony_ci        '[A-Za-z0-9_,;]+)*)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}(}|,|;|>)?$';
1228c339a94Sopenharmony_ci    let matchs = re.match(matchNoName, values);
1238c339a94Sopenharmony_ci    if (matchs) {
1248c339a94Sopenharmony_ci        let st = values.lastIndexOf('{');
1258c339a94Sopenharmony_ci        let end = values.indexOf('}');
1268c339a94Sopenharmony_ci        let number = NumberIncrease.getAndIncrease();
1278c339a94Sopenharmony_ci        interfaceName = 'AUTO_INTERFACE_%s'.format(number);
1288c339a94Sopenharmony_ci        let interfaceBody = values.substring(st + 1, end);
1298c339a94Sopenharmony_ci        let typeInterface = '{%s}'.format(interfaceBody);
1308c339a94Sopenharmony_ci        values = re.replaceAll(values, typeInterface, interfaceName);
1318c339a94Sopenharmony_ci        interfaceBody = re.replaceAll(interfaceBody, ',', ';');
1328c339a94Sopenharmony_ci        if (Object.prototype.hasOwnProperty.call(data, 'interface')) {
1338c339a94Sopenharmony_ci            data.interface.push({
1348c339a94Sopenharmony_ci                name: interfaceName,
1358c339a94Sopenharmony_ci                body: analyzeSubInterface(interfaceBody),
1368c339a94Sopenharmony_ci            });
1378c339a94Sopenharmony_ci        } else if (Object.prototype.hasOwnProperty.call(results, 'interface')) {
1388c339a94Sopenharmony_ci            results.interface.push({
1398c339a94Sopenharmony_ci                name: interfaceName,
1408c339a94Sopenharmony_ci                body: analyzeSubInterface(interfaceBody),
1418c339a94Sopenharmony_ci            });
1428c339a94Sopenharmony_ci        }
1438c339a94Sopenharmony_ci    }
1448c339a94Sopenharmony_ci
1458c339a94Sopenharmony_ci    matchs = re.match(matchNoName, values);
1468c339a94Sopenharmony_ci    if (matchs) {
1478c339a94Sopenharmony_ci        let resNoNameInter = analyzeFuncNoNameInterface(data, values);
1488c339a94Sopenharmony_ci        values = resNoNameInter.values;
1498c339a94Sopenharmony_ci    }
1508c339a94Sopenharmony_ci
1518c339a94Sopenharmony_ci    let result = {
1528c339a94Sopenharmony_ci        interfaceName: interfaceName,
1538c339a94Sopenharmony_ci        values: values,
1548c339a94Sopenharmony_ci    };
1558c339a94Sopenharmony_ci    return result;
1568c339a94Sopenharmony_ci}
1578c339a94Sopenharmony_ci
1588c339a94Sopenharmony_cifunction analyseSubReturn(ret, data, results) {
1598c339a94Sopenharmony_ci    // 匿名interface返回值 function fun4(input: string): { read: number; written: number };
1608c339a94Sopenharmony_ci    let tt = null;
1618c339a94Sopenharmony_ci    if (ret.indexOf(':') > 0) {
1628c339a94Sopenharmony_ci        ret = re.replaceAll(re.replaceAll(ret, ' ', ''), '\n', '');
1638c339a94Sopenharmony_ci        ret = re.replaceAll(ret, ',', ';');
1648c339a94Sopenharmony_ci        ret = ret.substring(1, ret.length - 1);
1658c339a94Sopenharmony_ci        tt = ret.split(';');
1668c339a94Sopenharmony_ci    }
1678c339a94Sopenharmony_ci    if (tt) {
1688c339a94Sopenharmony_ci        let len = tt.length;
1698c339a94Sopenharmony_ci        let res = '';
1708c339a94Sopenharmony_ci        let interfaceName = '';
1718c339a94Sopenharmony_ci        for (let i = 0; i < len; i++) {
1728c339a94Sopenharmony_ci            let regs1 = tt[i] + ';';
1738c339a94Sopenharmony_ci            res += regs1;
1748c339a94Sopenharmony_ci        }
1758c339a94Sopenharmony_ci
1768c339a94Sopenharmony_ci        let number = NumberIncrease.getAndIncrease();
1778c339a94Sopenharmony_ci        interfaceName = 'AUTO_INTERFACE_%s'.format(number);
1788c339a94Sopenharmony_ci        let interfaceBody = res;
1798c339a94Sopenharmony_ci        ret = interfaceName;
1808c339a94Sopenharmony_ci
1818c339a94Sopenharmony_ci        interfaceBody = re.replaceAll(interfaceBody, ',', ';');
1828c339a94Sopenharmony_ci        if (Object.prototype.hasOwnProperty.call(data, 'interface')) {
1838c339a94Sopenharmony_ci            data.interface.push({
1848c339a94Sopenharmony_ci                name: interfaceName,
1858c339a94Sopenharmony_ci                body: analyzeSubInterface(interfaceBody),
1868c339a94Sopenharmony_ci            });
1878c339a94Sopenharmony_ci        } else if (Object.prototype.hasOwnProperty.call(results, 'interface')) {
1888c339a94Sopenharmony_ci            results.interface.push({
1898c339a94Sopenharmony_ci                name: interfaceName,
1908c339a94Sopenharmony_ci                body: analyzeSubInterface(interfaceBody),
1918c339a94Sopenharmony_ci            });
1928c339a94Sopenharmony_ci        }
1938c339a94Sopenharmony_ci    }
1948c339a94Sopenharmony_ci    if (ret.indexOf('number') >= 0) {
1958c339a94Sopenharmony_ci        ret = ret.replaceAll('number', 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
1968c339a94Sopenharmony_ci    }
1978c339a94Sopenharmony_ci    return ret;
1988c339a94Sopenharmony_ci}
1998c339a94Sopenharmony_ci
2008c339a94Sopenharmony_cifunction getObjCallFunc(results, onObjCbType, values, ret) {
2018c339a94Sopenharmony_ci    if (results !== undefined) {
2028c339a94Sopenharmony_ci        results.callFunction.push({
2038c339a94Sopenharmony_ci            'name': onObjCbType,
2048c339a94Sopenharmony_ci            'body': values,
2058c339a94Sopenharmony_ci            'ret': ret,
2068c339a94Sopenharmony_ci        });
2078c339a94Sopenharmony_ci    }
2088c339a94Sopenharmony_ci}
2098c339a94Sopenharmony_cifunction getFuncResult(name, funcType, values, ret, isStatic) {
2108c339a94Sopenharmony_ci    let result = {
2118c339a94Sopenharmony_ci        name: name,
2128c339a94Sopenharmony_ci        type: funcType,
2138c339a94Sopenharmony_ci        value: values,
2148c339a94Sopenharmony_ci        ret: ret,
2158c339a94Sopenharmony_ci        isStatic: isStatic,
2168c339a94Sopenharmony_ci    };
2178c339a94Sopenharmony_ci    return result;
2188c339a94Sopenharmony_ci}
2198c339a94Sopenharmony_ci
2208c339a94Sopenharmony_cifunction getArrowCallFunc(tmp, results) {
2218c339a94Sopenharmony_ci    let callbackFunc = null;
2228c339a94Sopenharmony_ci
2238c339a94Sopenharmony_ci    if (tmp[2][0] !== undefined) {
2248c339a94Sopenharmony_ci        callbackFunc = tmp[2][0]; // 当方法的参数是回调方法,并且回调方法写法为=>函数
2258c339a94Sopenharmony_ci    }
2268c339a94Sopenharmony_ci    if (results !== undefined && callbackFunc !== null) {
2278c339a94Sopenharmony_ci        results.callFunction.push(callbackFunc);
2288c339a94Sopenharmony_ci    }
2298c339a94Sopenharmony_ci}
2308c339a94Sopenharmony_ci
2318c339a94Sopenharmony_ci/**函数解析 */
2328c339a94Sopenharmony_cifunction analyzeFunction(data, isStatic, name, values, ret, results, interfaceName = '') {
2338c339a94Sopenharmony_ci    let res = analyzeFuncNoNameInterface(data, values, results);
2348c339a94Sopenharmony_ci    let tmp;
2358c339a94Sopenharmony_ci    let funcType;
2368c339a94Sopenharmony_ci
2378c339a94Sopenharmony_ci    if (res) {
2388c339a94Sopenharmony_ci        tmp = analyzeParams(name, res.values);
2398c339a94Sopenharmony_ci        if (tmp !== null) {
2408c339a94Sopenharmony_ci            values = tmp[0];
2418c339a94Sopenharmony_ci            funcType = tmp[1];
2428c339a94Sopenharmony_ci            getArrowCallFunc(tmp, results);
2438c339a94Sopenharmony_ci        }
2448c339a94Sopenharmony_ci    }
2458c339a94Sopenharmony_ci
2468c339a94Sopenharmony_ci    tmp = analyzeReturn(ret);
2478c339a94Sopenharmony_ci    ret = tmp[0];
2488c339a94Sopenharmony_ci    if (tmp[1]) { // 返回类型为 Promise, 解析成等价的AsyncCallback方法
2498c339a94Sopenharmony_ci        funcType = FuncType.ASYNC;
2508c339a94Sopenharmony_ci        // 返回值是Promise的匿名interface
2518c339a94Sopenharmony_ci        let paramTypeVal = analyseSubReturn(ret.substring(8, ret.length - 1), data, results);
2528c339a94Sopenharmony_ci        // 将返回值Promise<type>改为AsyncCallback<type>,作为方法的入参
2538c339a94Sopenharmony_ci        let paramType = ret.replace('Promise', 'AsyncCallback');
2548c339a94Sopenharmony_ci        if (paramTypeVal) {
2558c339a94Sopenharmony_ci            // 匿名interface处理
2568c339a94Sopenharmony_ci            let paramAsync = paramType.substring(14, paramType.length - 1);
2578c339a94Sopenharmony_ci            paramType = paramType.replace(paramAsync, paramTypeVal);
2588c339a94Sopenharmony_ci        }
2598c339a94Sopenharmony_ci        values.push({ name: 'promise', optional: false, type: paramType });
2608c339a94Sopenharmony_ci        ret = 'void'; // 返回值由Promise改为void,与AsyncCallback接口保持一致
2618c339a94Sopenharmony_ci    }
2628c339a94Sopenharmony_ci    for (let j in values) {
2638c339a94Sopenharmony_ci        let v = values[j];
2648c339a94Sopenharmony_ci        v = getFuncParaType(v, res.interfaceName, data, results);
2658c339a94Sopenharmony_ci        if (v === null) {
2668c339a94Sopenharmony_ci            NapiLog.logError('analyzeFunction is not support this type %s.'.format(v), getLogErrInfo());
2678c339a94Sopenharmony_ci        }
2688c339a94Sopenharmony_ci    }
2698c339a94Sopenharmony_ci    ret = analyseSubReturn(ret, data, results);
2708c339a94Sopenharmony_ci    let result = getFuncResult(name, funcType, values, ret, isStatic);
2718c339a94Sopenharmony_ci    if (isOnObjCallback(name)) {
2728c339a94Sopenharmony_ci        let onObjCbType = getOnObjCallbackType(name, interfaceName);
2738c339a94Sopenharmony_ci        getObjCallFunc(results, onObjCbType, values, ret);
2748c339a94Sopenharmony_ci    }
2758c339a94Sopenharmony_ci    return result;
2768c339a94Sopenharmony_ci}
2778c339a94Sopenharmony_ci
2788c339a94Sopenharmony_cimodule.exports = {
2798c339a94Sopenharmony_ci    analyzeFunction,
2808c339a94Sopenharmony_ci    analyzeSubInterface,
2818c339a94Sopenharmony_ci    getFuncParaType,
2828c339a94Sopenharmony_ci    analyzeFuncNoNameInterface,
2838c339a94Sopenharmony_ci    analyseSubReturn,
2848c339a94Sopenharmony_ci};