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 } = require("../tools/common"); 17const { analyzeParams } = require("./params"); 18const { analyzeReturn } = require("./return"); 19const { NapiLog } = require("../tools/NapiLog"); 20const { randomInt } = require("crypto"); 21const { print } = require("../tools/tool"); 22 23function analyzeSubInterface(data) { 24 let body = re.replaceAll(data, "\n", "").split(";")// # replace(" ", ""). 25 let result = { 26 value: [], 27 function: [], 28 parentNameList: [], 29 childList: [], 30 parentList: [] 31 } 32 for (let i in body) { 33 let t = body[i] 34 while (t.length > 0 && t[0] == ' ')//去除前面的空格 35 t = t.substring(1, t.length) 36 while (t.length > 0 && t[-1] == ' ')//去除后面的空格 37 t = t.substring(0, t.length - 1) 38 if (t == "") break//如果t为空直接返回 39 let tt = re.match(" *([a-zA-Z0-9_]+) *: *([a-zA-Z_0-9<>,:{}[\\] ]+)", t) 40 if (tt) {//变量 41 42 let valueName = re.getReg(t, tt.regs[1]) 43 let valueType = re.getReg(t, tt.regs[2]) 44 let index = valueType.indexOf("number") 45 while (index !== -1) { 46 valueType = valueType.replace("number", "NUMBER_TYPE_" + NumberIncrease.getAndIncrease()) 47 index = valueType.indexOf("number") 48 } 49 result.value.push({ 50 name: valueName, 51 type: valueType 52 }) 53 } 54 } 55 return result 56} 57 58function getFuncParaType(v, interfaceName, data) { 59 let arrayType = re.match("(Async)*Callback<(Array<([a-zA-Z_0-9]+)>)>", v["type"]) 60 let parameter = v["type"] 61 if (arrayType) { 62 parameter = re.getReg(v["type"], arrayType.regs[2]) 63 } 64 if (isEnum(parameter, data)) { 65 let index = enumIndex(parameter, data) 66 if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_NUMBER) { 67 v["type"] = v["type"].replace(parameter, "NUMBER_TYPE_" + NumberIncrease.getAndIncrease()) 68 } else if (data.enum[index].body.enumValueType == EnumValueType.ENUM_VALUE_TYPE_STRING) { 69 v["type"] = v["type"].replace(parameter, "string") 70 } else { 71 NapiLog.logError("analyzeFunction getFuncParaType is not support this type %s" 72 .format(data.enum[index].body.enumValueType)); 73 return null 74 } 75 } 76 77 let interfaceType = re.match("{([A-Za-z0-9_]+:[A-Za-z0-9_,]+)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}$", v["type"]) 78 if (interfaceType) { 79 v["type"] = interfaceName 80 } 81 82 if (parameter.indexOf("number") >= 0) { 83 v["type"] = v["type"].replace("number", "NUMBER_TYPE_" + NumberIncrease.getAndIncrease()) 84 } 85 return v 86} 87 88function analyzeFuncNoNameInterface(data, values) { 89 values = re.replaceAll(re.replaceAll(values, " ", ""), "\n", "") 90 let interfaceName = "" 91 let matchNoName = "([:{,;a-zA-Z_0-9]*)\\?*(:[A-Za-z0-9_,;]*)?:{([A-Za-z0-9_]+:"+ 92 "[A-Za-z0-9_,;]+)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}(}|,|;)?$" 93 let matchs = re.match(matchNoName, values) 94 if (matchs) { 95 let st = values.lastIndexOf("{") 96 let end = values.indexOf("}") 97 let number = NumberIncrease.getAndIncrease(); 98 interfaceName = "AUTO_INTERFACE_%s".format(number) 99 let interfaceBody = values.substring(st+1, end) 100 let typeInterface = "{%s}".format(interfaceBody) 101 values = re.replaceAll(values, typeInterface, interfaceName) 102 interfaceBody = re.replaceAll(interfaceBody, ",", ";") 103 data.interface.push({ 104 name: interfaceName, 105 body: analyzeSubInterface(interfaceBody) 106 }) 107 } 108 109 matchs = re.match(matchNoName, values) 110 if(matchs) { 111 let resNoNameInter = analyzeFuncNoNameInterface(data, values) 112 values = resNoNameInter.values 113 } 114 115 let result = { 116 interfaceName: interfaceName, 117 values: values 118 } 119 return result 120} 121 122function analyseSubReturn(ret, data) { 123 //匿名interface返回值 function fun4(input: string): { read: number; written: number }; 124 ret = re.replaceAll(re.replaceAll(ret, " ", ""), "\n", "") 125 let tt = re.match("{([A-Za-z0-9_]+:[A-Za-z0-9_,;]+)([A-Za-z0-9_]+:[A-Za-z0-9_]+)}", ret) 126 if (tt) { 127 let len = tt.regs.length 128 let res = "" 129 let interfaceName = "" 130 for (let i=1; i<len; i++) { 131 let regs1 = re.getReg(ret, tt.regs[i]) 132 if (regs1 != "}" && regs1 != ",") { 133 res += regs1 134 } 135 } 136 137 let number = NumberIncrease.getAndIncrease(); 138 interfaceName = "AUTO_INTERFACE_%s".format(number) 139 let interfaceBody = res 140 ret = interfaceName 141 142 interfaceBody = re.replaceAll(interfaceBody, ",", ";") 143 data.interface.push({ 144 name: interfaceName, 145 body: analyzeSubInterface(interfaceBody) 146 }) 147 } 148 if (ret.indexOf("number") >= 0) { 149 ret = ret.replaceAll("number", "NUMBER_TYPE_" + NumberIncrease.getAndIncrease()) 150 } 151 return ret 152} 153 154/**函数解析 */ 155function analyzeFunction(data, isStatic, name, values, ret) { 156 let res = analyzeFuncNoNameInterface(data, values) 157 let tmp 158 let funcType 159 if (res) { 160 tmp = analyzeParams(name, res.values) 161 values = tmp[0] 162 funcType = tmp[1] 163 } 164 165 tmp = analyzeReturn(ret) 166 ret = tmp[0] 167 if (tmp[1]) { // 返回类型为 Promise, 解析成等价的AsyncCallback方法 168 funcType = FuncType.ASYNC 169 // 将返回值Promise<type>改为AsyncCallback<type>,作为方法的入参 170 let paramType = ret.replace("Promise", "AsyncCallback") 171 values.push({name: "promise", optional: false, type: paramType}) 172 ret = "void" // 返回值由Promise改为void,与AsyncCallback接口保持一致 173 } 174 for (let j in values) { 175 let v = values[j] 176 v = getFuncParaType(v, res.interfaceName, data) 177 if (v == null) { 178 NapiLog.logError("analyzeFunction is not support this type %s".format(v)); 179 } 180 } 181 ret = analyseSubReturn(ret, data) 182 let result = { 183 name: name, 184 type: funcType, 185 value: values, 186 ret: ret, 187 isStatic: isStatic 188 } 189 return result 190} 191 192module.exports = { 193 analyzeFunction, 194 analyzeSubInterface, 195 getFuncParaType 196}