Mmicroli添加注释
3b26ccbd创建于 2025年4月17日历史提交
/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const ts = require('typescript');

/**
 * 添加API信息到 apiMap
 * 
 * @param {Map} apiMap 
 * @param {ApiDigestInfo} apiDigestInfo 
 */
function addApiDigestInfo(apiMap, apiDigestInfo) {
  addApiInfo(apiMap, apiDigestInfo.getPackageName(),
    apiDigestInfo.getClassName(), apiDigestInfo.getApiName(),
    apiDigestInfo.getApiSignature(), apiDigestInfo);
}

/**
 * 将API摘要信息如以下数据格式保存 
 * @example
 * { packageName : Map }
 *                  |
 *      { className : { type: ApiDigestInfo, children: Map } }
 *                                                      |
 *                                             { apiName : Map }
 *                                                          |
 *                                                { signature : ApiDigestInfo[] }
 * 
 * @param {Map} apiMap API 摘要集合
 * @param {string} packageName 包名
 * @param {string} className 类型名
 * @param {string} apiSignature api节点签名
 * @param {ApiDigestInfo} api api摘要信息
 */
function addApiInfo(apiMap, packageName, className, apiName, apiSignature, api) {
  let dtsMap = apiMap.get(packageName);
  // 集合中没有该文件数据
  if (!dtsMap) {
    dtsMap = new Map();
    apiMap.set(packageName, dtsMap);
  }
  // 类数据
  let classApi = dtsMap.get(className);
  if (!classApi) {
    classApi = {
      children: new Map(),
    };
    dtsMap.set(className, classApi);
  }

  if (isTypeDeclaration(api) && !classApi.type) {
    classApi.type = api;
    return;
  }

  // api 映射表
  let apiNameMap = classApi.children.get(apiName);
  if (!apiNameMap) {
    apiNameMap = new Map();
    classApi.children.set(apiName, apiNameMap);
  }

  let apiArray = apiNameMap.get(apiSignature);
  if (!apiArray) {
    apiArray = [];
    apiNameMap.set(apiSignature, apiArray);
  }
  apiArray.push(api);
}

function isTypeDeclaration(api) {
  const types = [ApiType.ClassType.code, ApiType.InterfaceType.code, ApiType.EnumType.code, ApiType.NamespaceType.code, ApiType.SourceFile.code];
  return types.includes(api.getApiType().code);
}

/**
 * 获取AST节点的签名信息, 它由所有子节点非空字符串拼接而成,具有唯一性。
 * 类型的签名由 包名+类型名来确认唯一性。
 * 
 * @param {ts.Node} astNode 
 * @param {string} packageName 
 * @param {string} className 
 * @returns {string}
 */
function getNodeSignature(astNode, packageName, className) {
  if (ts.isInterfaceDeclaration(astNode) || ts.isClassDeclaration(astNode) ||
    ts.isModuleDeclaration(astNode) || ts.isEnumDeclaration(astNode) || ts.isSourceFile(astNode)) {
    return `${packageName}#${className}`;
  }
  let signature = '';
  if (astNode.getChildCount() > 0) {
    astNode.forEachChild((childNode) => {
      signature += `#${getNodeSignature(childNode)}`;
    });
  } else {
    signature = ts.isIdentifier(astNode) ? astNode.text.replace(/\'|\"/g, '') : astNode.getText().replace(/\'|\"/g, '');
  }
  return signature;
}

class ApiDigestInfo {
  constructor() {
  }

  /**
   * 设置包名,包名为d.ts文件与SDK根目录的相对路径
   * 
   * @param {string} packageName 
   * @returns {Object}
   */
  setPackageName(packageName) {
    this.packageName = packageName;
    return this;
  }

  /**
   * 获取包名
   * @returns {string}
   */
  getPackageName() {
    return this.packageName;
  }

  /**
   * 类型名称,如 class, enum, interface, namespace 名字
   * 
   * @param {string} className 
   * @returns {Object}
   */
  setClassName(className) {
    this.className = className;
    return this;
  }

  /**
   * 获取classs Name
   * @returns {string|string|any|string}
   */
  getClassName() {
    if (this.className) {
      return this.className;
    }
    let parentInfo = this.parent;
    while (parentInfo) {
      if (!parentInfo.className) {
        parentInfo = parentInfo.parent;
      } else {
        return parentInfo.className;
      }
    }
    return '';
  }

  /**
   * API的类型,如方法,属性,枚举等
   * 
   * @param {ApiType} apiType 
   * @returns {Object}
   */
  setApiType(apiType) {
    this.apiType = apiType;
    return this;
  }

  getApiType() {
    return this.apiType;
  }

  /**
   * API原始的文本
   * 
   * @param {string} rawText 
   * @returns {Object}
   */
  setRawText(rawText) {
    this.rawText = rawText;
    return this;
  }

  /**
   * 获取原始文本
   * @returns {string}
   */
  getRawText() {
    return this.rawText;
  }

  /**
   * API所属的d.ts文件路径
   * 
   * @param {string} path 
   * @returns {Object}
   */
  setPath(path) {
    this.path = path;
    return this;
  }

  /**
   * 获取路径
   * @returns {string}
   */
  getPath() {
    return this.path;
  }



  /**
   * API AST节点对象
   * 
   * @param {ts.Node} node 
   * @returns {Object}
   */
  setAstNode(node) {
    this.node = node;
    return this;
  }

  /**
   * 获取node
   * @returns {collaborationEditObject.Node}
   */
  getAstNode() {
    return this.node;
  }

  /**
   * API的JSDoc信息
   * 
   * @param {Object} jsdoc 
   * @returns {Object}
   */
  setJSdoc(jsdoc) {
    this.jsdoc = jsdoc;
    return this;
  }

  /**
   * 设置tagItem
   * @param jsdocTagItem
   */
  setJSDocTagItem(jsdocTagItem) {
    this.jsdocTagItem = jsdocTagItem;
  }

  /**
   * 获取tagItem
   * @returns {*}
   */
  getJSDocTagItem() {
    return this.jsdocTagItem;
  }

  /**
   * AST节点的签名信息,可以确保在一个模块中的唯一性
   * 
   * @param {ts.Node} astNode 
   * @param {string} packageName 
   * @param {string} className 
   * @returns {Object}
   */
  setApiSignature(astNode, packageName, className) {
    this.signature = getNodeSignature(astNode, packageName, className);
    return this;
  }

  /**
   * 获取api签名
   * @returns {string}
   */
  getApiSignature() {
    return this.signature;
  }

  /**
   * 设置API Name
   * @param apiName
   * @returns {ApiDigestInfo}
   */
  setApiName(apiName) {
    this.apiName = apiName;
    return this;
  }

  /**
   * 获取API Name
   * @returns {*}
   */
  getApiName() {
    return this.apiName;
  }

  /**
   * API 父节点摘要信息,可以确认某个节点的空间位置。
   * 
   * @param {Object} digestInfo 
   * @returns {Object}
   */
  setParent(digestInfo) {
    this.parent = digestInfo;
    return this;
  }

  getParent() {
    return this.parent;
  }

  /**
   * 设置 syscap
   * @param syscap
   * @returns {ApiDigestInfo}
   */
  setSyscap(syscap) {
    this.syscap = syscap;
    return this;
  }
}

const ApiType = {
  EnumType: { name: '枚举', code: 0 },
  EnumMember: { name: '枚举成员', code: 1 },
  ClassType: { name: '类', code: 2 },
  ClassProperty: { name: '类属性', code: 3 },
  ClassMethod: { name: '类方法', code: 4 },
  InterfaceType: { name: '接口', code: 5 },
  InterfaceMethod: { name: '接口方法', code: 6 },
  InterfaceProperty: { name: '接口属性', code: 7 },
  ExportType: { name: '类型导出', code: 8 },
  FunctionType: { name: '方法', code: 9 },
  NamespaceType: { name: '命名空间', code: 10 },
  TypeAliasDeclaration: { name: '类型成员', code: 11 },
  Constructor: { name: '构造器', code: 12 },
  CallSignature: { name: '类方法', code: 13 },
  SourceFile: { name: 'sourfile', code: 14 }
};

exports.ApiDigestInfo = ApiDigestInfo;
exports.ApiType = ApiType;
exports.apiDataHelper = {
  addApiInfo: addApiInfo,
  addApiDigestInfo: addApiDigestInfo,
  getNodeSignature: getNodeSignature,
};