From 4ac8a01c6240c94dffd4e4acb3181d16bb29f0ff Mon Sep 17 00:00:00 2001 From: codetypes Date: Wed, 19 Mar 2025 13:15:51 +0800 Subject: [PATCH] check expr in arg array --- .eslintrc.cjs | 1 - src/components/editor.tsx | 27 +++++++++++----- src/components/inspector.tsx | 6 ++-- src/components/register-node.ts | 56 ++++++++++++++++++++++++--------- src/misc/b3type.ts | 4 +-- src/misc/b3util.ts | 11 ++++++- 6 files changed, 77 insertions(+), 28 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index e59eea1..0f91df9 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -15,7 +15,6 @@ module.exports = { "react-refresh/only-export-components": "warn", // TODO: - "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-unsafe-assignment": "off", "@typescript-eslint/no-unsafe-argument": "off", diff --git a/src/components/editor.tsx b/src/components/editor.tsx index 15dc94a..45ade8b 100644 --- a/src/components/editor.tsx +++ b/src/components/editor.tsx @@ -1,5 +1,5 @@ import { ArrowDownOutlined, ArrowUpOutlined, CloseOutlined } from "@ant-design/icons"; -import G6, { G6GraphEvent, Item, TreeGraph } from "@antv/g6"; +import G6, { G6GraphEvent, Item, Matrix, TreeGraph } from "@antv/g6"; import { dialog } from "@electron/remote"; import { useSize } from "ahooks"; import { Button, Dropdown, Flex, FlexProps, Input, InputRef, MenuProps } from "antd"; @@ -319,7 +319,7 @@ export const Editor: FC = ({ onUpdate: updateState, data: editor, . node.def.args?.forEach((arg) => { if (isExprType(arg.type)) { - const expr: string | string[] = node.args?.[arg.name]; + const expr = node.args?.[arg.name] as string | string[] | undefined; if (typeof expr === "string") { for (const v of b3util.parseExpr(expr)) { if (highlight.includes(v)) { @@ -399,10 +399,20 @@ export const Editor: FC = ({ onUpdate: updateState, data: editor, . } } if (!found && node.args) { - for (const str in node.args) { - if (includeString(str, option) || includeString(node.args[str], option)) { - found = true; - break; + loop: for (const str in node.args) { + const value = node.args[str]; + if (typeof value === "string") { + if (includeString(value, option)) { + found = true; + break loop; + } + } else if (value instanceof Array) { + for (const v of value) { + if (includeString(v, option)) { + found = true; + break loop; + } + } } } } @@ -900,6 +910,7 @@ export const Editor: FC = ({ onUpdate: updateState, data: editor, . const icon = data.collapsed ? G6.Marker.expand : G6.Marker.collapse; const marker = item .get("group") + // eslint-disable-next-line @typescript-eslint/no-explicit-any .find((ele: any) => ele.get("name") === "collapse-icon"); editor.graph.refresh(); marker.attr("symbol", icon); @@ -935,9 +946,9 @@ export const Editor: FC = ({ onUpdate: updateState, data: editor, . }, }); - editor.graph.on("viewportchange", (data: any) => { + editor.graph.on("viewportchange", (data) => { if (data.action === "translate" || data.action === "zoom") { - editor.graphMatrix = data.matrix; + editor.graphMatrix = data.matrix as Matrix; } }); diff --git a/src/components/inspector.tsx b/src/components/inspector.tsx index c109c70..01615bc 100644 --- a/src/components/inspector.tsx +++ b/src/components/inspector.tsx @@ -106,6 +106,7 @@ const TreeInspector: FC = () => { form.setFieldValue("subtree", data.subtree); }, [workspace.editingTree, groupDefs]); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const finish = (values: any) => { workspace.editing?.dispatch("updateTree", { data: { @@ -117,10 +118,10 @@ const TreeInspector: FC = () => { .map((v) => (v.value ? v.name : undefined)) .filter((v) => v) .sort(), - declvar: (values["declvar"] as VarDef[]) + declvar: (values.declvar as VarDef[]) .filter((v) => v && v.name) .sort((a, b) => a.name.localeCompare(b.name)), - import: (values["import"] as ImportDef[]) + import: (values.import as ImportDef[]) .filter((v) => v && v.path) .sort((a, b) => a.path.localeCompare(b.path)) .map((v) => ({ @@ -633,6 +634,7 @@ const NodeInspector: FC = () => { const disabled = !editingNode.editable; // update value + // eslint-disable-next-line @typescript-eslint/no-explicit-any const finish = (values: any) => { const data = {} as NodeModel; data.id = editingNode.data.id; diff --git a/src/components/register-node.ts b/src/components/register-node.ts index 4792749..52b282b 100644 --- a/src/components/register-node.ts +++ b/src/components/register-node.ts @@ -1,4 +1,5 @@ import G6 from "@antv/g6"; +import { NodeDef } from "../behavior3/src/behavior3"; import { useWorkspace } from "../contexts/workspace-context"; import { TreeGraphData, getNodeType, isExprType } from "../misc/b3type"; import { checkTreeData, nodeDefs, parseExpr, usingGroups, usingVars } from "../misc/b3util"; @@ -71,9 +72,43 @@ const toBreakWord = (str: string, maxWidth: number, fontSize?: string) => { }; }; +const foundUndefined = (value?: string[]) => { + if (!value || !usingVars) { + return false; + } + return value.some((v) => v && usingVars?.[v] === undefined); +}; + +const foundUndefinedInArgs = (def: NodeDef, data: TreeGraphData) => { + if (!def.args || !data.args || !usingVars) { + return false; + } + for (const arg of def.args) { + if (!isExprType(arg.type)) { + continue; + } + const expr = data.args[arg.name] as string | string[] | undefined; + if (!expr) { + continue; + } + if (typeof expr === "string") { + if (foundUndefined(parseExpr(expr))) { + return true; + } + } else if (Array.isArray(expr)) { + for (const str of expr) { + if (foundUndefined(parseExpr(str))) { + return true; + } + } + } + } + return false; +}; + export const calcTreeDataSize = (data: TreeGraphData) => { let height = 50 + 2; - const updateHeight = (obj: any) => { + const updateHeight = (obj: unknown) => { if ((Array.isArray(obj) && obj.length) || (obj && Object.keys(obj).length > 0)) { const { line } = toBreakWord(`${i18n.t("regnode.args")}${JSON.stringify(obj)}`, 200); height += 20 * line; @@ -88,7 +123,7 @@ export const calcTreeDataSize = (data: TreeGraphData) => { return [220, height]; }; -const NODE_COLORS: any = { +const NODE_COLORS = { ["Composite"]: "#34d800", ["Decorator"]: "#ff6700", ["Condition"]: "#e4148b", @@ -149,18 +184,11 @@ G6.registerNode( if ( !nodeDefs.has(data.name) || (data.path && !data.children?.length) || - !checkTreeData(data) || (nodeDef.group && !nodeDef.group.some((g) => usingGroups[g])) || - (usingVars && - (data.input?.some((v) => v && usingVars?.[v] === undefined) || - data.output?.some((v) => v && usingVars?.[v] === undefined) || - nodeDef.args?.some( - (v) => - isExprType(v.type) && - parseExpr(data.args?.[v.name] ?? "").some( - (vv) => vv && usingVars?.[vv] === undefined - ) - ))) + !checkTreeData(data) || + foundUndefined(data.input) || + foundUndefined(data.output) || + foundUndefinedInArgs(nodeDef, data) ) { classify = "Error"; color = NODE_COLORS[classify]; @@ -359,7 +387,7 @@ G6.registerNode( }); } - const args: any = data.args; + const args = data.args; if (nodeDef.args && args && Object.keys(args).length > 0) { const { str, line } = toBreakWord(`${i18n.t("regnode.args")}${JSON.stringify(args)}`, 200); if (data.highlightArgs) { diff --git a/src/misc/b3type.ts b/src/misc/b3type.ts index 3c9fd93..604b7d4 100644 --- a/src/misc/b3type.ts +++ b/src/misc/b3type.ts @@ -24,7 +24,7 @@ export interface NodeModel { id: number; name: string; desc?: string; - args?: { [key: string]: any }; + args?: { [key: string]: unknown }; input?: string[]; output?: string[]; children?: NodeModel[]; @@ -74,7 +74,7 @@ export interface TreeModel { export interface TreeGraphData extends G6TreeGraphData { name: string; desc?: string; - args?: { [key: string]: any }; + args?: { [key: string]: unknown }; input?: string[]; output?: string[]; children?: TreeGraphData[]; diff --git a/src/misc/b3util.ts b/src/misc/b3util.ts index 4b54fa7..01e9caf 100644 --- a/src/misc/b3util.ts +++ b/src/misc/b3util.ts @@ -325,8 +325,17 @@ export const checkNodeData = (data: NodeModel | null | undefined) => { if (data.args && conf.args) { for (const arg of conf.args) { + const value = data.args?.[arg.name] as string | string[] | undefined; if (isExprType(arg.type)) { - for (const v of parseExpr(data.args[arg.name] ?? "")) { + const vars: string[] = []; + if (typeof value === "string") { + vars.push(...parseExpr(value)); + } else if (Array.isArray(value)) { + for (const v of value) { + vars.push(...parseExpr(v)); + } + } + for (const v of vars) { if (v && !usingVars[v]) { error(data, `expr variable '${arg.name}' is not defined`); hasError = true;