mirror of
https://gitee.com/openharmony/napi_generator
synced 2024-11-23 08:20:01 +00:00
add vs plugin code
Signed-off-by: gou-jingjing <goujingjing@kaihong.com>
This commit is contained in:
parent
88b086ee8e
commit
303e29a735
70
src/vscode_plugin/helloworld-sample/src/common/re.ts
Normal file
70
src/vscode_plugin/helloworld-sample/src/common/re.ts
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 { parse } from 'path';
|
||||
|
||||
export function search(ss: any, data: any) {
|
||||
ss = replaceAll(ss, '\\.', '\\.');
|
||||
let reg = new RegExp(ss);
|
||||
let tt = reg.exec(data);
|
||||
if (tt === null || tt === undefined) {
|
||||
return null;
|
||||
}
|
||||
//let ret = { 'regs': [] };
|
||||
let ret: { regs: number[][] } = { regs: [] };
|
||||
for (let i = 0; i < tt.length; i++) {
|
||||
let p = data.indexOf(tt[i]);
|
||||
if (tt[i] === null || tt[i] === undefined) {
|
||||
ret.regs.push([-1, -1]);
|
||||
}
|
||||
else {
|
||||
ret.regs.push([p, p + tt[i].length]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function match(ss: string, data: string) {
|
||||
let tt = search(ss, data);
|
||||
if (tt !== null && tt !== undefined && tt.regs[0][0] === 0) {
|
||||
return tt;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function removeReg(data: string, reg: any[]) {
|
||||
return data.substring(0, reg[0]) + data.substring(reg[1], data.length);
|
||||
}
|
||||
|
||||
export function getReg(data: string, reg: any[]) {
|
||||
return data.substring(reg[0], reg[1]);
|
||||
}
|
||||
|
||||
export function getFileInPath(tpath: string) {
|
||||
return parse(tpath).base;
|
||||
}
|
||||
|
||||
export function getPathInPath(tpath: string) {
|
||||
return parse(tpath).dir;
|
||||
}
|
||||
|
||||
export function all(sfrom: string | RegExp) {
|
||||
return new RegExp(sfrom, 'g');
|
||||
}
|
||||
|
||||
export function replaceAll(ss: string, sfrom: string, sto: string) {
|
||||
return ss.replace(all(sfrom), sto);
|
||||
}
|
||||
|
61
src/vscode_plugin/helloworld-sample/src/common/tool.ts
Normal file
61
src/vscode_plugin/helloworld-sample/src/common/tool.ts
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
export function replaceAll(s: string, sfrom: string, sto: any) {
|
||||
while (s.indexOf(sfrom) >= 0) {
|
||||
s = s.replace(sfrom, sto);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
export function getTab(tabLv: number) {
|
||||
let tab = '';
|
||||
for (let i = 0; i < tabLv; ++i) {
|
||||
tab += ' ';
|
||||
}
|
||||
return tab;
|
||||
}
|
||||
|
||||
export function removeComments(text: string): string {
|
||||
// 移除单行注释
|
||||
const singleLineRegex = /\/\/.*$/gm;
|
||||
// 移除多行注释
|
||||
const multiLineRegex = /\/\*[\s\S]*?\*\//gm;
|
||||
|
||||
// 替换单行注释为空
|
||||
let noComments = text.replace(singleLineRegex, '');
|
||||
// 替换多行注释为空
|
||||
noComments = noComments.replace(multiLineRegex, '');
|
||||
|
||||
return noComments;
|
||||
}
|
||||
|
||||
// 随机生成整数
|
||||
export function generateRandomInteger(min: number, max: number) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
// 去除字符串前面的空格
|
||||
export function removeTab(str: string) {
|
||||
str = replaceAll(str, '\r\n', '');
|
||||
str = replaceAll(str, '\r', '');
|
||||
str = replaceAll(str, '\n', '');
|
||||
while (str[0] === ' ') {
|
||||
str = str.replace(' ' , '')
|
||||
}
|
||||
return str;
|
||||
}
|
74
src/vscode_plugin/helloworld-sample/src/datatype.ts
Normal file
74
src/vscode_plugin/helloworld-sample/src/datatype.ts
Normal file
@ -0,0 +1,74 @@
|
||||
export interface FileTemp {
|
||||
name: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface DirTemp {
|
||||
name: string;
|
||||
files: FileTemp[];
|
||||
dirs: DirTemp[];
|
||||
}
|
||||
|
||||
export interface ParamObj {
|
||||
type: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface FuncObj {
|
||||
name: string;
|
||||
returns: string;
|
||||
parameters: ParamObj[];
|
||||
}
|
||||
|
||||
export interface ParseObj {
|
||||
funcs: FuncObj[];
|
||||
}
|
||||
|
||||
export interface ServiceRootInfo {
|
||||
serviceName: string,
|
||||
funcs: FuncObj[],
|
||||
serviceId: string,
|
||||
versionTag: string,
|
||||
}
|
||||
|
||||
export interface HdfRootInfo {
|
||||
driverName: string; // driverName即为文件名字
|
||||
funcs: FuncObj[];
|
||||
versionTag: string; // 默认4.1
|
||||
}
|
||||
|
||||
export interface FuncTransferMap {
|
||||
fromType: string;
|
||||
tranferContent: string[];
|
||||
}
|
||||
|
||||
// h2dtscpp
|
||||
export interface DtscppRootInfo {
|
||||
funcs: FuncObj[];
|
||||
rawFilePath: string;
|
||||
fileName: string;
|
||||
}
|
||||
|
||||
export interface FuncInfo {
|
||||
name: string,
|
||||
params: ParamObj[],
|
||||
retType: string,
|
||||
genName: string,
|
||||
}
|
||||
|
||||
// 保存 typedefine int cJSON_bool
|
||||
export interface TypeList {
|
||||
typeName: string; // cJSON_bool
|
||||
typeBody: string; // int
|
||||
}
|
||||
|
||||
export interface InterfaceBody {
|
||||
params: ParamObj[];
|
||||
funcs: FuncObj[];
|
||||
}
|
||||
// 保存 typedefine struct cJSON { int a; double b; string c;}
|
||||
export interface InterfaceList {
|
||||
interfaceName: string;
|
||||
interfaceBody: InterfaceBody;
|
||||
}
|
||||
|
188
src/vscode_plugin/helloworld-sample/src/extension.ts
Normal file
188
src/vscode_plugin/helloworld-sample/src/extension.ts
Normal file
@ -0,0 +1,188 @@
|
||||
// The module 'vscode' contains the VS Code extensibility API
|
||||
// Import the module and reference it with the alias vscode in your code below
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import { parseHeaderFile } from './parsec';
|
||||
import { DtscppRootInfo } from './datatype';
|
||||
import { parseTsFile } from './parsets';
|
||||
import { genServiceFile } from './gensa';
|
||||
import { genDtsFile } from './gendts';
|
||||
import { genHdfFile } from './genhdf';
|
||||
import { genDtsCppFile } from './gendtscpp';
|
||||
import fs = require('fs');
|
||||
|
||||
// this method is called when your extension is activated
|
||||
// your extension is activated the very first time the command is executed
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
||||
// This line of code will only be executed once when your extension is activated
|
||||
console.log('Congratulations, your extension "helloworld-sample" is now active!');
|
||||
vscode.window.showInformationMessage('Congratulations, your extension "helloworld-sample" is now active!');
|
||||
|
||||
// The command has been defined in the package.json file
|
||||
// Now provide the implementation of the command with registerCommand
|
||||
// The commandId parameter must match the command field in package.json
|
||||
const h2sa3_2 = vscode.commands.registerCommand('extension.h2sa3-2', async (uri) => {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
vscode.window.showInformationMessage('extension.h2sa3-2!');
|
||||
if (uri && uri.fsPath) {
|
||||
vscode.window.showInformationMessage('extension.h2sa3-2: h path: ' + uri.fsPath);
|
||||
let testContent = 'test vs plugin;'
|
||||
let paths = path.dirname(uri.fsPath);
|
||||
let filePath = path.join(paths, 'test222.txt');
|
||||
fs.writeFileSync(filePath, testContent);
|
||||
// parse
|
||||
let funDescList = await parseHeaderFile(uri.fsPath);
|
||||
console.log('parse header file res: ', funDescList);
|
||||
console.log('parse header file jsonstr: ', JSON.stringify(funDescList));
|
||||
// generator
|
||||
let out = path.dirname(uri.fsPath);
|
||||
let serviceName = path.basename(uri.fsPath, '.h');
|
||||
let rootInfo = {
|
||||
serviceName: serviceName,
|
||||
funcs: funDescList.funcs,
|
||||
serviceId: '19000',
|
||||
versionTag: '3.2'
|
||||
};
|
||||
genServiceFile(rootInfo, out);
|
||||
|
||||
vscode.window.showInformationMessage('h2sa3_2 end!');
|
||||
console.info('h2sa3_2 end!')
|
||||
|
||||
}
|
||||
// Display a message box to the user
|
||||
vscode.window.showInformationMessage('h2sa3_2!');
|
||||
});
|
||||
|
||||
context.subscriptions.push(h2sa3_2);
|
||||
|
||||
const h2sa4_1 = vscode.commands.registerCommand('extension.h2sa4-1', async (uri) => {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
if (uri && uri.fsPath) {
|
||||
// parse
|
||||
let funDescList = await parseHeaderFile(uri.fsPath);
|
||||
console.log('parse header file res: ', funDescList);
|
||||
console.log('parse header file jsonstr: ', JSON.stringify(funDescList));
|
||||
// generator
|
||||
let out = path.dirname(uri.fsPath);
|
||||
let serviceName = path.basename(uri.fsPath, '.h');
|
||||
let rootInfo = {
|
||||
serviceName: serviceName,
|
||||
funcs: funDescList.funcs,
|
||||
serviceId: '19000',
|
||||
versionTag: '4.1'
|
||||
};
|
||||
genServiceFile(rootInfo, out);
|
||||
|
||||
console.info('h2sa4_1 end!')
|
||||
|
||||
}
|
||||
// Display a message box to the user
|
||||
vscode.window.showInformationMessage('h2sa4_1!');
|
||||
});
|
||||
|
||||
context.subscriptions.push(h2sa4_1);
|
||||
|
||||
const h2hdf4_1 = vscode.commands.registerCommand('extension.h2hdf4-1', async (uri) => {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
if (uri && uri.fsPath) {
|
||||
// analyze
|
||||
let funDescList = await parseHeaderFile(uri.fsPath);
|
||||
console.log('parse header file res: ', funDescList);
|
||||
console.log('parse header file jsonstr: ', JSON.stringify(funDescList));
|
||||
|
||||
// generator
|
||||
let out = path.dirname(uri.fsPath);
|
||||
let driverName = path.basename(uri.fsPath, '.h').toLocaleLowerCase();
|
||||
let rootInfo = {
|
||||
driverName: driverName,
|
||||
funcs: funDescList.funcs,
|
||||
versionTag: '4.1'
|
||||
};
|
||||
genHdfFile(rootInfo, out);
|
||||
|
||||
console.info('h2hdf4_1 end!')
|
||||
}
|
||||
// Display a message box to the user
|
||||
vscode.window.showInformationMessage('h2hdf4_1!');
|
||||
});
|
||||
|
||||
context.subscriptions.push(h2hdf4_1);
|
||||
|
||||
const h2dts = vscode.commands.registerCommand('extension.h2dts', async (uri) => {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
if (uri && uri.fsPath) {
|
||||
// parse
|
||||
let funDescList = await parseHeaderFile(uri.fsPath);
|
||||
console.log('parse header file res: ', funDescList);
|
||||
console.log('parse header file jsonstr: ', JSON.stringify(funDescList));
|
||||
let fileName = path.basename(uri.fsPath, '.h');
|
||||
let rootInfo: DtscppRootInfo = {
|
||||
funcs: funDescList.funcs,
|
||||
rawFilePath: uri.fsPath, // e://xxx.h
|
||||
fileName: fileName // xxx
|
||||
};
|
||||
// generator
|
||||
let out = path.dirname(uri.fsPath);
|
||||
genDtsFile(rootInfo, out);
|
||||
|
||||
}
|
||||
// Display a message box to the user
|
||||
vscode.window.showInformationMessage('h2dts!');
|
||||
});
|
||||
|
||||
context.subscriptions.push(h2dts);
|
||||
|
||||
const h2dtscpp = vscode.commands.registerCommand('extension.h2dtscpp', async (uri) => {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
if (uri && uri.fsPath) {
|
||||
// let rawContent = fs.readFileSync(uri.fsPath);
|
||||
// parse
|
||||
let funDescList = await parseHeaderFile(uri.fsPath);
|
||||
let fileName = path.basename(uri.fsPath, '.h');
|
||||
console.log('parse header file res: ', funDescList);
|
||||
console.log('parse header file jsonstr: ', JSON.stringify(funDescList));
|
||||
let rootInfo: DtscppRootInfo = {
|
||||
funcs: funDescList.funcs,
|
||||
rawFilePath: uri.fsPath, // e://xxx.h
|
||||
fileName: fileName // xxx
|
||||
};
|
||||
|
||||
// generator
|
||||
let out = path.dirname(uri.fsPath);
|
||||
genDtsCppFile(rootInfo, out);
|
||||
|
||||
}
|
||||
// Display a message box to the user
|
||||
vscode.window.showInformationMessage('h2dtscpp!');
|
||||
});
|
||||
|
||||
context.subscriptions.push(h2dtscpp);
|
||||
|
||||
const dts2cpp = vscode.commands.registerCommand('extension.dts2cpp', (uri) => {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
console.log('uri is : ' + uri.fsPath );
|
||||
if (uri && uri.fsPath) {
|
||||
const extname = path.extname(uri.fsPath);
|
||||
const filename = path.basename(uri.fsPath);
|
||||
console.log('get filename ' );
|
||||
if (filename.endsWith('.d.ts')) {
|
||||
// Display a message box to the user
|
||||
// parseTsFile(uri.fsPath)
|
||||
let res = parseTsFile(uri.fsPath);
|
||||
console.info("res: " + JSON.stringify(res));
|
||||
vscode.window.showInformationMessage('dts2cpp!');
|
||||
} else {
|
||||
console.log('not dts uri is : ' + uri.fsPath );
|
||||
// Display a message box to the user
|
||||
vscode.window.showInformationMessage(`${uri.fsPath} is not a .d.ts file!`);
|
||||
}
|
||||
|
||||
// generator
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
context.subscriptions.push(dts2cpp);
|
||||
}
|
94
src/vscode_plugin/helloworld-sample/src/parsec.ts
Normal file
94
src/vscode_plugin/helloworld-sample/src/parsec.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import { ParamObj, FuncObj, ParseObj } from './datatype'
|
||||
|
||||
import fs = require('fs');
|
||||
|
||||
export function parseHeaderFile(filePath: string): Promise<ParseObj> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let parseRes: ParseObj = { funcs: [] };
|
||||
|
||||
// 读取文件内容
|
||||
fs.readFile(filePath, 'utf8', (err: NodeJS.ErrnoException | null, data: string) => {
|
||||
if (err) {
|
||||
vscode.window.showErrorMessage(`Error reading file: ${err.message}`);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
// 使用正则表达式提取函数定义
|
||||
const functionRegex1 = /([a-zA-Z_]\w*\s+)+([*a-zA-Z_]\w+)\s*\(([^)]*)\)\s*(?={|;)/g;
|
||||
const functionRegex2 = /(\w+\s*\(.*?\)\s+)(\w+)\s*\((.*?)\);\s*/g;
|
||||
|
||||
let functions = data.match(functionRegex1) || [];
|
||||
if (functions.length <= 0) {
|
||||
console.info("use functionRegex2");
|
||||
functions = data.match(functionRegex2) || [];
|
||||
}
|
||||
const functionDetails: (FuncObj | null)[] = functions.map(func => {
|
||||
// 函数解析逻辑...
|
||||
// 普通类型的函数识别
|
||||
if (func.trim().startsWith('typedef')) {
|
||||
func = func.replace('typedef', '');
|
||||
}
|
||||
let parts = func.trim().match(/([a-zA-Z_]\w+)\s+\(*([*a-zA-Z_]\w+)\)*\s*\(([^)]*)\)/);
|
||||
if (!parts) {
|
||||
console.info("use regex2");
|
||||
parts = func.trim().match(/(\w+\s*\(.*?\)\s+)(\w+)\s*\((.*?)\);\s*/);
|
||||
}
|
||||
if (parts) {
|
||||
let index = 1;
|
||||
let returnType = parts[index].trim();
|
||||
let functionName = parts[index + 1].trim();
|
||||
let paramList = parts[index + 2].split(',');
|
||||
if (parts[index].trim() === 'typedef') {
|
||||
console.info("typedef -------------", parts);
|
||||
returnType = parts[index + 1].trim();
|
||||
functionName = parts[index + 2].trim();
|
||||
paramList = parts[index + 3].split(',');
|
||||
}
|
||||
|
||||
let paramResList = [];
|
||||
for (let i=0; i<paramList.length; i++) {
|
||||
let paramItem = paramList[i].trim();
|
||||
|
||||
let lastTabIndex = paramItem.lastIndexOf(' ');
|
||||
let paramType = paramItem.substring(0, lastTabIndex).trim();
|
||||
let paramName = paramItem.substring(lastTabIndex, paramItem.length).trim();
|
||||
paramResList.push({
|
||||
name: paramName,
|
||||
type: paramType,
|
||||
})
|
||||
}
|
||||
console.info(`ret: ${returnType} func: ${functionName} params:(${paramResList.map(ditem => {
|
||||
return ' type: ' + ditem.type + ', ' + 'name: ' + ditem.name;
|
||||
})})`)
|
||||
let funcRes: FuncObj = {
|
||||
name: functionName,
|
||||
returns: returnType,
|
||||
parameters: paramResList
|
||||
}
|
||||
return funcRes;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(detail => detail !== null);
|
||||
|
||||
if (functionDetails.length > 0) {
|
||||
parseRes.funcs = [...functionDetails.filter((funcItem) : funcItem is FuncObj => funcItem !== null)];
|
||||
const message = functionDetails.map(detail =>
|
||||
`Function: ${detail!.name},
|
||||
Return Type: ${detail!.returns},
|
||||
Parameters: (${detail!.parameters.map(ditem => {
|
||||
return ' type: ' + ditem.type + ', ' + 'name: ' + ditem.name;
|
||||
})})`
|
||||
).join('\n');
|
||||
console.info(` return parseRes: ${JSON.stringify(parseRes)}`);
|
||||
vscode.window.showInformationMessage(message);
|
||||
resolve(parseRes);
|
||||
} else {
|
||||
vscode.window.showInformationMessage('No functions found.');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
221
src/vscode_plugin/helloworld-sample/src/parsets.ts
Normal file
221
src/vscode_plugin/helloworld-sample/src/parsets.ts
Normal file
@ -0,0 +1,221 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import { json } from 'stream/consumers';
|
||||
import internal = require('stream');
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
interface TypeArguments {
|
||||
pos: number;
|
||||
members: [];
|
||||
}
|
||||
|
||||
interface NameObj {
|
||||
pos: number;
|
||||
escapedText: string;
|
||||
}
|
||||
|
||||
interface TypeObj {
|
||||
pos: number;
|
||||
escapedText: string;
|
||||
}
|
||||
|
||||
interface MemberObj {
|
||||
pos: number;
|
||||
name: NameObj;
|
||||
type: TypeObj;
|
||||
}
|
||||
|
||||
|
||||
export interface ParamItem {
|
||||
type: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface TypeItem {
|
||||
name: string;
|
||||
subItemList: ParamItem[];
|
||||
}
|
||||
|
||||
export interface EnumItem {
|
||||
name: string;
|
||||
subItemList: string[];
|
||||
}
|
||||
|
||||
export interface FuncItem {
|
||||
name: string;
|
||||
returns: string;
|
||||
parameters: ParamItem[];
|
||||
}
|
||||
|
||||
export interface ClassObj {
|
||||
name: string;
|
||||
funcs: FuncItem[];
|
||||
}
|
||||
|
||||
export interface ParseObj {
|
||||
classList: ClassObj[];
|
||||
enumList: EnumItem[];
|
||||
typeList: TypeItem[];
|
||||
}
|
||||
|
||||
let gchecker: ts.TypeChecker;
|
||||
|
||||
function getTypeAliasSubtypes(typeAlias: ts.TypeAliasDeclaration, list: ParamItem[]) {
|
||||
// 检查类型是否为类型节点
|
||||
const typeNode = typeAlias.type;
|
||||
// console.log('getTypeAliasSubtypes');
|
||||
try {
|
||||
if (ts.isUnionTypeNode(typeNode)) {
|
||||
// 如果是联合类型(Union Type),遍历它的子类型
|
||||
console.log('isUnionTypeNode');
|
||||
return typeNode.types.map(type => JSON.stringify(type.getText()));
|
||||
} else if (ts.isIntersectionTypeNode(typeNode)) {
|
||||
// 如果是交叉类型(Intersection Type),遍历它的子类型
|
||||
console.log('isIntersectionTypeNode');
|
||||
return typeNode.types.map(type => JSON.stringify(type.decorators));
|
||||
} else if (ts.isTypeLiteralNode(typeNode)) {
|
||||
// 如果是类型字面量(Type Literal),遍历它的属性
|
||||
console.log('isTypeLiteralNode');
|
||||
return typeNode.members.map(member => {
|
||||
let nameStr = JSON.stringify(member.name);
|
||||
let nameObj = JSON.parse(nameStr);
|
||||
let propType = gchecker.getTypeAtLocation(member);
|
||||
let typeStr = gchecker.typeToString(propType);
|
||||
let kindStr = typeStr;
|
||||
list.push({
|
||||
type: kindStr,
|
||||
name: nameObj.escapedText,
|
||||
})
|
||||
return `(${nameObj.escapedText}:${kindStr})`;
|
||||
});
|
||||
}
|
||||
// 处理其他类型
|
||||
return [JSON.stringify(typeNode)];
|
||||
} catch (error) {
|
||||
console.error('Error processing node:', error);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function parseTsFile(filePath: string): ParseObj {
|
||||
let parseRes: ParseObj = {
|
||||
classList: [],
|
||||
enumList: [],
|
||||
typeList: [],
|
||||
}
|
||||
function visitor(node: ts.Node) {
|
||||
if (ts.isClassDeclaration(node) && node.name) {
|
||||
console.log(`Class: ${node.name.text}, ${node.members}`);
|
||||
let classItem: ClassObj = {
|
||||
name: node.name.text,
|
||||
funcs: [],
|
||||
};
|
||||
try {
|
||||
node.members.forEach(member => {
|
||||
// console.log(`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;
|
||||
console.log(`memberName: ${methodName} `);
|
||||
let returnStr = 'void';
|
||||
if (member.type) {
|
||||
let returnObjStr = JSON.stringify(member.type);
|
||||
// console.log(`returnObjStr: ${returnObjStr} `);
|
||||
let returnObj = JSON.parse(returnObjStr);
|
||||
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: ParamItem[] = [];
|
||||
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);
|
||||
// console.log(`paramTypeObjStr: ${paramTypeObjStr} }`);
|
||||
if (JSON.parse(paramTypeObjStr).typeName) {
|
||||
paramTypeStr = JSON.parse(paramTypeObjStr).typeName.escapedText;
|
||||
}
|
||||
}
|
||||
paramResList.push({
|
||||
name: paramStr,
|
||||
type: paramTypeStr,
|
||||
})
|
||||
return `${paramStr}: ${paramTypeStr}`
|
||||
}).join(', ');
|
||||
console.log(` Method: ${methodName}, Return Type: ${returnStr}, Parameters: ${params}`);
|
||||
classItem.funcs.push({
|
||||
name: methodName,
|
||||
returns: returnStr,
|
||||
parameters: paramResList,
|
||||
});
|
||||
parseRes.classList.push(classItem);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error processing node:', error);
|
||||
}
|
||||
} else if (ts.isEnumDeclaration(node) && node.name) {
|
||||
try {
|
||||
console.log(`Enum: ${node.name.text}`);
|
||||
let enumItem: EnumItem = {
|
||||
name: node.name.text,
|
||||
subItemList: [],
|
||||
};
|
||||
// console.log(`Enum: ${node.name.text}, ${node.members.length}`);
|
||||
node.members.forEach(member => {
|
||||
const memJsonStr = JSON.stringify(member.name);
|
||||
const memJsonObj = JSON.parse(memJsonStr);
|
||||
// console.log(`Member: ${memJsonObj.escapedText}`)
|
||||
enumItem.subItemList.push(memJsonObj.escapedText);
|
||||
})
|
||||
parseRes.enumList.push(enumItem);
|
||||
} catch (error) {
|
||||
console.error('Error processing node:', error);
|
||||
}
|
||||
|
||||
} else if (ts.isTypeAliasDeclaration(node) && node.name) {
|
||||
console.log(`Type: ${node.name.text}`);
|
||||
let typeItem: TypeItem = {
|
||||
name: node.name.text,
|
||||
subItemList: [],
|
||||
};
|
||||
// console.log(`Type: ${node.name.text}, ${node.typeParameters} ${typeof(node.type)}`);
|
||||
const subtypes = getTypeAliasSubtypes(node, typeItem.subItemList);
|
||||
parseRes.typeList.push(typeItem);
|
||||
console.log(`subtypes : ${subtypes}`);
|
||||
}
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user