• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 { FuncType, NumberIncrease, isEnum, EnumValueType, enumIndex, isType, typeIndex, isOnObjCallback,
17    getOnObjCallbackType, getLogErrInfo } = require('../tools/common');
18const { analyzeParams } = require('./params');
19const { analyzeReturn } = require('./return');
20const { NapiLog } = require('../tools/NapiLog');
21const { randomInt } = require('crypto');
22const { print } = require('../tools/tool');
23
24function analyzeSubInterface(data) {
25    let body = re.replaceAll(data, '\n', '').split(';'); //  # replace(' ', '').
26    let result = {
27        value: [],
28        function: [],
29        parentNameList: [],
30        childList: [],
31        parentList: [],
32    };
33    for (let i in body) {
34        let t = body[i];
35        while (t.length > 0 && t[0] === ' ') {
36            t = t.substring(1, t.length); // 去除前面的空格
37        }
38        while (t.length > 0 && t[-1] === ' ') {
39            t = t.substring(0, t.length - 1); // 去除后面的空格
40        }
41        if (t === '') {
42            break; // 如果t为空直接返回
43        }
44        let tt = re.match(' *([a-zA-Z0-9_]+) *: *([a-zA-Z_0-9<>,:{}[\\] ]+)', t);
45        if (tt) { // 变量
46            analyzeSubInterfaceVal(t, tt, result);
47        }
48    }
49    return result;
50}
51
52function analyzeSubInterfaceVal(t, tt, result) {
53    let valueName = re.getReg(t, tt.regs[1]);
54    let valueType = re.getReg(t, tt.regs[2]);
55    let index = valueType.indexOf('number');
56    while (index !== -1) {
57        valueType = valueType.replace('number', 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
58        index = valueType.indexOf('number');
59    }
60    result.value.push({
61        name: valueName,
62        type: valueType,
63    });
64}
65
66function getFuncParaType(v, interfaceName, data, results) {
67    let arrayType = re.match('(Async)*Callback<(Array<([a-zA-Z_0-9]+)>)>', v.type);
68    let parameter = v.type;
69    if (arrayType) {
70        parameter = re.getReg(v.type, arrayType.regs[2]);
71    }
72    if (isEnum(parameter, data)) {
73        let index = enumIndex(parameter, data);
74        if (data.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_NUMBER) {
75            v.type = v.type.replace(parameter, 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
76        } else if (data.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_STRING) {
77            v.type = v.type.replace(parameter, 'string');
78        } else {
79            NapiLog.logError('analyzeFunction getFuncParaType is not support this type %s.'
80                .format(data.enum[index].body.enumValueType), getLogErrInfo);
81            return null;
82        }
83    }
84    // interface & class中的方法参数类型是enum的情况
85    else if (isEnum(parameter, results)) {
86        let index = enumIndex(parameter, results);
87        if (results.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_NUMBER) {
88            v.type = v.type.replace(parameter, 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
89            v.realType = v.type;
90        } else if (results.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_STRING) {
91            v.type = v.type.replace(parameter, 'string');
92        } else {
93            NapiLog.logError('analyzeFunction getFuncParaType is not support this type %s.'
94                .format(results.enum[index].body.enumValueType), getLogErrInfo());
95            return null;
96        }
97    }
98
99    let interfaceType = re.match('{([A-Za-z0-9_]+:[A-Za-z0-9_,]+)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}$', v.type);
100    if (interfaceType) {
101        v.type = interfaceName;
102    }
103
104    if (parameter.indexOf('number') >= 0) {
105        v.type = v.type.replace('number', 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
106        v.realType = v.type;
107    }
108
109    // type的处理
110    if (isType(parameter, data)) {
111        let index = typeIndex(parameter, data);
112        if (data.type[index].isEnum) {
113            v.type = v.type.replace(parameter, 'string');
114        }
115    }
116    return v;
117}
118
119function analyzeFuncNoNameInterface(data, values, results) {
120    values = re.replaceAll(re.replaceAll(values, ' ', ''), '\n', '');
121    let interfaceName = '';
122    let matchNoName = '([:{<}>,;a-zA-Z_0-9]*)\\?*(:[A-Za-z0-9_,;]*)?:((Async)*Callback<)?{(([A-Za-z0-9_]+:' +
123        '[A-Za-z0-9_,;]+)*)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}(}|,|;|>)?$';
124    let matchs = re.match(matchNoName, values);
125    if (matchs) {
126        let st = values.lastIndexOf('{');
127        let end = values.indexOf('}');
128        let number = NumberIncrease.getAndIncrease();
129        interfaceName = 'AUTO_INTERFACE_%s'.format(number);
130        let interfaceBody = values.substring(st + 1, end);
131        let typeInterface = '{%s}'.format(interfaceBody);
132        values = re.replaceAll(values, typeInterface, interfaceName);
133        interfaceBody = re.replaceAll(interfaceBody, ',', ';');
134        if (Object.prototype.hasOwnProperty.call(data, 'interface')) {
135            data.interface.push({
136                name: interfaceName,
137                body: analyzeSubInterface(interfaceBody),
138            });
139        } else if (Object.prototype.hasOwnProperty.call(results, 'interface')) {
140            results.interface.push({
141                name: interfaceName,
142                body: analyzeSubInterface(interfaceBody),
143            });
144        }
145    }
146
147    matchs = re.match(matchNoName, values);
148    if (matchs) {
149        let resNoNameInter = analyzeFuncNoNameInterface(data, values);
150        values = resNoNameInter.values;
151    }
152
153    let result = {
154        interfaceName: interfaceName,
155        values: values,
156    };
157    return result;
158}
159
160function analyseSubReturn(ret, data, results) {
161    // 匿名interface返回值 function fun4(input: string): { read: number; written: number };
162    let tt = null;
163    if (ret.indexOf(':') > 0) {
164        ret = re.replaceAll(re.replaceAll(ret, ' ', ''), '\n', '');
165        ret = re.replaceAll(ret, ',', ';');
166        ret = ret.substring(1, ret.length - 1);
167        tt = ret.split(';');
168    }
169    if (tt) {
170         let len = tt.length;
171         let res = '';
172         let interfaceName = '';
173         for (let i = 0; i < len; i++) {
174             let regs1 = tt[i] + ';';
175             res += regs1;
176         }
177
178        let number = NumberIncrease.getAndIncrease();
179        interfaceName = 'AUTO_INTERFACE_%s'.format(number);
180        let interfaceBody = res;
181        ret = interfaceName;
182
183        interfaceBody = re.replaceAll(interfaceBody, ',', ';');
184        if (Object.prototype.hasOwnProperty.call(data, 'interface')) {
185            data.interface.push({
186                name: interfaceName,
187                body: analyzeSubInterface(interfaceBody),
188            });
189        } else if (Object.prototype.hasOwnProperty.call(results, 'interface')) {
190            results.interface.push({
191                name: interfaceName,
192                body: analyzeSubInterface(interfaceBody),
193            });
194        }
195    }
196    if (ret.indexOf('number') >= 0) {
197        ret = ret.replaceAll('number', 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease());
198    }
199    return ret;
200}
201
202function getObjCallFunc(results, onObjCbType, values, ret) {
203    if (results !== undefined) {
204        results.callFunction.push({
205            'name': onObjCbType,
206            'body': values,
207            'ret': ret,
208        });
209    }
210}
211function getFuncResult(name, funcType, values, ret, isStatic) {
212    let result = {
213        name: name,
214        type: funcType,
215        value: values,
216        ret: ret,
217        isStatic: isStatic,
218    };
219    return result;
220}
221
222function getArrowCallFunc(tmp, results) {
223    let callbackFunc = null;
224
225    if (tmp[2][0] !== undefined) {
226        callbackFunc = tmp[2][0]; // 当方法的参数是回调方法,并且回调方法写法为=>函数
227    }
228    if (results !== undefined && callbackFunc !== null) {
229        results.callFunction.push(callbackFunc);
230    }
231}
232
233/**函数解析 */
234function analyzeFunction(data, isStatic, name, values, ret, results, interfaceName = '') {
235    let res = analyzeFuncNoNameInterface(data, values, results);
236    let tmp;
237    let funcType;
238
239    if (res) {
240        tmp = analyzeParams(name, res.values);
241        if (tmp !== null) {
242            values = tmp[0];
243            funcType = tmp[1];
244            getArrowCallFunc(tmp, results);
245        }
246    }
247
248    tmp = analyzeReturn(ret);
249    ret = tmp[0];
250    if (tmp[1]) { // 返回类型为 Promise, 解析成等价的AsyncCallback方法
251        funcType = FuncType.ASYNC;
252        // 返回值是Promise的匿名interface
253        let paramTypeVal = analyseSubReturn(ret.substring(8, ret.length - 1), data, results);
254        // 将返回值Promise<type>改为AsyncCallback<type>,作为方法的入参
255        let paramType = ret.replace('Promise', 'AsyncCallback');
256        if (paramTypeVal) {
257            // 匿名interface处理
258            let paramAsync = paramType.substring(14, paramType.length - 1);
259            paramType = paramType.replace(paramAsync, paramTypeVal);
260        }
261        values.push({ name: 'promise', optional: false, type: paramType, realType: paramType });
262        ret = 'void'; // 返回值由Promise改为void,与AsyncCallback接口保持一致
263    }
264    for (let j in values) {
265        let v = values[j];
266        v = getFuncParaType(v, res.interfaceName, data, results);
267        if (v === null) {
268            NapiLog.logError('analyzeFunction is not support this type %s.'.format(v), getLogErrInfo());
269        }
270    }
271    ret = analyseSubReturn(ret, data, results);
272    let result = getFuncResult(name, funcType, values, ret, isStatic);
273    if (isOnObjCallback(name)) {
274        let onObjCbType = getOnObjCallbackType(name, interfaceName);
275        getObjCallFunc(results, onObjCbType, values, ret);
276    }
277    return result;
278}
279
280module.exports = {
281    analyzeFunction,
282    analyzeSubInterface,
283    getFuncParaType,
284    analyzeFuncNoNameInterface,
285    analyseSubReturn,
286};