* 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;
}
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,
};