• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;