161847f8eSopenharmony_ci/*
261847f8eSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
361847f8eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
461847f8eSopenharmony_ci * you may not use this file except in compliance with the License.
561847f8eSopenharmony_ci * You may obtain a copy of the License at
661847f8eSopenharmony_ci *
761847f8eSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
861847f8eSopenharmony_ci *
961847f8eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1061847f8eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1161847f8eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1261847f8eSopenharmony_ci * See the License for the specific language governing permissions and
1361847f8eSopenharmony_ci * limitations under the License.
1461847f8eSopenharmony_ci */
1561847f8eSopenharmony_ci
1661847f8eSopenharmony_ciconst { FileSystem, Logger } = require('./utils');
1761847f8eSopenharmony_ciconst path = require('path');
1861847f8eSopenharmony_ciconst ts = require('typescript');
1961847f8eSopenharmony_ciconst fs = require('fs');
2061847f8eSopenharmony_ci
2161847f8eSopenharmony_ciclass SystemApiRecognizer {
2261847f8eSopenharmony_ci  constructor(systemRoot) {
2361847f8eSopenharmony_ci    this.systemRoot = systemRoot;
2461847f8eSopenharmony_ci    this.arkUIDecorator = new Set(['@Builder', '@Styles', '@Extend']);
2561847f8eSopenharmony_ci    this.arkUIRender = new Set(['build']);
2661847f8eSopenharmony_ci    this.componentAttributeMap = new Map();
2761847f8eSopenharmony_ci    this.componentAttributeTypeSymbolMap = new Map();
2861847f8eSopenharmony_ci    this.forEachComponents = new Set(['LazyForEach', 'ForEach']);
2961847f8eSopenharmony_ci    this.apiInfoSet = new Set([]);
3061847f8eSopenharmony_ci  }
3161847f8eSopenharmony_ci
3261847f8eSopenharmony_ci  /**
3361847f8eSopenharmony_ci   * 遍历AST, 识别系统API调用。
3461847f8eSopenharmony_ci   *
3561847f8eSopenharmony_ci   * @param {ts.Node} node
3661847f8eSopenharmony_ci   * @param {string} fileName
3761847f8eSopenharmony_ci   */
3861847f8eSopenharmony_ci  visitNode(node, fileName) {
3961847f8eSopenharmony_ci    this.recognizeDecorators(node, fileName, undefined);
4061847f8eSopenharmony_ci    if (this.isArkUIRenderMethod(node)) {
4161847f8eSopenharmony_ci      this.visitUIRenderNode(node.body, fileName);
4261847f8eSopenharmony_ci    } else {
4361847f8eSopenharmony_ci      this.visitNormalNode(node, fileName);
4461847f8eSopenharmony_ci    }
4561847f8eSopenharmony_ci  }
4661847f8eSopenharmony_ci
4761847f8eSopenharmony_ci  recognizeDecorators(node, fileName, position) {
4861847f8eSopenharmony_ci    let decoratorArray = [];
4961847f8eSopenharmony_ci    if (node.decorators) {
5061847f8eSopenharmony_ci      decoratorArray = node.decorators;
5161847f8eSopenharmony_ci    } else if (node.modifiers) {
5261847f8eSopenharmony_ci      decoratorArray = node.modifiers;
5361847f8eSopenharmony_ci    }
5461847f8eSopenharmony_ci
5561847f8eSopenharmony_ci    decoratorArray.forEach(decorator => {
5661847f8eSopenharmony_ci      const symbol = this.typeChecker.getSymbolAtLocation(decorator.expression);
5761847f8eSopenharmony_ci      if (!symbol) {
5861847f8eSopenharmony_ci        return;
5961847f8eSopenharmony_ci      }
6061847f8eSopenharmony_ci      const apiDecInfo = this.getSdkApiFromValueDeclaration(symbol.valueDeclaration.parent.parent);
6161847f8eSopenharmony_ci      if (apiDecInfo) {
6261847f8eSopenharmony_ci        apiDecInfo.setPosition(position ?
6361847f8eSopenharmony_ci          position :
6461847f8eSopenharmony_ci          ts.getLineAndCharacterOfPosition(decorator.getSourceFile(), decorator.getStart()));
6561847f8eSopenharmony_ci        apiDecInfo.setSourceFileName(fileName);
6661847f8eSopenharmony_ci        apiDecInfo.setQualifiedTypeName('global');
6761847f8eSopenharmony_ci        apiDecInfo.setPropertyName(this.getDecortorName(symbol.valueDeclaration));
6861847f8eSopenharmony_ci        this.addApiInformation(apiDecInfo);
6961847f8eSopenharmony_ci      }
7061847f8eSopenharmony_ci    });
7161847f8eSopenharmony_ci  }
7261847f8eSopenharmony_ci
7361847f8eSopenharmony_ci  getDecortorName(node) {
7461847f8eSopenharmony_ci    return node.name ? node.name.getText() : undefined;
7561847f8eSopenharmony_ci  }
7661847f8eSopenharmony_ci
7761847f8eSopenharmony_ci  /**
7861847f8eSopenharmony_ci   * 遍历访问TypeScript 节点
7961847f8eSopenharmony_ci   *
8061847f8eSopenharmony_ci   * @param {ts.Node} node
8161847f8eSopenharmony_ci   * @param {string} fileName
8261847f8eSopenharmony_ci   */
8361847f8eSopenharmony_ci  visitNormalNode(node, fileName) {
8461847f8eSopenharmony_ci    if (node) {
8561847f8eSopenharmony_ci      if (ts.isCallExpression(node)) {
8661847f8eSopenharmony_ci        this.recognizeNormalCallExpression(node, fileName);
8761847f8eSopenharmony_ci      } else {
8861847f8eSopenharmony_ci        this.recognizeNormal(node, fileName);
8961847f8eSopenharmony_ci        ts.forEachChild(node, (child) => {
9061847f8eSopenharmony_ci          this.visitNode(child, fileName);
9161847f8eSopenharmony_ci        });
9261847f8eSopenharmony_ci      }
9361847f8eSopenharmony_ci    }
9461847f8eSopenharmony_ci  }
9561847f8eSopenharmony_ci
9661847f8eSopenharmony_ci  /**
9761847f8eSopenharmony_ci   * 遍历访问 UI 渲染节点
9861847f8eSopenharmony_ci   *
9961847f8eSopenharmony_ci   * @param {ts.Block} node
10061847f8eSopenharmony_ci   * @param {string} fileName
10161847f8eSopenharmony_ci   */
10261847f8eSopenharmony_ci  visitUIRenderNode(node, fileName) {
10361847f8eSopenharmony_ci    if (!node.statements) {
10461847f8eSopenharmony_ci      return;
10561847f8eSopenharmony_ci    }
10661847f8eSopenharmony_ci    node.statements.forEach((statement) => {
10761847f8eSopenharmony_ci      this.recognizeUIComponents(statement, fileName);
10861847f8eSopenharmony_ci    });
10961847f8eSopenharmony_ci  }
11061847f8eSopenharmony_ci
11161847f8eSopenharmony_ci  setTypeChecker(typeChecker) {
11261847f8eSopenharmony_ci    this.typeChecker = typeChecker;
11361847f8eSopenharmony_ci  }
11461847f8eSopenharmony_ci
11561847f8eSopenharmony_ci  /**
11661847f8eSopenharmony_ci   * 保存系统API
11761847f8eSopenharmony_ci   *
11861847f8eSopenharmony_ci   * @param {ApiDeclarationInformation} apiInfo
11961847f8eSopenharmony_ci   */
12061847f8eSopenharmony_ci  addApiInformation(apiInfo) {
12161847f8eSopenharmony_ci    if (!this.apiInfos) {
12261847f8eSopenharmony_ci      this.apiInfos = [];
12361847f8eSopenharmony_ci    }
12461847f8eSopenharmony_ci    if (this.apiInfoSet.has(this.formatApiInfo(apiInfo))) {
12561847f8eSopenharmony_ci      return;
12661847f8eSopenharmony_ci    }
12761847f8eSopenharmony_ci    this.apiInfos.push(apiInfo);
12861847f8eSopenharmony_ci    this.apiInfoSet.add(this.formatApiInfo(apiInfo));
12961847f8eSopenharmony_ci  }
13061847f8eSopenharmony_ci
13161847f8eSopenharmony_ci  formatApiInfo(apiInfo) {
13261847f8eSopenharmony_ci    return `${apiInfo.dtsName}#${apiInfo.typeName}#${apiInfo.apiRawText}#${apiInfo.sourceFileName}#${apiInfo.pos}`;
13361847f8eSopenharmony_ci  }
13461847f8eSopenharmony_ci
13561847f8eSopenharmony_ci  getApiInformations() {
13661847f8eSopenharmony_ci    const apiDecInfos = this.apiInfos ? this.apiInfos : [];
13761847f8eSopenharmony_ci    apiDecInfos.forEach((apiInfo) => {
13861847f8eSopenharmony_ci      apiInfo.setApiNode(undefined);
13961847f8eSopenharmony_ci    });
14061847f8eSopenharmony_ci    return apiDecInfos;
14161847f8eSopenharmony_ci  }
14261847f8eSopenharmony_ci
14361847f8eSopenharmony_ci  isSdkApi(apiFilePath) {
14461847f8eSopenharmony_ci    return FileSystem.isInDirectory(this.systemRoot, apiFilePath);
14561847f8eSopenharmony_ci  }
14661847f8eSopenharmony_ci
14761847f8eSopenharmony_ci  /**
14861847f8eSopenharmony_ci   * 判断是否为创建ArkUI组件的方法
14961847f8eSopenharmony_ci   *
15061847f8eSopenharmony_ci   * @param {ts.Node} node
15161847f8eSopenharmony_ci   */
15261847f8eSopenharmony_ci  isArkUIRenderMethod(node) {
15361847f8eSopenharmony_ci    if (ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node)) {
15461847f8eSopenharmony_ci      return this.isBuildMethodInStruct(node) || this.hasArkUIDecortor(node);
15561847f8eSopenharmony_ci    }
15661847f8eSopenharmony_ci    return false;
15761847f8eSopenharmony_ci  }
15861847f8eSopenharmony_ci
15961847f8eSopenharmony_ci  /**
16061847f8eSopenharmony_ci   * 是否为struct 中的 build 方法。
16161847f8eSopenharmony_ci   *
16261847f8eSopenharmony_ci   * @param {ts.Node} node
16361847f8eSopenharmony_ci   * @returns ture or false
16461847f8eSopenharmony_ci   */
16561847f8eSopenharmony_ci  isBuildMethodInStruct(node) {
16661847f8eSopenharmony_ci    return node.name && this.arkUIRender.has(node.name.getText()) && ts.isStructDeclaration(node.parent);
16761847f8eSopenharmony_ci  }
16861847f8eSopenharmony_ci
16961847f8eSopenharmony_ci  /**
17061847f8eSopenharmony_ci   * 判断是否有ArkUI注解
17161847f8eSopenharmony_ci   *
17261847f8eSopenharmony_ci   * @param {ts.Node} node
17361847f8eSopenharmony_ci   * @returns true or false
17461847f8eSopenharmony_ci   */
17561847f8eSopenharmony_ci  hasArkUIDecortor(node) {
17661847f8eSopenharmony_ci    if (node.decorators) {
17761847f8eSopenharmony_ci      for (const decorator of node.decorators) {
17861847f8eSopenharmony_ci        const decoratorName = this.getDecortorIdefiner(decorator);
17961847f8eSopenharmony_ci        if (!decoratorName) {
18061847f8eSopenharmony_ci          continue;
18161847f8eSopenharmony_ci        }
18261847f8eSopenharmony_ci        const decoratorStr = `@${decoratorName.getText()}`;
18361847f8eSopenharmony_ci        if (!this.arkUIDecorator.has(decoratorStr)) {
18461847f8eSopenharmony_ci          continue;
18561847f8eSopenharmony_ci        }
18661847f8eSopenharmony_ci        const decoratroSymbol = this.typeChecker.getSymbolAtLocation(decoratorName);
18761847f8eSopenharmony_ci        if (this.isSdkApi(decoratroSymbol.valueDeclaration.getSourceFile().fileName)) {
18861847f8eSopenharmony_ci          return true;
18961847f8eSopenharmony_ci        }
19061847f8eSopenharmony_ci      }
19161847f8eSopenharmony_ci    }
19261847f8eSopenharmony_ci    return false;
19361847f8eSopenharmony_ci  }
19461847f8eSopenharmony_ci
19561847f8eSopenharmony_ci  getDecortorIdefiner(decoratorExp) {
19661847f8eSopenharmony_ci    if (ts.isDecorator(decoratorExp) || ts.isCallExpression(decoratorExp)) {
19761847f8eSopenharmony_ci      return this.getDecortorIdefiner(decoratorExp.expression);
19861847f8eSopenharmony_ci    }
19961847f8eSopenharmony_ci    return ts.isIdentifier(decoratorExp) ? decoratorExp : undefined;
20061847f8eSopenharmony_ci  }
20161847f8eSopenharmony_ci
20261847f8eSopenharmony_ci  /**
20361847f8eSopenharmony_ci   * 获取AST节点的API信息。
20461847f8eSopenharmony_ci   *
20561847f8eSopenharmony_ci   * @param {ts.Node} node
20661847f8eSopenharmony_ci   * @param {string} fileName
20761847f8eSopenharmony_ci   * @param {Function} positionCallback
20861847f8eSopenharmony_ci   * @returns {ApiDeclarationInformation | undefined} apiDecInfo
20961847f8eSopenharmony_ci   */
21061847f8eSopenharmony_ci  recognizeApiWithNode(node, fileName, positionCallback, useDeclarations) {
21161847f8eSopenharmony_ci    let finallySymbol = undefined;
21261847f8eSopenharmony_ci    if (!node) {
21361847f8eSopenharmony_ci      return finallySymbol;
21461847f8eSopenharmony_ci    }
21561847f8eSopenharmony_ci
21661847f8eSopenharmony_ci    try {
21761847f8eSopenharmony_ci      let symbol = this.typeChecker.getSymbolAtLocation(node);
21861847f8eSopenharmony_ci      if (symbol && symbol.flags === ts.SymbolFlags.Alias) {
21961847f8eSopenharmony_ci        symbol = this.typeChecker.getAliasedSymbol(symbol);
22061847f8eSopenharmony_ci      }
22161847f8eSopenharmony_ci      finallySymbol = this.recognizeApiWithNodeAndSymbol(node, symbol, fileName, positionCallback, useDeclarations);
22261847f8eSopenharmony_ci    } catch (error) {
22361847f8eSopenharmony_ci      Logger.error('UNKNOW NODE', error);
22461847f8eSopenharmony_ci    }
22561847f8eSopenharmony_ci    return finallySymbol;
22661847f8eSopenharmony_ci  }
22761847f8eSopenharmony_ci
22861847f8eSopenharmony_ci  recognizeApiWithNodeAndSymbol(node, symbol, fileName, positionCallback, useDeclarations) {
22961847f8eSopenharmony_ci    if (symbol) {
23061847f8eSopenharmony_ci      const apiDecInfo = this.getSdkApiDeclarationWithSymbol(symbol, node, useDeclarations);
23161847f8eSopenharmony_ci      const position = ts.getLineAndCharacterOfPosition(node.getSourceFile(), positionCallback(node));
23261847f8eSopenharmony_ci      if (symbol.valueDeclaration && this.isSdkApi(symbol.valueDeclaration.getSourceFile().fileName)) {
23361847f8eSopenharmony_ci        this.recognizeDecorators(symbol.valueDeclaration, fileName, position);
23461847f8eSopenharmony_ci      }
23561847f8eSopenharmony_ci      if (apiDecInfo) {
23661847f8eSopenharmony_ci        apiDecInfo.setPosition(position);
23761847f8eSopenharmony_ci        apiDecInfo.setSourceFileName(fileName);
23861847f8eSopenharmony_ci        this.addApiInformation(apiDecInfo);
23961847f8eSopenharmony_ci        return apiDecInfo;
24061847f8eSopenharmony_ci      }
24161847f8eSopenharmony_ci    }
24261847f8eSopenharmony_ci    return undefined;
24361847f8eSopenharmony_ci  }
24461847f8eSopenharmony_ci
24561847f8eSopenharmony_ci  /**
24661847f8eSopenharmony_ci   * 识别TS代码节点中的系统API
24761847f8eSopenharmony_ci   *
24861847f8eSopenharmony_ci   * @param {ts.Node} node
24961847f8eSopenharmony_ci   * @param {string} fileName
25061847f8eSopenharmony_ci   */
25161847f8eSopenharmony_ci  recognizeNormal(node, fileName) {
25261847f8eSopenharmony_ci    if (ts.isPropertyAccessExpression(node)) {
25361847f8eSopenharmony_ci      this.recognizePropertyAccessExpression(node, fileName);
25461847f8eSopenharmony_ci    } else if (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) {
25561847f8eSopenharmony_ci      this.recognizeHeritageClauses(node, fileName);
25661847f8eSopenharmony_ci    } else if (ts.isNewExpression(node) && ts.isIdentifier(node.expression)) {
25761847f8eSopenharmony_ci      this.recognizeApiWithNode(node.expression, fileName, (node) => node.getStart());
25861847f8eSopenharmony_ci    } else if (ts.isStructDeclaration(node)) {
25961847f8eSopenharmony_ci      this.recognizeHeritageClauses(node, fileName);
26061847f8eSopenharmony_ci    } else if (ts.isTypeReferenceNode(node)) {
26161847f8eSopenharmony_ci      this.recognizeTypeReferenceNode(node, fileName);
26261847f8eSopenharmony_ci    } else if (ts.isObjectLiteralExpression(node)) {
26361847f8eSopenharmony_ci      this.recognizeObjectLiteralExpression(node, fileName);
26461847f8eSopenharmony_ci    } else if (ts.isCallExpression(node)) {
26561847f8eSopenharmony_ci      this.recognizeEtsComponentAndAttributeApi(node.expression, fileName);
26661847f8eSopenharmony_ci    }
26761847f8eSopenharmony_ci  }
26861847f8eSopenharmony_ci
26961847f8eSopenharmony_ci  recognizeTypeReferenceNode(node, fileName) {
27061847f8eSopenharmony_ci    if (ts.isTypeReferenceNode(node)) {
27161847f8eSopenharmony_ci      this.recognizeTypeReferenceNode(node.typeName, fileName);
27261847f8eSopenharmony_ci    } else if (ts.isQualifiedName(node)) {
27361847f8eSopenharmony_ci      this.recognizeApiWithNode(node.typeName?.right, fileName, (node) => node.getStart(), true);
27461847f8eSopenharmony_ci    } else if (ts.isIdentifier(node)) {
27561847f8eSopenharmony_ci      this.recognizeApiWithNode(node, fileName, (node) => node.getStart(), true);
27661847f8eSopenharmony_ci    }
27761847f8eSopenharmony_ci  }
27861847f8eSopenharmony_ci
27961847f8eSopenharmony_ci  recognizeNormalCallExpression(node, fileName) {
28061847f8eSopenharmony_ci    if (!node) {
28161847f8eSopenharmony_ci      return undefined;
28261847f8eSopenharmony_ci    }
28361847f8eSopenharmony_ci    if (ts.isCallExpression(node)) {
28461847f8eSopenharmony_ci      const apiDecInfo = this.recognizeNormalCallExpression(node.expression, fileName);
28561847f8eSopenharmony_ci      this.recognizeNormalCallExpressionArguments(apiDecInfo, node.arguments, fileName);
28661847f8eSopenharmony_ci      return apiDecInfo;
28761847f8eSopenharmony_ci    } else if (ts.isPropertyAccessExpression(node)) {
28861847f8eSopenharmony_ci      this.recognizeNormalCallExpression(node.expression, fileName);
28961847f8eSopenharmony_ci      return this.recognizePropertyAccessExpression(node, fileName);
29061847f8eSopenharmony_ci    } else if (ts.isIdentifier(node)) {
29161847f8eSopenharmony_ci      return this.recognizeApiWithNode(node, fileName, (node) => node.getStart());
29261847f8eSopenharmony_ci    } else {
29361847f8eSopenharmony_ci      return undefined;
29461847f8eSopenharmony_ci    }
29561847f8eSopenharmony_ci  }
29661847f8eSopenharmony_ci
29761847f8eSopenharmony_ci  recognizeNormalCallExpressionArguments(apiDecInfo, args, fileName) {
29861847f8eSopenharmony_ci    if (args.length === 0) {
29961847f8eSopenharmony_ci      return;
30061847f8eSopenharmony_ci    }
30161847f8eSopenharmony_ci    const parameters = apiDecInfo ? apiDecInfo.apiNode.parameters : undefined;
30261847f8eSopenharmony_ci    args.forEach((arg, index) => {
30361847f8eSopenharmony_ci      // interface 定义作为函数入参时, 统计为API
30461847f8eSopenharmony_ci      this.recognizeArgument(arg, fileName);
30561847f8eSopenharmony_ci      if (!(parameters && parameters[index] && parameters[index].type)) {
30661847f8eSopenharmony_ci        return;
30761847f8eSopenharmony_ci      }
30861847f8eSopenharmony_ci      const paramType = parameters[index].type;
30961847f8eSopenharmony_ci      if (ts.isTypeReferenceNode(paramType)) {
31061847f8eSopenharmony_ci        const paramTypeApiDecInfo = this.recognizeApiWithNode(paramType.typeName, fileName, (node) => node.getStart(), true);
31161847f8eSopenharmony_ci        if (paramTypeApiDecInfo) {
31261847f8eSopenharmony_ci          this.modifyTypeReferenceSourceFileName(paramType.typeName, paramTypeApiDecInfo);
31361847f8eSopenharmony_ci          paramTypeApiDecInfo.setApiType('interface');
31461847f8eSopenharmony_ci          paramTypeApiDecInfo.setPosition(ts.getLineAndCharacterOfPosition(arg.getSourceFile(), arg.getStart()));
31561847f8eSopenharmony_ci        }
31661847f8eSopenharmony_ci      }
31761847f8eSopenharmony_ci    });
31861847f8eSopenharmony_ci  }
31961847f8eSopenharmony_ci
32061847f8eSopenharmony_ci  modifyTypeReferenceSourceFileName(typeNameNode, apiDecInfo) {
32161847f8eSopenharmony_ci    const symbol = this.typeChecker.getSymbolAtLocation(typeNameNode);
32261847f8eSopenharmony_ci    if (symbol) {
32361847f8eSopenharmony_ci      const typeDec = symbol.declarations[0];
32461847f8eSopenharmony_ci      let importDec = typeDec;
32561847f8eSopenharmony_ci      while (importDec && !ts.isImportDeclaration(importDec)) {
32661847f8eSopenharmony_ci        importDec = importDec.parent;
32761847f8eSopenharmony_ci      }
32861847f8eSopenharmony_ci      if (!importDec) {
32961847f8eSopenharmony_ci        return;
33061847f8eSopenharmony_ci      }
33161847f8eSopenharmony_ci      const moduleSpecifier = importDec.moduleSpecifier;
33261847f8eSopenharmony_ci      this.saveApiDecInfo(moduleSpecifier, apiDecInfo, typeNameNode);
33361847f8eSopenharmony_ci    }
33461847f8eSopenharmony_ci  }
33561847f8eSopenharmony_ci
33661847f8eSopenharmony_ci  saveApiDecInfo(moduleSpecifier, apiDecInfo, typeNameNode) {
33761847f8eSopenharmony_ci    const specialInterfaceSet = new Set(['Callback', 'AsyncCallback']);
33861847f8eSopenharmony_ci    if (ts.isStringLiteral(moduleSpecifier, apiDecInfo)) {
33961847f8eSopenharmony_ci      const useTypeFileName = apiDecInfo.apiNode.getSourceFile().fileName;
34061847f8eSopenharmony_ci      const moduleRelativePaths = moduleSpecifier.getText().match(/^['"](.*)['"]$/);
34161847f8eSopenharmony_ci      const MODULE_PATH_LENGTH = 2;
34261847f8eSopenharmony_ci      if (moduleRelativePaths.length < MODULE_PATH_LENGTH) {
34361847f8eSopenharmony_ci        return;
34461847f8eSopenharmony_ci      }
34561847f8eSopenharmony_ci      const modulePath = path.resolve(path.dirname(useTypeFileName), `${moduleRelativePaths[1]}.d.ts`);
34661847f8eSopenharmony_ci      if (fs.existsSync(modulePath)) {
34761847f8eSopenharmony_ci        if (specialInterfaceSet.has(typeNameNode.getText())) {
34861847f8eSopenharmony_ci          apiDecInfo.apiText = this.getSpecialInterfaceText(modulePath, typeNameNode.getText());
34961847f8eSopenharmony_ci        }
35061847f8eSopenharmony_ci        const dtsPath = path.relative(this.systemRoot, modulePath).replace(/\\/g, '/');
35161847f8eSopenharmony_ci        apiDecInfo.dtsName = path.basename(modulePath);
35261847f8eSopenharmony_ci        apiDecInfo.packageName = path.relative(this.systemRoot, modulePath);
35361847f8eSopenharmony_ci        apiDecInfo.dtsPath = this.formatDtsPath(dtsPath);
35461847f8eSopenharmony_ci        apiDecInfo.typeName = apiDecInfo.propertyName;
35561847f8eSopenharmony_ci      }
35661847f8eSopenharmony_ci    }
35761847f8eSopenharmony_ci  }
35861847f8eSopenharmony_ci
35961847f8eSopenharmony_ci  getSpecialInterfaceText(modulePath, interfaceName) {
36061847f8eSopenharmony_ci    const fileContent = fs.readFileSync(modulePath, 'utf-8');
36161847f8eSopenharmony_ci    const apiFileName = path.basename(modulePath).replace('d.ts', '.ts');
36261847f8eSopenharmony_ci    const sourceFile = ts.createSourceFile(apiFileName, fileContent, ts.ScriptTarget.ES2017, true);
36361847f8eSopenharmony_ci    let interfaceText = '';
36461847f8eSopenharmony_ci    sourceFile.statements.forEach(stat => {
36561847f8eSopenharmony_ci      if (ts.isInterfaceDeclaration(stat) && stat.name.escapedText === interfaceName) {
36661847f8eSopenharmony_ci        interfaceText = stat.getText().split('{')[0];
36761847f8eSopenharmony_ci      }
36861847f8eSopenharmony_ci    });
36961847f8eSopenharmony_ci    return interfaceText;
37061847f8eSopenharmony_ci  }
37161847f8eSopenharmony_ci
37261847f8eSopenharmony_ci  formatDtsPath(dtsPath) {
37361847f8eSopenharmony_ci    if (dtsPath.indexOf('api/@internal/full/canvaspattern.d.ts') > -1) {
37461847f8eSopenharmony_ci      return dtsPath.replace('api/@internal/full/', 'interface/sdk-js/api/common/full/');
37561847f8eSopenharmony_ci    } else if (dtsPath.indexOf('api/@internal/full/featureability.d.ts') > -1) {
37661847f8eSopenharmony_ci      return dtsPath.replace('api/@internal/full/', '/interface/sdk-js/api/common/full/');
37761847f8eSopenharmony_ci    } else if (dtsPath.indexOf('api/internal/full') > -1) {
37861847f8eSopenharmony_ci      return dtsPath.replace('api/@internal/full/', '/interface/sdk-js/api/@internal/ets/');
37961847f8eSopenharmony_ci    } else if (dtsPath.indexOf('component/') > -1) {
38061847f8eSopenharmony_ci      return dtsPath.replace('component/', 'interface/sdk-js/api/@internal/component/ets/');
38161847f8eSopenharmony_ci    } else {
38261847f8eSopenharmony_ci      return path.join('/interface/sdk-js', dtsPath).replace(/\\/g, '/');
38361847f8eSopenharmony_ci    }
38461847f8eSopenharmony_ci  }
38561847f8eSopenharmony_ci
38661847f8eSopenharmony_ci  /**
38761847f8eSopenharmony_ci   * 识别UI组件及其属性
38861847f8eSopenharmony_ci   *
38961847f8eSopenharmony_ci   * @param {ts.Node} node
39061847f8eSopenharmony_ci   * @param {string} fileName
39161847f8eSopenharmony_ci   */
39261847f8eSopenharmony_ci  recognizeUIComponents(node, fileName, parentName) {
39361847f8eSopenharmony_ci    if (ts.isEtsComponentExpression(node)) {
39461847f8eSopenharmony_ci      // ETS组件的声明, EtsComponentExpression 表示有子组件的组件.
39561847f8eSopenharmony_ci      this.recognizeEtsComponentExpression(node, fileName);
39661847f8eSopenharmony_ci    } else if (ts.isCallExpression(node)) {
39761847f8eSopenharmony_ci      // 组件链式调用
39861847f8eSopenharmony_ci      this.recognizeComponentAttributeChain(node, fileName, []);
39961847f8eSopenharmony_ci    } else if (ts.isIfStatement(node)) {
40061847f8eSopenharmony_ci      this.recognizeIfStatement(node, fileName);
40161847f8eSopenharmony_ci    } else {
40261847f8eSopenharmony_ci      ts.forEachChild(node, (child) => {
40361847f8eSopenharmony_ci        this.recognizeUIComponents(child, fileName);
40461847f8eSopenharmony_ci      });
40561847f8eSopenharmony_ci    }
40661847f8eSopenharmony_ci  }
40761847f8eSopenharmony_ci
40861847f8eSopenharmony_ci  /**
40961847f8eSopenharmony_ci   * 识别在对象内,作为入参的API
41061847f8eSopenharmony_ci   *
41161847f8eSopenharmony_ci   * @param {ts.Node} node
41261847f8eSopenharmony_ci   * @param {string} fileName
41361847f8eSopenharmony_ci   * @returns
41461847f8eSopenharmony_ci   */
41561847f8eSopenharmony_ci  recognizeObjectLiteralExpression(node, fileName) {
41661847f8eSopenharmony_ci    let parentName = '';
41761847f8eSopenharmony_ci    if (node.parent && node.parent.expression && ts.isIdentifier(node.parent.expression)) {
41861847f8eSopenharmony_ci      parentName = node.parent.expression.escapedName ?
41961847f8eSopenharmony_ci        node.parent.expression.escapedName : node.parent.expression.escapedText;
42061847f8eSopenharmony_ci    }
42161847f8eSopenharmony_ci    const parentType = this.typeChecker.getContextualType(node);
42261847f8eSopenharmony_ci    if (!parentType || !parentType.properties) {
42361847f8eSopenharmony_ci      return;
42461847f8eSopenharmony_ci    }
42561847f8eSopenharmony_ci    if (parentType.properties.length === 0) {
42661847f8eSopenharmony_ci      return;
42761847f8eSopenharmony_ci    }
42861847f8eSopenharmony_ci    if (!parentType.properties[0].valueDeclaration) {
42961847f8eSopenharmony_ci      return;
43061847f8eSopenharmony_ci    }
43161847f8eSopenharmony_ci    const sourceFile = parentType.properties[0].valueDeclaration.getSourceFile();
43261847f8eSopenharmony_ci
43361847f8eSopenharmony_ci    //判断是否为系统API
43461847f8eSopenharmony_ci    if (!this.isSdkApi(sourceFile.fileName)) {
43561847f8eSopenharmony_ci      return;
43661847f8eSopenharmony_ci    }
43761847f8eSopenharmony_ci    let parentSymbol = sourceFile.locals.get(parentName);
43861847f8eSopenharmony_ci    const apiMapInParent = this.getApiMapInParent(parentSymbol, parentType);
43961847f8eSopenharmony_ci
44061847f8eSopenharmony_ci    node.properties.forEach(property => {
44161847f8eSopenharmony_ci      const apiNode = apiMapInParent.get(property.name.escapedText);
44261847f8eSopenharmony_ci      if (!apiNode) {
44361847f8eSopenharmony_ci        return;
44461847f8eSopenharmony_ci      }
44561847f8eSopenharmony_ci      if (ts.isTypeLiteralNode(apiNode.parent)) {
44661847f8eSopenharmony_ci        return;
44761847f8eSopenharmony_ci      }
44861847f8eSopenharmony_ci      const apiDecInfo = this.getSdkApiFromValueDeclaration(apiNode, property, fileName);
44961847f8eSopenharmony_ci      if (apiDecInfo) {
45061847f8eSopenharmony_ci        const position = ts.getLineAndCharacterOfPosition(property.getSourceFile(), property.name.getStart());
45161847f8eSopenharmony_ci        this.recognizeDecorators(apiNode, fileName, position);
45261847f8eSopenharmony_ci        apiDecInfo.setPosition(position);
45361847f8eSopenharmony_ci        apiDecInfo.setSourceFileName(fileName);
45461847f8eSopenharmony_ci        this.addApiInformation(apiDecInfo);
45561847f8eSopenharmony_ci      }
45661847f8eSopenharmony_ci    });
45761847f8eSopenharmony_ci  }
45861847f8eSopenharmony_ci
45961847f8eSopenharmony_ci  getApiMapInParent(parentSymbol, parentType) {
46061847f8eSopenharmony_ci    const apiMapInParent = new Map();
46161847f8eSopenharmony_ci    if (!parentSymbol) {
46261847f8eSopenharmony_ci      parentType.members.forEach((memberValue, member) => {
46361847f8eSopenharmony_ci        apiMapInParent.set(member, memberValue.valueDeclaration);
46461847f8eSopenharmony_ci      });
46561847f8eSopenharmony_ci    } else {
46661847f8eSopenharmony_ci      parentSymbol.declarations[0]?.members?.forEach(member => {
46761847f8eSopenharmony_ci        if (!member.name) {
46861847f8eSopenharmony_ci          return;
46961847f8eSopenharmony_ci        }
47061847f8eSopenharmony_ci        apiMapInParent.set(member.name.escapedText, member);
47161847f8eSopenharmony_ci      });
47261847f8eSopenharmony_ci    }
47361847f8eSopenharmony_ci    return apiMapInParent;
47461847f8eSopenharmony_ci  }
47561847f8eSopenharmony_ci
47661847f8eSopenharmony_ci  /**
47761847f8eSopenharmony_ci   * 识别条件渲染
47861847f8eSopenharmony_ci   * @param {ts.Node} node
47961847f8eSopenharmony_ci   * @param {string} fileName
48061847f8eSopenharmony_ci   */
48161847f8eSopenharmony_ci  recognizeIfStatement(node, fileName) {
48261847f8eSopenharmony_ci    this.recognizeArgument(node.expression, fileName);
48361847f8eSopenharmony_ci    const thenStatements = ts.isBlock(node) ? node.statements :
48461847f8eSopenharmony_ci      (ts.isBlock(node.thenStatement) ? node.thenStatement.statements : undefined);
48561847f8eSopenharmony_ci    if (thenStatements) {
48661847f8eSopenharmony_ci      thenStatements.forEach((child) => {
48761847f8eSopenharmony_ci        this.recognizeUIComponents(child, fileName);
48861847f8eSopenharmony_ci      });
48961847f8eSopenharmony_ci    }
49061847f8eSopenharmony_ci    if (node.elseStatement) {
49161847f8eSopenharmony_ci      this.recognizeIfStatement(node.elseStatement, fileName);
49261847f8eSopenharmony_ci    }
49361847f8eSopenharmony_ci  }
49461847f8eSopenharmony_ci
49561847f8eSopenharmony_ci  /**
49661847f8eSopenharmony_ci   * 识别组件链式调用中的API
49761847f8eSopenharmony_ci   * @param {ts.Node} node
49861847f8eSopenharmony_ci   * @param {string} fileName
49961847f8eSopenharmony_ci   */
50061847f8eSopenharmony_ci  recognizeComponentAttributeChain(node, fileName) {
50161847f8eSopenharmony_ci    if (ts.isCallExpression(node)) {
50261847f8eSopenharmony_ci      const chainResult = this.recognizeComponentAttributeChain(node.expression, fileName);
50361847f8eSopenharmony_ci      this.recognizeArguments(node.arguments, fileName);
50461847f8eSopenharmony_ci      return new ComponentAttrResult(chainResult.componentInfo, undefined);
50561847f8eSopenharmony_ci    } else if (ts.isPropertyAccessExpression(node)) {
50661847f8eSopenharmony_ci      const chainResult = this.recognizeComponentAttributeChain(node.expression, fileName);
50761847f8eSopenharmony_ci      const attrInfo = this.recognizeEtsComponentAndAttributeApi(node, fileName);
50861847f8eSopenharmony_ci      if (chainResult.componentInfo && attrInfo) {
50961847f8eSopenharmony_ci        attrInfo.setComponentName(chainResult.componentInfo.propertyName);
51061847f8eSopenharmony_ci      }
51161847f8eSopenharmony_ci      return new ComponentAttrResult(chainResult.componentInfo, attrInfo);
51261847f8eSopenharmony_ci    } else if (ts.isEtsComponentExpression(node)) {
51361847f8eSopenharmony_ci      return new ComponentAttrResult(this.recognizeEtsComponentExpression(node, fileName), undefined);
51461847f8eSopenharmony_ci    } else if (ts.isIdentifier(node)) {
51561847f8eSopenharmony_ci      return new ComponentAttrResult(this.recognizeEtsComponentAndAttributeApi(node, fileName), undefined);
51661847f8eSopenharmony_ci    } else {
51761847f8eSopenharmony_ci      return new ComponentAttrResult(undefined, undefined);
51861847f8eSopenharmony_ci    }
51961847f8eSopenharmony_ci  }
52061847f8eSopenharmony_ci
52161847f8eSopenharmony_ci  /**
52261847f8eSopenharmony_ci   * 识别ArkUI组件表达式
52361847f8eSopenharmony_ci   * @param {ts.EtsComponentExpression} node
52461847f8eSopenharmony_ci   * @param {string} fileName
52561847f8eSopenharmony_ci   * @returns
52661847f8eSopenharmony_ci   */
52761847f8eSopenharmony_ci  recognizeEtsComponentExpression(node, fileName) {
52861847f8eSopenharmony_ci    // node.expression is component name Identifier
52961847f8eSopenharmony_ci    const apiDecInfo = this.recognizeEtsComponentAndAttributeApi(node.expression, fileName);
53061847f8eSopenharmony_ci
53161847f8eSopenharmony_ci    if (node.arguments) {
53261847f8eSopenharmony_ci      this.recognizeComponentArguments(apiDecInfo, node.arguments, fileName);
53361847f8eSopenharmony_ci    }
53461847f8eSopenharmony_ci
53561847f8eSopenharmony_ci    if (node.body) {
53661847f8eSopenharmony_ci      node.body.statements.forEach((statement) => {
53761847f8eSopenharmony_ci        this.recognizeUIComponents(statement, fileName);
53861847f8eSopenharmony_ci      });
53961847f8eSopenharmony_ci    }
54061847f8eSopenharmony_ci
54161847f8eSopenharmony_ci    return apiDecInfo;
54261847f8eSopenharmony_ci  }
54361847f8eSopenharmony_ci
54461847f8eSopenharmony_ci  /**
54561847f8eSopenharmony_ci   * 识别组件入参
54661847f8eSopenharmony_ci   * @param {ApiDeclarationInformation} apiDecInfo
54761847f8eSopenharmony_ci   * @param {ts.Node[]} args
54861847f8eSopenharmony_ci   * @param {string} fileName
54961847f8eSopenharmony_ci   */
55061847f8eSopenharmony_ci  recognizeComponentArguments(apiDecInfo, args, fileName) {
55161847f8eSopenharmony_ci    // ForEach, LazyForEach
55261847f8eSopenharmony_ci    if (apiDecInfo && this.forEachComponents.has(apiDecInfo.propertyName)) {
55361847f8eSopenharmony_ci      args.forEach((arg, index) => {
55461847f8eSopenharmony_ci        // itemGenerator
55561847f8eSopenharmony_ci        if (index === 1) {
55661847f8eSopenharmony_ci          this.visitUIRenderNode(arg.body ? arg.body : arg, fileName);
55761847f8eSopenharmony_ci        } else {
55861847f8eSopenharmony_ci          this.recognizeArgument(arg, fileName);
55961847f8eSopenharmony_ci        }
56061847f8eSopenharmony_ci      });
56161847f8eSopenharmony_ci    } else {
56261847f8eSopenharmony_ci      this.recognizeArguments(args, fileName);
56361847f8eSopenharmony_ci    }
56461847f8eSopenharmony_ci  }
56561847f8eSopenharmony_ci
56661847f8eSopenharmony_ci  /**
56761847f8eSopenharmony_ci   * 识别参数中的API
56861847f8eSopenharmony_ci   * @param {ts.Node[]} args
56961847f8eSopenharmony_ci   * @param {string} fileName
57061847f8eSopenharmony_ci   */
57161847f8eSopenharmony_ci  recognizeArguments(args, fileName) {
57261847f8eSopenharmony_ci    args.forEach((arg) => {
57361847f8eSopenharmony_ci      this.recognizeArgument(arg, fileName);
57461847f8eSopenharmony_ci    });
57561847f8eSopenharmony_ci  }
57661847f8eSopenharmony_ci
57761847f8eSopenharmony_ci  recognizeArgument(node, fileName) {
57861847f8eSopenharmony_ci    if (!node) {
57961847f8eSopenharmony_ci      return;
58061847f8eSopenharmony_ci    }
58161847f8eSopenharmony_ci    this.recognizeNormal(node, fileName);
58261847f8eSopenharmony_ci    ts.forEachChild(node, (child) => {
58361847f8eSopenharmony_ci      this.recognizeArgument(child, fileName);
58461847f8eSopenharmony_ci    });
58561847f8eSopenharmony_ci  }
58661847f8eSopenharmony_ci
58761847f8eSopenharmony_ci
58861847f8eSopenharmony_ci  /**
58961847f8eSopenharmony_ci   * 获取组件或属性的API详情
59061847f8eSopenharmony_ci   *
59161847f8eSopenharmony_ci   * @param {ts.Identifier} node
59261847f8eSopenharmony_ci   * @param {string} fileName
59361847f8eSopenharmony_ci   * @returns {ApiDeclarationInformation | undefined} apiDecInfo
59461847f8eSopenharmony_ci   */
59561847f8eSopenharmony_ci  recognizeEtsComponentAndAttributeApi(node, fileName) {
59661847f8eSopenharmony_ci    // recognize component
59761847f8eSopenharmony_ci    const apiDecInfo = this.recognizeApiWithNode(node, fileName,
59861847f8eSopenharmony_ci      (node) => ts.isPropertyAccessExpression(node) ? node.name.getStart() : node.getStart());
59961847f8eSopenharmony_ci    return apiDecInfo;
60061847f8eSopenharmony_ci  }
60161847f8eSopenharmony_ci
60261847f8eSopenharmony_ci  /**
60361847f8eSopenharmony_ci   * 通过语义分析,识别继承关系中的系统API
60461847f8eSopenharmony_ci   *
60561847f8eSopenharmony_ci   * @param {ts.ClassDeclaration | ts.InterfaceDeclaration} node
60661847f8eSopenharmony_ci   * @param {ts.ClassDeclaration|ts.InterfaceDeclaration} node
60761847f8eSopenharmony_ci   */
60861847f8eSopenharmony_ci  recognizeHeritageClauses(node, fileName) {
60961847f8eSopenharmony_ci    if (!node.heritageClauses) {
61061847f8eSopenharmony_ci      return;
61161847f8eSopenharmony_ci    }
61261847f8eSopenharmony_ci    const nodeType = this.typeChecker.getTypeAtLocation(node);
61361847f8eSopenharmony_ci    const nodeSymbol = nodeType.getSymbol();
61461847f8eSopenharmony_ci    if (!nodeSymbol.members) {
61561847f8eSopenharmony_ci      return;
61661847f8eSopenharmony_ci    }
61761847f8eSopenharmony_ci    const heritagePropertyMap = this.collectAllHeritageMethods(node);
61861847f8eSopenharmony_ci    if (!nodeSymbol.valueDeclaration) {
61961847f8eSopenharmony_ci      return;
62061847f8eSopenharmony_ci    }
62161847f8eSopenharmony_ci    if (!nodeSymbol.valueDeclaration.heritageClauses) {
62261847f8eSopenharmony_ci      return;
62361847f8eSopenharmony_ci    }
62461847f8eSopenharmony_ci    if (heritagePropertyMap.size === 0) {
62561847f8eSopenharmony_ci      const extendNodes = nodeSymbol.valueDeclaration.heritageClauses[0].types;
62661847f8eSopenharmony_ci      this.getExtendClassPropertyMap(extendNodes, heritagePropertyMap);
62761847f8eSopenharmony_ci    }
62861847f8eSopenharmony_ci    if (heritagePropertyMap === 0) {
62961847f8eSopenharmony_ci      return;
63061847f8eSopenharmony_ci    }
63161847f8eSopenharmony_ci    nodeSymbol.members.forEach((memberSymbol, memberName) => {
63261847f8eSopenharmony_ci      if (heritagePropertyMap.has(memberName)) {
63361847f8eSopenharmony_ci        const apiDecInfo = this.getSdkApiDeclarationWithSymbol(heritagePropertyMap.get(memberName), undefined);
63461847f8eSopenharmony_ci        if (apiDecInfo) {
63561847f8eSopenharmony_ci          apiDecInfo.setPosition(ts.getLineAndCharacterOfPosition(node.getSourceFile(), memberSymbol.valueDeclaration.getStart()));
63661847f8eSopenharmony_ci          apiDecInfo.setSourceFileName(fileName);
63761847f8eSopenharmony_ci          this.addApiInformation(apiDecInfo);
63861847f8eSopenharmony_ci        }
63961847f8eSopenharmony_ci      }
64061847f8eSopenharmony_ci    });
64161847f8eSopenharmony_ci  }
64261847f8eSopenharmony_ci
64361847f8eSopenharmony_ci  /**
64461847f8eSopenharmony_ci   * 通过向上查找继承的节点,收集多次继承情况下的API
64561847f8eSopenharmony_ci   * @param {ts.Node} extendNodes
64661847f8eSopenharmony_ci   * @param {Map} extendClassPropertyMap
64761847f8eSopenharmony_ci   */
64861847f8eSopenharmony_ci  getExtendClassPropertyMap(extendNodes, extendClassPropertyMap) {
64961847f8eSopenharmony_ci    extendNodes.forEach(extendNode => {
65061847f8eSopenharmony_ci      const extendNodeType = this.typeChecker.getTypeAtLocation(extendNode);
65161847f8eSopenharmony_ci      if (!extendNodeType) {
65261847f8eSopenharmony_ci        return;
65361847f8eSopenharmony_ci      }
65461847f8eSopenharmony_ci      const extendNodeSymbol = extendNodeType.getSymbol();
65561847f8eSopenharmony_ci      if (!extendNodeSymbol) {
65661847f8eSopenharmony_ci        return;
65761847f8eSopenharmony_ci      }
65861847f8eSopenharmony_ci      const valueDeclaration = extendNodeSymbol.declarations[0];
65961847f8eSopenharmony_ci      if (valueDeclaration && !this.isSdkApi(valueDeclaration.getSourceFile().fileName) && extendNodeSymbol.valueDeclaration &&
66061847f8eSopenharmony_ci        extendNodeSymbol.valueDeclaration.heritageClauses) {
66161847f8eSopenharmony_ci        const parentNodes = extendNodeSymbol.valueDeclaration.heritageClauses[0].types;
66261847f8eSopenharmony_ci        this.getExtendClassPropertyMap(parentNodes, extendClassPropertyMap);
66361847f8eSopenharmony_ci      } else {
66461847f8eSopenharmony_ci        extendNodeSymbol.members.forEach((memberSymbol, memberName) => {
66561847f8eSopenharmony_ci          extendClassPropertyMap.set(memberName, memberSymbol);
66661847f8eSopenharmony_ci        });
66761847f8eSopenharmony_ci      }
66861847f8eSopenharmony_ci    });
66961847f8eSopenharmony_ci  }
67061847f8eSopenharmony_ci
67161847f8eSopenharmony_ci  /**
67261847f8eSopenharmony_ci   * 搜集所有父类(属于SDK中的API)的方法和属性。
67361847f8eSopenharmony_ci   *
67461847f8eSopenharmony_ci   * @param {ts.Node} node
67561847f8eSopenharmony_ci   * @returns Map
67661847f8eSopenharmony_ci   */
67761847f8eSopenharmony_ci  collectAllHeritageMethods(node) {
67861847f8eSopenharmony_ci    const heritageMembers = new Map();
67961847f8eSopenharmony_ci    if (!node.heritageClauses) {
68061847f8eSopenharmony_ci      return heritageMembers;
68161847f8eSopenharmony_ci    }
68261847f8eSopenharmony_ci    node.heritageClauses.forEach((heritage) => {
68361847f8eSopenharmony_ci      heritage.types.forEach((child) => {
68461847f8eSopenharmony_ci        const childSymbol = this.typeChecker.getSymbolAtLocation(child.expression);
68561847f8eSopenharmony_ci        if (!childSymbol) {
68661847f8eSopenharmony_ci          return;
68761847f8eSopenharmony_ci        }
68861847f8eSopenharmony_ci        const type = this.typeChecker.getTypeOfSymbolAtLocation(childSymbol, child);
68961847f8eSopenharmony_ci        const typeSymbol = type.getSymbol();
69061847f8eSopenharmony_ci        if (!typeSymbol) {
69161847f8eSopenharmony_ci          return;
69261847f8eSopenharmony_ci        }
69361847f8eSopenharmony_ci        if (!typeSymbol && childSymbol.members) {
69461847f8eSopenharmony_ci          this.setHeritageMembersFroMmembers(heritageMembers, childSymbol.members);
69561847f8eSopenharmony_ci          return;
69661847f8eSopenharmony_ci        }
69761847f8eSopenharmony_ci        const valueDeclaration = typeSymbol.valueDeclaration;
69861847f8eSopenharmony_ci        if (!valueDeclaration || !this.isSdkApi(valueDeclaration.getSourceFile().fileName)) {
69961847f8eSopenharmony_ci          return;
70061847f8eSopenharmony_ci        }
70161847f8eSopenharmony_ci        this.setHeritageMembersFroMmembers(heritageMembers, typeSymbol.members);
70261847f8eSopenharmony_ci      });
70361847f8eSopenharmony_ci    });
70461847f8eSopenharmony_ci    return heritageMembers;
70561847f8eSopenharmony_ci  }
70661847f8eSopenharmony_ci
70761847f8eSopenharmony_ci  /**
70861847f8eSopenharmony_ci   * 搜集所有父类(属于SDK中的API)的方法和属性。
70961847f8eSopenharmony_ci   *
71061847f8eSopenharmony_ci   * @param {Map} heritageMembers
71161847f8eSopenharmony_ci   * @param {ts.NodeArray} members
71261847f8eSopenharmony_ci   */
71361847f8eSopenharmony_ci  setHeritageMembersFroMmembers(heritageMembers, members) {
71461847f8eSopenharmony_ci    members.forEach((memberSymbol, memberName) => {
71561847f8eSopenharmony_ci      heritageMembers.set(memberName, memberSymbol);
71661847f8eSopenharmony_ci    });
71761847f8eSopenharmony_ci  }
71861847f8eSopenharmony_ci
71961847f8eSopenharmony_ci  /**
72061847f8eSopenharmony_ci   * 解析属性访问
72161847f8eSopenharmony_ci   *
72261847f8eSopenharmony_ci   * @param {ts.PropertyAccessExpression} node
72361847f8eSopenharmony_ci   */
72461847f8eSopenharmony_ci  recognizePropertyAccessExpression(node, fileName) {
72561847f8eSopenharmony_ci    return this.recognizeApiWithNode(node, fileName, (node) => node.name.getStart());
72661847f8eSopenharmony_ci  }
72761847f8eSopenharmony_ci
72861847f8eSopenharmony_ci  /**
72961847f8eSopenharmony_ci   * 获取 export {xx} 中xx的定义
73061847f8eSopenharmony_ci   * @param {ts.Symbol} symbol
73161847f8eSopenharmony_ci   */
73261847f8eSopenharmony_ci  getAliasExcludesRealValueDeclarations(symbol) {
73361847f8eSopenharmony_ci    const symbolName = symbol.escapedName;
73461847f8eSopenharmony_ci    const sourceFile = symbol.declarations[0].getSourceFile();
73561847f8eSopenharmony_ci    const realSymbol = sourceFile.locals ? sourceFile.locals.get(symbolName) : undefined;
73661847f8eSopenharmony_ci    return realSymbol ? realSymbol.valueDeclaration : undefined;
73761847f8eSopenharmony_ci  }
73861847f8eSopenharmony_ci
73961847f8eSopenharmony_ci  getApiRawText(node) {
74061847f8eSopenharmony_ci    switch (node.kind) {
74161847f8eSopenharmony_ci      case ts.SyntaxKind.ClassDeclaration:
74261847f8eSopenharmony_ci        return `class ${node.name ? node.name.getText() : ''}`;
74361847f8eSopenharmony_ci      case ts.SyntaxKind.InterfaceDeclaration:
74461847f8eSopenharmony_ci        return `interface ${node.name ? node.name.getText() : ''}`;
74561847f8eSopenharmony_ci      case ts.SyntaxKind.EnumDeclaration:
74661847f8eSopenharmony_ci        return `enum ${node.name ? node.name.getText() : ''}`;
74761847f8eSopenharmony_ci      case ts.SyntaxKind.ModuleDeclaration:
74861847f8eSopenharmony_ci        return `namespace ${node.name ? node.name.getText() : ''}`;
74961847f8eSopenharmony_ci      case ts.SyntaxKind.StructDeclaration:
75061847f8eSopenharmony_ci        return `struct ${node.name ? node.name.getText() : ''}`;
75161847f8eSopenharmony_ci      case node.getText() === 'AsyncCallback' || node.getText() === 'Callback':
75261847f8eSopenharmony_ci        return '';
75361847f8eSopenharmony_ci      default:
75461847f8eSopenharmony_ci        return node.getText();
75561847f8eSopenharmony_ci    }
75661847f8eSopenharmony_ci  }
75761847f8eSopenharmony_ci
75861847f8eSopenharmony_ci  getApiTypeName(node) {
75961847f8eSopenharmony_ci    if (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node) || ts.isEnumDeclaration(node) ||
76061847f8eSopenharmony_ci      ts.isModuleDeclaration(node)) {
76161847f8eSopenharmony_ci      return node.name ? node.name.getText() : '';
76261847f8eSopenharmony_ci    }
76361847f8eSopenharmony_ci    return undefined;
76461847f8eSopenharmony_ci  }
76561847f8eSopenharmony_ci
76661847f8eSopenharmony_ci  /**
76761847f8eSopenharmony_ci   * 获取节点定义在哪个文件哪个类型下。
76861847f8eSopenharmony_ci   *
76961847f8eSopenharmony_ci   * @param {ts.Symbol} type
77061847f8eSopenharmony_ci   */
77161847f8eSopenharmony_ci  getSdkApiDeclarationWithSymbol(symbol, node, useDeclarations) {
77261847f8eSopenharmony_ci    const sourceSymbol = symbol;
77361847f8eSopenharmony_ci    let valudeDec = sourceSymbol && sourceSymbol.valueDeclaration ? sourceSymbol.valueDeclaration :
77461847f8eSopenharmony_ci      (sourceSymbol.flags & ts.SymbolFlags.AliasExcludes ? this.getAliasExcludesRealValueDeclarations(symbol) : undefined);
77561847f8eSopenharmony_ci    valudeDec = !valudeDec && useDeclarations ? symbol.declarations[0] : valudeDec;
77661847f8eSopenharmony_ci    if (!valudeDec) {
77761847f8eSopenharmony_ci      return undefined;
77861847f8eSopenharmony_ci    }
77961847f8eSopenharmony_ci    if (valudeDec.kind === ts.SyntaxKind.TypeParameter) {
78061847f8eSopenharmony_ci      return undefined;
78161847f8eSopenharmony_ci    }
78261847f8eSopenharmony_ci    const sourceFile = valudeDec.getSourceFile();
78361847f8eSopenharmony_ci    if (!this.isSdkApi(sourceFile.fileName)) {
78461847f8eSopenharmony_ci      return undefined;
78561847f8eSopenharmony_ci    }
78661847f8eSopenharmony_ci    let apiDecInfo = undefined;
78761847f8eSopenharmony_ci    if (symbol.declarations.length > 1) {
78861847f8eSopenharmony_ci      apiDecInfo = this.getSdkApiFromMultiDeclarations(symbol, node);
78961847f8eSopenharmony_ci    }
79061847f8eSopenharmony_ci    return apiDecInfo ? apiDecInfo : this.getSdkApiFromValueDeclaration(valudeDec);
79161847f8eSopenharmony_ci  }
79261847f8eSopenharmony_ci
79361847f8eSopenharmony_ci  getSdkApiFromMultiDeclarations(symbol, node) {
79461847f8eSopenharmony_ci    if (!node) {
79561847f8eSopenharmony_ci      return undefined;
79661847f8eSopenharmony_ci    }
79761847f8eSopenharmony_ci    let callExpressionNode = node;
79861847f8eSopenharmony_ci    while (callExpressionNode && !ts.isCallExpression(callExpressionNode)) {
79961847f8eSopenharmony_ci      callExpressionNode = callExpressionNode.parent;
80061847f8eSopenharmony_ci    }
80161847f8eSopenharmony_ci    if (!callExpressionNode) {
80261847f8eSopenharmony_ci      return undefined;
80361847f8eSopenharmony_ci    }
80461847f8eSopenharmony_ci    const matchedDec = this.findBestMatchedDeclaration(callExpressionNode, symbol);
80561847f8eSopenharmony_ci    if (!matchedDec) {
80661847f8eSopenharmony_ci      return undefined;
80761847f8eSopenharmony_ci    }
80861847f8eSopenharmony_ci    return this.getSdkApiFromValueDeclaration(matchedDec);
80961847f8eSopenharmony_ci  }
81061847f8eSopenharmony_ci
81161847f8eSopenharmony_ci  /**
81261847f8eSopenharmony_ci   * 查找参数个数匹配,参数类型匹配的API
81361847f8eSopenharmony_ci   * @param {number} argumentLength
81461847f8eSopenharmony_ci   * @param {ts.Symbol} symbol
81561847f8eSopenharmony_ci   * @returns api declaration node.
81661847f8eSopenharmony_ci   */
81761847f8eSopenharmony_ci  findBestMatchedDeclaration(callExpressionNode, symbol) {
81861847f8eSopenharmony_ci    const callExpArgLen = callExpressionNode.arguments.length;
81961847f8eSopenharmony_ci    if (callExpArgLen === 0) {
82061847f8eSopenharmony_ci      return undefined;
82161847f8eSopenharmony_ci    }
82261847f8eSopenharmony_ci    let matchedDecs = [];
82361847f8eSopenharmony_ci    for (let dec of symbol.declarations) {
82461847f8eSopenharmony_ci      if (dec.parameters && dec.parameters.length === callExpArgLen) {
82561847f8eSopenharmony_ci        matchedDecs.push(dec);
82661847f8eSopenharmony_ci      }
82761847f8eSopenharmony_ci    }
82861847f8eSopenharmony_ci    if (matchedDecs.length === 1) {
82961847f8eSopenharmony_ci      return matchedDecs[0];
83061847f8eSopenharmony_ci    }
83161847f8eSopenharmony_ci    if ('on' === callExpressionNode.expression.name.getText()) {
83261847f8eSopenharmony_ci      return this.findBestMatchedApi(callExpressionNode, matchedDecs);
83361847f8eSopenharmony_ci    }
83461847f8eSopenharmony_ci    const lastArgument = callExpressionNode.arguments[callExpArgLen - 1];
83561847f8eSopenharmony_ci    if (this.isAsyncCallbackCallExp(lastArgument)) {
83661847f8eSopenharmony_ci      matchedDecs = matchedDecs.filter((value) => {
83761847f8eSopenharmony_ci        return this.isAsyncCallbackApi(value);
83861847f8eSopenharmony_ci      });
83961847f8eSopenharmony_ci    } else {
84061847f8eSopenharmony_ci      matchedDecs = matchedDecs.filter((value) => {
84161847f8eSopenharmony_ci        return !this.isAsyncCallbackApi(value);
84261847f8eSopenharmony_ci      });
84361847f8eSopenharmony_ci    }
84461847f8eSopenharmony_ci    return matchedDecs.length > 0 ? matchedDecs[0] : undefined;
84561847f8eSopenharmony_ci  }
84661847f8eSopenharmony_ci
84761847f8eSopenharmony_ci  /**
84861847f8eSopenharmony_ci   * 通过匹配type字符串找到正确的API
84961847f8eSopenharmony_ci   *
85061847f8eSopenharmony_ci   * @param { ts.Node } callExpressionNode
85161847f8eSopenharmony_ci   * @param { Array } matchedDecs
85261847f8eSopenharmony_ci   * @returns
85361847f8eSopenharmony_ci   */
85461847f8eSopenharmony_ci  findBestMatchedApi(callExpressionNode, matchedDecs) {
85561847f8eSopenharmony_ci    let apiNode = undefined;
85661847f8eSopenharmony_ci    if (ts.isStringLiteral(callExpressionNode.arguments[0])) {
85761847f8eSopenharmony_ci      const useType = callExpressionNode.arguments[0].text;
85861847f8eSopenharmony_ci      for (let i = 0; i < matchedDecs.length; i++) {
85961847f8eSopenharmony_ci        const matchDec = matchedDecs[i];
86061847f8eSopenharmony_ci        const apiSubscribeTypes = this.getSubscribeApiType(matchDec.parameters[0].type);
86161847f8eSopenharmony_ci        if (apiSubscribeTypes.has(useType)) {
86261847f8eSopenharmony_ci          apiNode = matchDec;
86361847f8eSopenharmony_ci        }
86461847f8eSopenharmony_ci      }
86561847f8eSopenharmony_ci    }
86661847f8eSopenharmony_ci
86761847f8eSopenharmony_ci    if (!apiNode) {
86861847f8eSopenharmony_ci      apiNode = matchedDecs[0];
86961847f8eSopenharmony_ci    }
87061847f8eSopenharmony_ci    return apiNode;
87161847f8eSopenharmony_ci  }
87261847f8eSopenharmony_ci
87361847f8eSopenharmony_ci  getSubscribeApiType(typeNode) {
87461847f8eSopenharmony_ci    const literalTypeSet = new Set();
87561847f8eSopenharmony_ci    if (ts.isLiteralTypeNode(typeNode)) {
87661847f8eSopenharmony_ci      literalTypeSet.add(typeNode.literal.text);
87761847f8eSopenharmony_ci    } else if (ts.isUnionTypeNode(typeNode)) {
87861847f8eSopenharmony_ci      typeNode.types.forEach(type => {
87961847f8eSopenharmony_ci        literalTypeSet.add(type.literal.text);
88061847f8eSopenharmony_ci      });
88161847f8eSopenharmony_ci    }
88261847f8eSopenharmony_ci    return literalTypeSet;
88361847f8eSopenharmony_ci  }
88461847f8eSopenharmony_ci
88561847f8eSopenharmony_ci  isAsyncCallbackCallExp(node) {
88661847f8eSopenharmony_ci    const type = this.typeChecker.getTypeAtLocation(node);
88761847f8eSopenharmony_ci    if (!type || !type.symbol || !type.symbol.valueDeclaration) {
88861847f8eSopenharmony_ci      return false;
88961847f8eSopenharmony_ci    }
89061847f8eSopenharmony_ci    const typeValueDec = type.symbol.valueDeclaration;
89161847f8eSopenharmony_ci    return ts.isArrowFunction(typeValueDec) || ts.isMethodDeclaration(typeValueDec) ||
89261847f8eSopenharmony_ci      ts.isFunctionDeclaration(typeValueDec) || ts.isMethodSignature(typeValueDec) ||
89361847f8eSopenharmony_ci      ts.isFunctionExpression(typeValueDec);
89461847f8eSopenharmony_ci  }
89561847f8eSopenharmony_ci
89661847f8eSopenharmony_ci  isAsyncCallbackApi(declaration) {
89761847f8eSopenharmony_ci    if (!declaration.parameters) {
89861847f8eSopenharmony_ci      return false;
89961847f8eSopenharmony_ci    }
90061847f8eSopenharmony_ci    const lastArgument = declaration.parameters[declaration.parameters.length - 1];
90161847f8eSopenharmony_ci    const argumentType = this.typeChecker.getTypeAtLocation(lastArgument);
90261847f8eSopenharmony_ci    if (argumentType && argumentType.symbol) {
90361847f8eSopenharmony_ci      return argumentType.symbol.escapedName === 'AsyncCallback';
90461847f8eSopenharmony_ci    } else {
90561847f8eSopenharmony_ci      if (!lastArgument.type || !lastArgument.type.typeName) {
90661847f8eSopenharmony_ci        return false;
90761847f8eSopenharmony_ci      }
90861847f8eSopenharmony_ci      return 'AsyncCallback' === lastArgument.type.typeName.getText();
90961847f8eSopenharmony_ci    }
91061847f8eSopenharmony_ci  }
91161847f8eSopenharmony_ci
91261847f8eSopenharmony_ci  getSdkApiFromValueDeclaration(valudeDec) {
91361847f8eSopenharmony_ci    const sourceFile = valudeDec.getSourceFile();
91461847f8eSopenharmony_ci    const apiInfo = new ApiDeclarationInformation();
91561847f8eSopenharmony_ci    const dtsPath = sourceFile.fileName.replace(this.systemRoot.replace(/\\/g, '/'), '');
91661847f8eSopenharmony_ci    apiInfo.setPropertyName(this.getMethodOrTypeName(valudeDec));
91761847f8eSopenharmony_ci    apiInfo.setApiRawText(this.getApiRawText(valudeDec));
91861847f8eSopenharmony_ci    apiInfo.setPackageName(this.getPackageName(sourceFile.fileName));
91961847f8eSopenharmony_ci    apiInfo.setSdkFileName(path.basename(sourceFile.fileName));
92061847f8eSopenharmony_ci    apiInfo.setTypeName(this.getApiTypeName(valudeDec));
92161847f8eSopenharmony_ci    apiInfo.setApiNode(valudeDec);
92261847f8eSopenharmony_ci    apiInfo.setApiType(this.getApiType(valudeDec));
92361847f8eSopenharmony_ci    apiInfo.setDtsPath(this.formatDtsPath(dtsPath));
92461847f8eSopenharmony_ci    apiInfo.setCompletedText(this.getApiText(valudeDec));
92561847f8eSopenharmony_ci
92661847f8eSopenharmony_ci    if (ts.isSourceFile(valudeDec.parent) && ts.isFunctionDeclaration(valudeDec)) {
92761847f8eSopenharmony_ci      apiInfo.setQualifiedTypeName('global');
92861847f8eSopenharmony_ci    }
92961847f8eSopenharmony_ci
93061847f8eSopenharmony_ci    let curDeclaration = valudeDec.parent;
93161847f8eSopenharmony_ci    while (!ts.isSourceFile(curDeclaration)) {
93261847f8eSopenharmony_ci      const nodeName = this.getMethodOrTypeName(curDeclaration);
93361847f8eSopenharmony_ci      if (nodeName) {
93461847f8eSopenharmony_ci        apiInfo.setTypeName(nodeName);
93561847f8eSopenharmony_ci        apiInfo.setQualifiedTypeName(nodeName);
93661847f8eSopenharmony_ci      }
93761847f8eSopenharmony_ci      curDeclaration = curDeclaration.parent;
93861847f8eSopenharmony_ci    }
93961847f8eSopenharmony_ci
94061847f8eSopenharmony_ci    const qualifiedName = apiInfo.qualifiedTypeName ?
94161847f8eSopenharmony_ci      `${apiInfo.qualifiedTypeName}.${apiInfo.propertyName}` : `${apiInfo.propertyName}`;
94261847f8eSopenharmony_ci    apiInfo.setQualifiedName(qualifiedName);
94361847f8eSopenharmony_ci    return this.fillJSDocInformation(apiInfo, valudeDec);
94461847f8eSopenharmony_ci  }
94561847f8eSopenharmony_ci
94661847f8eSopenharmony_ci  getApiType(valudeDec) {
94761847f8eSopenharmony_ci    let type = apiType.get(valudeDec.kind);
94861847f8eSopenharmony_ci    if (ts.isPropertySignature(valudeDec) && valudeDec.type && ts.isFunctionTypeNode(valudeDec.type)) {
94961847f8eSopenharmony_ci      type = 'method';
95061847f8eSopenharmony_ci    }
95161847f8eSopenharmony_ci    return type;
95261847f8eSopenharmony_ci  }
95361847f8eSopenharmony_ci
95461847f8eSopenharmony_ci  getApiText(node) {
95561847f8eSopenharmony_ci    switch (node.kind) {
95661847f8eSopenharmony_ci      case ts.SyntaxKind.ClassDeclaration:
95761847f8eSopenharmony_ci        return node.getText().split('{')[0];
95861847f8eSopenharmony_ci      case ts.SyntaxKind.InterfaceDeclaration:
95961847f8eSopenharmony_ci        return node.getText().split('{')[0];
96061847f8eSopenharmony_ci      case ts.SyntaxKind.EnumDeclaration:
96161847f8eSopenharmony_ci        return node.getText().split('{')[0];
96261847f8eSopenharmony_ci      case ts.SyntaxKind.ModuleDeclaration:
96361847f8eSopenharmony_ci        return node.getText().split('{')[0];
96461847f8eSopenharmony_ci      case ts.SyntaxKind.StructDeclaration:
96561847f8eSopenharmony_ci        return node.getText().split('{')[0];
96661847f8eSopenharmony_ci      default:
96761847f8eSopenharmony_ci        return node.getText();
96861847f8eSopenharmony_ci    }
96961847f8eSopenharmony_ci  }
97061847f8eSopenharmony_ci
97161847f8eSopenharmony_ci  /**
97261847f8eSopenharmony_ci   * 补充JsDoc中的信息。
97361847f8eSopenharmony_ci   *
97461847f8eSopenharmony_ci   * @param {ApiDeclarationInformation} apiInfo
97561847f8eSopenharmony_ci   * @param {ts.Node} node
97661847f8eSopenharmony_ci   * @returns
97761847f8eSopenharmony_ci   */
97861847f8eSopenharmony_ci  fillJSDocInformation(apiInfo, node) {
97961847f8eSopenharmony_ci    this.forEachJsDocTags(node, (tag) => {
98061847f8eSopenharmony_ci      (this.fillDeprecatedInfo(tag, apiInfo) || this.fillUseInsteadInfo(tag, apiInfo));
98161847f8eSopenharmony_ci    });
98261847f8eSopenharmony_ci    if (!apiInfo.deprecated) {
98361847f8eSopenharmony_ci      const thiz = this;
98461847f8eSopenharmony_ci      function reachJsDocTag(tag) {
98561847f8eSopenharmony_ci        thiz.fillDeprecatedInfo(tag, apiInfo);
98661847f8eSopenharmony_ci        return apiInfo.deprecated;
98761847f8eSopenharmony_ci      }
98861847f8eSopenharmony_ci
98961847f8eSopenharmony_ci      function reachParent(parent) {
99061847f8eSopenharmony_ci        thiz.forEachJsDocTags(parent, reachJsDocTag);
99161847f8eSopenharmony_ci        return apiInfo.deprecated;
99261847f8eSopenharmony_ci      }
99361847f8eSopenharmony_ci      this.forEachNodeParent(node, reachParent);
99461847f8eSopenharmony_ci    }
99561847f8eSopenharmony_ci    return apiInfo;
99661847f8eSopenharmony_ci  }
99761847f8eSopenharmony_ci
99861847f8eSopenharmony_ci  fillUseInsteadInfo(tag, apiInfo) {
99961847f8eSopenharmony_ci    if (tag.kind === ts.SyntaxKind.JSDocTag &&
100061847f8eSopenharmony_ci      tag.tagName.getText() === 'useinstead') {
100161847f8eSopenharmony_ci      apiInfo.setUseInstead(tag.comment);
100261847f8eSopenharmony_ci      return true;
100361847f8eSopenharmony_ci    }
100461847f8eSopenharmony_ci    return false;
100561847f8eSopenharmony_ci  }
100661847f8eSopenharmony_ci
100761847f8eSopenharmony_ci  fillDeprecatedInfo(tag, apiInfo) {
100861847f8eSopenharmony_ci    if (tag.kind === ts.SyntaxKind.JSDocDeprecatedTag) {
100961847f8eSopenharmony_ci      apiInfo.setDeprecated(tag.comment);
101061847f8eSopenharmony_ci      return true;
101161847f8eSopenharmony_ci    }
101261847f8eSopenharmony_ci    return false;
101361847f8eSopenharmony_ci  }
101461847f8eSopenharmony_ci
101561847f8eSopenharmony_ci  forEachJsDocTags(node, callback) {
101661847f8eSopenharmony_ci    if (!node.jsDoc || !callback) {
101761847f8eSopenharmony_ci      return;
101861847f8eSopenharmony_ci    }
101961847f8eSopenharmony_ci    const latestJsDoc = node.jsDoc[node.jsDoc.length - 1];
102061847f8eSopenharmony_ci    if (!latestJsDoc.tags) {
102161847f8eSopenharmony_ci      return;
102261847f8eSopenharmony_ci    }
102361847f8eSopenharmony_ci    for (const tag of latestJsDoc.tags) {
102461847f8eSopenharmony_ci      if (callback(tag)) {
102561847f8eSopenharmony_ci        break;
102661847f8eSopenharmony_ci      };
102761847f8eSopenharmony_ci    };
102861847f8eSopenharmony_ci  }
102961847f8eSopenharmony_ci
103061847f8eSopenharmony_ci  forEachNodeParent(node, callback) {
103161847f8eSopenharmony_ci    if (!node || !callback) {
103261847f8eSopenharmony_ci      return;
103361847f8eSopenharmony_ci    }
103461847f8eSopenharmony_ci    let curNode = node.parent;
103561847f8eSopenharmony_ci    while (curNode) {
103661847f8eSopenharmony_ci      if (callback(curNode)) {
103761847f8eSopenharmony_ci        break;
103861847f8eSopenharmony_ci      }
103961847f8eSopenharmony_ci      curNode = curNode.parent;
104061847f8eSopenharmony_ci    }
104161847f8eSopenharmony_ci  }
104261847f8eSopenharmony_ci
104361847f8eSopenharmony_ci  getMethodOrTypeName(node) {
104461847f8eSopenharmony_ci    return node.name ? node.name.getText() : undefined;
104561847f8eSopenharmony_ci  }
104661847f8eSopenharmony_ci
104761847f8eSopenharmony_ci  getPackageName(filePath) {
104861847f8eSopenharmony_ci    const isArkUI = FileSystem.isInDirectory(path.resolve(this.systemRoot, 'component'), filePath);
104961847f8eSopenharmony_ci    return isArkUI ? 'ArkUI' : path.relative(this.systemRoot, filePath);
105061847f8eSopenharmony_ci  }
105161847f8eSopenharmony_ci}
105261847f8eSopenharmony_ci
105361847f8eSopenharmony_ciconst apiType = new Map([
105461847f8eSopenharmony_ci  [ts.SyntaxKind.FunctionDeclaration, 'method'],
105561847f8eSopenharmony_ci  [ts.SyntaxKind.MethodSignature, 'method'],
105661847f8eSopenharmony_ci  [ts.SyntaxKind.MethodDeclaration, 'method'],
105761847f8eSopenharmony_ci  [ts.SyntaxKind.EnumMember, 'enum_instance'],
105861847f8eSopenharmony_ci  [ts.SyntaxKind.PropertySignature, 'field'],
105961847f8eSopenharmony_ci  [ts.SyntaxKind.VariableStatement, 'constant'],
106061847f8eSopenharmony_ci  [ts.SyntaxKind.VariableDeclaration, 'constant'],
106161847f8eSopenharmony_ci  [ts.SyntaxKind.VariableDeclarationList, 'constant'],
106261847f8eSopenharmony_ci  [ts.SyntaxKind.TypeAliasDeclaration, 'type'],
106361847f8eSopenharmony_ci  [ts.SyntaxKind.ClassDeclaration, 'class'],
106461847f8eSopenharmony_ci  [ts.SyntaxKind.InterfaceDeclaration, 'interface'],
106561847f8eSopenharmony_ci  [ts.SyntaxKind.EnumDeclaration, 'enum_class'],
106661847f8eSopenharmony_ci  [ts.SyntaxKind.PropertyDeclaration, 'field']
106761847f8eSopenharmony_ci]);
106861847f8eSopenharmony_ci
106961847f8eSopenharmony_ciclass ComponentAttrResult {
107061847f8eSopenharmony_ci  constructor(componentInfo, attrInfo) {
107161847f8eSopenharmony_ci    this.componentInfo = componentInfo;
107261847f8eSopenharmony_ci    this.attrInfo = attrInfo;
107361847f8eSopenharmony_ci  }
107461847f8eSopenharmony_ci}
107561847f8eSopenharmony_ci
107661847f8eSopenharmony_ciclass ApiDeclarationInformation {
107761847f8eSopenharmony_ci  constructor() {
107861847f8eSopenharmony_ci    this.dtsName = '';
107961847f8eSopenharmony_ci    this.packageName = '';
108061847f8eSopenharmony_ci    this.propertyName = '';
108161847f8eSopenharmony_ci    this.qualifiedTypeName = '';
108261847f8eSopenharmony_ci    this.pos = '';
108361847f8eSopenharmony_ci    this.sourceFileName = '';
108461847f8eSopenharmony_ci    this.deprecated = '';
108561847f8eSopenharmony_ci    this.apiRawText = '';
108661847f8eSopenharmony_ci    this.qualifiedName = '';
108761847f8eSopenharmony_ci    this.useInstead = '';
108861847f8eSopenharmony_ci    this.typeName = '';
108961847f8eSopenharmony_ci  }
109061847f8eSopenharmony_ci
109161847f8eSopenharmony_ci  setSdkFileName(fileName) {
109261847f8eSopenharmony_ci    this.dtsName = fileName;
109361847f8eSopenharmony_ci  }
109461847f8eSopenharmony_ci
109561847f8eSopenharmony_ci  setPackageName(packageName) {
109661847f8eSopenharmony_ci    this.packageName = packageName;
109761847f8eSopenharmony_ci  }
109861847f8eSopenharmony_ci
109961847f8eSopenharmony_ci  setPropertyName(propertyName) {
110061847f8eSopenharmony_ci    this.propertyName = propertyName;
110161847f8eSopenharmony_ci  }
110261847f8eSopenharmony_ci
110361847f8eSopenharmony_ci  setQualifiedTypeName(typeName) {
110461847f8eSopenharmony_ci    if (!this.qualifiedTypeName) {
110561847f8eSopenharmony_ci      this.qualifiedTypeName = typeName;
110661847f8eSopenharmony_ci    } else {
110761847f8eSopenharmony_ci      this.qualifiedTypeName = `${typeName}.${this.qualifiedTypeName}`;
110861847f8eSopenharmony_ci    }
110961847f8eSopenharmony_ci  }
111061847f8eSopenharmony_ci
111161847f8eSopenharmony_ci  setTypeName(typeName) {
111261847f8eSopenharmony_ci    if (typeName && (!this.typeName || this.typeName === '')) {
111361847f8eSopenharmony_ci      this.typeName = typeName;
111461847f8eSopenharmony_ci    }
111561847f8eSopenharmony_ci  }
111661847f8eSopenharmony_ci
111761847f8eSopenharmony_ci  setPosition(pos) {
111861847f8eSopenharmony_ci    const { line, character } = pos;
111961847f8eSopenharmony_ci    this.pos = `${line + 1},${character + 1}`;
112061847f8eSopenharmony_ci  }
112161847f8eSopenharmony_ci
112261847f8eSopenharmony_ci  setSourceFileName(sourceFileName) {
112361847f8eSopenharmony_ci    this.sourceFileName = sourceFileName;
112461847f8eSopenharmony_ci  }
112561847f8eSopenharmony_ci
112661847f8eSopenharmony_ci  /**
112761847f8eSopenharmony_ci   * 设置废弃版本号
112861847f8eSopenharmony_ci   *
112961847f8eSopenharmony_ci   * @param {string} deprecated
113061847f8eSopenharmony_ci   */
113161847f8eSopenharmony_ci  setDeprecated(deprecated) {
113261847f8eSopenharmony_ci    const regExpResult = deprecated.match(/\s*since\s*(\d)+.*/);
113361847f8eSopenharmony_ci    const RESULT_LENGTH = 2;
113461847f8eSopenharmony_ci    if (regExpResult !== null && regExpResult.length === RESULT_LENGTH) {
113561847f8eSopenharmony_ci      this.deprecated = regExpResult[1];
113661847f8eSopenharmony_ci    }
113761847f8eSopenharmony_ci  }
113861847f8eSopenharmony_ci
113961847f8eSopenharmony_ci  setApiRawText(apiRawText) {
114061847f8eSopenharmony_ci    this.apiRawText = apiRawText.replace(/\;/g, '');
114161847f8eSopenharmony_ci  }
114261847f8eSopenharmony_ci
114361847f8eSopenharmony_ci  setQualifiedName(qualifiedName) {
114461847f8eSopenharmony_ci    this.qualifiedName = qualifiedName;
114561847f8eSopenharmony_ci  }
114661847f8eSopenharmony_ci
114761847f8eSopenharmony_ci  setUseInstead(useInstead) {
114861847f8eSopenharmony_ci    this.useInstead = useInstead;
114961847f8eSopenharmony_ci  }
115061847f8eSopenharmony_ci
115161847f8eSopenharmony_ci  setComponentName(componentName) {
115261847f8eSopenharmony_ci    this.componentName = componentName;
115361847f8eSopenharmony_ci  }
115461847f8eSopenharmony_ci
115561847f8eSopenharmony_ci  setApiNode(node) {
115661847f8eSopenharmony_ci    this.apiNode = node;
115761847f8eSopenharmony_ci  }
115861847f8eSopenharmony_ci
115961847f8eSopenharmony_ci  setApiType(apiType) {
116061847f8eSopenharmony_ci    this.apiType = apiType;
116161847f8eSopenharmony_ci  }
116261847f8eSopenharmony_ci
116361847f8eSopenharmony_ci  setDtsPath(dtsPath) {
116461847f8eSopenharmony_ci    this.dtsPath = dtsPath;
116561847f8eSopenharmony_ci  }
116661847f8eSopenharmony_ci
116761847f8eSopenharmony_ci  setCompletedText(completedText) {
116861847f8eSopenharmony_ci    this.apiText = completedText;
116961847f8eSopenharmony_ci  }
117061847f8eSopenharmony_ci}
117161847f8eSopenharmony_ci
117261847f8eSopenharmony_ciexports.SystemApiRecognizer = SystemApiRecognizer;