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; 43 } 44 let tt = re.match(' *([a-zA-Z0-9_]+) *: *([a-zA-Z_0-9<>,:{}[\\] ]+)', t); 45 if (tt) { // 变量 46 analyzeSubInterfaceVariable(t, tt, result); 47 } 48 } 49 return result; 50} 51 52function analyzeSubInterfaceVariable(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 } else if (results.enum[index].body.enumValueType === EnumValueType.ENUM_VALUE_TYPE_STRING) { 90 v.type = v.type.replace(parameter, 'string'); 91 } else { 92 NapiLog.logError('analyzeFunction getFuncParaType is not support this type %s.' 93 .format(results.enum[index].body.enumValueType), getLogErrInfo()); 94 return null; 95 } 96 } 97 98 let interfaceType = re.match('{([A-Za-z0-9_]+:[A-Za-z0-9_,]+)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}$', v.type); 99 if (interfaceType) { 100 v.type = interfaceName; 101 } 102 103 if (parameter.indexOf('number') >= 0) { 104 v.type = v.type.replace('number', 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease()); 105 } 106 107 // type的处理 108 if (isType(parameter, data)) { 109 let index = typeIndex(parameter, data); 110 if (data.type[index].isEnum) { 111 v.type = v.type.replace(parameter, 'string'); 112 } 113 } 114 return v; 115} 116 117function analyzeFuncNoNameInterface(data, values, results) { 118 values = re.replaceAll(re.replaceAll(values, ' ', ''), '\n', ''); 119 let interfaceName = ''; 120 let matchNoName = '([:{<}>,;a-zA-Z_0-9]*)\\?*(:[A-Za-z0-9_,;]*)?:((Async)*Callback<)?{(([A-Za-z0-9_]+:' + 121 '[A-Za-z0-9_,;]+)*)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}(}|,|;|>)?$'; 122 let matchs = re.match(matchNoName, values); 123 if (matchs) { 124 let st = values.lastIndexOf('{'); 125 let end = values.indexOf('}'); 126 let number = NumberIncrease.getAndIncrease(); 127 interfaceName = 'AUTO_INTERFACE_%s'.format(number); 128 let interfaceBody = values.substring(st + 1, end); 129 let typeInterface = '{%s}'.format(interfaceBody); 130 values = re.replaceAll(values, typeInterface, interfaceName); 131 interfaceBody = re.replaceAll(interfaceBody, ',', ';'); 132 if (Object.prototype.hasOwnProperty.call(data, 'interface')) { 133 data.interface.push({ 134 name: interfaceName, 135 body: analyzeSubInterface(interfaceBody), 136 }); 137 } else if (Object.prototype.hasOwnProperty.call(results, 'interface')) { 138 results.interface.push({ 139 name: interfaceName, 140 body: analyzeSubInterface(interfaceBody), 141 }); 142 } 143 } 144 145 matchs = re.match(matchNoName, values); 146 if (matchs) { 147 let resNoNameInter = analyzeFuncNoNameInterface(data, values); 148 values = resNoNameInter.values; 149 } 150 151 let result = { 152 interfaceName: interfaceName, 153 values: values, 154 }; 155 return result; 156} 157 158function analyseSubReturn(ret, data, results) { 159 // 匿名interface返回值 function fun4(input: string): { read: number; written: number }; 160 let tt = null; 161 if (ret.indexOf(':') > 0) { 162 ret = re.replaceAll(re.replaceAll(ret, ' ', ''), '\n', ''); 163 ret = re.replaceAll(ret, ',', ';'); 164 ret = ret.substring(1, ret.length - 1); 165 tt = ret.split(';'); 166 } 167 if (tt) { 168 let len = tt.length; 169 let res = ''; 170 let interfaceName = ''; 171 for (let i = 0; i < len; i++) { 172 let regs1 = tt[i] + ';'; 173 res += regs1; 174 } 175 176 let number = NumberIncrease.getAndIncrease(); 177 interfaceName = 'AUTO_INTERFACE_%s'.format(number); 178 let interfaceBody = res; 179 ret = interfaceName; 180 181 interfaceBody = re.replaceAll(interfaceBody, ',', ';'); 182 if (Object.prototype.hasOwnProperty.call(data, 'interface')) { 183 data.interface.push({ 184 name: interfaceName, 185 body: analyzeSubInterface(interfaceBody), 186 }); 187 } else if (Object.prototype.hasOwnProperty.call(results, 'interface')) { 188 results.interface.push({ 189 name: interfaceName, 190 body: analyzeSubInterface(interfaceBody), 191 }); 192 } 193 } 194 if (ret.indexOf('number') >= 0) { 195 ret = ret.replaceAll('number', 'NUMBER_TYPE_' + NumberIncrease.getAndIncrease()); 196 } 197 return ret; 198} 199 200function getObjCallFunc(results, onObjCbType, values, ret) { 201 if (results !== undefined) { 202 results.callFunction.push({ 203 'name': onObjCbType, 204 'body': values, 205 'ret': ret, 206 }); 207 } 208} 209function getFuncResult(name, funcType, values, ret, isStatic) { 210 let result = { 211 name: name, 212 type: funcType, 213 value: values, 214 ret: ret, 215 isStatic: isStatic, 216 }; 217 return result; 218} 219 220function getArrowCallFunc(tmp, results) { 221 let callbackFunc = null; 222 223 if (tmp[2][0] !== undefined) { 224 callbackFunc = tmp[2][0]; // 当方法的参数是回调方法,并且回调方法写法为=>函数 225 } 226 if (results !== undefined && callbackFunc !== null) { 227 results.callFunction.push(callbackFunc); 228 } 229} 230 231/**函数解析 */ 232function analyzeFunction(data, isStatic, name, values, ret, results, interfaceName = '') { 233 let res = analyzeFuncNoNameInterface(data, values, results); 234 let tmp; 235 let funcType; 236 237 if (res) { 238 tmp = analyzeParams(name, res.values); 239 if (tmp !== null) { 240 values = tmp[0]; 241 funcType = tmp[1]; 242 getArrowCallFunc(tmp, results); 243 } 244 } 245 246 tmp = analyzeReturn(ret); 247 ret = tmp[0]; 248 if (tmp[1]) { // 返回类型为 Promise, 解析成等价的AsyncCallback方法 249 funcType = FuncType.ASYNC; 250 // 返回值是Promise的匿名interface 251 let paramTypeVal = analyseSubReturn(ret.substring(8, ret.length - 1), data, results); 252 // 将返回值Promise<type>改为AsyncCallback<type>,作为方法的入参 253 let paramType = ret.replace('Promise', 'AsyncCallback'); 254 if (paramTypeVal) { 255 // 匿名interface处理 256 let paramAsync = paramType.substring(14, paramType.length - 1); 257 paramType = paramType.replace(paramAsync, paramTypeVal); 258 } 259 values.push({ name: 'promise', optional: false, type: paramType }); 260 ret = 'void'; // 返回值由Promise改为void,与AsyncCallback接口保持一致 261 } 262 for (let j in values) { 263 let v = values[j]; 264 v = getFuncParaType(v, res.interfaceName, data, results); 265 if (v === null) { 266 NapiLog.logError('analyzeFunction is not support this type %s.'.format(v), getLogErrInfo()); 267 } 268 } 269 ret = analyseSubReturn(ret, data, results); 270 let result = getFuncResult(name, funcType, values, ret, isStatic); 271 if (isOnObjCallback(name)) { 272 let onObjCbType = getOnObjCallbackType(name, interfaceName); 273 getObjCallFunc(results, onObjCbType, values, ret); 274 } 275 return result; 276} 277 278module.exports = { 279 analyzeFunction, 280 analyzeSubInterface, 281 getFuncParaType, 282 analyzeFuncNoNameInterface, 283 analyseSubReturn, 284};