Forge
csharp3407750f
1using System.Text.Json;
2
3namespace AgentForge.Mcp.Core;
4
5internal static class AnchorArgs
6{
7 internal static IReadOnlyList<AnchorPayload>? ParseOptional(IReadOnlyDictionary<string, JsonElement> args, string key)
8 {
9 if (!args.TryGetValue(key, out var value) || value.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
10 return null;
11
12 if (value.ValueKind != JsonValueKind.Array)
13 throw new ArgumentException($"{key} must be a JSON array.");
14
15 var anchors = new List<AnchorPayload>();
16 foreach (var item in value.EnumerateArray())
17 {
18 var file = RequirePropertyString(item, "file");
19 var lineStart = RequirePropertyInt(item, "line_start", "lineStart");
20 var lineEnd = OptionalPropertyInt(item, "line_end", "lineEnd");
21 var memberKey = OptionalPropertyString(item, "member_key", "memberKey");
22 var syntaxScope = OptionalPropertyString(item, "syntax_scope", "syntaxScope")
23 ?? OptionalSyntaxScopeObject(item);
24 anchors.Add(new AnchorPayload(file, lineStart, lineEnd, memberKey, syntaxScope));
25 }
26
27 return anchors;
28 }
29
30 internal static IReadOnlyList<string>? ParseOptionalBrackets(IReadOnlyDictionary<string, JsonElement> args, string key)
31 {
32 if (!args.TryGetValue(key, out var value) || value.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined)
33 return null;
34
35 if (value.ValueKind != JsonValueKind.Array)
36 throw new ArgumentException($"{key} must be a JSON array.");
37
38 var brackets = new List<string>();
39 foreach (var item in value.EnumerateArray())
40 {
41 if (item.ValueKind != JsonValueKind.String)
42 throw new ArgumentException($"{key} items must be strings.");
43 var text = item.GetString()?.Trim();
44 if (!string.IsNullOrWhiteSpace(text))
45 brackets.Add(text);
46 }
47
48 return brackets.Count > 0 ? brackets : null;
49 }
50
51 private static string? OptionalSyntaxScopeObject(JsonElement element)
52 {
53 if (!element.TryGetProperty("syntax_scope", out var snake) && !element.TryGetProperty("syntaxScope", out snake))
54 return null;
55
56 return snake.ValueKind switch
57 {
58 JsonValueKind.String => snake.GetString(),
59 JsonValueKind.Object => snake.GetRawText(),
60 _ => null,
61 };
62 }
63
64 private static string RequirePropertyString(JsonElement element, params string[] names)
65 {
66 foreach (var name in names)
67 {
68 if (element.TryGetProperty(name, out var value) && value.ValueKind == JsonValueKind.String)
69 {
70 var text = value.GetString()?.Trim() ?? "";
71 if (text.Length > 0)
72 return text;
73 }
74 }
75
76 throw new ArgumentException($"Anchor {names[0]} is required.");
77 }
78
79 private static string? OptionalPropertyString(JsonElement element, params string[] names)
80 {
81 foreach (var name in names)
82 {
83 if (element.TryGetProperty(name, out var value) && value.ValueKind == JsonValueKind.String)
84 return value.GetString();
85 }
86
87 return null;
88 }
89
90 private static int RequirePropertyInt(JsonElement element, params string[] names)
91 {
92 foreach (var name in names)
93 {
94 if (element.TryGetProperty(name, out var value) && value.TryGetInt32(out var number))
95 return number;
96 }
97
98 throw new ArgumentException($"Anchor {names[0]} is required.");
99 }
100
101 private static int? OptionalPropertyInt(JsonElement element, params string[] names)
102 {
103 foreach (var name in names)
104 {
105 if (element.TryGetProperty(name, out var value) && value.TryGetInt32(out var number))
106 return number;
107 }
108
109 return null;
110 }
111}
112
113internal sealed record AnchorPayload(
114 string File,
115 int LineStart,
116 int? LineEnd,
117 string? MemberKey,
118 string? SyntaxScope = null);
119
View only · write via MCP/CIDE