添加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文件头校验策略的过滤条件" > <filefilter name="copyrightPolicyFilter" desc="compatibilitylicense文件头校验策略的过滤条件" >
<filteritem type="filepath" name="build-tools/dts_parser/build_package/.*" desc="可执行脚本,无法添加版权头"/> <filteritem type="filepath" name="build-tools/dts_parser/build_package/.*" desc="可执行脚本,无法添加版权头"/>
</filefilter> </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> </filefilterlist>
</oatconfig> </oatconfig>

File diff suppressed because one or more lines are too long

View File

@ -15,6 +15,7 @@
import ts from 'typescript'; import ts from 'typescript';
import _ from 'lodash'; import _ from 'lodash';
import path from 'path';
import { import {
ApiInfo, ApiInfo,
@ -61,6 +62,13 @@ export class NodeProcessorHelper {
// 如果是字符串的话,会出现单双引号重复的情况 // 如果是字符串的话,会出现单双引号重复的情况
static regQuotation: RegExp = /^[\'|\"](.*)[\'|\"]$/; 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( static processReference(
sourceFile: ts.SourceFile, sourceFile: ts.SourceFile,
parentMap: Map<string, object>, parentMap: Map<string, object>,
@ -99,6 +107,9 @@ export class NodeProcessorHelper {
return; return;
} }
childNodes.forEach((cNode: ts.Node) => { childNodes.forEach((cNode: ts.Node) => {
if (apiInfo.getApiType() === ApiType.STRUCT && cNode.getFullText() === '') { // 去除struct的默认构造方法
return;
}
NodeProcessorHelper.processNode(cNode, currentMap as ApiInfosMap, apiInfo); NodeProcessorHelper.processNode(cNode, currentMap as ApiInfosMap, apiInfo);
}); });
} }
@ -618,7 +629,7 @@ export class NodeProcessorHelper {
methodInfo.setReturnValue(returnValues); methodInfo.setReturnValue(returnValues);
methodInfo.setReturnValueType(methodNode.type.kind); methodInfo.setReturnValueType(methodNode.type.kind);
if (Boolean(process.env.NEED_DETECTION)) { if (Boolean(process.env.NEED_DETECTION)) {
NodeProcessorHelper.processFunctionTypeReference( NodeProcessorHelper.processFunctionTypeNode(
methodNode.type, methodNode.type,
methodInfo, methodInfo,
new ParamInfo(ApiType.PARAM), new ParamInfo(ApiType.PARAM),
@ -655,7 +666,7 @@ export class NodeProcessorHelper {
} }
let typeMapValue: string | undefined = undefined; let typeMapValue: string | undefined = undefined;
if (Boolean(process.env.NEED_DETECTION)) { 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)) { if (ts.isLiteralTypeNode(param.type)) {
typeMapValue = typeMap.get(param.type.literal.kind); typeMapValue = typeMap.get(param.type.literal.kind);
@ -664,6 +675,61 @@ export class NodeProcessorHelper {
return paramInfo; 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 * jsdoc
@ -676,7 +742,7 @@ export class NodeProcessorHelper {
* true * true
* false * false
*/ */
static processFunctionTypeReference( static processFunctionTypeNode(
typeNode: ts.TypeNode, typeNode: ts.TypeNode,
methodInfo: MethodInfo, methodInfo: MethodInfo,
paramInfo: ParamInfo, paramInfo: ParamInfo,
@ -686,17 +752,61 @@ export class NodeProcessorHelper {
NodeProcessorHelper.processFunctionTypeObject(typeNode, methodInfo, paramInfo, isParam); NodeProcessorHelper.processFunctionTypeObject(typeNode, methodInfo, paramInfo, isParam);
} else if (ts.isUnionTypeNode(typeNode)) { } else if (ts.isUnionTypeNode(typeNode)) {
typeNode.types.forEach((type: ts.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)) { if (!ts.isTypeReferenceNode(typeNode)) {
return; 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 { try {
const tsProgram: ts.Program = parserParam.getTsProgram(); const tsProgram: ts.Program = parserParam.getTsProgram();
const typeChecker: ts.TypeChecker = tsProgram.getTypeChecker(); const filePath: string = parserParam.getFilePath();
const nodeType: ts.Type = typeChecker.getTypeAtLocation(typeNode); Object.assign(tsProgram, {
const declarations: ts.Declaration[] | undefined = nodeType.symbol.declarations; 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) { if (!declarations) {
return; return;
} }
@ -722,6 +832,7 @@ export class NodeProcessorHelper {
} finally { } finally {
} }
} }
/** /**
* *
* doc存储 * doc存储
@ -757,6 +868,9 @@ export class NodeProcessorHelper {
} else { } else {
methodInfo.addObjLocations(jsDoc); 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)) { if (Boolean(process.env.NEED_DETECTION)) {
parserParam.setProgram(fileArr); parserParam.setProgram([fileDir]);
} }
const sourceFileInfo: ApiInfo = new ApiInfo(ApiType.SOURCE_FILE, sourceFile, undefined); const sourceFileInfo: ApiInfo = new ApiInfo(ApiType.SOURCE_FILE, sourceFile, undefined);
sourceFileInfo.setFilePath(relFilePath); 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 { export class ReferenceInfo extends BasicApiInfo {
pathName: string = ''; pathName: string = '';
@ -818,7 +818,7 @@ export class ParserParam {
rootNames: [], rootNames: [],
options: {}, options: {},
}); });
constructor() {} constructor() { }
getFileDir(): string { getFileDir(): string {
return this.fileDir; return this.fileDir;
@ -864,16 +864,18 @@ export class ParserParam {
} }
setProgram(apiLibs: Array<string>): void { setProgram(apiLibs: Array<string>): void {
const compilerOption = { const compilerOption: ts.CompilerOptions = {
target: ts.ScriptTarget.ES2017, target: ts.ScriptTarget.ES2017,
ets: this.getETSOptions([]), ets: this.getETSOptions([]),
allowJs: false, allowJs: false,
lib: [...apiLibs, ...this.rootNames], lib: [...apiLibs, ...this.rootNames],
module: ts.ModuleKind.CommonJS, module: ts.ModuleKind.CommonJS,
}; };
const compilerHost: ts.CompilerHost = ts.createCompilerHost(compilerOption);
this.tsProgram = ts.createProgram({ this.tsProgram = ts.createProgram({
rootNames: [...apiLibs, ...this.rootNames], rootNames: [...apiLibs],
options: compilerOption, options: compilerOption,
host: compilerHost
}); });
} }
} }