mirror of
https://gitee.com/openharmony/napi_generator
synced 2024-11-23 08:20:01 +00:00
fix code check
Signed-off-by: wangshi <wangshi@kaihong.com>
This commit is contained in:
parent
520ce30585
commit
0f44deb1e5
@ -1,418 +0,0 @@
|
||||
/*
|
||||
* 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!')
|
||||
}
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export let dts2cpp_key = [
|
||||
{
|
||||
keys: ['char', 'string'],
|
||||
|
Loading…
Reference in New Issue
Block a user