Skip to content

Commit

Permalink
feat: Add cxx-parser related parsers (#1)
Browse files Browse the repository at this point in the history
* feat: Add cxx-parser related parsers
  • Loading branch information
littleGnAl authored Sep 19, 2023
1 parent e0b5e4a commit ba77625
Show file tree
Hide file tree
Showing 14 changed files with 1,285 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.ccls-cache/
node_modules/
src/**/*.js
package-lock.json
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@agoraio-extensions:registry=https://npm.pkg.github.com
674 changes: 673 additions & 1 deletion package-lock.json

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,21 @@
"name": "@agoraio-extensions/terra_shared_configs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"postinstall": "tsc"
},
"author": "",
"license": "ISC"
"license": "ISC",
"dependencies": {
"@agoraio-extensions/cxx-parser": ">=0.1.3",
"@agoraio-extensions/terra-core": ">=0.1.2",
"@types/node": "^20.6.0",
"@types/mustache": "^4.2.2",
"glob": "^10.3.4",
"mustache": "^4.2.0",
"ts-node": "^10.9.1",
"typescript": "^4.8.4"
}
}
7 changes: 7 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export * from './parsers/add_node_parser';
export * from './parsers/fix_enum_constant_parser';
export * from './parsers/order_node_parser';
export * from './parsers/pointer_to_array_parser';
export * from './parsers/remove_node_parser';
export * from './parsers/update_simple_type_parser';
export * from './renderers/mustache_renderer';
85 changes: 85 additions & 0 deletions src/parsers/add_node_parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import path from "path";
import {
ParseResult,
TerraContext,
} from "@agoraio-extensions/terra-core";
import { CXXFile, CXXParser, CXXParserConfigs, CXXTYPE, Clazz } from "@agoraio-extensions/cxx-parser";


function generateCustomNodes(parseConfig: TerraContext, cxxParserConfigs: CXXParserConfigs): ParseResult | undefined {
const customParser = CXXParser;
return customParser(
parseConfig,
cxxParserConfigs,
undefined,
);
}

export function AddNodeParser(
terraContext: TerraContext,
args: any,
preParseResult?: ParseResult
): ParseResult | undefined {
const customNodes = generateCustomNodes(terraContext, args);
customNodes?.nodes.forEach((f) => {
let file = f as CXXFile;
// find file which has same name after remove custrom prefix
const foundFile = preParseResult?.nodes.find(
(it) => {
return path.basename(file.file_path) ===
`${path.basename(
(it as CXXFile).file_path
)}`;
}

);
if (!foundFile) {
return;
}

file.nodes.forEach((customNode) => {
if (!(customNode.__TYPE === CXXTYPE.Clazz)) {
// only add enum and struct
if (
customNode.__TYPE === CXXTYPE.Enumz ||
customNode.__TYPE === CXXTYPE.Struct
) {
(foundFile as CXXFile).nodes.push(customNode);
}
return;
}

// find class which has same name
const foundClass = (foundFile as CXXFile).nodes.find(
(it) => it.__TYPE === CXXTYPE.Clazz && it.name === customNode.name
) as Clazz;
if (!foundClass) {
// add class if not found
(foundFile as CXXFile).nodes.push(customNode);
return;
}

(customNode as Clazz).methods.forEach((customMethod) => {
// find method which has same name
const foundMethodIndex = foundClass.methods.findIndex(
(it) => it.name === customMethod.name
);
if (foundMethodIndex == -1) {
// add method if not found
foundClass.methods.push(customMethod);
return;
}

// mark method as custom
customMethod.user_data = foundClass.methods[foundMethodIndex];
// replace method with custom method
foundClass.methods[foundMethodIndex] = customMethod;
// remove overload function unless it has been marked as custom
foundClass.methods = foundClass.methods.filter(
(it) => it.name !== customMethod.name || it.user_data !== undefined
);
});
});
});
return preParseResult;
}
65 changes: 65 additions & 0 deletions src/parsers/fix_enum_constant_parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { CXXFile, CXXTYPE, EnumConstant, Enumz } from '@agoraio-extensions/cxx-parser';
import { ParseResult, TerraContext } from '@agoraio-extensions/terra-core';

const TYPES_SIZE: Record<string, string> = {
'sizeof(int16_t)': '2',
};

function fixEnumConstantValue(enumz: Enumz, constant: EnumConstant): string {
let value = constant.source;
enumz.enum_constants.forEach((it) => {
if (value.includes(it.name)) {
// 当前枚举值包含其他枚举值,需要替换,示例如下:
// QUALITY_UNSUPPORTED = 7,
// QUALITY_DETECTING = QUALITY_UNSUPPORTED,
value = value.replace(it.name, it.value);
}
});
Object.keys(TYPES_SIZE).forEach((it) => {
if (value.includes(it)) {
// 当前枚举值包含sizeof表达式,需要替换,示例如下:
// QUALITY_UNSUPPORTED = sizeof(int16_t),
value = value.replace(it, TYPES_SIZE[it] as string);
}
});
if (!/^\d+$/.test(value)) {
// 当前枚举值不是纯数字, 执行表达式计算,示例如下:
// QUALITY_UNSUPPORTED = 1 << 4,
return `${eval(`${value}`)}`;
}
// 当前枚举值是纯数字, 直接返回
return `${value}`;
}

export function FixEnumConstantParser(
terraContext: TerraContext,
args: any,
preParseResult?: ParseResult
): ParseResult | undefined {
preParseResult?.nodes.forEach((file) => {
(file as CXXFile).nodes.forEach((customNode) => {
if (customNode.__TYPE === CXXTYPE.Enumz) {
let enumz = customNode.asEnumz();
let lastEnumValue = -1;
enumz.enum_constants.forEach((enumConstant) => {
if (enumConstant.source === '') {
// 当前枚举source为空,需要Parser赋值,示例如下:
// QUALITY_UNSUPPORTED = 7,
// QUALITY_DETECTING,
enumConstant.source = `${++lastEnumValue}`;
}
lastEnumValue = parseInt(enumConstant.source);
if (isNaN(lastEnumValue)) {
enumConstant.value = fixEnumConstantValue(
enumz,
enumConstant
);
} else {
enumConstant.value = `${lastEnumValue}`;
}
});
}
});
});
return preParseResult;
}
Empty file.
30 changes: 30 additions & 0 deletions src/parsers/order_node_parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { CXXFile, CXXTYPE, CXXTerraNode } from "@agoraio-extensions/cxx-parser";
import { ParseResult, TerraContext } from "@agoraio-extensions/terra-core";

export function OrderNodeParser(
terraContext: TerraContext,
args: any,
preParseResult?: ParseResult
): ParseResult | undefined {
preParseResult?.nodes.forEach((f) => {
let file = f as CXXFile;
const parentNodes = new Map<string, CXXTerraNode>();
file.nodes.forEach((node) => {
if (node.__TYPE === CXXTYPE.Struct || node.__TYPE === CXXTYPE.Clazz) {
parentNodes.set(node.name, node);
}
});
file.nodes.forEach((node, index) => {
if (node.__TYPE === CXXTYPE.Struct || node.__TYPE === CXXTYPE.Enumz) {
if (parentNodes.has(node.parent_name)) {
// 如果当前node属于某个父节点,那么将当前node放到父节点之前
const parentNode = parentNodes.get(node.parent_name)!;
file.nodes[index] = parentNode;
file.nodes[file.nodes.findIndex((item) => item === parentNode)] =
node;
}
}
});
});
return preParseResult;
}
74 changes: 74 additions & 0 deletions src/parsers/pointer_to_array_parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { CXXFile, CXXTYPE, CXXTerraNode, MemberVariable, SimpleTypeKind, Variable } from '@agoraio-extensions/cxx-parser';
import { ParseResult, TerraContext, resolvePath } from '@agoraio-extensions/terra-core';
import { readFileSync } from 'fs';

export type PointerToArrayParserArgs = {
configJson?: string;
configJsonFilePath?: string;
};

function markArray(
nodes: (Variable | MemberVariable)[],
parentNode: CXXTerraNode,
name_configs: string[],
regex_configs: string[] = []
) {
nodes.forEach((node) => {
if (node.type.kind !== SimpleTypeKind.pointer_t) {
return;
}

const config = name_configs.find(
(v) => v === `${parentNode.fullName}.${node.realName}`
);
if (config) {
// 配置表中配置了该变量则标记为数组
node.type.kind = SimpleTypeKind.array_t;
return;
}

regex_configs.forEach((v) => {
const regex = new RegExp(v);
if (regex.test(node.realName)) {
// 满足正则表达式则标记为数组
node.type.kind = SimpleTypeKind.array_t;
}
});
});
}

export function PointerToArrayParser(
terraContext: TerraContext,
_args: any,
preParseResult?: ParseResult
): ParseResult | undefined {
let args = _args as PointerToArrayParserArgs;

if (args.configJson === undefined) {
args.configJson = readFileSync(
resolvePath(args.configJsonFilePath!, terraContext.configDir)
// getAbsolutePath(parseConfig.rootDir, args.configJsonFilePath)
).toString();
}
const configs: string[] = JSON.parse(args.configJson!);
let name_configs = configs.filter(
(v) => !v.startsWith('^') && !v.endsWith('$')
);
let regex_configs = configs.filter(
(v) => v.startsWith('^') || v.endsWith('$')
);
preParseResult?.nodes.forEach((f) => {
let file = f as CXXFile;
file.nodes.forEach((node) => {
if (node.__TYPE === CXXTYPE.Struct) {
markArray(node.asStruct().member_variables, node, name_configs, regex_configs);
} else if (node.__TYPE === CXXTYPE.Clazz) {
markArray(node.asClazz().member_variables, node, name_configs, regex_configs);
node.asClazz().methods.forEach((method) => {
markArray(method.parameters, method, name_configs, regex_configs);
});
}
});
});
return preParseResult;
}
68 changes: 68 additions & 0 deletions src/parsers/remove_node_parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { CXXFile, CXXTYPE, CXXTerraNode } from '@agoraio-extensions/cxx-parser';
import { ParseResult, TerraContext, resolvePath } from '@agoraio-extensions/terra-core';
import { readFileSync } from 'fs';

export type RemoveNodeParserArgs = {
configJson?: string;
configJsonFilePath?: string;
};

function filterNode<T extends CXXTerraNode>(nodes: T[], name_configs: string[], regex_configs: string[]): T[] {
return nodes.filter((node) => {
var flag = true;
if (name_configs.includes(node.fullName)) {
// 配置表中配置了该node则过滤掉
flag = false;
}
regex_configs.forEach((v) => {
const regex = new RegExp(v);
if (regex.test(node.realName)) {
// 满足正则表达式则过滤掉
flag = false;
}
});
return flag;
});
}


export function RemoveNodeParser(
terraContext: TerraContext,
_args: any,
preParseResult?: ParseResult
): ParseResult | undefined {
let args = _args as RemoveNodeParserArgs;
if (args.configJson === undefined) {
args.configJson = readFileSync(
resolvePath(args.configJsonFilePath!, terraContext.configDir)
// getAbsolutePath(parseConfig.rootDir, args.configJsonFilePath)
).toString();
}
const configs: string[] = JSON.parse(args.configJson!);
let name_configs = configs.filter(
(v) => !v.startsWith('^') && !v.endsWith('$')
);
let regex_configs = configs.filter(
(v) => v.startsWith('^') || v.endsWith('$')
);
preParseResult?.nodes.forEach((f) => {
let file = f as CXXFile;
file.nodes = filterNode(file.nodes, name_configs, regex_configs);
file.nodes.forEach((node) => {
if (node.__TYPE === CXXTYPE.Struct) {
node.asStruct().member_variables = filterNode(
node.asStruct().member_variables, name_configs, regex_configs
);
} else if (node.__TYPE === CXXTYPE.Clazz) {
node.asClazz().member_variables = filterNode(
node.asClazz().member_variables, name_configs, regex_configs
);
node.asClazz().methods = filterNode(node.asClazz().methods, name_configs, regex_configs);
node.asClazz().methods.forEach((method) => {
method.parameters = filterNode(method.parameters, name_configs, regex_configs);
});
}
});
});
return preParseResult;
}
Loading

0 comments on commit ba77625

Please sign in to comment.