mirror of
https://gitee.com/openharmony/napi_generator
synced 2024-11-26 18:20:35 +00:00
refactory h2dts
Signed-off-by: wangshi <wangshi@kaihong.com>
This commit is contained in:
parent
e18849d2dd
commit
90297f68c5
@ -59,6 +59,7 @@ export interface ClassObj {
|
||||
}
|
||||
|
||||
export interface FuncObj {
|
||||
type: string;
|
||||
name: string;
|
||||
returns: string;
|
||||
parameters: ParamObj[];
|
||||
@ -90,6 +91,13 @@ export interface FuncTransferMap {
|
||||
tranferContent: string[];
|
||||
}
|
||||
|
||||
// h2dts
|
||||
export interface GenInfo {
|
||||
parseObj: ParseObj;
|
||||
rawFilePath: string;
|
||||
fileName: string;
|
||||
}
|
||||
|
||||
// h2dtscpp
|
||||
export interface DtscppRootInfo {
|
||||
funcs: FuncObj[];
|
||||
|
@ -19,7 +19,7 @@ import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import { parseHeaderFile } from './parsec';
|
||||
import { DtscppRootInfo } from './datatype';
|
||||
import { DtscppRootInfo, GenInfo } from './datatype';
|
||||
import { parseTsFile } from './parsets';
|
||||
import { genServiceFile } from './gensa';
|
||||
import { genDtsFile } from './gendts';
|
||||
@ -129,22 +129,21 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
// 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,
|
||||
let parseRes = await parseHeaderFile(uri.fsPath);
|
||||
console.log('parse header file res: ', parseRes);
|
||||
|
||||
let rootInfo: GenInfo = {
|
||||
parseObj: parseRes,
|
||||
rawFilePath: uri.fsPath, // e://xxx.h
|
||||
fileName: fileName // xxx
|
||||
fileName: path.basename(uri.fsPath, '.h') // xxx
|
||||
};
|
||||
// generator
|
||||
let out = path.dirname(uri.fsPath);
|
||||
genDtsFile(rootInfo, out);
|
||||
|
||||
let outPath = genDtsFile(rootInfo);
|
||||
vscode.window.showInformationMessage(`h2dts: gen dts to ${outPath}`);
|
||||
} else {
|
||||
// Display a message box to the user
|
||||
vscode.window.showErrorMessage(`h2dts: error uri ${JSON.stringify(uri)}!`);
|
||||
}
|
||||
// Display a message box to the user
|
||||
vscode.window.showInformationMessage('h2dts!');
|
||||
});
|
||||
|
||||
context.subscriptions.push(h2dts);
|
||||
|
418
src/vscode_plugin/src/gendts copy.tsbak
Normal file
418
src/vscode_plugin/src/gendts copy.tsbak
Normal file
@ -0,0 +1,418 @@
|
||||
/*
|
||||
* 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 re = require('./common/re');
|
||||
import fs = require('fs');
|
||||
import util = require('util');
|
||||
import { DtscppRootInfo, FuncInfo, FuncObj, InterfaceBody, InterfaceList, ParamObj, TypeList } from './datatype';
|
||||
import { dtsFuncTemplate } from './template/func_template';
|
||||
import { generateRandomInteger, removeComments, removeTab, replaceAll } from './common/tool';
|
||||
import path = require('path');
|
||||
const MIN_RANDOM = 100;
|
||||
const MAX_RANDOM = 999
|
||||
|
||||
export function isStringType(cType: string) {
|
||||
switch (cType) {
|
||||
case 'string':
|
||||
case 'std::string':
|
||||
case 'char':
|
||||
case 'wchar_t':
|
||||
case 'char16_t':
|
||||
case 'char32_t':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function isBoolType(cType: string) {
|
||||
if (cType === 'bool') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isNumberType(cType: string) {
|
||||
switch (cType) {
|
||||
case 'short':
|
||||
case 'int':
|
||||
case 'uint32_t':
|
||||
case 'size_t':
|
||||
case 'long':
|
||||
case 'long long':
|
||||
case 'float':
|
||||
case 'double':
|
||||
case 'long double':
|
||||
case 'int16_t':
|
||||
case 'uint16_t':
|
||||
case 'int32_t':
|
||||
case 'int64_t':
|
||||
case 'uint64_t':
|
||||
case 'double_t':
|
||||
case 'float_t':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function basicC2js(cType: string) {
|
||||
let jsType = '';
|
||||
if (isStringType(cType)) {
|
||||
jsType = 'string';
|
||||
} else if (isBoolType(cType)) {
|
||||
jsType = 'boolean';
|
||||
} else if (isNumberType(cType)) {
|
||||
jsType = 'number';
|
||||
} else {
|
||||
jsType = cType;
|
||||
}
|
||||
return jsType;
|
||||
}
|
||||
|
||||
export function getJsTypeFromC(cType: string) {
|
||||
let basicCtype = cType;
|
||||
let matchs = re.match('(std::)?vector<([\x21-\x7e ]+)>', basicCtype);
|
||||
let isArray = 0;
|
||||
if (matchs) {
|
||||
basicCtype = re.getReg(basicCtype, matchs.regs[2]).trim();
|
||||
isArray = 1;
|
||||
}
|
||||
|
||||
let unsignedIdx = basicCtype.indexOf('unsigned');
|
||||
if (unsignedIdx >= 0) {
|
||||
// cut off the keywords 'unsigned'
|
||||
basicCtype = basicCtype.substring(unsignedIdx + 8, basicCtype.length).trim();
|
||||
}
|
||||
let jsType = basicC2js(basicCtype);
|
||||
if (isArray) {
|
||||
jsType = util.format('Array<%s>', jsType);
|
||||
}
|
||||
// 去掉const
|
||||
jsType = replaceAll(jsType, 'const', '');
|
||||
// struct cJson * 的情况
|
||||
let matchStruct = re.match('(struct)?[A-Z_a-z0-9 *]+', basicCtype);
|
||||
if (matchStruct) {
|
||||
let index = basicCtype.indexOf('struct');
|
||||
// 去掉struct和*
|
||||
if (index >= 0) {
|
||||
jsType = jsType.substring(index + 6, basicCtype.length);
|
||||
}
|
||||
jsType = replaceAll(jsType, '*', '').trim();
|
||||
}
|
||||
jsType = basicC2js(jsType);
|
||||
return jsType;
|
||||
}
|
||||
|
||||
function isJsBasicType(type: string) {
|
||||
if (type === 'number' || type === 'string' || type === 'boolean') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getInterFuncName(str: string) {
|
||||
let strArr = str.split(' ');
|
||||
return replaceAll(strArr[1], '*', '');
|
||||
}
|
||||
|
||||
function getInterFuncRetType(str: string) {
|
||||
let strArr = str.split(' ');
|
||||
// let retType = getJsTypeFromC(replaceAll(strArr[0], '*', ''));
|
||||
return replaceAll(strArr[0], '*', '');
|
||||
}
|
||||
|
||||
function getInterFuncParams(str: string, paramObj: ParamObj[]) {
|
||||
let paramsStr = '';
|
||||
let paramObject: ParamObj = {
|
||||
name: '',
|
||||
type: '',
|
||||
arraySize: 0
|
||||
}
|
||||
let paramArr = replaceAll(str, '*', '').split(',');
|
||||
for (let i = 0; i < paramArr.length; i++) {
|
||||
let param = removeTab(paramArr[i]).split(' ');
|
||||
const paramType = replaceAll(param[0], ' ', '');
|
||||
const paramVal = replaceAll(param[1], ' ', '');
|
||||
paramObject.name = paramVal;
|
||||
paramObject.type = paramType;
|
||||
paramObj.push(paramObject);
|
||||
let rawType = getJsTypeFromC(paramType);
|
||||
paramsStr += paramVal + ': ' + rawType;
|
||||
if (i !== paramArr.length - 1) {
|
||||
paramsStr += ', ';
|
||||
}
|
||||
}
|
||||
return paramsStr;
|
||||
}
|
||||
|
||||
export function getTypeBody(testType: string, typeList: TypeList[]) {
|
||||
for (let i = 0; i < typeList.length; i++)
|
||||
{
|
||||
if (typeList[i].typeName === testType) {
|
||||
return typeList[i].typeBody;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export function getInterfaceBody(testType: string, interfaceList: InterfaceList[]) {
|
||||
for (let i = 0; i < interfaceList.length; i++)
|
||||
{
|
||||
if (interfaceList[i].interfaceName === testType) {
|
||||
return interfaceList[i].interfaceBody;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function genDtsInterface(path: string, typeList: TypeList[], interfaceList: InterfaceList[]) {
|
||||
// 解析typedef: 使用正则表达式提取typedef struct定义
|
||||
const typedefsRegex1 = /typedef\s+struct\s+\w+\s*{\s*[\s\S]*?}\s*\w+;/g;
|
||||
// 正则表达式匹配 typedef 后跟基本数据类型和自定义类型名称
|
||||
const typedefsRegex2 = /typedef\s+\w+\s+\w+\s*;/g;
|
||||
// 正则表达式匹配 class xxx {};
|
||||
const classRegex = /class\s+(\w+)\s+([a-zA-Z0-9_]+)?\s*(\{[^}]*\};)/g;
|
||||
let rawContent = removeComments(fs.readFileSync(path).toString());
|
||||
let structMatch = rawContent.match(typedefsRegex1);
|
||||
if (!structMatch) {
|
||||
structMatch = rawContent.match(classRegex);
|
||||
}
|
||||
let basicTypeMatch = rawContent.match(typedefsRegex2);
|
||||
let interfaceListDef: string = '';
|
||||
|
||||
// 使用正则表达式的 exec 方法来获取匹配项
|
||||
if (structMatch) {
|
||||
for (let index = 0; index < structMatch.length; index++) {
|
||||
let matchs = removeComments(structMatch[index]);
|
||||
let structIndex = matchs.indexOf('struct');
|
||||
let classIndex = matchs.indexOf('class')
|
||||
let leftIndex = matchs.indexOf('{');
|
||||
let rightIndex = matchs.indexOf('}');
|
||||
let interfaceName = '';
|
||||
if (structIndex >= 0) {
|
||||
interfaceName = matchs.substring(structIndex + 6, leftIndex).trim();
|
||||
} else if (classIndex >= 0) {
|
||||
interfaceName = matchs.substring(classIndex + 5, leftIndex).trim();
|
||||
}
|
||||
let params = matchs.substring(leftIndex + 1, rightIndex).split(';');
|
||||
let interDefine = 'interface ' + interfaceName + ' {\n';
|
||||
let paramsContent: ParamObj[] = [];
|
||||
let interFuncsContent: FuncObj[] = [];
|
||||
let interfaceBody: InterfaceBody = {
|
||||
params: paramsContent,
|
||||
funcs: interFuncsContent
|
||||
}
|
||||
let interfaceContent: InterfaceList = {
|
||||
interfaceName: interfaceName,
|
||||
interfaceBody: interfaceBody
|
||||
}
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
// 去除空格和换行符
|
||||
let paramStr = removeTab(params[i]);
|
||||
if (paramStr === '') {
|
||||
continue;
|
||||
}
|
||||
// 成员函数的处理
|
||||
const funcRegex = /\w+\s+\*?\(([^\)]+)\)\s*\(([^\)]*)\)\s*/;
|
||||
const funcRegex2 = /(\w+)\s+(::\w+|[\w:]+)\s*\(([^)]*)\)\s*/;
|
||||
let match = paramStr.match(funcRegex);
|
||||
let match2 = paramStr.match(funcRegex2);
|
||||
if (match) {
|
||||
// 处理成员函数 仅仅限于成员函数是函数指针的情况
|
||||
let interFuncParams: ParamObj[] = []
|
||||
let returnType = getInterFuncRetType(match[0]);
|
||||
let funcName = getInterFuncName(match[1]);
|
||||
funcName = util.format('KH%s_%s', generateRandomInteger(MIN_RANDOM, MAX_RANDOM), funcName);
|
||||
let params = getInterFuncParams(match[2], interFuncParams);
|
||||
interDefine += util.format(' %s:(%s) => %s;\n',funcName, params, returnType);
|
||||
let funcObj: FuncObj = {
|
||||
name: funcName,
|
||||
returns: returnType,
|
||||
parameters: interFuncParams
|
||||
}
|
||||
interFuncsContent.push(funcObj);
|
||||
} else if (match2) {
|
||||
let interFuncParams: ParamObj[] = []
|
||||
let returnType = getInterFuncRetType(match2[1]);
|
||||
let funcName = match2[2];
|
||||
funcName = util.format('KH%s_%s', generateRandomInteger(MIN_RANDOM, MAX_RANDOM), funcName);
|
||||
let params = getInterFuncParams(match2[3], interFuncParams);
|
||||
interDefine += util.format(' %s:(%s) => %s;\n',funcName, params, returnType);
|
||||
let funcObj: FuncObj = {
|
||||
name: funcName,
|
||||
returns: returnType,
|
||||
parameters: interFuncParams
|
||||
}
|
||||
interFuncsContent.push(funcObj);
|
||||
} else {
|
||||
let lastTabIndex = paramStr.lastIndexOf(' ');
|
||||
const variableName = paramStr.substring(lastTabIndex + 1, paramStr.length).replace('*', '')
|
||||
const variabletype = paramStr.substring(0, lastTabIndex);
|
||||
let rawType = getJsTypeFromC(variabletype);
|
||||
if (!isJsBasicType(rawType)) {
|
||||
rawType += ' | null';
|
||||
}
|
||||
let variableDefine = ' ' + variableName + ': ' + rawType + ';\n'
|
||||
interDefine += variableDefine;
|
||||
let paramObj: ParamObj = {
|
||||
name: variableName,
|
||||
type: replaceAll(variabletype, 'struct', '').trim(),
|
||||
arraySize: 0
|
||||
}
|
||||
paramsContent.push(paramObj);
|
||||
}
|
||||
}
|
||||
interfaceBody.funcs = interFuncsContent;
|
||||
interfaceBody.params = paramsContent;
|
||||
interfaceContent.interfaceBody = interfaceBody;
|
||||
interfaceList.push(interfaceContent);
|
||||
|
||||
interDefine += '}\n';
|
||||
interfaceListDef += interDefine;
|
||||
}
|
||||
}
|
||||
|
||||
if (basicTypeMatch) {
|
||||
for (let index = 0; index < basicTypeMatch.length; index++) {
|
||||
console.log('Basic type typedef match:', basicTypeMatch[0]); // 输出匹配的基本类型定义
|
||||
let matchs = basicTypeMatch[index].split(' ');
|
||||
let rawType = getJsTypeFromC(matchs[1].trim());
|
||||
let defineType = matchs[2].split(';')
|
||||
let typedefine = 'type ' + defineType[0] + ' = ' + rawType + ';\n';
|
||||
interfaceListDef += typedefine;
|
||||
let typeListContent: TypeList = {
|
||||
typeName: defineType[0],
|
||||
typeBody: matchs[1].trim()
|
||||
}
|
||||
typeList.push(typeListContent);
|
||||
}
|
||||
}
|
||||
|
||||
return interfaceListDef;
|
||||
}
|
||||
|
||||
export function genTsFunction(func: FuncInfo, rawFileName: string) {
|
||||
let funcParams = '';
|
||||
for (let i = 0; i < func.params.length; ++i) {
|
||||
funcParams += i > 0 ? ', ' : '';
|
||||
funcParams += func.params[i].name + ': ' + func.params[i].type;
|
||||
}
|
||||
let funcContent = replaceAll(dtsFuncTemplate, '[file_introduce_replace]', rawFileName);
|
||||
funcContent = replaceAll(funcContent, '[func_introduce_replace]', func.name);
|
||||
funcContent = replaceAll(funcContent, '[input_introduce_replace]', funcParams === '' ? 'void' : funcParams);
|
||||
funcContent = replaceAll(funcContent, '[func_name_replace]', func.genName);
|
||||
funcContent = replaceAll(funcContent, '[func_param_replace]', funcParams);
|
||||
funcContent = replaceAll(funcContent, '[func_return_replace]', func.retType);
|
||||
|
||||
return funcContent;
|
||||
}
|
||||
|
||||
function createParam(parseParamInfo: ParamObj) {
|
||||
let tsParam: ParamObj = {
|
||||
name: '',
|
||||
type: '',
|
||||
arraySize: 0
|
||||
};
|
||||
|
||||
let cppParam: ParamObj = {
|
||||
name: '',
|
||||
type: '',
|
||||
arraySize: 0
|
||||
};
|
||||
tsParam.name = replaceAll(parseParamInfo.name, '*', '');
|
||||
cppParam.name = tsParam.name;
|
||||
cppParam.type = removeMarco(parseParamInfo.type);
|
||||
let rawType = getJsTypeFromC(parseParamInfo.type);
|
||||
tsParam.type = removeMarco(rawType);
|
||||
return [tsParam, cppParam];
|
||||
}
|
||||
|
||||
function removeMarco(type: string) {
|
||||
// 去掉宏定义
|
||||
let leftCraftIndex = type.indexOf('(');
|
||||
let rightCraftIndex = type.indexOf(')');
|
||||
if (leftCraftIndex >= 0 && rightCraftIndex > 0) {
|
||||
type = removeTab(type.substring(leftCraftIndex + 1, rightCraftIndex));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function createFuncInfo(parseFuncInfo: FuncObj) {
|
||||
let funcInfo: FuncInfo = {
|
||||
name: '',
|
||||
params: [],
|
||||
retType: '',
|
||||
genName: ''
|
||||
};
|
||||
|
||||
let cppFuncInfo: FuncInfo = {
|
||||
name: '',
|
||||
params: [],
|
||||
retType: '',
|
||||
genName: ''
|
||||
}
|
||||
funcInfo.name = parseFuncInfo.name;
|
||||
cppFuncInfo.name = parseFuncInfo.name;
|
||||
funcInfo.genName = util.format('KH%s_%s', generateRandomInteger(MIN_RANDOM, MAX_RANDOM), funcInfo.name);
|
||||
cppFuncInfo.genName = funcInfo.genName;
|
||||
let parseParams = parseFuncInfo.parameters;
|
||||
for (let i = 0; i < parseParams.length; ++i) {
|
||||
let paramsRes = createParam(parseParams[i]);
|
||||
let tsParam = paramsRes[0]
|
||||
let cppParam = paramsRes[1];
|
||||
if (tsParam.type !== '') {
|
||||
funcInfo.params.push(tsParam);
|
||||
cppFuncInfo.params.push(cppParam);
|
||||
}
|
||||
}
|
||||
|
||||
let retType = parseFuncInfo.returns === '' ? 'void' : parseFuncInfo.returns;
|
||||
retType = removeMarco(retType);
|
||||
cppFuncInfo.retType = retType;
|
||||
funcInfo.retType = getJsTypeFromC(retType);
|
||||
return [funcInfo, cppFuncInfo];
|
||||
}
|
||||
|
||||
export function analyzeRootFunction(funcInfo: FuncInfo[], cppFuncInfo: FuncInfo[], parseFunctions: FuncObj[]) {
|
||||
for (let i = 0; i < parseFunctions.length; ++i) {
|
||||
let result = createFuncInfo(parseFunctions[i]);
|
||||
funcInfo[i] = result[0];
|
||||
cppFuncInfo[i] = result[1];
|
||||
}
|
||||
}
|
||||
|
||||
export function genDtsFile(rootInfo: DtscppRootInfo, out: string) {
|
||||
let typeList: TypeList[] = []
|
||||
let interfaceList: InterfaceList[] = []
|
||||
let interDef = genDtsInterface(rootInfo.rawFilePath, typeList, interfaceList);
|
||||
let tsFuncContent = '';
|
||||
// analyze
|
||||
let tsfunctions: FuncInfo[] = [];
|
||||
let cppfunctions: FuncInfo[] = [];
|
||||
analyzeRootFunction(tsfunctions, cppfunctions, rootInfo.funcs);
|
||||
let rawFileName = path.basename(rootInfo.rawFilePath);
|
||||
for (let i = 0; i < rootInfo.funcs.length; i++) {
|
||||
// gen dts function
|
||||
tsFuncContent += genTsFunction(tsfunctions[i], rawFileName);
|
||||
}
|
||||
let dtsFileName = rootInfo.fileName + '.d.ts';
|
||||
let dtsContent = interDef + tsFuncContent;
|
||||
|
||||
let outPath = path.join(out, dtsFileName);
|
||||
fs.writeFileSync(outPath, dtsContent);
|
||||
|
||||
console.info('generate success!')
|
||||
}
|
@ -12,13 +12,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import re = require('./common/re');
|
||||
import fs = require('fs');
|
||||
import util = require('util');
|
||||
import { DtscppRootInfo, FuncInfo, FuncObj, InterfaceBody, InterfaceList, ParamObj, TypeList } from './datatype';
|
||||
import { dtsFuncTemplate } from './template/func_template';
|
||||
import { generateRandomInteger, removeComments, removeTab, replaceAll } from './common/tool';
|
||||
import { DtscppRootInfo, FuncObj, InterfaceBody, ParamObj, FuncInfo, GenInfo, InterfaceList, TypeList } from './datatype';
|
||||
import { dts2cpp_key } from './template/dtscpp/dts2cpp_key';
|
||||
import path = require('path');
|
||||
|
||||
import { generateRandomInteger, removeComments, removeTab, replaceAll } from './common/tool';
|
||||
import util = require('util');
|
||||
import re = require('./common/re');
|
||||
import { dtsFuncTemplate } from './template/func_template';
|
||||
|
||||
const MIN_RANDOM = 100;
|
||||
const MAX_RANDOM = 999
|
||||
|
||||
@ -43,6 +46,22 @@ export function isBoolType(cType: string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function genTsFunction(func: FuncInfo, rawFileName: string) {
|
||||
let funcParams = '';
|
||||
for (let i = 0; i < func.params.length; ++i) {
|
||||
funcParams += i > 0 ? ', ' : '';
|
||||
funcParams += func.params[i].name + ': ' + func.params[i].type;
|
||||
}
|
||||
let funcContent = replaceAll(dtsFuncTemplate, '[file_introduce_replace]', rawFileName);
|
||||
funcContent = replaceAll(funcContent, '[func_introduce_replace]', func.name);
|
||||
funcContent = replaceAll(funcContent, '[input_introduce_replace]', funcParams === '' ? 'void' : funcParams);
|
||||
funcContent = replaceAll(funcContent, '[func_name_replace]', func.genName);
|
||||
funcContent = replaceAll(funcContent, '[func_param_replace]', funcParams);
|
||||
funcContent = replaceAll(funcContent, '[func_return_replace]', func.retType);
|
||||
|
||||
return funcContent;
|
||||
}
|
||||
|
||||
export function isNumberType(cType: string) {
|
||||
switch (cType) {
|
||||
case 'short':
|
||||
@ -81,6 +100,17 @@ function basicC2js(cType: string) {
|
||||
return jsType;
|
||||
}
|
||||
|
||||
function getInterFuncRetType(str: string) {
|
||||
let strArr = str.split(' ');
|
||||
// let retType = getJsTypeFromC(replaceAll(strArr[0], '*', ''));
|
||||
return replaceAll(strArr[0], '*', '');
|
||||
}
|
||||
|
||||
function getInterFuncName(str: string) {
|
||||
let strArr = str.split(' ');
|
||||
return replaceAll(strArr[1], '*', '');
|
||||
}
|
||||
|
||||
export function getJsTypeFromC(cType: string) {
|
||||
let basicCtype = cType;
|
||||
let matchs = re.match('(std::)?vector<([\x21-\x7e ]+)>', basicCtype);
|
||||
@ -115,25 +145,6 @@ export function getJsTypeFromC(cType: string) {
|
||||
return jsType;
|
||||
}
|
||||
|
||||
function isJsBasicType(type: string) {
|
||||
if (type === 'number' || type === 'string' || type === 'boolean') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getInterFuncName(str: string) {
|
||||
let strArr = str.split(' ');
|
||||
return replaceAll(strArr[1], '*', '');
|
||||
}
|
||||
|
||||
function getInterFuncRetType(str: string) {
|
||||
let strArr = str.split(' ');
|
||||
// let retType = getJsTypeFromC(replaceAll(strArr[0], '*', ''));
|
||||
return replaceAll(strArr[0], '*', '');
|
||||
}
|
||||
|
||||
function getInterFuncParams(str: string, paramObj: ParamObj[]) {
|
||||
let paramsStr = '';
|
||||
let paramObject: ParamObj = {
|
||||
@ -158,166 +169,22 @@ function getInterFuncParams(str: string, paramObj: ParamObj[]) {
|
||||
return paramsStr;
|
||||
}
|
||||
|
||||
export function getTypeBody(testType: string, typeList: TypeList[]) {
|
||||
for (let i = 0; i < typeList.length; i++)
|
||||
{
|
||||
if (typeList[i].typeName === testType) {
|
||||
return typeList[i].typeBody;
|
||||
}
|
||||
return '';
|
||||
function isJsBasicType(type: string) {
|
||||
if (type === 'number' || type === 'string' || type === 'boolean') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getInterfaceBody(testType: string, interfaceList: InterfaceList[]) {
|
||||
for (let i = 0; i < interfaceList.length; i++)
|
||||
{
|
||||
if (interfaceList[i].interfaceName === testType) {
|
||||
return interfaceList[i].interfaceBody;
|
||||
}
|
||||
function removeMarco(type: string) {
|
||||
// 去掉宏定义
|
||||
let leftCraftIndex = type.indexOf('(');
|
||||
let rightCraftIndex = type.indexOf(')');
|
||||
if (leftCraftIndex >= 0 && rightCraftIndex > 0) {
|
||||
type = removeTab(type.substring(leftCraftIndex + 1, rightCraftIndex));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function genDtsInterface(path: string, typeList: TypeList[], interfaceList: InterfaceList[]) {
|
||||
// 解析typedef: 使用正则表达式提取typedef struct定义
|
||||
const typedefsRegex1 = /typedef\s+struct\s+\w+\s*{\s*[\s\S]*?}\s*\w+;/g;
|
||||
// 正则表达式匹配 typedef 后跟基本数据类型和自定义类型名称
|
||||
const typedefsRegex2 = /typedef\s+\w+\s+\w+\s*;/g;
|
||||
// 正则表达式匹配 class xxx {};
|
||||
const classRegex = /class\s+(\w+)\s+([a-zA-Z0-9_]+)?\s*(\{[^}]*\};)/g;
|
||||
let rawContent = removeComments(fs.readFileSync(path).toString());
|
||||
let structMatch = rawContent.match(typedefsRegex1);
|
||||
if (!structMatch) {
|
||||
structMatch = rawContent.match(classRegex);
|
||||
}
|
||||
let basicTypeMatch = rawContent.match(typedefsRegex2);
|
||||
let interfaceListDef: string = '';
|
||||
|
||||
// 使用正则表达式的 exec 方法来获取匹配项
|
||||
if (structMatch) {
|
||||
for (let index = 0; index < structMatch.length; index++) {
|
||||
let matchs = removeComments(structMatch[index]);
|
||||
let structIndex = matchs.indexOf('struct');
|
||||
let classIndex = matchs.indexOf('class')
|
||||
let leftIndex = matchs.indexOf('{');
|
||||
let rightIndex = matchs.indexOf('}');
|
||||
let interfaceName = '';
|
||||
if (structIndex >= 0) {
|
||||
interfaceName = matchs.substring(structIndex + 6, leftIndex).trim();
|
||||
} else if (classIndex >= 0) {
|
||||
interfaceName = matchs.substring(classIndex + 5, leftIndex).trim();
|
||||
}
|
||||
let params = matchs.substring(leftIndex + 1, rightIndex).split(';');
|
||||
let interDefine = 'interface ' + interfaceName + ' {\n';
|
||||
let paramsContent: ParamObj[] = [];
|
||||
let interFuncsContent: FuncObj[] = [];
|
||||
let interfaceBody: InterfaceBody = {
|
||||
params: paramsContent,
|
||||
funcs: interFuncsContent
|
||||
}
|
||||
let interfaceContent: InterfaceList = {
|
||||
interfaceName: interfaceName,
|
||||
interfaceBody: interfaceBody
|
||||
}
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
// 去除空格和换行符
|
||||
let paramStr = removeTab(params[i]);
|
||||
if (paramStr === '') {
|
||||
continue;
|
||||
}
|
||||
// 成员函数的处理
|
||||
const funcRegex = /\w+\s+\*?\(([^\)]+)\)\s*\(([^\)]*)\)\s*/;
|
||||
const funcRegex2 = /(\w+)\s+(::\w+|[\w:]+)\s*\(([^)]*)\)\s*/;
|
||||
let match = paramStr.match(funcRegex);
|
||||
let match2 = paramStr.match(funcRegex2);
|
||||
if (match) {
|
||||
// 处理成员函数 仅仅限于成员函数是函数指针的情况
|
||||
let interFuncParams: ParamObj[] = []
|
||||
let returnType = getInterFuncRetType(match[0]);
|
||||
let funcName = getInterFuncName(match[1]);
|
||||
funcName = util.format('KH%s_%s', generateRandomInteger(MIN_RANDOM, MAX_RANDOM), funcName);
|
||||
let params = getInterFuncParams(match[2], interFuncParams);
|
||||
interDefine += util.format(' %s:(%s) => %s;\n',funcName, params, returnType);
|
||||
let funcObj: FuncObj = {
|
||||
name: funcName,
|
||||
returns: returnType,
|
||||
parameters: interFuncParams
|
||||
}
|
||||
interFuncsContent.push(funcObj);
|
||||
} else if (match2) {
|
||||
let interFuncParams: ParamObj[] = []
|
||||
let returnType = getInterFuncRetType(match2[1]);
|
||||
let funcName = match2[2];
|
||||
funcName = util.format('KH%s_%s', generateRandomInteger(MIN_RANDOM, MAX_RANDOM), funcName);
|
||||
let params = getInterFuncParams(match2[3], interFuncParams);
|
||||
interDefine += util.format(' %s:(%s) => %s;\n',funcName, params, returnType);
|
||||
let funcObj: FuncObj = {
|
||||
name: funcName,
|
||||
returns: returnType,
|
||||
parameters: interFuncParams
|
||||
}
|
||||
interFuncsContent.push(funcObj);
|
||||
} else {
|
||||
let lastTabIndex = paramStr.lastIndexOf(' ');
|
||||
const variableName = paramStr.substring(lastTabIndex + 1, paramStr.length).replace('*', '')
|
||||
const variabletype = paramStr.substring(0, lastTabIndex);
|
||||
let rawType = getJsTypeFromC(variabletype);
|
||||
if (!isJsBasicType(rawType)) {
|
||||
rawType += ' | null';
|
||||
}
|
||||
let variableDefine = ' ' + variableName + ': ' + rawType + ';\n'
|
||||
interDefine += variableDefine;
|
||||
let paramObj: ParamObj = {
|
||||
name: variableName,
|
||||
type: replaceAll(variabletype, 'struct', '').trim(),
|
||||
arraySize: 0
|
||||
}
|
||||
paramsContent.push(paramObj);
|
||||
}
|
||||
}
|
||||
interfaceBody.funcs = interFuncsContent;
|
||||
interfaceBody.params = paramsContent;
|
||||
interfaceContent.interfaceBody = interfaceBody;
|
||||
interfaceList.push(interfaceContent);
|
||||
|
||||
interDefine += '}\n';
|
||||
interfaceListDef += interDefine;
|
||||
}
|
||||
}
|
||||
|
||||
if (basicTypeMatch) {
|
||||
for (let index = 0; index < basicTypeMatch.length; index++) {
|
||||
console.log('Basic type typedef match:', basicTypeMatch[0]); // 输出匹配的基本类型定义
|
||||
let matchs = basicTypeMatch[index].split(' ');
|
||||
let rawType = getJsTypeFromC(matchs[1].trim());
|
||||
let defineType = matchs[2].split(';')
|
||||
let typedefine = 'type ' + defineType[0] + ' = ' + rawType + ';\n';
|
||||
interfaceListDef += typedefine;
|
||||
let typeListContent: TypeList = {
|
||||
typeName: defineType[0],
|
||||
typeBody: matchs[1].trim()
|
||||
}
|
||||
typeList.push(typeListContent);
|
||||
}
|
||||
}
|
||||
|
||||
return interfaceListDef;
|
||||
}
|
||||
|
||||
export function genTsFunction(func: FuncInfo, rawFileName: string) {
|
||||
let funcParams = '';
|
||||
for (let i = 0; i < func.params.length; ++i) {
|
||||
funcParams += i > 0 ? ', ' : '';
|
||||
funcParams += func.params[i].name + ': ' + func.params[i].type;
|
||||
}
|
||||
let funcContent = replaceAll(dtsFuncTemplate, '[file_introduce_replace]', rawFileName);
|
||||
funcContent = replaceAll(funcContent, '[func_introduce_replace]', func.name);
|
||||
funcContent = replaceAll(funcContent, '[input_introduce_replace]', funcParams === '' ? 'void' : funcParams);
|
||||
funcContent = replaceAll(funcContent, '[func_name_replace]', func.genName);
|
||||
funcContent = replaceAll(funcContent, '[func_param_replace]', funcParams);
|
||||
funcContent = replaceAll(funcContent, '[func_return_replace]', func.retType);
|
||||
|
||||
return funcContent;
|
||||
return type;
|
||||
}
|
||||
|
||||
function createParam(parseParamInfo: ParamObj) {
|
||||
@ -340,16 +207,6 @@ function createParam(parseParamInfo: ParamObj) {
|
||||
return [tsParam, cppParam];
|
||||
}
|
||||
|
||||
function removeMarco(type: string) {
|
||||
// 去掉宏定义
|
||||
let leftCraftIndex = type.indexOf('(');
|
||||
let rightCraftIndex = type.indexOf(')');
|
||||
if (leftCraftIndex >= 0 && rightCraftIndex > 0) {
|
||||
type = removeTab(type.substring(leftCraftIndex + 1, rightCraftIndex));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function createFuncInfo(parseFuncInfo: FuncObj) {
|
||||
let funcInfo: FuncInfo = {
|
||||
name: '',
|
||||
@ -394,25 +251,301 @@ export function analyzeRootFunction(funcInfo: FuncInfo[], cppFuncInfo: FuncInfo[
|
||||
}
|
||||
}
|
||||
|
||||
export function genDtsFile(rootInfo: DtscppRootInfo, out: string) {
|
||||
let typeList: TypeList[] = []
|
||||
let interfaceList: InterfaceList[] = []
|
||||
let interDef = genDtsInterface(rootInfo.rawFilePath, typeList, interfaceList);
|
||||
let tsFuncContent = '';
|
||||
// analyze
|
||||
let tsfunctions: FuncInfo[] = [];
|
||||
let cppfunctions: FuncInfo[] = [];
|
||||
analyzeRootFunction(tsfunctions, cppfunctions, rootInfo.funcs);
|
||||
let rawFileName = path.basename(rootInfo.rawFilePath);
|
||||
for (let i = 0; i < rootInfo.funcs.length; i++) {
|
||||
// gen dts function
|
||||
tsFuncContent += genTsFunction(tsfunctions[i], rawFileName);
|
||||
export function genDtsInterface(path: string, typeList: TypeList[], interfaceList: InterfaceList[]) {
|
||||
// 解析typedef: 使用正则表达式提取typedef struct定义
|
||||
const typedefsRegex1 = /typedef\s+struct\s+\w+\s*{\s*[\s\S]*?}\s*\w+;/g;
|
||||
// 正则表达式匹配 typedef 后跟基本数据类型和自定义类型名称
|
||||
const typedefsRegex2 = /typedef\s+\w+\s+\w+\s*;/g;
|
||||
// 正则表达式匹配 class xxx {};
|
||||
const classRegex = /class\s+(\w+)\s+([a-zA-Z0-9_]+)?\s*(\{[^}]*\};)/g;
|
||||
let rawContent = removeComments(fs.readFileSync(path).toString());
|
||||
let structMatch = rawContent.match(typedefsRegex1);
|
||||
if (!structMatch) {
|
||||
structMatch = rawContent.match(classRegex);
|
||||
}
|
||||
let basicTypeMatch = rawContent.match(typedefsRegex2);
|
||||
let interfaceListDef: string = '';
|
||||
|
||||
// 使用正则表达式的 exec 方法来获取匹配项
|
||||
if (structMatch) {
|
||||
for (let index = 0; index < structMatch.length; index++) {
|
||||
let matchs = removeComments(structMatch[index]);
|
||||
let structIndex = matchs.indexOf('struct');
|
||||
let classIndex = matchs.indexOf('class')
|
||||
let leftIndex = matchs.indexOf('{');
|
||||
let rightIndex = matchs.indexOf('}');
|
||||
let interfaceName = '';
|
||||
if (structIndex >= 0) {
|
||||
interfaceName = matchs.substring(structIndex + 6, leftIndex).trim();
|
||||
} else if (classIndex >= 0) {
|
||||
interfaceName = matchs.substring(classIndex + 5, leftIndex).trim();
|
||||
}
|
||||
let params = matchs.substring(leftIndex + 1, rightIndex).split(';');
|
||||
let interDefine = 'interface ' + interfaceName + ' {\n';
|
||||
let paramsContent: ParamObj[] = [];
|
||||
let interFuncsContent: FuncObj[] = [];
|
||||
let interfaceBody: InterfaceBody = {
|
||||
params: paramsContent,
|
||||
funcs: interFuncsContent
|
||||
}
|
||||
let interfaceContent: InterfaceList = {
|
||||
interfaceName: interfaceName,
|
||||
interfaceBody: interfaceBody
|
||||
}
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
// 去除空格和换行符
|
||||
let paramStr = removeTab(params[i]);
|
||||
if (paramStr === '') {
|
||||
continue;
|
||||
}
|
||||
// 成员函数的处理
|
||||
const funcRegex = /\w+\s+\*?\(([^\)]+)\)\s*\(([^\)]*)\)\s*/;
|
||||
const funcRegex2 = /(\w+)\s+(::\w+|[\w:]+)\s*\(([^)]*)\)\s*/;
|
||||
let match = paramStr.match(funcRegex);
|
||||
let match2 = paramStr.match(funcRegex2);
|
||||
if (match) {
|
||||
// 处理成员函数 仅仅限于成员函数是函数指针的情况
|
||||
let interFuncParams: ParamObj[] = []
|
||||
let returnType = getInterFuncRetType(match[0]);
|
||||
let funcName = getInterFuncName(match[1]);
|
||||
funcName = util.format('KH%s_%s', generateRandomInteger(MIN_RANDOM, MAX_RANDOM), funcName);
|
||||
let params = getInterFuncParams(match[2], interFuncParams);
|
||||
interDefine += util.format(' %s:(%s) => %s;\n',funcName, params, returnType);
|
||||
let funcObj: FuncObj = {
|
||||
type: '',
|
||||
name: funcName,
|
||||
returns: returnType,
|
||||
parameters: interFuncParams
|
||||
}
|
||||
interFuncsContent.push(funcObj);
|
||||
} else if (match2) {
|
||||
let interFuncParams: ParamObj[] = []
|
||||
let returnType = getInterFuncRetType(match2[1]);
|
||||
let funcName = match2[2];
|
||||
funcName = util.format('KH%s_%s', generateRandomInteger(MIN_RANDOM, MAX_RANDOM), funcName);
|
||||
let params = getInterFuncParams(match2[3], interFuncParams);
|
||||
interDefine += util.format(' %s:(%s) => %s;\n',funcName, params, returnType);
|
||||
let funcObj: FuncObj = {
|
||||
type: '',
|
||||
name: funcName,
|
||||
returns: returnType,
|
||||
parameters: interFuncParams
|
||||
}
|
||||
interFuncsContent.push(funcObj);
|
||||
} else {
|
||||
let lastTabIndex = paramStr.lastIndexOf(' ');
|
||||
const variableName = paramStr.substring(lastTabIndex + 1, paramStr.length).replace('*', '')
|
||||
const variabletype = paramStr.substring(0, lastTabIndex);
|
||||
let rawType = getJsTypeFromC(variabletype);
|
||||
if (!isJsBasicType(rawType)) {
|
||||
rawType += ' | null';
|
||||
}
|
||||
let variableDefine = ' ' + variableName + ': ' + rawType + ';\n'
|
||||
interDefine += variableDefine;
|
||||
let paramObj: ParamObj = {
|
||||
name: variableName,
|
||||
type: replaceAll(variabletype, 'struct', '').trim(),
|
||||
arraySize: 0
|
||||
}
|
||||
paramsContent.push(paramObj);
|
||||
}
|
||||
}
|
||||
interfaceBody.funcs = interFuncsContent;
|
||||
interfaceBody.params = paramsContent;
|
||||
interfaceContent.interfaceBody = interfaceBody;
|
||||
interfaceList.push(interfaceContent);
|
||||
|
||||
interDefine += '}\n';
|
||||
interfaceListDef += interDefine;
|
||||
}
|
||||
}
|
||||
|
||||
if (basicTypeMatch) {
|
||||
for (let index = 0; index < basicTypeMatch.length; index++) {
|
||||
console.log('Basic type typedef match:', basicTypeMatch[0]); // 输出匹配的基本类型定义
|
||||
let matchs = basicTypeMatch[index].split(' ');
|
||||
let rawType = getJsTypeFromC(matchs[1].trim());
|
||||
let defineType = matchs[2].split(';')
|
||||
let typedefine = 'type ' + defineType[0] + ' = ' + rawType + ';\n';
|
||||
interfaceListDef += typedefine;
|
||||
let typeListContent: TypeList = {
|
||||
typeName: defineType[0],
|
||||
typeBody: matchs[1].trim()
|
||||
}
|
||||
typeList.push(typeListContent);
|
||||
}
|
||||
}
|
||||
|
||||
return interfaceListDef;
|
||||
}
|
||||
|
||||
export function getTypeBody(testType: string, typeList: TypeList[]) {
|
||||
for (let i = 0; i < typeList.length; i++)
|
||||
{
|
||||
if (typeList[i].typeName === testType) {
|
||||
return typeList[i].typeBody;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export function getInterfaceBody(testType: string, interfaceList: InterfaceList[]) {
|
||||
for (let i = 0; i < interfaceList.length; i++)
|
||||
{
|
||||
if (interfaceList[i].interfaceName === testType) {
|
||||
return interfaceList[i].interfaceBody;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------
|
||||
function transTskey2Ckey(key: string) {
|
||||
for(const keyItem of dts2cpp_key) {
|
||||
for(const str of keyItem.keys) {
|
||||
if (key.includes(str)) {
|
||||
return keyItem.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
let replaceKeyList = ['enum', 'struct', 'union'];
|
||||
for(const rkey of replaceKeyList) {
|
||||
key = key.replace(rkey, '').trim();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
function getDtsEnum(rootInfo: GenInfo) {
|
||||
let enumList = rootInfo.parseObj.enums;
|
||||
let out = '';
|
||||
for(const enumItem of enumList) {
|
||||
let enumHead = `export enum ${enumItem.name} {\n`
|
||||
let enumBody = ''
|
||||
enumItem.members.forEach(element => {
|
||||
enumBody += `\t${element},\n`
|
||||
});
|
||||
out += enumHead + enumBody + '};\n\n'
|
||||
if (enumItem.name && enumItem.alias && enumItem.name !== enumItem.alias) {
|
||||
out += `export type ${enumItem.alias} = ${enumItem.name};\n\n`
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function getDtsFunction(rootInfo: GenInfo) {
|
||||
let funcList = rootInfo.parseObj.funcs;
|
||||
let out = '';
|
||||
for(const funcItem of funcList) {
|
||||
let funcHead = '';
|
||||
let funcTail = '';
|
||||
let enumBody = ''
|
||||
let returnType = transTskey2Ckey(funcItem.returns);
|
||||
if (funcItem.type === 'typedef') {
|
||||
funcHead = `export interface ${funcItem.name} {\n`;
|
||||
funcTail = '};\n\n';
|
||||
funcItem.parameters.forEach(element => {
|
||||
if (element.name && element.type) {
|
||||
enumBody += `${element.name}: ${transTskey2Ckey(element.type)}, `
|
||||
}
|
||||
});
|
||||
enumBody = `\t(${enumBody.slice(0, -2)}): ${returnType};\n`
|
||||
out += funcHead + `${enumBody}` + funcTail;
|
||||
} else {
|
||||
funcHead = `export function ${funcItem.name}(`
|
||||
funcTail = `): ${returnType};\n\n`;
|
||||
funcItem.parameters.forEach(element => {
|
||||
if (element.name && element.type) {
|
||||
enumBody += `${element.name}: ${transTskey2Ckey(element.type)}, `
|
||||
}
|
||||
});
|
||||
out += funcHead + enumBody.slice(0, -2) + funcTail;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function getDtsClasses(rootInfo: GenInfo) {
|
||||
let classList = rootInfo.parseObj.classes;
|
||||
let out = '';
|
||||
for(const classItem of classList) {
|
||||
let classHead = `export class ${classItem.name} {\n`
|
||||
let classBody = ''
|
||||
for(const attribute of classItem.variableList) {
|
||||
classBody += `\t${attribute.name}: ${transTskey2Ckey(attribute.type)};\n`
|
||||
};
|
||||
for(const method of classItem.functionList) {
|
||||
let methodContent = '';
|
||||
for(const param of method.parameters) {
|
||||
methodContent = `${param.name}: ${transTskey2Ckey(param.type)}, `;
|
||||
}
|
||||
classBody += `\t${method.name}(${methodContent.slice(0, -2)}): ${transTskey2Ckey(method.returns)};\n`
|
||||
};
|
||||
out += classHead + classBody + '};\n\n'
|
||||
if (classItem.name && classItem.alias) {
|
||||
out += `export type ${classItem.alias} = ${classItem.name};\n\n`
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function getDtsStructs(rootInfo: GenInfo) {
|
||||
let structList = rootInfo.parseObj.structs;
|
||||
let out = '';
|
||||
for(const structItem of structList) {
|
||||
let structHead = `export type ${structItem.name} = {\n`
|
||||
let structBody = ''
|
||||
for(const attribute of structItem.members) {
|
||||
structBody += `\t${attribute.name}: ${transTskey2Ckey(attribute.type)};\n`
|
||||
};
|
||||
for(const method of structItem.functions) {
|
||||
let methodContent = '';
|
||||
for(const param of method.parameters) {
|
||||
if (param.name && param.type) {
|
||||
methodContent = `${param.name}: ${transTskey2Ckey(param.type)}, `;
|
||||
}
|
||||
}
|
||||
structBody += `\t${method.name}(${methodContent.slice(0, -2)}): ${transTskey2Ckey(method.returns)};\n`
|
||||
};
|
||||
out += structHead + structBody + '};\n\n'
|
||||
if (structItem.name && structItem.alias && structItem.name !== structItem.alias) {
|
||||
out += `export type ${structItem.alias} = ${structItem.name};\n\n`
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function getDtsUnions(rootInfo: GenInfo) {
|
||||
let unionList = rootInfo.parseObj.unions;
|
||||
let out = '';
|
||||
for(const unionItem of unionList) {
|
||||
let unionHead = `export type ${unionItem.name} = `
|
||||
let unionBody = ''
|
||||
for(const element of unionItem.members) {
|
||||
unionBody += `${transTskey2Ckey(element.type)} | `
|
||||
};
|
||||
out += unionHead + unionBody.slice(0, -2) + ';\n\n'
|
||||
if (unionItem.name && unionItem.alias && unionItem.name !== unionItem.alias) {
|
||||
out += `export type ${unionItem.alias} = ${unionItem.name};\n\n`
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function genDtsFile(rootInfo: GenInfo) {
|
||||
// gen enums
|
||||
let fileContent = getDtsEnum(rootInfo);
|
||||
// gen functions
|
||||
fileContent += getDtsFunction(rootInfo);
|
||||
// gen classes
|
||||
fileContent += getDtsClasses(rootInfo);
|
||||
// gen struct
|
||||
fileContent += getDtsStructs(rootInfo);
|
||||
// gen union
|
||||
fileContent += getDtsUnions(rootInfo);
|
||||
|
||||
let dtsFileName = rootInfo.fileName + '.d.ts';
|
||||
let dtsContent = interDef + tsFuncContent;
|
||||
|
||||
let outPath = path.join(out, dtsFileName);
|
||||
fs.writeFileSync(outPath, dtsContent);
|
||||
|
||||
let dirPath = path.dirname(rootInfo.rawFilePath);
|
||||
let outPath = path.join(dirPath, dtsFileName);
|
||||
fs.writeFileSync(outPath, fileContent);
|
||||
console.info('generate success!')
|
||||
return outPath;
|
||||
}
|
@ -29,7 +29,7 @@ function parseEnum(data: string) {
|
||||
const enumName = match[1] ||match[3] || match[4];
|
||||
const aliasName = match[3];
|
||||
const membersString = match[2] || match[5];
|
||||
const members = membersString.split(';')
|
||||
const members = membersString.split(',')
|
||||
.map(member => member.trim().replace(/[\n\r\s]/g, ''))
|
||||
.filter(member => member.length > 0);
|
||||
let enumItem = {
|
||||
@ -45,7 +45,7 @@ function parseEnum(data: string) {
|
||||
|
||||
function parseUnion(data: string) {
|
||||
// 使用正则表达式提取联合体定义
|
||||
const unionRegex = /typedef\s+struct\s*(\w*)\s*{([^}]*)}\s*(\w+)\s*;|union\s+(\w+)\s*{([^}]*)}\s*;/g;
|
||||
const unionRegex = /typedef\s+union\s*(\w*)\s*{([^}]*)}\s*(\w+)\s*;|union\s+(\w+)\s*{([^}]*)}\s*;/g;
|
||||
const unions: UnionObj[] = [];
|
||||
let match;
|
||||
while ((match = unionRegex.exec(data)) !== null) {
|
||||
@ -64,7 +64,8 @@ function parseUnion(data: string) {
|
||||
|
||||
members.forEach(declaration => {
|
||||
// 使用正则表达式匹配类型和变量名
|
||||
const match = declaration.match(/(\w+)\s+(\w+)(\[(\d+)\])?/);
|
||||
// const match = declaration.match(/(\w+)\s+(\w+)(\[(\d+)\])?/);
|
||||
const match = declaration.match(/(\w[\w\s\*]+)\s+(\w+)\s*/);
|
||||
if (match) {
|
||||
const type = match[1]; // 类型
|
||||
const variable = match[2]; // 变量名
|
||||
@ -101,25 +102,59 @@ function parseStruct(data: string) {
|
||||
const members = membersString.split(';')
|
||||
.map(member => member.trim().replace(/[\n\r]/g, ''))
|
||||
.filter(member => member.length > 0);
|
||||
|
||||
const variables: string[] = [];
|
||||
const methods: string[] = [];
|
||||
|
||||
members.forEach(member => {
|
||||
// 匹配方法声明
|
||||
const methodRegex = /(\w[\w\s\*]+)\s+(\w+)\(([^)]*)\)\s*/;
|
||||
const variableRegex = /(\w[\w\s\*]+)\s+(\w+)\s*/;
|
||||
|
||||
if (methodRegex.test(member)) {
|
||||
methods.push(member.trim().replace(/[\n\r]/g, ''));
|
||||
} else if (variableRegex.test(member)) {
|
||||
variables.push(member.trim().replace(/[\n\r]/g, ''));
|
||||
}
|
||||
});
|
||||
|
||||
let structItem: StructObj = {
|
||||
"name": structName,
|
||||
"alias": alias,
|
||||
"members": parseMembers(members),
|
||||
"functions": []
|
||||
"members": parseMembers(variables),
|
||||
"functions": parseMethods(methods)
|
||||
}
|
||||
|
||||
structs.push(structItem);
|
||||
}
|
||||
console.info(` return structs: ${JSON.stringify(structs)}`);
|
||||
// console.info(` return structs: ${JSON.stringify(structs)}`);
|
||||
return structs;
|
||||
}
|
||||
// /^(const\s+)?([\w\s*]+)\s+(\w+)(?:\[(\d+)\])?$/
|
||||
function parseParameters(members: string[]): ParamObj[] {
|
||||
// const memberRegex = /^(const\s+)?([\w\s*]+)\s+(\w+)(?:\[(\d+)\])?$/;
|
||||
const memberRegex = /^(const\s+)?([\w\s*]+)\s+(\w+)(?:\[(\d*)\])?$/;
|
||||
// console.info(` parseParameters members: ${JSON.stringify(members)}`);
|
||||
return members.map(member => {
|
||||
const match = member.trim().match(memberRegex);
|
||||
// console.info(` parseParameters match: ${JSON.stringify(match)}`);
|
||||
if (match) {
|
||||
const type = match[2];
|
||||
const name = match[3];
|
||||
// const arraySize = match[4] ? parseInt(match[4], 10) : -1;
|
||||
const arraySize = match[4] && match[4] !== "" ? parseInt(match[4], 10) : -1;
|
||||
return { type, name, arraySize };
|
||||
}
|
||||
return {};
|
||||
}).filter((m): m is ParamObj => m !== null); // 类型保护
|
||||
}
|
||||
|
||||
function parseMembers(members: string[]): ParamObj[] {
|
||||
const memberRegex = /(?:public:|private:)?\s*(\w+(?:\s+\w+)?)\s+(\w+)(?:\[(\d+)\])?/;
|
||||
|
||||
// console.info(` parseMembers members: ${JSON.stringify(members)}`);
|
||||
return members.map(member => {
|
||||
const match = member.trim().match(memberRegex);
|
||||
// console.info(` parseMembers match: ${JSON.stringify(match)}`);
|
||||
if (match) {
|
||||
const type = match[1];
|
||||
const name = match[2];
|
||||
@ -130,8 +165,9 @@ function parseMembers(members: string[]): ParamObj[] {
|
||||
}).filter((m): m is ParamObj => m !== null); // 类型保护
|
||||
}
|
||||
|
||||
function parseFunctions(functions: string[]): FuncObj[] {
|
||||
const functionRegex = /(\w+)\s+(\w+)\(([^)]*)\)/; // 正则表达式匹配返回值、函数名和参数
|
||||
function parseMethods(functions: string[]): FuncObj[] {
|
||||
const functionRegex = /^(\w[\w\s]*\*?)\s+(\w+)\((.*?)\)$/;
|
||||
// const functionRegex = /(\w+)\s+(\w+)\(([^)]*)\)/; // 正则表达式匹配返回值、函数名和参数
|
||||
|
||||
return functions.map(func => {
|
||||
const match = func.trim().match(functionRegex);
|
||||
@ -139,7 +175,7 @@ function parseFunctions(functions: string[]): FuncObj[] {
|
||||
const returns = match[1]; // 返回值类型
|
||||
const name = match[2]; // 方法名
|
||||
const parameterstr = match[3].split(',').map(param => param.trim()).filter(Boolean); // 分割参数并去除空值
|
||||
const parameters = parseMembers(parameterstr);
|
||||
const parameters = parseParameters(parameterstr);
|
||||
return { returns, name, parameters };
|
||||
}
|
||||
return {};
|
||||
@ -176,7 +212,7 @@ function parseClass(data: string) {
|
||||
const variableList = parseMembers(variables);
|
||||
// console.log(`parseMembers: ${JSON.stringify(variableList)}`)
|
||||
|
||||
const functionList: FuncObj[] = parseFunctions(methods);
|
||||
const functionList: FuncObj[] = parseMethods(methods);
|
||||
// console.log(`parsedFunctions: ${JSON.stringify(functionList)}`);
|
||||
|
||||
const classItem: ClassObj = {
|
||||
@ -187,11 +223,11 @@ function parseClass(data: string) {
|
||||
}
|
||||
classes.push(classItem);
|
||||
}
|
||||
console.info(` return classes: ${JSON.stringify(classes)}`);
|
||||
// console.info(` return classes: ${JSON.stringify(classes)}`);
|
||||
return classes;
|
||||
}
|
||||
|
||||
function parseFunction(data: string) {
|
||||
function parseFunctionOld(data: string) {
|
||||
// 使用正则表达式提取函数定义
|
||||
const functionRegex1 = /([a-zA-Z_]\w*\s+)+([*a-zA-Z_]\w+)\s*\(([^)]*)\)\s*(?={|;)/g;
|
||||
const functionRegex2 = /(\w+\s*\(.*?\)\s+)(\w+)\s*\((.*?)\);\s*/g;
|
||||
@ -237,17 +273,19 @@ function parseFunction(data: string) {
|
||||
arraySize: 0,
|
||||
})
|
||||
}
|
||||
console.info(`ret: ${returnType} func: ${functionName} params:(${paramResList.map(ditem => {
|
||||
return ' type: ' + ditem.type + ', ' + 'name: ' + ditem.name;
|
||||
})})`)
|
||||
// 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
|
||||
type: 'function',
|
||||
name: functionName,
|
||||
returns: returnType,
|
||||
parameters: paramResList
|
||||
}
|
||||
return funcRes;
|
||||
}
|
||||
let res: FuncObj = {
|
||||
type: '',
|
||||
name: '',
|
||||
returns: '',
|
||||
parameters: []
|
||||
@ -256,6 +294,7 @@ function parseFunction(data: string) {
|
||||
})
|
||||
.filter(detail => detail !== null);
|
||||
|
||||
console.log(`parse oldfunc : ${JSON.stringify(functionDetails)}`)
|
||||
return functionDetails;
|
||||
// if (functionDetails.length > 0) {
|
||||
// const funcs = [...functionDetails.filter((funcItem) : funcItem is FuncObj => funcItem !== null)];
|
||||
@ -266,13 +305,37 @@ function parseFunction(data: string) {
|
||||
// return ' type: ' + ditem.type + ', ' + 'name: ' + ditem.name;
|
||||
// })})`
|
||||
// ).join('\n');
|
||||
// console.info(` return parseFunctions: ${JSON.stringify(funcs)}`);
|
||||
// console.info(` return parseMethods: ${JSON.stringify(funcs)}`);
|
||||
// return funcs;
|
||||
// } else {
|
||||
// vscode.window.showInformationMessage('No functions found.');
|
||||
// }
|
||||
}
|
||||
|
||||
function parseFunction(data: string): FuncObj[] {
|
||||
// const funcRegex = /^(static\s+)?(const\s+)?([\w\s\[\]*]+)\s+(\w+)\s*\(([^)]*)\);/gm;
|
||||
const funcRegex = /(?:typedef\s+([\w\s\[\]*]+)\s+\(\*\s*(\w+)\)\s*\(([^)]*)\);|^(static\s+)?(const\s+)?([\w\s\[\]*]+)\s+(\w+)\s*\(([^)]*)\);)/gm
|
||||
const functions: FuncObj[] = []
|
||||
let match;
|
||||
while ((match = funcRegex.exec(data)) !== null) {
|
||||
// console.log(`func match: ${JSON.stringify(match)}`)
|
||||
const returnType = match[1] ? match[1].trim() : match[6].trim(); //match[3].trim();
|
||||
const name = match[2] ? match[2].trim() : match[7].trim(); //match[4].trim();
|
||||
const params = (match[3] ? match[3] : match[8] || "").split(',').map(param => param.trim()).filter(param => param); //match[5].split(',').map(param => param.trim()).filter(param => param);
|
||||
let isInterface = match[0].includes('typedef');
|
||||
let funcItem: FuncObj = {
|
||||
"type": isInterface ? "typedef" : "function",
|
||||
"returns": returnType,
|
||||
"name": name,
|
||||
"parameters": parseParameters(params)
|
||||
}
|
||||
|
||||
functions.push(funcItem);
|
||||
}
|
||||
// console.info(` return functions: ${JSON.stringify(functions)}`);
|
||||
return functions;
|
||||
}
|
||||
|
||||
export function parseHeaderFile(filePath: string): Promise<ParseObj> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let parseRes: ParseObj = {
|
||||
@ -303,7 +366,7 @@ export function parseHeaderFile(filePath: string): Promise<ParseObj> {
|
||||
classes: classList,
|
||||
funcs: funcList
|
||||
}
|
||||
console.info(` return parse result: ${JSON.stringify(parseRes)}`);
|
||||
// console.info(` return parse result: ${JSON.stringify(parseRes)}`);
|
||||
resolve(parseRes);
|
||||
});
|
||||
});
|
||||
|
14
src/vscode_plugin/src/template/dtscpp/dts2cpp_key.ts
Normal file
14
src/vscode_plugin/src/template/dtscpp/dts2cpp_key.ts
Normal file
@ -0,0 +1,14 @@
|
||||
export let dts2cpp_key = [
|
||||
{
|
||||
keys: ['char', 'string'],
|
||||
value: 'string'
|
||||
},
|
||||
{
|
||||
keys: ['size_t', 'int', 'short', 'long', 'double', 'float'],
|
||||
value: 'number'
|
||||
},
|
||||
{
|
||||
keys: ['bool'],
|
||||
value: 'boolean'
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue
Block a user