添加typereference节点解析结果

Signed-off-by: wangcaoyu <wangcaoyu@huawei.com>
This commit is contained in:
wangcaoyu 2024-04-19 11:25:24 +08:00
parent c385fc0a41
commit 02fa107aa8
5 changed files with 252 additions and 13 deletions

View File

@ -80,6 +80,12 @@ Note:If the text contains special characters, please escape them according to th
<filefilter name="copyrightPolicyFilter" desc="compatibilitylicense文件头校验策略的过滤条件" >
<filteritem type="filepath" name="build-tools/dts_parser/build_package/.*" desc="可执行脚本,无法添加版权头"/>
</filefilter>
<filefilter name="defaultPolicyFilter" desc="compatibilitylicense文件头校验策略的过滤条件" >
<filteritem type="filepath" name="build-tools/dts_parser/package/.*" desc="可执行脚本无法添加LICENSE头"/>
</filefilter>
<filefilter name="copyrightPolicyFilter" desc="compatibilitylicense文件头校验策略的过滤条件" >
<filteritem type="filepath" name="build-tools/dts_parser/package/.*" desc="可执行脚本,无法添加版权头"/>
</filefilter>
</filefilterlist>
</oatconfig>

File diff suppressed because one or more lines are too long

View File

@ -15,6 +15,7 @@
import ts from 'typescript';
import _ from 'lodash';
import path from 'path';
import {
ApiInfo,
@ -61,6 +62,13 @@ export class NodeProcessorHelper {
// 如果是字符串的话,会出现单双引号重复的情况
static regQuotation: RegExp = /^[\'|\"](.*)[\'|\"]$/;
/**
* typereference对应symbol集合
*
* @type {Map<string, Map<string, ts.Symbol>>}
*/
static symbolOfTypeReferenceMap: Map<string, Map<string, ts.Symbol>> = new Map<string, Map<string, ts.Symbol>>();
static processReference(
sourceFile: ts.SourceFile,
parentMap: Map<string, object>,
@ -99,6 +107,9 @@ export class NodeProcessorHelper {
return;
}
childNodes.forEach((cNode: ts.Node) => {
if (apiInfo.getApiType() === ApiType.STRUCT && cNode.getFullText() === '') { // 去除struct的默认构造方法
return;
}
NodeProcessorHelper.processNode(cNode, currentMap as ApiInfosMap, apiInfo);
});
}
@ -308,7 +319,7 @@ export class NodeProcessorHelper {
//export * from 'test';
exportDeclareInfo.setApiName(
StringConstant.EXPORT +
(exportDeclarationNode.moduleSpecifier ? exportDeclarationNode.moduleSpecifier.getText() : '')
(exportDeclarationNode.moduleSpecifier ? exportDeclarationNode.moduleSpecifier.getText() : '')
);
} else if (ts.isNamespaceExport(exportClause)) {
//export * as myTest from 'test';
@ -618,7 +629,7 @@ export class NodeProcessorHelper {
methodInfo.setReturnValue(returnValues);
methodInfo.setReturnValueType(methodNode.type.kind);
if (Boolean(process.env.NEED_DETECTION)) {
NodeProcessorHelper.processFunctionTypeReference(
NodeProcessorHelper.processFunctionTypeNode(
methodNode.type,
methodInfo,
new ParamInfo(ApiType.PARAM),
@ -655,7 +666,7 @@ export class NodeProcessorHelper {
}
let typeMapValue: string | undefined = undefined;
if (Boolean(process.env.NEED_DETECTION)) {
NodeProcessorHelper.processFunctionTypeReference(param.type, methodInfo, paramInfo, true);
NodeProcessorHelper.processFunctionTypeNode(param.type, methodInfo, paramInfo, true);
}
if (ts.isLiteralTypeNode(param.type)) {
typeMapValue = typeMap.get(param.type.literal.kind);
@ -664,6 +675,61 @@ export class NodeProcessorHelper {
return paramInfo;
}
/**
* node节点获取当前文件名称
*
* @param {ts.Node} node
* @return {string}
*/
static getFilePathFromNode(node: ts.Node): string {
if (ts.isSourceFile(node)) {
return node.fileName;
} else {
return NodeProcessorHelper.getFilePathFromNode(node.parent);
}
}
/**
* SymbolOfTypeReferenceMap对象
*
* @param {string} filePath
* @param {ts.TypeReferenceNode} tsNode typeReference
* @param {ts.Symbol} symbol typereference对应symbol
*/
static setSymbolOfTypeReferenceMap(filePath: string, tsNode: ts.TypeReferenceNode, symbol: ts.Symbol): void {
if (!NodeProcessorHelper.symbolOfTypeReferenceMap.has(filePath)) {
NodeProcessorHelper.symbolOfTypeReferenceMap.set(filePath, new Map<string, ts.Symbol>());
}
const typeSymbolMap: Map<string, ts.Symbol> | undefined =
NodeProcessorHelper.symbolOfTypeReferenceMap.get(filePath);
if (!typeSymbolMap) {
return;
}
if (!typeSymbolMap.has(tsNode.getFullText().trim())) {
typeSymbolMap.set(tsNode.getFullText().trim(), symbol);
}
}
/**
* symbolOfTypeReferenceMap获取值
*
* @param {string} filePath
* @param {ts.TypeReferenceNode} tsNode typeReference
* @return {(ts.Symbol | undefined)} symbol值
*/
static getSymbolOfTypeReferenceMap(filePath: string, tsNode: ts.TypeReferenceNode): ts.Symbol | undefined {
const fileSymbolMap: Map<string, ts.Symbol> | undefined =
NodeProcessorHelper.symbolOfTypeReferenceMap.get(filePath);
if (!fileSymbolMap) {
return;
}
const typeSymbol: ts.Symbol | undefined = fileSymbolMap.get(tsNode.getFullText().trim())
if (!typeSymbol) {
return;
}
return typeSymbol;
}
/**
*
* jsdoc
@ -676,7 +742,7 @@ export class NodeProcessorHelper {
* true
* false
*/
static processFunctionTypeReference(
static processFunctionTypeNode(
typeNode: ts.TypeNode,
methodInfo: MethodInfo,
paramInfo: ParamInfo,
@ -686,17 +752,61 @@ export class NodeProcessorHelper {
NodeProcessorHelper.processFunctionTypeObject(typeNode, methodInfo, paramInfo, isParam);
} else if (ts.isUnionTypeNode(typeNode)) {
typeNode.types.forEach((type: ts.TypeNode) => {
NodeProcessorHelper.processFunctionTypeReference(type, methodInfo, paramInfo, isParam);
NodeProcessorHelper.processFunctionTypeNode(type, methodInfo, paramInfo, isParam);
});
} else if (ts.isFunctionTypeNode(typeNode)) {
typeNode.parameters.forEach((parameter: ts.ParameterDeclaration) => {
if (parameter.type) {
NodeProcessorHelper.processFunctionTypeNode(parameter.type, methodInfo, paramInfo, isParam);
}
})
NodeProcessorHelper.processFunctionTypeNode(typeNode.type, methodInfo, paramInfo, isParam);
}
if (!ts.isTypeReferenceNode(typeNode)) {
return;
}
NodeProcessorHelper.processFunctionTypeReference(typeNode, methodInfo, paramInfo, isParam);
}
/**
*
*
* @param { ts.TypeNode } typeNode
* @param { MethodInfo } methodInfo MethodInfo对象
* @param { ParamInfo } paramInfo ParamInfo对象
* @param { boolean } [isParam = true] type
* true
* false
*/
static processFunctionTypeReference(
typeNode: ts.TypeReferenceNode,
methodInfo: MethodInfo,
paramInfo: ParamInfo,
isParam: boolean = true
): void {
const typeArguments: ts.NodeArray<ts.TypeNode> | undefined = typeNode.typeArguments;
typeArguments?.forEach((typeArgument: ts.TypeNode) => {
NodeProcessorHelper.processFunctionTypeNode(typeArgument, methodInfo, paramInfo, isParam);
})
try {
const tsProgram: ts.Program = parserParam.getTsProgram();
const typeChecker: ts.TypeChecker = tsProgram.getTypeChecker();
const nodeType: ts.Type = typeChecker.getTypeAtLocation(typeNode);
const declarations: ts.Declaration[] | undefined = nodeType.symbol.declarations;
const filePath: string = parserParam.getFilePath();
Object.assign(tsProgram, {
getSymbolOfTypeReference: (tsNode: ts.TypeReferenceNode, symbol: ts.Symbol) => {
const currentFilePath: string = NodeProcessorHelper.getFilePathFromNode(tsNode);
if (path.resolve(currentFilePath) !== path.resolve(filePath)) {
return;
}
NodeProcessorHelper.setSymbolOfTypeReferenceMap(filePath, tsNode, symbol);
}
})
tsProgram.emit();
const currentTypeSymbol: ts.Symbol | undefined =
NodeProcessorHelper.getSymbolOfTypeReferenceMap(filePath, typeNode);
if (!currentTypeSymbol) {
return;
}
const declarations: ts.Declaration[] | undefined = currentTypeSymbol.declarations;
if (!declarations) {
return;
}
@ -722,6 +832,7 @@ export class NodeProcessorHelper {
} finally {
}
}
/**
*
* doc存储
@ -757,6 +868,9 @@ export class NodeProcessorHelper {
} else {
methodInfo.addObjLocations(jsDoc);
}
if (ts.isPropertySignature(member) && member.type) {
NodeProcessorHelper.processFunctionTypeNode(member.type, methodInfo, paramInfo, isParam);
}
});
}

View File

@ -92,7 +92,7 @@ export class Parser {
}
});
if (Boolean(process.env.NEED_DETECTION)) {
parserParam.setProgram(fileArr);
parserParam.setProgram([fileDir]);
}
const sourceFileInfo: ApiInfo = new ApiInfo(ApiType.SOURCE_FILE, sourceFile, undefined);
sourceFileInfo.setFilePath(relFilePath);

View File

@ -231,7 +231,7 @@ export class BasicApiInfo {
}
}
export class ExportDefaultInfo extends BasicApiInfo {}
export class ExportDefaultInfo extends BasicApiInfo { }
export class ReferenceInfo extends BasicApiInfo {
pathName: string = '';
@ -818,7 +818,7 @@ export class ParserParam {
rootNames: [],
options: {},
});
constructor() {}
constructor() { }
getFileDir(): string {
return this.fileDir;
@ -864,16 +864,18 @@ export class ParserParam {
}
setProgram(apiLibs: Array<string>): void {
const compilerOption = {
const compilerOption: ts.CompilerOptions = {
target: ts.ScriptTarget.ES2017,
ets: this.getETSOptions([]),
allowJs: false,
lib: [...apiLibs, ...this.rootNames],
module: ts.ModuleKind.CommonJS,
};
const compilerHost: ts.CompilerHost = ts.createCompilerHost(compilerOption);
this.tsProgram = ts.createProgram({
rootNames: [...apiLibs, ...this.rootNames],
rootNames: [...apiLibs],
options: compilerOption,
host: compilerHost
});
}
}