From d1f76f758e9d13652ac682a19a25b1c849414596 Mon Sep 17 00:00:00 2001 From: wangshi Date: Thu, 20 Feb 2025 14:29:15 +0800 Subject: [PATCH 1/2] add parse ts Signed-off-by: wangshi --- src/vscode_plugin/src/gen/datatype.ts | 3 +- src/vscode_plugin/src/parse/parsets.ts | 337 +++++++++++------- .../src/test/suite/parse/parsecclass.test.ts | 8 +- .../src/test/suite/parse/parsecenum.test.ts | 8 +- .../src/test/suite/parse/parsecfunc.test.ts | 41 +-- .../src/test/suite/parse/parsecstruct.test.ts | 8 +- .../src/test/suite/parse/parsecunion.test.ts | 8 +- .../src/test/suite/parse/parsetsclass.test.ts | 59 +++ .../src/test/suite/parse/parsetsenum.test.ts | 47 +++ .../src/test/suite/parse/parsetsfunc.test.ts | 48 +++ .../test/suite/parse/parsetsstruct.test.ts | 53 +++ .../src/test/suite/parse/parsetstype.test.ts | 53 +++ .../src/test/suite/parse/parsetsunion.ts | 0 13 files changed, 517 insertions(+), 156 deletions(-) create mode 100644 src/vscode_plugin/src/test/suite/parse/parsetsclass.test.ts create mode 100644 src/vscode_plugin/src/test/suite/parse/parsetsenum.test.ts create mode 100644 src/vscode_plugin/src/test/suite/parse/parsetsfunc.test.ts create mode 100644 src/vscode_plugin/src/test/suite/parse/parsetsstruct.test.ts create mode 100644 src/vscode_plugin/src/test/suite/parse/parsetstype.test.ts create mode 100644 src/vscode_plugin/src/test/suite/parse/parsetsunion.ts diff --git a/src/vscode_plugin/src/gen/datatype.ts b/src/vscode_plugin/src/gen/datatype.ts index a2c2b38d..248cabde 100644 --- a/src/vscode_plugin/src/gen/datatype.ts +++ b/src/vscode_plugin/src/gen/datatype.ts @@ -69,7 +69,8 @@ export interface FuncObj { export interface TypeObj { name: string, alias: string, - members: ParamObj[] + members: ParamObj[], + functions: FuncObj[] } export interface ParseObj { diff --git a/src/vscode_plugin/src/parse/parsets.ts b/src/vscode_plugin/src/parse/parsets.ts index 3cb3c223..7517ead1 100644 --- a/src/vscode_plugin/src/parse/parsets.ts +++ b/src/vscode_plugin/src/parse/parsets.ts @@ -18,7 +18,7 @@ import * as path from 'path'; import * as ts from 'typescript'; import { json } from 'stream/consumers'; import internal = require('stream'); -import { ParamObj, FuncObj, ClassObj, EnumObj, TypeObj, ParseObj } from '../gen/datatype' +import { ParamObj, FuncObj, ClassObj, StructObj, EnumObj, TypeObj, ParseObj } from '../gen/datatype' import { Logger } from '../common/log'; const fs = require('fs'); @@ -44,6 +44,7 @@ interface MemberObj { type: TypeObject; } + const NUMBER_TYPE = 148; const STRING_TYPE = 152; const BOOLEAN_TYPE = 134; @@ -127,7 +128,7 @@ export function getParamType(paramType: any) { return paramText; } -export function parseTsFile(filePath: string): ParseObj { +export function doParseTs(filePath: string, sourceCode: string): ParseObj { let parseRes: ParseObj = { enums: [], unions: [], @@ -138,125 +139,152 @@ export function parseTsFile(filePath: string): ParseObj { } function visitor(node: ts.Node) { if (ts.isClassDeclaration(node) && node.name) { - Logger.getInstance().debug(`Class: ${node.name.text}, ${node.members}`); - let classItem: ClassObj = { - name: node.name.text, - alias: '', - functionList: [], - variableList: [] - }; - try { - node.members.forEach(member => { - // Logger.getInstance().debug(`Member: ${JSON.stringify(member)}`) - if (ts.isMethodDeclaration(member) && member.name) { - const methodstr = member.name ? JSON.stringify(member.name) : 'noname'; - const methodObject = JSON.parse(methodstr); - const methodName = methodObject.escapedText; - Logger.getInstance().debug(`memberName: ${methodName} `); - let returnStr = 'void'; - if (member.type) { - let returnObjStr = JSON.stringify(member.type); - // Logger.getInstance().debug(`returnObjStr: ${returnObjStr} `); - let returnObj = JSON.parse(returnObjStr); - returnStr = getParamType(member.type); - if (returnObj.typeName) { - let returnNameStr = JSON.stringify(returnObj.typeName); - let returnName = JSON.parse(returnNameStr).escapedText; - let returnArgsStr = JSON.stringify(returnObj.typeArguments); - let returnArgsObj = JSON.parse(returnArgsStr); - const returnArgs = returnArgsObj.map((argItem: TypeArguments) => { - let argStr = argItem.members.map((memItem: MemberObj) => { - let memNameStr = ''; - let memTypeStr = 'void'; - if (memItem.name) { - memNameStr = memItem.name.escapedText; - } - if (memItem.type) { - memTypeStr = memItem.type.escapedText ? memItem.type.escapedText : 'any'; - } - return `${memNameStr}: ${memTypeStr}`; - }).join(', '); - return argStr; - }) - returnStr = `${returnName} <${returnArgs}>` - }; - } - let paramResList: ParamObj[] = []; - const params = member.parameters.map(param => { - // `${param.name}: ${param.type ? param.type : 'any'}` - let paramObjStr = JSON.stringify(param.name); - let paramStr = JSON.parse(paramObjStr).escapedText; - let paramTypeStr: string = 'any'; - - if (param.type) { - let paramTypeObjStr = JSON.stringify(param.type); - // Logger.getInstance().debug(`paramTypeObjStr: ${paramTypeObjStr} }`); - paramTypeStr = getParamType(param.type); - if (JSON.parse(paramTypeObjStr).typeName) { - paramTypeStr = JSON.parse(paramTypeObjStr).typeName.escapedText; + Logger.getInstance().debug(`Class: ${node.name.text}, ${node.members}`); + let classItem: ClassObj = { + name: node.name.text, + alias: '', + functionList: [], + variableList: [] + }; + try { + node.members.forEach(member => { + // Logger.getInstance().debug(`Member: ${JSON.stringify(member)}`) + if (ts.isMethodDeclaration(member) && member.name) { + const methodstr = member.name ? JSON.stringify(member.name) : 'noname'; + const methodObject = JSON.parse(methodstr); + const methodName = methodObject.escapedText; + Logger.getInstance().debug(`memberName: ${methodName} `); + let returnStr = 'void'; + if (member.type) { + let returnObjStr = JSON.stringify(member.type); + // Logger.getInstance().debug(`returnObjStr: ${returnObjStr} `); + let returnObj = JSON.parse(returnObjStr); + returnStr = getParamType(member.type); + if (returnObj.typeName) { + let returnNameStr = JSON.stringify(returnObj.typeName); + let returnName = JSON.parse(returnNameStr).escapedText; + let returnArgsStr = JSON.stringify(returnObj.typeArguments); + let returnArgsObj = JSON.parse(returnArgsStr); + const returnArgs = returnArgsObj.map((argItem: TypeArguments) => { + let argStr = argItem.members.map((memItem: MemberObj) => { + let memNameStr = ''; + let memTypeStr = 'void'; + if (memItem.name) { + memNameStr = memItem.name.escapedText; } - } - paramResList.push({ - name: paramStr, - type: paramTypeStr, - arraySize: 0 - }) - return `${paramStr}: ${paramTypeStr}` - }).join(', '); - Logger.getInstance().debug(` Method: ${methodName}, Return Type: ${returnStr}, Parameters: ${params}`); - classItem.functionList.push({ - name: methodName, - returns: returnStr, - parameters: paramResList, - type: '', - }); - } else if (ts.isPropertyDeclaration(member) || ts.isPropertyAssignment(member)) { - // 判断是否是类的成员变量 - if ('type' in member && 'text' in member.name) { - let paramTypeText = getParamType(member.type); - let parameter: ParamObj = { - name: member.name.text, - type: paramTypeText, - arraySize: 0 - } - classItem.variableList.push(parameter); + if (memItem.type) { + memTypeStr = memItem.type.escapedText ? memItem.type.escapedText : 'any'; + } + return `${memNameStr}: ${memTypeStr}`; + }).join(', '); + return argStr; + }) + returnStr = `${returnName} <${returnArgs}>` + }; + } + let paramResList: ParamObj[] = []; + const params = member.parameters.map(param => { + // `${param.name}: ${param.type ? param.type : 'any'}` + let paramObjStr = JSON.stringify(param.name); + let paramStr = JSON.parse(paramObjStr).escapedText; + let paramTypeStr: string = 'any'; + + if (param.type) { + let paramTypeObjStr = JSON.stringify(param.type); + // Logger.getInstance().debug(`paramTypeObjStr: ${paramTypeObjStr} }`); + paramTypeStr = getParamType(param.type); + if (JSON.parse(paramTypeObjStr).typeName) { + paramTypeStr = JSON.parse(paramTypeObjStr).typeName.escapedText; + } } + paramResList.push({ + name: paramStr, + type: paramTypeStr, + arraySize: 0, + arraySizeList: [] + }) + return `${paramStr}: ${paramTypeStr}` + }).join(', '); + Logger.getInstance().debug(` Method: ${methodName}, Return Type: ${returnStr}, Parameters: ${params}`); + classItem.functionList.push({ + name: methodName, + returns: returnStr, + parameters: paramResList, + type: '', + }); + } else if (ts.isPropertyDeclaration(member) || ts.isPropertyAssignment(member)) { + // 判断是否是类的成员变量 + if ('type' in member && 'text' in member.name) { + let paramTypeText = getParamType(member.type); + let parameter: ParamObj = { + name: member.name.text, + type: paramTypeText, + arraySize: 0, + arraySizeList: [] } - parseRes.classes.push(classItem); - }); - } catch (error) { - Logger.getInstance().error('Error processing node:' + error); - } + classItem.variableList.push(parameter); + } + } + }); + parseRes.classes.push(classItem); + } catch (error) { + Logger.getInstance().error('Error processing node:' + error); + } } else if (ts.isEnumDeclaration(node) && node.name) { - try { - Logger.getInstance().debug(`Enum: ${node.name.text}`); - let enumItem: EnumObj = { - name: node.name.text, - alias: '', - members: [], - }; - // Logger.getInstance().debug(`Enum: ${node.name.text}, ${node.members.length}`); - node.members.forEach(member => { - const memJsonStr = JSON.stringify(member.name); - const memJsonObj = JSON.parse(memJsonStr); - // Logger.getInstance().debug(`Member: ${memJsonObj.escapedText}`) - enumItem.members.push(memJsonObj.escapedText); - }) - parseRes.enums.push(enumItem); - } catch (error) { - Logger.getInstance().error('Error processing node:' + error); - } + try { + Logger.getInstance().debug(`Enum: ${node.name.text}`); + let enumItem: EnumObj = { + name: node.name.text, + alias: '', + members: [], + }; + // Logger.getInstance().debug(`Enum: ${node.name.text}, ${node.members.length}`); + node.members.forEach(member => { + const memJsonStr = JSON.stringify(member.name); + const memJsonObj = JSON.parse(memJsonStr); + // Logger.getInstance().debug(`Member: ${memJsonObj.escapedText}`) + enumItem.members.push(memJsonObj.escapedText); + }) + parseRes.enums.push(enumItem); + } catch (error) { + Logger.getInstance().error('Error processing node:' + error); + } } else if (ts.isTypeAliasDeclaration(node) && node.name) { - Logger.getInstance().debug(`Type: ${node.name.text}`); - let typeItem: TypeObj = { - name: node.name.text, - alias: getParamType(node.type), - members: [], - }; - // Logger.getInstance().debug(`Type: ${node.name.text}, ${node.typeParameters} ${typeof(node.type)}`); - const subtypes = getTypeAliasSubtypes(node, typeItem.members); - parseRes.types!.push(typeItem); - Logger.getInstance().debug(`subtypes : ${subtypes}`); + Logger.getInstance().debug(`Type: ${node.name.text}`); + let typeItem: TypeObj = { + name: node.name.text, + alias: getParamType(node.type), + members: [], + functions: [] + }; + node.type.members.forEach(member => { + // 处理属性 + if (ts.isPropertySignature(member)) { + typeItem.members.push({ + name: member.name.getText(sourceFile), + type: member.type?.getText(sourceFile) || "unknown", + arraySize: 0, + arraySizeList: [] + }); + } + // 处理方法 + if (ts.isMethodSignature(member)) { + const parameters = member.parameters.map(param => ({ + name: param.name.getText(sourceFile), + type: param.type?.getText(sourceFile) || "any", + arraySize: 0, + arraySizeList: [] + })); + + typeItem.functions.push({ + name: member.name.getText(sourceFile), + returns: member.type?.getText(sourceFile) || "void", + type: '', + parameters: parameters + }); + } + }); + parseRes.types!.push(typeItem); } else if (ts.isFunctionDeclaration(node) && node.name) { Logger.getInstance().debug(`Type: ${node.name.text}`); const parameters = node.parameters; @@ -275,7 +303,8 @@ export function parseTsFile(filePath: string): ParseObj { let parameter: ParamObj = { name: paramName, type: paramText, - arraySize: 0 + arraySize: 0, + arraySizeList: [] } parames.push(parameter); }); @@ -290,15 +319,85 @@ export function parseTsFile(filePath: string): ParseObj { type: '', } parseRes.funcs.push(funcItem); + } else if (ts.isInterfaceDeclaration(node) && node.name) { + Logger.getInstance().debug(`structItem: ${node.name.text}, ${node.members}`); + let structItem: StructObj = { + name: node.name.text, + alias: '', + members: [], + functions: [] + }; + try { + node.members.forEach(member => { + // Logger.getInstance().debug(`Member: ${JSON.stringify(member)}`) + if (ts.isMethodDeclaration(member) && member.name) { + // 判断是否是方法 + let paramTypeText = getParamType(member.type); + let parameter: ParamObj = { + name: 'test', + type: paramTypeText, + arraySize: 0, + arraySizeList: [] + } + structItem.members.push(parameter); + } else if (ts.isPropertyDeclaration(member) || ts.isPropertyAssignment(member)) { + // 判断是否是类的成员变量 + if ('type' in member && 'text' in member.name) { + let paramTypeText = getParamType(member.type); + let parameter: ParamObj = { + name: member.name.text, + type: paramTypeText, + arraySize: 0, + arraySizeList: [] + } + structItem.members.push(parameter); + } + } else if (ts.isPropertySignature(member)) { + const name = member.name.getText(sourceFile); + const type = member.type?.getText(sourceFile) || 'any'; + let parameter = { + name: name, + type: type, + arraySize: 0, + arraySizeList: [] + }; + structItem.members.push(parameter); + } else if (ts.isMethodSignature(member)) { + const parameters = member.parameters.map(param => ({ + name: param.name.getText(sourceFile), + type: param.type?.getText(sourceFile) || "any", + arraySize: 0, + arraySizeList: [] + })); + + const name = member.name.getText(sourceFile); + const type = member.type?.getText(sourceFile) || 'void'; + let funcobj = { + type: '', + name: name, + returns: type, + parameters: parameters + } + structItem.functions.push(funcobj); + } + }); + parseRes.structs.push(structItem); + } catch (error) { + Logger.getInstance().error('Error processing node:' + error); + } } ts.forEachChild(node, visitor); } - - const sourceCode = fs.readFileSync(filePath, 'utf8'); + const sourceFile = ts.createSourceFile(filePath, sourceCode, ts.ScriptTarget.Latest); const program = ts.createProgram([filePath], {}); gchecker = program.getTypeChecker(); ts.forEachChild(sourceFile, visitor); return parseRes; +} + +export function parseTsFile(filePath: string): ParseObj { + const sourceCode = fs.readFileSync(filePath, 'utf8'); + return doParseTs(filePath, sourceCode); } \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/parse/parsecclass.test.ts b/src/vscode_plugin/src/test/suite/parse/parsecclass.test.ts index d78de258..c711fac1 100644 --- a/src/vscode_plugin/src/test/suite/parse/parsecclass.test.ts +++ b/src/vscode_plugin/src/test/suite/parse/parsecclass.test.ts @@ -25,7 +25,7 @@ suite('Parse_Class_C_Suite', () => { vscode.window.showInformationMessage('Start all tests.'); //1, 测试 parseClass 一般情况 - test('parseClass_test_1', () => { + test('parseClass_c_test_1', () => { let testclass = `typedef class OTC { private: int len; @@ -59,7 +59,7 @@ suite('Parse_Class_C_Suite', () => { }); //2, 测试边界情况 - test('parseClass_test_2', () => { + test('parseClass_c_test_2', () => { let testclass = `typedef class testa { private: short snum; @@ -363,7 +363,7 @@ suite('Parse_Class_C_Suite', () => { }); //3, 测试异常情况 - test('parseClass_test_3', () => { + test('parseClass_c_test_3', () => { let teststr: string = ''; let classObjList = parsec.parseClass(teststr); assert.strictEqual(classObjList.length, 0); @@ -418,7 +418,7 @@ suite('Parse_Class_C_Suite', () => { }); //4, 测试错误情况 - test('parseClass_test_4', () => { + test('parseClass_c_test_4', () => { let classObjList = parsec.parseClass(''); assert.strictEqual(classObjList.length, 0); diff --git a/src/vscode_plugin/src/test/suite/parse/parsecenum.test.ts b/src/vscode_plugin/src/test/suite/parse/parsecenum.test.ts index 39250e18..b56fd846 100644 --- a/src/vscode_plugin/src/test/suite/parse/parsecenum.test.ts +++ b/src/vscode_plugin/src/test/suite/parse/parsecenum.test.ts @@ -25,7 +25,7 @@ suite('Parse_Enum_C_Suite', () => { vscode.window.showInformationMessage('Start all tests.'); //1, 测试 parseEnum 一般情况 - test('parseEnum_test_1', () => { + test('parseEnum_c_test_1', () => { let testenum = `typedef enum { NEW, APPEND, @@ -43,7 +43,7 @@ suite('Parse_Enum_C_Suite', () => { }); //2, 测试边界情况 - test('parseEnum_test_2', () => { + test('parseEnum_c_test_2', () => { let testenum = `typedef enum { NEW, APPEND, @@ -173,7 +173,7 @@ suite('Parse_Enum_C_Suite', () => { }); //3, 测试异常情况 - test('parseEnum_test_3', () => { + test('parseEnum_c_test_3', () => { let teststr: string = ''; let enumObjList = parsec.parseEnum(teststr); assert.strictEqual(enumObjList.length, 0); @@ -229,7 +229,7 @@ suite('Parse_Enum_C_Suite', () => { }); //4, 测试错误情况 - test('parseEnum_test_4', () => { + test('parseEnum_c_test_4', () => { let enumObjList = parsec.parseEnum(''); assert.strictEqual(enumObjList.length, 0); diff --git a/src/vscode_plugin/src/test/suite/parse/parsecfunc.test.ts b/src/vscode_plugin/src/test/suite/parse/parsecfunc.test.ts index 5801a3d8..e68af7f2 100644 --- a/src/vscode_plugin/src/test/suite/parse/parsecfunc.test.ts +++ b/src/vscode_plugin/src/test/suite/parse/parsecfunc.test.ts @@ -26,7 +26,7 @@ suite('Parse_C_Func_Suite', () => { vscode.window.showInformationMessage('Start all tests.'); //1, 测试 parseEnum 一般情况 - test('parseFunction_test_1', () => { + test('parseFunction_c_test_1', () => { let testenum = `int add(int a,int b);` let funcObjList = parsec.parseFunction(testenum); assert.strictEqual(funcObjList.length, 1); @@ -43,22 +43,7 @@ suite('Parse_C_Func_Suite', () => { }); //2, 测试边界情况 - test('parseFunction_test_2', () => { - // let paramstr = 'int a,test alen, test blen, test clen, test dlen'; - // let paramreg = /(\w+<[^>]*>\s+\w+|\w+\s+\w+)/g; - // let match; - // let matches = []; - - // while ((match = paramreg.exec(paramstr)) !== null) { - // matches.push(match[0]); - // } - - // let match: RegExpExecArray | null; - // let declarations: string[] = []; - // while ((match = paramreg.exec(paramstr)) != null) { - // declarations.push(match[1]); - // }; - + test('parseFunction_c_test_2', () => { let testenum = `int add_T(int a,int b);` let funcObjList = parsec.parseFunction(testenum); assert.strictEqual(funcObjList.length, 1); @@ -809,7 +794,7 @@ suite('Parse_C_Func_Suite', () => { assert.strictEqual(funcItem.parameters[0].type, 'wchar_t*'); }); - test('parseFunction_test_21', () => { + test('parseFunction_c_test_21', () => { let testenum = `std::function tfunc(int a);` let funcObjList = parsec.parseFunction(testenum); assert.strictEqual(funcObjList.length, 1); @@ -835,7 +820,7 @@ suite('Parse_C_Func_Suite', () => { }) //3, 测试异常情况 - test('parseFunction_test_3', () => { + test('parseFunction_c_test_3', () => { let teststr: string = ''; let funcObjList = parsec.parseFunction(teststr); assert.strictEqual(funcObjList.length, 0); @@ -853,6 +838,7 @@ suite('Parse_C_Func_Suite', () => { assert.strictEqual(funcItem.parameters.length, 2); assert.strictEqual(funcItem.name, 'test'); assert.strictEqual(funcItem.returns, 'void'); + assert.strictEqual(funcItem.type, 'function'); assert.strictEqual(funcItem.parameters[0].type, 'ENUM_1'); assert.strictEqual(funcItem.parameters[1].type, 'ENUM_2'); @@ -863,6 +849,7 @@ suite('Parse_C_Func_Suite', () => { assert.strictEqual(funcItem.parameters.length, 2); assert.strictEqual(funcItem.name, 'test'); assert.strictEqual(funcItem.returns, 'int'); + assert.strictEqual(funcItem.type, 'function'); assert.strictEqual(funcItem.parameters[0].type, 'ENUM_1'); assert.strictEqual(funcItem.parameters[1].type, 'ENUM_2'); @@ -885,6 +872,20 @@ suite('Parse_C_Func_Suite', () => { funcItem = funcObjList[0]; assert.strictEqual(funcItem.name, 'test'); assert.strictEqual(funcItem.returns, 'typedef void'); + assert.strictEqual(funcItem.type, 'typedef'); + assert.strictEqual(funcItem.parameters.length, 2); + assert.strictEqual(funcItem.parameters[0].name, 'a'); + assert.strictEqual(funcItem.parameters[0].type, 'int'); + assert.strictEqual(funcItem.parameters[1].name, 'b'); + assert.strictEqual(funcItem.parameters[1].type, 'float'); + + teststr = `typedef void (*test)(int a, float b);` + funcObjList = parsec.parseFunction(teststr); + assert.strictEqual(funcObjList.length, 1); + funcItem = funcObjList[0]; + assert.strictEqual(funcItem.name, 'test'); + assert.strictEqual(funcItem.returns, 'void'); + assert.strictEqual(funcItem.type, 'typedef'); assert.strictEqual(funcItem.parameters.length, 2); assert.strictEqual(funcItem.parameters[0].name, 'a'); assert.strictEqual(funcItem.parameters[0].type, 'int'); @@ -893,7 +894,7 @@ suite('Parse_C_Func_Suite', () => { }); //4, 测试错误情况 - test('parseFunction_test_4', () => { + test('parseFunction_c_test_4', () => { let funcObjList = parsec.parseFunction(''); assert.strictEqual(funcObjList.length, 0); diff --git a/src/vscode_plugin/src/test/suite/parse/parsecstruct.test.ts b/src/vscode_plugin/src/test/suite/parse/parsecstruct.test.ts index 811032af..aaba07e3 100644 --- a/src/vscode_plugin/src/test/suite/parse/parsecstruct.test.ts +++ b/src/vscode_plugin/src/test/suite/parse/parsecstruct.test.ts @@ -25,7 +25,7 @@ suite('Parse_C_Struct_Suite', () => { vscode.window.showInformationMessage('Start all tests.'); //1, 测试 parseStruct 一般情况 - test('parseStruct_test_1', () => { + test('parseStruct_c_test_1', () => { let testenum = `typedef struct { int a; char b; @@ -55,7 +55,7 @@ suite('Parse_C_Struct_Suite', () => { }); //2, 测试边界情况 - test('parseStruct_test_2', () => { + test('parseStruct_c_test_2', () => { let testenum = `typedef struct optype { int len; float width; @@ -419,7 +419,7 @@ suite('Parse_C_Struct_Suite', () => { }); //3, 测试异常情况 - test('parseStruct_test_3', () => { + test('parseStruct_c_test_3', () => { let teststr: string = ''; let structObjList = parsec.parseStruct(teststr); assert.strictEqual(structObjList.length, 0); @@ -486,7 +486,7 @@ suite('Parse_C_Struct_Suite', () => { }); // //4, 测试错误情况 - test('parseStruct_test_4', () => { + test('parseStruct_c_test_4', () => { let structObjList = parsec.parseStruct(''); assert.strictEqual(structObjList.length, 0); diff --git a/src/vscode_plugin/src/test/suite/parse/parsecunion.test.ts b/src/vscode_plugin/src/test/suite/parse/parsecunion.test.ts index 9c16051a..54a01b7c 100644 --- a/src/vscode_plugin/src/test/suite/parse/parsecunion.test.ts +++ b/src/vscode_plugin/src/test/suite/parse/parsecunion.test.ts @@ -26,7 +26,7 @@ suite('Parse_C_Union_Suite', () => { vscode.window.showInformationMessage('Start all tests.'); //1, 测试 parseUnion 一般情况 - test('parseUnion_test_1', () => { + test('parseUnion_c_test_1', () => { let testenum = `typedef union { int len; float width; @@ -48,7 +48,7 @@ suite('Parse_C_Union_Suite', () => { }); //2, 测试边界情况 - test('parseUnion_test_2', () => { + test('parseUnion_c_test_2', () => { let testenum = `typedef union optype { int len; float width; @@ -356,7 +356,7 @@ suite('Parse_C_Union_Suite', () => { }); //3, 测试异常情况 - test('parseUnion_test_3', () => { + test('parseUnion_c_test_3', () => { let teststr: string = ''; let unionObjList = parsec.parseUnion(teststr); assert.strictEqual(unionObjList.length, 0); @@ -424,7 +424,7 @@ suite('Parse_C_Union_Suite', () => { }); // //4, 测试错误情况 - test('parseUnion_test_4', () => { + test('parseUnion_c_test_4', () => { let unionObjList = parsec.parseUnion(''); assert.strictEqual(unionObjList.length, 0); diff --git a/src/vscode_plugin/src/test/suite/parse/parsetsclass.test.ts b/src/vscode_plugin/src/test/suite/parse/parsetsclass.test.ts new file mode 100644 index 00000000..b22f1dc8 --- /dev/null +++ b/src/vscode_plugin/src/test/suite/parse/parsetsclass.test.ts @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as parsec from '../../../parse/parsec'; +import * as parsets from '../../../parse/parsets'; +// import * as myExtension from '../../extension'; + +suite('Parse_Class_TS_Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + + //1, 测试 parseClass 一般情况 + test('parseClass_ts_test_1', () => { + let testclass = `class OTC { + len: number; + name: string; + contruct(a: number) { + }; + deconstruct() {}; + };` + let classObjList = parsets.doParseTs("test.ts", testclass); + assert.strictEqual(classObjList.classes.length, 1); + let classItem = classObjList.classes[0]; + assert.strictEqual(classItem.name, 'OTC'); + assert.strictEqual(classItem.functionList.length, 2); + assert.strictEqual(classItem.functionList[0].name, 'contruct'); + assert.strictEqual(classItem.functionList[0].returns, 'void'); + assert.strictEqual(classItem.functionList[0].parameters.length, 1); + assert.strictEqual(classItem.functionList[0].parameters[0].name, 'a'); + assert.strictEqual(classItem.functionList[0].parameters[0].type, 'number'); + assert.strictEqual(classItem.functionList[0].parameters[0].arraySize, 0); + assert.strictEqual(classItem.functionList[1].name, 'deconstruct'); + assert.strictEqual(classItem.functionList[1].returns, 'void'); + + assert.strictEqual(classItem.variableList.length, 2); + assert.strictEqual(classItem.variableList[0].name, 'len'); + assert.strictEqual(classItem.variableList[0].type, 'number'); + assert.strictEqual(classItem.variableList[0].arraySize, 0); + assert.strictEqual(classItem.variableList[1].name, 'name'); + assert.strictEqual(classItem.variableList[1].type, 'string'); + assert.strictEqual(classItem.variableList[0].arraySize, 0); + }); +}) \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/parse/parsetsenum.test.ts b/src/vscode_plugin/src/test/suite/parse/parsetsenum.test.ts new file mode 100644 index 00000000..a7853a40 --- /dev/null +++ b/src/vscode_plugin/src/test/suite/parse/parsetsenum.test.ts @@ -0,0 +1,47 @@ +/* +* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as parsec from '../../../parse/parsec'; +import * as parsets from '../../../parse/parsets'; +// import * as myExtension from '../../extension'; + +suite('Parse_Enum_TS_Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + + //1, 测试 parseClass 一般情况 + test('parseEnum_ts_test_1', () => { + let testenum = `enum Direction { + Up, + Down, + Left, + Right + };` + let enumObjList = parsets.doParseTs("test.ts", testenum); + assert.strictEqual(enumObjList.enums.length, 1); + let enumItem = enumObjList.enums[0]; + assert.strictEqual(enumItem.name, 'Direction'); + assert.strictEqual(enumItem.members.length, 4); + assert.strictEqual(enumItem.members[0], 'Up'); + assert.strictEqual(enumItem.members[1], 'Down'); + assert.strictEqual(enumItem.members[2], 'Left'); + assert.strictEqual(enumItem.members[3], 'Right'); + + }); +}) \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/parse/parsetsfunc.test.ts b/src/vscode_plugin/src/test/suite/parse/parsetsfunc.test.ts new file mode 100644 index 00000000..2bcc8136 --- /dev/null +++ b/src/vscode_plugin/src/test/suite/parse/parsetsfunc.test.ts @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as parsec from '../../../parse/parsec'; +import * as parsets from '../../../parse/parsets'; +// import * as myExtension from '../../extension'; + +suite('Parse_Func_TS_Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + + //1, 测试 parseClass 一般情况 + test('parseFunc_ts_test_1', () => { + let testfunc = `function add(a: number, b: number): number { + return a + b; + } + + let result = add(5, 3); + ;` + let funcObjList = parsets.doParseTs("test.ts", testfunc); + assert.strictEqual(funcObjList.funcs.length, 1); + let funcItem = funcObjList.funcs[0]; + assert.strictEqual(funcItem.name, 'add'); + assert.strictEqual(funcItem.returns, 'number'); + assert.strictEqual(funcItem.parameters.length, 2); + assert.strictEqual(funcItem.parameters[0].name, 'a'); + assert.strictEqual(funcItem.parameters[0].type, 'number'); + assert.strictEqual(funcItem.parameters[1].name, 'b'); + assert.strictEqual(funcItem.parameters[1].type, 'number'); + + }); +}) \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/parse/parsetsstruct.test.ts b/src/vscode_plugin/src/test/suite/parse/parsetsstruct.test.ts new file mode 100644 index 00000000..a5270482 --- /dev/null +++ b/src/vscode_plugin/src/test/suite/parse/parsetsstruct.test.ts @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as parsec from '../../../parse/parsec'; +import * as parsets from '../../../parse/parsets'; +// import * as myExtension from '../../extension'; + +suite('Parse_Struct_TS_Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + + //1, 测试 parseClass 一般情况 + test('parseStruct_ts_test_1', () => { + let teststruct = `interface Point { + x: number; + y: number; + draw(message: string): void; + };` + let structObjList = parsets.doParseTs("test.ts", teststruct); + assert.strictEqual(structObjList.structs.length, 1); + let structItem = structObjList.structs[0]; + assert.strictEqual(structItem.name, 'Point'); + + assert.strictEqual(structItem.members.length, 2); + assert.strictEqual(structItem.members[0].name, 'x'); + assert.strictEqual(structItem.members[0].type, 'number'); + assert.strictEqual(structItem.members[1].name, 'y'); + assert.strictEqual(structItem.members[1].type, 'number'); + + assert.strictEqual(structItem.functions.length, 1); + assert.strictEqual(structItem.functions[0].name, 'draw'); + assert.strictEqual(structItem.functions[0].returns, 'void'); + assert.strictEqual(structItem.functions[0].parameters.length, 1); + assert.strictEqual(structItem.functions[0].parameters[0].name, 'message'); + assert.strictEqual(structItem.functions[0].parameters[0].type, 'string'); + }); +}) \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/parse/parsetstype.test.ts b/src/vscode_plugin/src/test/suite/parse/parsetstype.test.ts new file mode 100644 index 00000000..0a653333 --- /dev/null +++ b/src/vscode_plugin/src/test/suite/parse/parsetstype.test.ts @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as parsec from '../../../parse/parsec'; +import * as parsets from '../../../parse/parsets'; +// import * as myExtension from '../../extension'; + +suite('Parse_Type_TS_Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + + //1, 测试 parseClass 一般情况 + test('parseType_ts_test_1', () => { + let testtype = `type Point = { + x: number; + y: number; + draw(message: string): void; + };` + let typeObjList = parsets.doParseTs("test.ts", testtype); + assert.strictEqual(typeObjList.types?.length, 1); + let typeItem = typeObjList.types[0]; + assert.strictEqual(typeItem.name, 'Point'); + + assert.strictEqual(typeItem.members.length, 2); + assert.strictEqual(typeItem.members[0].name, 'x'); + assert.strictEqual(typeItem.members[0].type, 'number'); + assert.strictEqual(typeItem.members[1].name, 'y'); + assert.strictEqual(typeItem.members[1].type, 'number'); + + assert.strictEqual(typeItem.functions.length, 1); + assert.strictEqual(typeItem.functions[0].name, 'draw'); + assert.strictEqual(typeItem.functions[0].returns, 'void'); + assert.strictEqual(typeItem.functions[0].parameters.length, 1); + assert.strictEqual(typeItem.functions[0].parameters[0].name, 'message'); + assert.strictEqual(typeItem.functions[0].parameters[0].type, 'string'); + }); +}) \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/parse/parsetsunion.ts b/src/vscode_plugin/src/test/suite/parse/parsetsunion.ts new file mode 100644 index 00000000..e69de29b -- Gitee From d7d368dbb6802d9081a2415cd5d4e77f2fa0867b Mon Sep 17 00:00:00 2001 From: wangshi Date: Thu, 20 Feb 2025 15:00:31 +0800 Subject: [PATCH 2/2] update parse ts Signed-off-by: wangshi --- src/vscode_plugin/src/gen/datatype.ts | 3 +- src/vscode_plugin/src/parse/parsec.ts | 1 + src/vscode_plugin/src/parse/parsets.ts | 66 +++++++++++-------- .../src/test/suite/parse/parsetsunion.test.ts | 40 +++++++++++ .../src/test/suite/parse/parsetsunion.ts | 0 5 files changed, 81 insertions(+), 29 deletions(-) create mode 100644 src/vscode_plugin/src/test/suite/parse/parsetsunion.test.ts delete mode 100644 src/vscode_plugin/src/test/suite/parse/parsetsunion.ts diff --git a/src/vscode_plugin/src/gen/datatype.ts b/src/vscode_plugin/src/gen/datatype.ts index 248cabde..873f3820 100644 --- a/src/vscode_plugin/src/gen/datatype.ts +++ b/src/vscode_plugin/src/gen/datatype.ts @@ -70,7 +70,8 @@ export interface TypeObj { name: string, alias: string, members: ParamObj[], - functions: FuncObj[] + functions: FuncObj[], + types: string[] } export interface ParseObj { diff --git a/src/vscode_plugin/src/parse/parsec.ts b/src/vscode_plugin/src/parse/parsec.ts index 9e6adb78..0b839797 100644 --- a/src/vscode_plugin/src/parse/parsec.ts +++ b/src/vscode_plugin/src/parse/parsec.ts @@ -437,6 +437,7 @@ export function parseFunctionOld(data: string) { name: paramName, type: paramType, arraySize: 0, + arraySizeList: [] }) } // Logger.getInstance().info(`ret: ${returnType} func: ${functionName} params:(${paramResList.map(ditem => { diff --git a/src/vscode_plugin/src/parse/parsets.ts b/src/vscode_plugin/src/parse/parsets.ts index 7517ead1..bb009a0a 100644 --- a/src/vscode_plugin/src/parse/parsets.ts +++ b/src/vscode_plugin/src/parse/parsets.ts @@ -255,35 +255,45 @@ export function doParseTs(filePath: string, sourceCode: string): ParseObj { name: node.name.text, alias: getParamType(node.type), members: [], - functions: [] + functions: [], + types: [], }; - node.type.members.forEach(member => { - // 处理属性 - if (ts.isPropertySignature(member)) { - typeItem.members.push({ - name: member.name.getText(sourceFile), - type: member.type?.getText(sourceFile) || "unknown", - arraySize: 0, - arraySizeList: [] - }); - } - // 处理方法 - if (ts.isMethodSignature(member)) { - const parameters = member.parameters.map(param => ({ - name: param.name.getText(sourceFile), - type: param.type?.getText(sourceFile) || "any", - arraySize: 0, - arraySizeList: [] - })); - - typeItem.functions.push({ - name: member.name.getText(sourceFile), - returns: member.type?.getText(sourceFile) || "void", - type: '', - parameters: parameters - }); - } - }); + if (node.type && node.type.members) { + node.type.members.forEach(member => { + // 处理属性 + if (ts.isPropertySignature(member)) { + typeItem.members.push({ + name: member.name.getText(sourceFile), + type: member.type?.getText(sourceFile) || "unknown", + arraySize: 0, + arraySizeList: [] + }); + } + // 处理方法 + if (ts.isMethodSignature(member)) { + const parameters = member.parameters.map(param => ({ + name: param.name.getText(sourceFile), + type: param.type?.getText(sourceFile) || "any", + arraySize: 0, + arraySizeList: [] + })); + + typeItem.functions.push({ + name: member.name.getText(sourceFile), + returns: member.type?.getText(sourceFile) || "void", + type: '', + parameters: parameters + }); + } + + }); + } else if (ts.isUnionTypeNode(node.type)) { + // 处理联合类型 + node.type.types.forEach(typeNode => { + typeItem.types.push(typeNode.getText(sourceFile)); + }); + } + parseRes.types!.push(typeItem); } else if (ts.isFunctionDeclaration(node) && node.name) { Logger.getInstance().debug(`Type: ${node.name.text}`); diff --git a/src/vscode_plugin/src/test/suite/parse/parsetsunion.test.ts b/src/vscode_plugin/src/test/suite/parse/parsetsunion.test.ts new file mode 100644 index 00000000..1f648fa3 --- /dev/null +++ b/src/vscode_plugin/src/test/suite/parse/parsetsunion.test.ts @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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. +*/ + +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import * as parsec from '../../../parse/parsec'; +import * as parsets from '../../../parse/parsets'; +// import * as myExtension from '../../extension'; + +suite('Parse_Union_TS_Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + + //1, 测试 parseClass 一般情况 + test('parseUnion_ts_test_1', () => { + let testtype = `type Point = string | number;` + let typeObjList = parsets.doParseTs("test.ts", testtype); + assert.strictEqual(typeObjList.types?.length, 1); + let typeItem = typeObjList.types[0]; + assert.strictEqual(typeItem.name, 'Point'); + + assert.strictEqual(typeItem.types.length, 2); + assert.strictEqual(typeItem.types[0], 'string'); + assert.strictEqual(typeItem.types[1], 'number'); + }); +}) \ No newline at end of file diff --git a/src/vscode_plugin/src/test/suite/parse/parsetsunion.ts b/src/vscode_plugin/src/test/suite/parse/parsetsunion.ts deleted file mode 100644 index e69de29b..00000000 -- Gitee