Skip to content

Commit 5e00c85

Browse files
🐛 Bug(Blueprint): 修复 BP→BS 转换中不可达节点未被排除的问题,新增从 Entry 出发的 BFS 可达性分析
1 parent d8f9305 commit 5e00c85

3 files changed

Lines changed: 46 additions & 3 deletions

File tree

KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/ExecutionFlowWalker.cs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,18 @@ public void WalkExecutionFlow(ReverseConversionContext ctx)
5656
/// <summary>
5757
/// Generates statements from stored BlockScopes (BlockScopes-based path).
5858
/// Processes each scope, generates statements for its nodes, resolves control flow,
59-
/// and inserts ToLoopCond statements.
59+
/// and inserts ToLoopCond statements. Nodes not reachable from Entry via execution
60+
/// edges are excluded.
6061
/// </summary>
6162
public void WalkFromBlockScopes(Contract.Workflow.Blueprint blueprint, ReverseConversionContext ctx)
6263
{
6364
// Build scopesByName lookup
6465
foreach (var scope in blueprint.BlockScopes)
6566
ctx.ScopesByName[scope.Name] = scope;
6667

68+
// Reachability filter: only include nodes reachable from Entry via exec edges
69+
var reachableNodeIds = FindReachableNodeIds(blueprint, ctx);
70+
6771
// Generate statements from stored block membership
6872
foreach (var scope in blueprint.BlockScopes)
6973
{
@@ -81,6 +85,9 @@ public void WalkFromBlockScopes(Contract.Workflow.Blueprint blueprint, ReverseCo
8185

8286
foreach (var nodeId in scope.NodeIds)
8387
{
88+
// Skip nodes not reachable from Entry via execution edges
89+
if (!reachableNodeIds.Contains(nodeId)) continue;
90+
8491
if (!ctx.NodeById.TryGetValue(nodeId, out var node)) continue;
8592
var stmt = GenerateStatement(node, ctx);
8693
if (stmt != null)
@@ -117,6 +124,42 @@ public void WalkFromBlockScopes(Contract.Workflow.Blueprint blueprint, ReverseCo
117124
DetectAndInsertLoopbackToLoopConds(blueprint, ctx);
118125
}
119126

127+
// ─── Reachability Analysis ──────────────────────────────────────────
128+
129+
/// <summary>
130+
/// Performs BFS from the Entry node following only execution output pins
131+
/// to determine which nodes are reachable from Entry. Nodes not in the
132+
/// returned set should be excluded from BS output.
133+
/// </summary>
134+
private static HashSet<string> FindReachableNodeIds(
135+
Contract.Workflow.Blueprint blueprint, ReverseConversionContext ctx)
136+
{
137+
var reachable = new HashSet<string>();
138+
var entry = blueprint.Nodes.FirstOrDefault(n => n.NodeType == BlueprintNodeType.Entry);
139+
if (entry == null) return reachable;
140+
141+
var queue = new Queue<BlueprintNode>();
142+
queue.Enqueue(entry);
143+
reachable.Add(entry.Id);
144+
145+
while (queue.Count > 0)
146+
{
147+
var current = queue.Dequeue();
148+
foreach (var pin in current.OutputPins)
149+
{
150+
if (pin.Type != PinType.Execution) continue;
151+
var conn = ctx.ExecConnections.FirstOrDefault(c => c.SourcePinId == pin.Id);
152+
if (conn == null) continue;
153+
var target = blueprint.GetNodeById(conn.TargetNodeId);
154+
if (target == null || reachable.Contains(target.Id)) continue;
155+
reachable.Add(target.Id);
156+
queue.Enqueue(target);
157+
}
158+
}
159+
160+
return reachable;
161+
}
162+
120163
// ─── Node Walking ────────────────────────────────────────────────────
121164

122165
private void WalkNode(BlueprintNode node, BlockDefinition currentBlock,

0 commit comments

Comments
 (0)