1/* 2 * Copyright (c) 2023 Huawei Device 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 */ 15 16const fs = require('fs'); 17const ts = require('typescript'); 18// 是否统计type类型API的开关,true表示合并 19const typeCollection = true; 20// 是否合并同名函数的开关,true不合并 21const isNotMerge = true; 22// 是否支持API Diff工具的开关,true表示支持 23const supportDiffTool = true; 24 25// 解析文件 文本内容并将结果push到列表中并去重 26function parse(fileContentList) { 27 const api = []; 28 const exportApi = []; 29 const returnDeclarationArr = new Set([]); 30 const hash = new Set([]); 31 32 fileContentList.forEach(item => { 33 const fileName = item.fileName.replace(/\.d.ts$/g, '.ts'); 34 let packageName = item.fileRoot.indexOf('component\\ets\\') >= 0 || 35 item.fileRoot.indexOf('component/ets/') >= 0 ? 'ArkUI' : fileName.replace((/\@|.ts$/g), '').replace(/D:\\/g, ''); 36 ts.transpileModule(item.fileContent, { 37 compilerOptions: { 38 'target': ts.ScriptTarget.ES2017, 39 }, 40 fileName: fileName, 41 transformers: { before: [getReturnDeclarationArr(packageName, exportApi, returnDeclarationArr)] }, 42 }); 43 }); 44 45 fileContentList.forEach(item => { 46 const fileName = item.fileName.replace(/\.d.ts$/g, '.ts'); 47 let packageName = item.fileRoot.indexOf('component\\ets\\') >= 0 || 48 item.fileRoot.indexOf('component/ets/') >= 0 ? 'ArkUI' : fileName.replace(/\@|.ts$/g, '').replace(/D:\\/g, ''); 49 ts.transpileModule(item.fileContent, { 50 compilerOptions: { 51 'target': ts.ScriptTarget.ES2017, 52 }, 53 fileName: fileName, 54 transformers: { before: [processDeclarationSourceFile(packageName, api, exportApi, returnDeclarationArr, hash, item.fileRoot)] }, 55 }); 56 }); 57 return api; 58} 59 60// 获取返回值类型 61function visitAllNode(node, returnDeclarationArr) { 62 if ((ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node)) && node && node.type && 63 ts.isTypeReferenceNode(node.type)) { 64 returnDeclarationArr.add(node.type.typeName.getText()); 65 } 66 node.getChildren().forEach(item => { 67 visitAllNode(item, returnDeclarationArr); 68 }); 69} 70 71// 获取导入Api的数组 72function getExportApi(node, packageName, exportApi) { 73 node.statements.forEach(stat => { 74 if (ts.isModuleDeclaration(stat)) { 75 if (stat.getText().indexOf('namespace') > 0) { 76 let apiInfo = { 77 isSystemApi: '公开API', 78 version: '', 79 deprecated: '', 80 permission: 'N/A', 81 sysCap: 'N/A', 82 model: '', 83 }; 84 exportApi.push({ 85 packageName: packageName, 86 className: stat.name.escapedText.toString(), 87 methodName: '', 88 apiInfo: getApiInfo(stat, apiInfo), 89 }); 90 } 91 } 92 }); 93} 94 95// 获取返回值类型和命名空间 96const getReturnDeclarationArr = (packageName, exportApi, returnDeclarationArr) => { 97 return (context) => { 98 return (node) => { 99 visitAllNode(node, returnDeclarationArr); 100 getExportApi(node, packageName, exportApi); 101 return node; 102 }; 103 }; 104}; 105 106 107// 搜集API接口并去重 108function processDeclarationSourceFile(packageName, api, exportApi, returnDeclarationArr, hash, dtsPath) { 109 return (context) => { 110 return (node) => { 111 const statements = node.statements; 112 const currentClassFuncSet = new Set([]); 113 const currentTypeList = new Array(); 114 statements.forEach(stat => { 115 if (ts.isTypeAliasDeclaration(stat)) { 116 if (stat.type.types) { 117 let typeObj = { 118 name: stat.name.escapedText, 119 value: [], 120 }; 121 stat.type.types.forEach(type => { 122 if (type.literal && type.literal.text) { 123 typeObj.value.push(type.literal.text); 124 } 125 }); 126 if (typeObj.value.length > 0) { 127 currentTypeList.push(typeObj); 128 } 129 } 130 } 131 }); 132 133 statements.forEach(stat => { 134 let apiInfo = { 135 isSystemApi: '公开API', 136 version: '', 137 deprecated: '', 138 permission: 'N/A', 139 sysCap: 'N/A', 140 model: '', 141 headimport: 'N/A', 142 endexport: 'N/A', 143 }; 144 collectApi(packageName, api, stat, apiInfo, exportApi, returnDeclarationArr, hash, dtsPath, 145 currentTypeList, currentClassFuncSet); 146 }); 147 return node; 148 }; 149 }; 150} 151 152function collectApi(packageName, api, stat, apiInfo, exportApi, returnDeclarationArr, hash, dtsPath, currentTypeList, 153 currentClassFuncSet) { 154 if (ts.isInterfaceDeclaration(stat)) { 155 collectInterfaceDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, 156 currentTypeList, dtsPath); 157 158 } else if (ts.isModuleDeclaration(stat)) { 159 collectModuleDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, 160 currentTypeList, dtsPath); 161 162 } else if (ts.isClassDeclaration(stat)) { 163 collectClassDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, 164 currentTypeList, dtsPath); 165 166 } else if (ts.isEnumDeclaration(stat)) { 167 collectEnumDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, 168 currentTypeList, dtsPath); 169 170 } else if (ts.isTypeAliasDeclaration(stat)) { 171 // 不统计 172 } else if (ts.isVariableStatement(stat)) { 173 const apiName = stat.declarationList.declarations[0].name.escapedText; 174 addApi(packageName, 'global', apiName, stat.getText().trim(), getApiInfo(stat, apiInfo), 175 'Decorator', api, hash, dtsPath, 8); 176 } else { 177 if (ts.isMethodDeclaration(stat) || ts.isMethodSignature(stat) || ts.isFunctionDeclaration(stat)) { 178 var methodName = stat.name.escapedText ? stat.name.escapedText.toString() : stat.name.text.toString(); 179 let className = ''; 180 exportApi.forEach(item => { 181 if (item.methodName === methodName && item.packageName === packageName) { 182 className = item.className; 183 if (item.apiInfo) { 184 apiInfo = item.apiInfo; 185 } 186 } 187 }); 188 addFunctionOnOffApi(packageName, className, methodName, getApiInfo(stat, apiInfo), 'Method', api, 189 hash, currentClassFuncSet, stat, dtsPath); 190 } 191 } 192} 193 194function collectInterfaceDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList, dtsPath) { 195 const className = stat.name.escapedText.toString(); 196 const interfaceChildren = stat.members; 197 let tmpApiInfo = getApiInfo(stat, apiInfo); 198 // 如果用于API Diff工具,就将一个类也统计为一个API; 199 if (supportDiffTool) { 200 addApi(packageName, className, '', '', tmpApiInfo, 'InterfaceDeclaration', api, hash, dtsPath, '10'); 201 } 202 collectEachChildNode(interfaceChildren, packageName, className, 'Field', api, exportApi, returnDeclarationArr, hash, 203 tmpApiInfo, currentTypeList, dtsPath); 204} 205 206function collectClassDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList, dtsPath) { 207 const className = stat.name.escapedText.toString(); 208 const classChildren = stat.members; 209 let tmpApiInfo = getApiInfo(stat, apiInfo); 210 if (supportDiffTool) { 211 addApi(packageName, className, '', '', tmpApiInfo, 'ClassDeclaration', api, hash, dtsPath, '12'); 212 } 213 collectEachChildNode(classChildren, packageName, className, 'Field', api, exportApi, returnDeclarationArr, hash, 214 tmpApiInfo, currentTypeList, dtsPath); 215} 216 217function collectEnumDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList, dtsPath) { 218 const className = stat.name.escapedText.toString(); 219 const enumChildren = stat.members; 220 let tmpApiInfo = getApiInfo(stat, apiInfo); 221 if (supportDiffTool) { 222 addApi(packageName, className, '', '', tmpApiInfo, 'EnumDeclaration', api, hash, dtsPath, '13'); 223 } 224 collectEachChildNode(enumChildren, packageName, className, 'Enum', api, exportApi, returnDeclarationArr, hash, 225 tmpApiInfo, currentTypeList, dtsPath); 226} 227 228function collectModuleDeclaration(stat, packageName, api, exportApi, returnDeclarationArr, hash, apiInfo, currentTypeList, dtsPath) { 229 const className = stat.name.escapedText ? stat.name.escapedText.toString() : stat.name.text.toString(); 230 const moduleChildren = stat.body.statements; 231 let tmpApiInfo = getApiInfo(stat, apiInfo); 232 if (supportDiffTool) { 233 addApi(packageName, className, '', '', tmpApiInfo, 'ModelDeclaration', api, hash, dtsPath, '11'); 234 } 235 collectEachChildNode(moduleChildren, packageName, className, 'Field', api, exportApi, returnDeclarationArr, hash, 236 tmpApiInfo, currentTypeList, dtsPath); 237} 238 239function collectTypeApi(child, packageName, className, faterApiType, api, exportApi, returnDeclarationArr, 240 hash, apiInfo, dtsPath) { 241 let typeObj = { 242 name: child.name.escapedText, 243 value: [], 244 }; 245 if (child.type.types) { 246 child.type.types?.forEach(type => { 247 if (type.literal && type.literal.text) { 248 typeObj.value.push(type.literal.text); 249 if (typeCollection && type.literal) { 250 let faterApiInfo = JSON.parse(JSON.stringify(apiInfo)); 251 addApi(packageName, child.name.escapedText, type.literal.text, child.getText(), 252 getApiInfo(child, faterApiInfo), 'Type', api, hash, dtsPath, 1); 253 } 254 } else { 255 if (type.getText() !== '') { 256 typeObj.value.push(type.getText()); 257 if (typeCollection && type.literal) { 258 let faterApiInfo = JSON.parse(JSON.stringify(apiInfo)); 259 addApi(packageName, child.name.escapedText, type.getText(), child.getText(), 260 getApiInfo(child, faterApiInfo), 'Type', api, hash, dtsPath, 2); 261 } 262 } 263 } 264 }); 265 } else if (child.type.members) { 266 child.type.members?.forEach(member => { 267 member.type.types?.forEach(type => { 268 if (type.literal && type.literal.text) { 269 typeObj.value.push(type.literal.text); 270 if (typeCollection) { 271 let faterApiInfo = JSON.parse(JSON.stringify(apiInfo)); 272 addApi(packageName, child.name.escapedText, type.literal.text, child.getText(), 273 getApiInfo(child, faterApiInfo), 'Type', api, hash, dtsPath, 3); 274 } 275 } else { 276 if (type.getText() !== '') { 277 typeObj.value.push(type.getText()); 278 if (typeCollection) { 279 let faterApiInfo = JSON.parse(JSON.stringify(apiInfo)); 280 addApi(packageName, className, child.name.escapedText, child.getText(), 281 getApiInfo(child, faterApiInfo), 'Type', api, hash, dtsPath, 4); 282 } 283 } 284 } 285 }); 286 }); 287 } 288 return typeObj; 289} 290 291function collectEachChildNode(children, packageName, className, faterApiType, api, exportApi, returnDeclarationArr, 292 hash, apiInfo, currentTypeList, dtsPath) { 293 const currentClassFunSet = new Set([]); 294 children.forEach(child => { 295 if (ts.isTypeAliasDeclaration(child)) { 296 if (child.type) { 297 let typeObj = collectTypeApi(child, packageName, className, faterApiType, api, exportApi, returnDeclarationArr, 298 hash, apiInfo, dtsPath); 299 if (typeObj.value.length > 0) { 300 currentTypeList.push(typeObj); 301 } 302 } 303 } 304 }); 305 children.forEach(child => { 306 let faterApiInfo = JSON.parse(JSON.stringify(apiInfo)); 307 let apiType = new String(faterApiType); 308 if (/export.*\{.*\}/g.test(child.getText())) { 309 exportApi.push({ 310 packageName: packageName, 311 className: className, 312 methodName: child.getText().replace('export', '').replace('{', '').replace('}', '').replace(';', '').trim(), 313 apiInfo: faterApiInfo, 314 }); 315 return; 316 } 317 if (ts.isInterfaceDeclaration(child)) { 318 collectInterfaceDeclaration(child, packageName, api, exportApi, returnDeclarationArr, hash, faterApiInfo, currentTypeList, dtsPath); 319 } else if (ts.isModuleDeclaration(child)) { 320 collectModuleDeclaration(child, packageName, api, exportApi, returnDeclarationArr, hash, faterApiInfo, currentTypeList, dtsPath); 321 } else if (ts.isClassDeclaration(child)) { 322 collectClassDeclaration(child, packageName, api, exportApi, returnDeclarationArr, hash, faterApiInfo, currentTypeList, dtsPath); 323 } else if (ts.isEnumDeclaration(child)) { 324 collectEnumDeclaration(child, packageName, api, exportApi, returnDeclarationArr, hash, faterApiInfo, currentTypeList, dtsPath); 325 } else if (ts.isTypeAliasDeclaration(child)) { 326 // 不统计 327 } else { 328 if ((ts.isMethodDeclaration(child) || ts.isMethodSignature(child) || ts.isFunctionDeclaration(child)) && 329 (child.name.escapedText === 'on' || child.name.escapedText === 'off') && child.parameters && child.parameters.length > 0) { 330 apiType = 'Method'; 331 collectOnOffApi(child, apiType, packageName, className, faterApiType, api, exportApi, currentTypeList, 332 hash, apiInfo, currentClassFunSet, dtsPath); 333 } else { 334 collectOtherApi(child, packageName, className, faterApiInfo, apiType, api, 335 hash, currentClassFunSet, child, dtsPath, returnDeclarationArr); 336 } 337 } 338 }); 339} 340 341function collectOtherApi(child, packageName, className, faterApiInfo, apiType, api, 342 hash, currentClassFunSet, child, dtsPath, returnDeclarationArr) { 343 let methodName = ''; 344 if (ts.isMethodDeclaration(child) || ts.isMethodSignature(child) || ts.isFunctionDeclaration(child) || 345 ts.isCallSignatureDeclaration(child) || ts.isConstructSignatureDeclaration(child) || 346 ts.isIndexSignatureDeclaration(child)) { 347 if (child.name) { 348 methodName = child.name.getText(); 349 } else { 350 methodName = className; 351 } 352 apiType = 'Method'; 353 } else if (ts.isPropertyDeclaration(child) || ts.isPropertySignature(child)) { 354 if (child.type && child.type.parameters) { 355 methodName = child.name.escapedText; 356 apiType = 'Method'; 357 } else { 358 methodName = child.name.escapedText; 359 apiType = 'Field'; 360 } 361 } else { 362 if (child.name) { 363 methodName = child.name.getText(); 364 } 365 } 366 if (methodName !== '') { 367 addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api, 368 hash, currentClassFunSet, child, dtsPath); 369 } else { 370 if (child.getText().indexOf('constructor') === 0) { 371 methodName = 'constructor'; 372 apiType = 'Method'; 373 } else if (child.getText().indexOf('const') === 0) { 374 methodName = collectFieleOrConstant(apiType, methodName, child, returnDeclarationArr).methodName; 375 apiType = collectFieleOrConstant(apiType, methodName, child, returnDeclarationArr).apiType; 376 } else if (/\w+:\s*\w+/g.test(child.getText())) { 377 apiType = 'Field'; 378 methodName = child.getText().split(':')[0].trim(); 379 } 380 if (methodName !== '') { 381 addApi(packageName, className, methodName, child.getText(), 382 getApiInfo(child, faterApiInfo), apiType, api, hash, dtsPath, 5); 383 } 384 } 385} 386 387function collectFieleOrConstant(apiType, methodName, child, returnDeclarationArr) { 388 if (child.getText().replace('const', '').indexOf(':') > 0) { 389 if (returnDeclarationArr.has(child.getText().replace('const', '').split(':')[1].trim())) { 390 apiType = 'Field'; 391 } else { 392 apiType = 'Constant'; 393 } 394 methodName = child.getText().replace('const', '').split(':')[0].trim(); 395 } else if (child.getText().replace('const', '').indexOf('=') > 0) { 396 if (returnDeclarationArr.has(child.getText().replace('const', '').split('=')[1].trim())) { 397 apiType = 'Field'; 398 } else { 399 apiType = 'Constant'; 400 } 401 methodName = child.getText().replace('const', '').split('=')[0].trim(); 402 } 403 return { apiType, methodName }; 404} 405 406function collectOnOffApi(child, apiType, packageName, className, faterApiInfo, api, exportApi, currentTypeList, 407 hash, apiInfo, currentClassFunSet, dtsPath) { 408 for (let i = 0; i < child.parameters.length; i++) { 409 const param = child.parameters[i]; 410 if (param.name.escapedText === 'type' || param.name.escapedText === 'event' || 411 param.name.escapedText === 'eventType') { 412 if (param.type && param.type.literal && param.type.literal.text) { 413 collectTypeOrEventApi(packageName, className, faterApiInfo, apiType, api, 414 hash, currentClassFunSet, child, dtsPath, param); 415 } else if (param.type && param.type.types && param.type.types.length > 0) { 416 param.type.types.forEach(type => { 417 if (type.literal && type.literal.text) { 418 let methodName = child.name.escapedText + '_' + type.literal.text; 419 addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api, 420 hash, currentClassFunSet, child, dtsPath); 421 } 422 }); 423 } else if (param.type && param.type.typeName && param.type.typeName.escapedText) { 424 inCurrentTypeListApi(packageName, className, faterApiInfo, apiType, api, 425 hash, currentClassFunSet, child, dtsPath, currentTypeList, param); 426 } else if (param.type && param.type.typeName && param.type.typeName.left && 427 param.type.typeName.right) { 428 let methodName = child.name.escapedText + '_' + param.type.typeName.left.escapedText + '_' + 429 param.type.typeName.right.escapedText; 430 addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api, 431 hash, currentClassFunSet, child, dtsPath); 432 } else { 433 let methodName = child.name.escapedText; 434 addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api, 435 hash, currentClassFunSet, child, dtsPath); 436 } 437 break; 438 } else { 439 let methodName = child.name.escapedText; 440 addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api, 441 hash, currentClassFunSet, child, dtsPath); 442 } 443 } 444} 445 446function inCurrentTypeListApi(packageName, className, faterApiInfo, apiType, api, hash, currentClassFunSet, child, 447 dtsPath, currentTypeList, param) { 448 if (currentTypeList && currentTypeList.length > 0) { 449 currentTypeList.forEach(type => { 450 if (type.name === param.type.typeName.escapedText) { 451 type.value.forEach(typeString => { 452 let methodName = child.name.escapedText + '_' + typeString; 453 addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api, 454 hash, currentClassFunSet, child, dtsPath); 455 }); 456 } 457 }); 458 } else { 459 let methodName = child.name.escapedText; 460 addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api, 461 hash, currentClassFunSet, child, dtsPath); 462 } 463} 464 465function collectTypeOrEventApi(packageName, className, faterApiInfo, apiType, api, 466 hash, currentClassFunSet, child, dtsPath, param) { 467 const typeTextArr = param.getText().replace(/\s*/g, '').split(':'); 468 if (typeTextArr[0] === 'type' || typeTextArr[0] === 'event') { 469 let methodName = child.name.escapedText + '_' + param.type.literal.text; 470 addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api, 471 hash, currentClassFunSet, child, dtsPath); 472 } else { 473 let methodName = child.name.escapedText + '_' + param.type.literal.text; 474 addFunctionOnOffApi(packageName, className, methodName, faterApiInfo, apiType, api, 475 hash, currentClassFunSet, child, dtsPath); 476 } 477} 478 479function addFunctionOnOffApi(packageName, className, methodName, apiInfo, apiType, api, 480 hash, currentClassFunSet, childNode, dtsPath) { 481 // 合并同名函数 482 if (currentClassFunSet.has(methodName) && !isNotMerge) { 483 for (let i = 0; i < api.length; i++) { 484 const curApi = api[i]; 485 if (curApi.packageName === packageName && curApi.className === className && 486 curApi.methodName === methodName) { 487 if (curApi.methodText.indexOf(`${childNode.getText().replace('declare', '').trim()}`) < 0) { 488 curApi.methodText += `\n${childNode.getText().replace('declare', '').replace(/\r|\n/ig, '').trim()}`; 489 break; 490 } 491 } 492 } 493 } else { 494 notMergeSameNameFun(packageName, className, methodName, apiInfo, apiType, api, 495 hash, currentClassFunSet, childNode, dtsPath); 496 } 497} 498 499function notMergeSameNameFun(packageName, className, methodName, apiInfo, apiType, api, 500 hash, currentClassFunSet, childNode, dtsPath) { 501 if (!currentClassFunSet.has(methodName)) { 502 currentClassFunSet.add(methodName); 503 addApi(packageName, className, methodName, childNode.getText().replace('declare', '').trim(), 504 getApiInfo(childNode, apiInfo), apiType, api, hash, dtsPath, 6); 505 } else { 506 if (childNode.getFullText().indexOf('\/**') >= 0) { 507 addApi(packageName, className, methodName, childNode.getText().replace('declare', '').trim(), 508 getApiInfo(childNode, apiInfo), apiType, api, hash, dtsPath, 7); 509 } else { 510 let firstApiInfo = {}; 511 for (let i = 0; i < api.length; i++) { 512 const curApi = api[i]; 513 if (curApi.packageName === packageName && curApi.className === className && 514 curApi.methodName === methodName) { 515 firstApiInfo.isSystemApi = curApi.isSystemApi; 516 firstApiInfo.version = curApi.version; 517 firstApiInfo.sysCap = curApi.sysCap; 518 firstApiInfo.permission = curApi.permission; 519 firstApiInfo.model = curApi.model; 520 firstApiInfo.deprecated = curApi.deprecated; 521 firstApiInfo.useinsteadInfo = curApi.useinsteadInfo; 522 firstApiInfo.typeInfo = curApi.typeInfo; 523 firstApiInfo.errorCode = curApi.errorCode; 524 } 525 } 526 addApi(packageName, className, methodName, childNode.getText().replace('declare', '').trim(), 527 firstApiInfo, apiType, api, hash, dtsPath, 8); 528 } 529 } 530} 531 532function getApiInfo(node, apiInfos) { 533 const notesStr = node.getFullText().replace(node.getText(), ''); 534 let noteArr = notesStr.split('/**'); 535 if (notesStr !== '' && noteArr.length <= 2) { 536 const note = 'one'; 537 return getParentApiInfo(node, 'NA', note); 538 } else if (notesStr !== '' && noteArr.length >= 3) { 539 const note = 'two'; 540 const newNoteStr = noteArr[2]; 541 return getParentApiInfo(node, newNoteStr, note); 542 } else if (notesStr === '') { 543 const note = 'one'; 544 return getParentApiInfo(node, 'NA', note); 545 } 546} 547 548function matchLabelInfo(node, noteParagraph, note) { 549 const noteInfo = {}; 550 const notesStr = noteParagraph === 'NA' ? node.getFullText().replace(node.getText(), '') : noteParagraph; 551 noteInfo.note = note; 552 noteInfo.model = getModelInfo(notesStr); 553 noteInfo.errorCode = getErrorCode(notesStr); 554 noteInfo.deprecated = getDeprecatedInfo(notesStr); 555 noteInfo.permission = getPermissionInfo(notesStr); 556 if (/\@[S|s][Y|y][S|s][T|t][E|e][M|m][A|a][P|p][I|i]/g.test(notesStr)) { 557 noteInfo.isSystemApi = '系统API'; 558 } else { 559 noteInfo.isSystemApi = '公开API'; 560 } 561 562 if (/\@[S|s][I|i][N|n][C|c][E|e]\s*(\d+)/g.test(notesStr)) { 563 notesStr.replace(/\@[S|s][I|i][N|n][C|c][E|e]\s*(\d+)/g, (versionInfo) => { 564 noteInfo.version = versionInfo.replace(/\@[S|s][I|i][N|n][C|c][E|e]/g, '').trim(); 565 }); 566 } else { 567 noteInfo.version = 'N/A'; 568 } 569 570 if (/\@[S|s][Y|y][S|s][C|c][A|a][P|p]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g.test(notesStr)) { 571 notesStr.replace(/\@[S|s][Y|y][S|s][C|c][A|a][P|p]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g, sysCapInfo => { 572 noteInfo.sysCap = sysCapInfo.replace(/\@[S|s][Y|y][S|s][C|c][A|a][P|p]/g, '').trim(); 573 }); 574 } 575 576 if (/\@[U|u][S|s][E|e][I|i][N|n][S|s][T|t][E|e][A|a][D|d]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g.test(notesStr)) { 577 notesStr.replace(/\@[U|u][S|s][E|e][I|i][N|n][S|s][T|t][E|e][A|a][D|d]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g, useinsteadInfo => { 578 noteInfo.useinsteadInfo = useinsteadInfo.replace(/\@[U|u][S|s][E|e][I|i][N|n][S|s][T|t][E|e][A|a][D|d]\s*/g, '') 579 .replace(/\r|\n/ig, '').replace('*/', ''); 580 }); 581 } else { 582 noteInfo.useinsteadInfo = 'N/A'; 583 } 584 585 if (/\@[T|t][Y|y][P|p][E|e]\s\{\s(\S)+\s\}/g.test(notesStr)) { 586 notesStr.replace(/\@[T|t][Y|y][P|p][E|e]\s\{\s(\S)+\s\}/g, typeInfo => { 587 noteInfo.typeInfo = typeInfo.replace(/\@[T|t][Y|y][P|p][E|e]\s/g, '').replace('{', '').replace('}', '').trim(); 588 }); 589 } else { 590 noteInfo.typeInfo = 'N/A'; 591 } 592 return noteInfo; 593} 594 595function getPermissionInfo(notesStr) { 596 let permission = ''; 597 if (/\@[P|p][E|e][R|r][M|m][I|i][S|s][S|s][I|i][O|o][N|n]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g.test(notesStr)) { 598 notesStr.replace(/\@[P|p][E|e][R|r][M|m][I|i][S|s][S|s][I|i][O|o][N|n]\s*((\w|\.|\/|\{|\@|\}|\s)+)/g, 599 permissionInfo => { 600 permission = permissionInfo.replace( 601 /\@[P|p][E|e][R|r][M|m][I|i][S|s][S|s][I|i][O|o][N|n]/g, '').trim(); 602 return permission; 603 }); 604 } else { 605 permission = 'N/A'; 606 } 607 return permission; 608} 609 610function getDeprecatedInfo(notesStr) { 611 let deprecated = ''; 612 if (/\@[D|d][E|e][P|p][R|r][E|e][C|c][A|a][T|t][E|e][D|d].*[S|s][I|i][N|n][C|c][E|e]\s*(\d+)/g.test(notesStr)) { 613 notesStr.replace(/\@[D|d][E|e][P|p][R|r][E|e][C|c][A|a][T|t][E|e][D|d].*[S|s][I|i][N|n][C|c][E|e]\s*(\d+)/g, 614 deprecatedInfo => { 615 deprecated = deprecatedInfo.replace( 616 /\@[D|d][E|e][P|p][R|r][E|e][C|c][A|a][T|t][E|e][D|d].*[S|s][I|i][N|n][C|c][E|e]\s*/g, '').trim(); 617 618 }); 619 } else { 620 deprecated = 'N/A'; 621 } 622 return deprecated; 623} 624 625function getErrorCode(notesStr) { 626 let errorCode = ''; 627 if (/\@throws (\{ BusinessError }|\{BusinessError})\s*(\d+)/g.test(notesStr)) { 628 notesStr.replace(/\@throws (\{ BusinessError }|\{BusinessError})\s*(\d+)/g, (code) => { 629 if (errorCode === '') { 630 errorCode += `${code.replace(/\@throws (\{ BusinessError }|\{BusinessError})/, '')}`; 631 } else { 632 errorCode += `,${code.replace(/\@throws (\{ BusinessError }|\{BusinessError})/, '')}`; 633 } 634 }); 635 } else { 636 errorCode = 'N/A'; 637 } 638 return errorCode; 639} 640 641function getModelInfo(notesStr) { 642 let model = ''; 643 if (/\@[F|f][A|a][M|m][O|o][D|d][E|e][L|l][O|o][N|n][L|l][Y|y]/g.test(notesStr)) { 644 notesStr.replace(/\@[F|f][A|a][M|m][O|o][D|d][E|e][L|l][O|o][N|n][L|l][Y|y]/g, modelInfo => { 645 model = modelInfo; 646 }); 647 } else if (/\@[S|s][T|t][A|a][G|g][E|e][M|m][O|o][D|d][E|e][L|l][O|o][N|n][L|l][Y|y]/g.test(notesStr)) { 648 notesStr.replace(/\@[S|s][T|t][A|a][G|g][E|e][M|m][O|o][D|d][E|e][L|l][O|o][N|n][L|l][Y|y]/g, modelInfo => { 649 model = modelInfo; 650 }); 651 } else { 652 model = 'N/A'; 653 } 654 return model; 655} 656 657function getParentApiInfo(node, noteStr, note) { 658 let apiInfo = {}; 659 if (!apiInfo.sysCap) { 660 if (matchLabelInfo(node, noteStr, note).sysCap) { 661 apiInfo.sysCap = matchLabelInfo(node, noteStr, note).sysCap; 662 } else if (node.parent) { 663 apiInfo.sysCap = getParentApiInfo(node.parent, noteStr, apiInfo).sysCap; 664 } else { 665 apiInfo.sysCap = 'N/A'; 666 } 667 } 668 if (!apiInfo.deprecated) { 669 if (matchLabelInfo(node, noteStr, note).deprecated) { 670 apiInfo.deprecated = matchLabelInfo(node, noteStr, note).deprecated; 671 } else if (node.parent) { 672 apiInfo.deprecated = getParentApiInfo(node.parent, noteStr, apiInfo).deprecated; 673 } else { 674 apiInfo.deprecated = 'N/A'; 675 } 676 } 677 apiInfo.typeInfo = matchLabelInfo(node, noteStr, note).typeInfo; 678 apiInfo.useinsteadInfo = matchLabelInfo(node, noteStr, note).useinsteadInfo; 679 apiInfo.errorCode = matchLabelInfo(node, noteStr, note).errorCode; 680 apiInfo.note = matchLabelInfo(node, noteStr, note).note; 681 apiInfo.version = matchLabelInfo(node, noteStr, note).version; 682 apiInfo.model = matchLabelInfo(node, noteStr, note).model; 683 apiInfo.isSystemApi = matchLabelInfo(node, noteStr, note).isSystemApi; 684 apiInfo.permission = matchLabelInfo(node, noteStr, note).permission; 685 return apiInfo; 686} 687 688 689// ======================================================================================= 690function addApiImport(packageName, headimport, api, dtsPath) { 691 api.push({ 692 packageName: packageName, 693 className: '', 694 methodName: '', 695 methodText: '', 696 isSystemApi: '', 697 version: '', 698 deprecated: '',//废弃起始版本 699 apiType: 'import',//apiType 700 sysCap: '', 701 permission: '', 702 model: '', 703 headimport: headimport, 704 endexport: '', 705 dtsPath: dtsPath, 706 }); 707} 708 709function addApiExport(packageName, endexport, api, dtsPath) { 710 api.push({ 711 packageName: packageName, 712 className: '', 713 methodName: '', 714 methodText: '', 715 isSystemApi: '', 716 version: '', 717 deprecated: '',//废弃起始版本 718 apiType: 'export',//apiType 719 sysCap: '', 720 permission: '', 721 model: '', 722 headimport: '', 723 endexport: endexport, 724 dtsPath: dtsPath, 725 }); 726} 727 728function addApi(packageName, className, methodName, methodText, apiInfo, apiType, api, hash, dtsPath, type) { 729 let recard = isNotMerge ? `${packageName}.${className}/${methodName}/${methodText}` : 730 `${packageName}.${className}/${methodName}`; 731 if (!hash.has(recard)) { 732 hash.add(recard); 733 api.push({ 734 packageName: packageName, 735 className: className, 736 methodName: methodName, 737 methodText: methodText.replace(/export\s/g, ''), 738 isSystemApi: apiInfo.isSystemApi, 739 version: apiInfo.version, 740 deprecated: apiInfo.deprecated,//废弃起始版本 741 apiType: apiType, 742 sysCap: apiInfo.sysCap, 743 permission: apiInfo.permission, 744 model: apiInfo.model, 745 headimport: '', 746 endexport: '', 747 dtsPath: dtsPath, 748 useinsteadInfo: apiInfo.useinsteadInfo, 749 errorCode: apiInfo.errorCode, 750 typeInfo: apiInfo.typeInfo, 751 note: apiInfo.note, 752 }); 753 } 754} 755exports.parse = parse;