Skip to content

Commit c9b8b53

Browse files
🧩 Refactor(BlockScript): Introduce BlockScriptWellKnown class to centralize string constants for blocks, pins, and functions; refactor existing code to use these constants for improved readability and maintainability.
1 parent 3cf0397 commit c9b8b53

19 files changed

Lines changed: 180 additions & 93 deletions
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
namespace KitX.Core.Workflow.BlockScripting;
2+
3+
/// <summary>
4+
/// Well-known string constants for the BlockScript/Blueprint pipeline.
5+
/// Eliminates magic strings across parser, converter, executor, and export strategies.
6+
/// </summary>
7+
public static class BlockScriptWellKnown
8+
{
9+
/// <summary>Block marker and block name constants</summary>
10+
public static class Blocks
11+
{
12+
public const string MainBlock = "MainBlock";
13+
public const string ConstBlock = "ConstBlock";
14+
public const string PubVarBlock = "PubVarBlock";
15+
16+
// DSL markers (used in source text)
17+
public const string MarkerConstBlock = "#ConstBlock";
18+
public const string MarkerPubVarBlock = "#PubVarBlock";
19+
public const string MarkerMainBlock = "#MainBlock";
20+
public const string MarkerBlockPrefix = "#Block ";
21+
}
22+
23+
/// <summary>Pin name constants</summary>
24+
public static class Pins
25+
{
26+
public const string Exec = "Exec";
27+
public const string Condition = "Condition";
28+
public const string Value = "Value";
29+
public const string Return = "Return";
30+
public const string True = "True";
31+
public const string False = "False";
32+
public const string LoopBody = "LoopBody";
33+
public const string LoopEnd = "LoopEnd";
34+
}
35+
36+
/// <summary>Built-in flow control and action function names</summary>
37+
public static class Functions
38+
{
39+
public const string Branch = "Branch";
40+
public const string Loop = "Loop";
41+
public const string LoopBodyEnd = "LoopBodyEnd";
42+
public const string Break = "Break";
43+
public const string Print = "Print";
44+
public const string Pause = "Pause";
45+
public const string Get = "Get";
46+
public const string Set = "Set";
47+
}
48+
}

‎KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockStatementExtractor.cs‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
using KitX.Core.Workflow.Blueprint.Pipeline;
88
using Serilog;
99

10+
using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Blocks;
11+
using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Functions;
12+
1013
namespace KitX.Core.Workflow.BlockScripting;
1114

1215
/// <summary>
@@ -26,9 +29,9 @@ public BlockDefinition CreateBlockDefinition(RecognizedBlock recognized, BlockVa
2629
{
2730
blockName = recognized.BlockType switch
2831
{
29-
BlockType.ConstBlock => "ConstBlock",
30-
BlockType.PubVarBlock => "PubVarBlock",
31-
BlockType.MainBlock => "MainBlock",
32+
BlockType.ConstBlock => ConstBlock,
33+
BlockType.PubVarBlock => PubVarBlock,
34+
BlockType.MainBlock => MainBlock,
3235
_ => blockName
3336
};
3437
}
@@ -203,15 +206,15 @@ private void ExtractStatements(SyntaxNode root, BlockDefinition block, BlockType
203206
{
204207
var methodName = ExprUtils.GetMethodName(invoke);
205208

206-
if (methodName == "Branch")
209+
if (methodName == Branch)
207210
{
208211
block.Statements.Add(CreateFlowControlStatement(invoke, FlowControlType.Branch, exprStmt.GetLineNumber(), exprText));
209212
}
210-
else if (methodName == "Loop")
213+
else if (methodName == Loop)
211214
{
212215
block.Statements.Add(CreateFlowControlStatement(invoke, FlowControlType.Loop, exprStmt.GetLineNumber(), exprText));
213216
}
214-
else if (methodName == "LoopBodyEnd")
217+
else if (methodName == LoopBodyEnd)
215218
{
216219
block.Statements.Add(CreateFlowControlStatement(invoke, FlowControlType.LoopBodyEnd, exprStmt.GetLineNumber(), exprText));
217220
}
@@ -233,15 +236,15 @@ private void ExtractStatements(SyntaxNode root, BlockDefinition block, BlockType
233236
var methodName = ExprUtils.GetMethodName(assignInvoke);
234237
Log.Debug("[BlockStatementExtractor] assignment.Right is InvocationExpressionSyntax, methodName = {MethodName}", methodName);
235238

236-
if (methodName == "Branch")
239+
if (methodName == Branch)
237240
{
238241
block.Statements.Add(CreateFlowControlStatement(assignInvoke, FlowControlType.Branch, exprStmt.GetLineNumber(), exprText));
239242
}
240-
else if (methodName == "Loop")
243+
else if (methodName == Loop)
241244
{
242245
block.Statements.Add(CreateFlowControlStatement(assignInvoke, FlowControlType.Loop, exprStmt.GetLineNumber(), exprText));
243246
}
244-
else if (methodName == "LoopBodyEnd")
247+
else if (methodName == LoopBodyEnd)
245248
{
246249
block.Statements.Add(CreateFlowControlStatement(assignInvoke, FlowControlType.LoopBodyEnd, exprStmt.GetLineNumber(), exprText));
247250
}

‎KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockStructureRecognizer.cs‎

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using KitX.Core.Contract.Workflow;
55
using Serilog;
66

7+
using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Blocks;
8+
79
namespace KitX.Core.Workflow.BlockScripting;
810

911
/// <summary>
@@ -72,7 +74,7 @@ public void RecognizeBlocks()
7274
var blockName = string.Empty;
7375
if (blockType == BlockType.NamedBlock)
7476
{
75-
blockName = trimmed.Substring("#Block ".Length).Trim();
77+
blockName = trimmed.Substring(MarkerBlockPrefix.Length).Trim();
7678
}
7779

7880
// Start new block
@@ -122,21 +124,21 @@ private int GetLineStartPosition(int zeroBasedLineIndex)
122124
private BlockType? TryParseBlockMarker(string trimmed)
123125
{
124126
// #ConstBlock
125-
if (trimmed == "#ConstBlock")
127+
if (trimmed == MarkerConstBlock)
126128
return BlockType.ConstBlock;
127129

128130
// #PubVarBlock
129-
if (trimmed == "#PubVarBlock")
131+
if (trimmed == MarkerPubVarBlock)
130132
return BlockType.PubVarBlock;
131133

132134
// #MainBlock
133-
if (trimmed == "#MainBlock")
135+
if (trimmed == MarkerMainBlock)
134136
return BlockType.MainBlock;
135137

136138
// #Block Name
137-
if (trimmed.StartsWith("#Block "))
139+
if (trimmed.StartsWith(MarkerBlockPrefix))
138140
{
139-
var name = trimmed.Substring("#Block ".Length).Trim();
141+
var name = trimmed.Substring(MarkerBlockPrefix.Length).Trim();
140142
if (!string.IsNullOrEmpty(name))
141143
return BlockType.NamedBlock;
142144
}
@@ -161,10 +163,10 @@ private string ExtractPureCode(int start, int end)
161163
var trimmed = line.Trim();
162164

163165
// Skip block marker lines
164-
if (trimmed == "#ConstBlock" ||
165-
trimmed == "#PubVarBlock" ||
166-
trimmed == "#MainBlock" ||
167-
trimmed.StartsWith("#Block "))
166+
if (trimmed == MarkerConstBlock ||
167+
trimmed == MarkerPubVarBlock ||
168+
trimmed == MarkerMainBlock ||
169+
trimmed.StartsWith(MarkerBlockPrefix))
168170
{
169171
continue;
170172
}

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

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
using System.Collections.Generic;
22
using System.Linq;
33
using KitX.Core.Contract.Workflow;
4+
using KitX.Core.Workflow.BlockScripting;
45
using KitX.Core.Workflow.Blueprint.ReversePipeline;
56
using Serilog;
67

8+
using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Pins;
9+
using static KitX.Core.Workflow.BlockScripting.BlockScriptWellKnown.Blocks;
10+
711
namespace KitX.Core.Workflow.Blueprint;
812

913
/// <summary>
@@ -37,7 +41,7 @@ public void WalkExecutionFlow(ReverseConversionContext ctx)
3741
return;
3842
}
3943

40-
var mainBlock = new BlockDefinition { Type = BlockType.MainBlock, Name = "MainBlock" };
44+
var mainBlock = new BlockDefinition { Type = BlockType.MainBlock, Name = BlockScriptWellKnown.Blocks.MainBlock };
4145
ctx.Script.MainBlock = mainBlock;
4246

4347
var visited = new HashSet<string>();
@@ -63,7 +67,7 @@ public void WalkFromBlockScopes(Contract.Workflow.Blueprint blueprint, ReverseCo
6367
BlockDefinition block;
6468
if (scope.IsMainBlock)
6569
{
66-
block = new BlockDefinition { Type = BlockType.MainBlock, Name = "MainBlock" };
70+
block = new BlockDefinition { Type = BlockType.MainBlock, Name = BlockScriptWellKnown.Blocks.MainBlock };
6771
ctx.Script.MainBlock = block;
6872
}
6973
else
@@ -94,9 +98,9 @@ public void WalkFromBlockScopes(Contract.Workflow.Blueprint blueprint, ReverseCo
9498
{
9599
if (scope.OwnerNodeId == null) continue;
96100
if (!ctx.ControlFlowMap.TryGetValue(scope.OwnerNodeId, out var flow)) continue;
97-
if (scope.OwnerArmName == "True" || scope.OwnerArmName == "LoopBody")
101+
if (scope.OwnerArmName == BlockScriptWellKnown.Pins.True || scope.OwnerArmName == BlockScriptWellKnown.Pins.LoopBody)
98102
flow.TrueBlockName = scope.Name;
99-
else if (scope.OwnerArmName == "False" || scope.OwnerArmName == "LoopEnd")
103+
else if (scope.OwnerArmName == BlockScriptWellKnown.Pins.False || scope.OwnerArmName == BlockScriptWellKnown.Pins.LoopEnd)
100104
flow.FalseBlockName = scope.Name;
101105
}
102106

@@ -138,7 +142,7 @@ private void WalkNode(BlueprintNode node, BlockDefinition currentBlock,
138142
return;
139143
}
140144

141-
var execOut = node.OutputPins.FirstOrDefault(p => p.Name == "Exec");
145+
var execOut = node.OutputPins.FirstOrDefault(p => p.Name == Exec);
142146
if (execOut == null)
143147
{
144148
if (loopbackTargetId != null)
@@ -216,11 +220,11 @@ private static FlowControlStatement CreateLoopBodyEndStatement(string? returnTo
216220
if (node.NodeType is BlueprintNodeType.Call or BlueprintNodeType.CallHelper
217221
&& stmt is ExpressionStatement exprStmt)
218222
{
219-
var returnPin = node.OutputPins.FirstOrDefault(p => p.Name == "Return");
220-
bool hasReturn = returnPin != null && ctx.ConsumedOutputs.Contains((node.Id, "Return"));
223+
var returnPin = node.OutputPins.FirstOrDefault(p => p.Name == Return);
224+
bool hasReturn = returnPin != null && ctx.ConsumedOutputs.Contains((node.Id, Return));
221225
if (hasReturn)
222226
{
223-
var pubVar = NodeExportHelper.FindOutputPubVar(node, "Return", ctx);
227+
var pubVar = NodeExportHelper.FindOutputPubVar(node, Return, ctx);
224228
if (pubVar != null)
225229
exprStmt.SourceCode = $"{pubVar} = {exprStmt.Expression};";
226230
}
@@ -231,10 +235,10 @@ private static FlowControlStatement CreateLoopBodyEndStatement(string? returnTo
231235

232236
private BlockStatement? GenerateGetStatementViaStrategy(BlueprintNode node, ReverseConversionContext ctx)
233237
{
234-
if (!ctx.ConsumedOutputs.Contains((node.Id, "Value")))
238+
if (!ctx.ConsumedOutputs.Contains((node.Id, Value)))
235239
return null;
236240

237-
var pubVar = NodeExportHelper.FindOutputPubVar(node, "Value", ctx);
241+
var pubVar = NodeExportHelper.FindOutputPubVar(node, Value, ctx);
238242
if (pubVar == null) return null;
239243

240244
if (!_strategies.TryGetValue(BlueprintNodeType.Get, out var strategy))
@@ -297,7 +301,7 @@ private void ProcessBranchSubGraphs(BlueprintNode branchNode, ReverseConversionC
297301
var falseBlockName = string.Empty;
298302
var currentLoopback = ctx.CurrentLoopbackTargetId;
299303

300-
foreach (var pinName in new[] { "True", "False" })
304+
foreach (var pinName in new[] { True, False })
301305
{
302306
var pin = branchNode.OutputPins.FirstOrDefault(p => p.Name == pinName);
303307
if (pin == null) continue;
@@ -316,7 +320,7 @@ private void ProcessBranchSubGraphs(BlueprintNode branchNode, ReverseConversionC
316320
ctx.Script.NamedBlocks[blockName] = block;
317321
processedTargets.Add(conn.TargetNodeId);
318322

319-
if (pinName == "True") trueBlockName = blockName;
323+
if (pinName == True) trueBlockName = blockName;
320324
else falseBlockName = blockName;
321325
}
322326

@@ -329,7 +333,7 @@ private void ProcessLoopSubGraphs(BlueprintNode loopNode, ReverseConversionConte
329333
var loopBodyBlockName = string.Empty;
330334
var loopEndBlockName = string.Empty;
331335

332-
var loopBodyPin = loopNode.OutputPins.FirstOrDefault(p => p.Name == "LoopBody");
336+
var loopBodyPin = loopNode.OutputPins.FirstOrDefault(p => p.Name == LoopBody);
333337
if (loopBodyPin != null)
334338
{
335339
var conn = ctx.ExecConnections.FirstOrDefault(c => c.SourcePinId == loopBodyPin.Id);
@@ -351,7 +355,7 @@ private void ProcessLoopSubGraphs(BlueprintNode loopNode, ReverseConversionConte
351355
}
352356
}
353357

354-
var loopEndPin = loopNode.OutputPins.FirstOrDefault(p => p.Name == "LoopEnd");
358+
var loopEndPin = loopNode.OutputPins.FirstOrDefault(p => p.Name == LoopEnd);
355359
if (loopEndPin != null)
356360
{
357361
var conn = ctx.ExecConnections.FirstOrDefault(c => c.SourcePinId == loopEndPin.Id);
@@ -420,7 +424,7 @@ private static (BlueprintNode? loopNode, List<BlueprintNode> path) FollowExecCha
420424
if (current.NodeType == BlueprintNodeType.Loop)
421425
return (current, path);
422426

423-
var execOutPin = current.OutputPins.FirstOrDefault(p => p.Name == "Exec");
427+
var execOutPin = current.OutputPins.FirstOrDefault(p => p.Name == Exec);
424428
if (execOutPin == null) break;
425429

426430
var execConn = ctx.ExecConnections.FirstOrDefault(c => c.SourcePinId == execOutPin.Id);
@@ -438,7 +442,7 @@ private static (BlueprintNode? loopNode, List<BlueprintNode> path) FollowExecCha
438442
private void GenerateConditionStatements(BlueprintNode loopNode, BlockDefinition blockDef,
439443
ReverseConversionContext ctx)
440444
{
441-
var condPin = loopNode.InputPins.FirstOrDefault(p => p.Name == "Condition");
445+
var condPin = loopNode.InputPins.FirstOrDefault(p => p.Name == Condition);
442446
if (condPin == null) return;
443447

444448
var condConn = ctx.DataConnections.FirstOrDefault(c => c.TargetPinId == condPin.Id);
@@ -456,7 +460,7 @@ private void GenerateDataChainStatements(string sourceNodeId,
456460

457461
foreach (var inputPin in sourceNode.InputPins)
458462
{
459-
if (inputPin.Name == "Exec") continue;
463+
if (inputPin.Name == Exec) continue;
460464
var upConn = ctx.DataConnections.FirstOrDefault(c => c.TargetPinId == inputPin.Id);
461465
if (upConn != null)
462466
GenerateDataChainStatements(upConn.SourceNodeId, blockDef, ctx, generated);

‎KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/ExportStrategies/BranchNodeExportStrategy.cs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using KitX.Core.Contract.Workflow;
2+
using KitX.Core.Workflow.BlockScripting;
23

34
namespace KitX.Core.Workflow.Blueprint.ExportStrategies;
45

@@ -9,7 +10,7 @@ public class BranchNodeExportStrategy : INodeExportStrategy
910

1011
public BlockStatement? ToStatement(BlueprintNode node, INodeExportHelper helper)
1112
{
12-
var condition = helper.GetInputValue(node, "Condition");
13+
var condition = helper.GetInputValue(node, BlockScriptWellKnown.Pins.Condition);
1314
return new FlowControlStatement
1415
{
1516
ControlType = FlowControlType.Branch,
@@ -23,8 +24,8 @@ public IEnumerable<OutputArmDescriptor> GetOutputArms(BlueprintNode node)
2324
{
2425
return
2526
[
26-
new OutputArmDescriptor { PinName = "True", IsLoopback = false },
27-
new OutputArmDescriptor { PinName = "False", IsLoopback = false }
27+
new OutputArmDescriptor { PinName = BlockScriptWellKnown.Pins.True, IsLoopback = false },
28+
new OutputArmDescriptor { PinName = BlockScriptWellKnown.Pins.False, IsLoopback = false }
2829
];
2930
}
3031
}

‎KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/ExportStrategies/LoopNodeExportStrategy.cs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using KitX.Core.Contract.Workflow;
2+
using KitX.Core.Workflow.BlockScripting;
23

34
namespace KitX.Core.Workflow.Blueprint.ExportStrategies;
45

@@ -9,7 +10,7 @@ public class LoopNodeExportStrategy : INodeExportStrategy
910

1011
public BlockStatement? ToStatement(BlueprintNode node, INodeExportHelper helper)
1112
{
12-
var condition = helper.GetInputValue(node, "Condition");
13+
var condition = helper.GetInputValue(node, BlockScriptWellKnown.Pins.Condition);
1314
return new FlowControlStatement
1415
{
1516
ControlType = FlowControlType.Loop,
@@ -23,8 +24,8 @@ public IEnumerable<OutputArmDescriptor> GetOutputArms(BlueprintNode node)
2324
{
2425
return
2526
[
26-
new OutputArmDescriptor { PinName = "LoopBody", IsLoopback = true },
27-
new OutputArmDescriptor { PinName = "LoopEnd", IsLoopback = false }
27+
new OutputArmDescriptor { PinName = BlockScriptWellKnown.Pins.LoopBody, IsLoopback = true },
28+
new OutputArmDescriptor { PinName = BlockScriptWellKnown.Pins.LoopEnd, IsLoopback = false }
2829
];
2930
}
3031
}

‎KitX Clients/KitX Core/KitX.Core/Workflow/Blueprint/ExportStrategies/PrintNodeExportStrategy.cs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using KitX.Core.Contract.Workflow;
2+
using KitX.Core.Workflow.BlockScripting;
23

34
namespace KitX.Core.Workflow.Blueprint.ExportStrategies;
45

@@ -9,11 +10,11 @@ public class PrintNodeExportStrategy : INodeExportStrategy
910

1011
public BlockStatement? ToStatement(BlueprintNode node, INodeExportHelper helper)
1112
{
12-
var value = helper.GetInputValue(node, "Value");
13+
var value = helper.GetInputValue(node, BlockScriptWellKnown.Pins.Value);
1314
return new ExpressionStatement
1415
{
15-
Expression = $"Print({value});",
16-
SourceCode = $"Print({value});",
16+
Expression = $"{BlockScriptWellKnown.Functions.Print}({value});",
17+
SourceCode = $"{BlockScriptWellKnown.Functions.Print}({value});",
1718
LineNumber = 1
1819
};
1920
}

0 commit comments

Comments
 (0)