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};