| 1 | using System.Text; |
| 2 | using System.Text.Json; |
| 3 | using DotnetDebug.Core; |
| 4 | |
| 5 | namespace DotnetDebugMcp; |
| 6 | |
| 7 | internal static class BreakpointToolHandlers |
| 8 | { |
| 9 | internal static string HandleSetBreakpoints(IReadOnlyDictionary<string, JsonElement> args) |
| 10 | { |
| 11 | if (!McpArgumentHelpers.TryGetString(args, "workspace_path", out var workspacePath) || string.IsNullOrWhiteSpace(workspacePath)) |
| 12 | throw new ArgumentException("workspace_path is required."); |
| 13 | if (!McpArgumentHelpers.TryGetString(args, "target_path", out var targetPath) || string.IsNullOrWhiteSpace(targetPath)) |
| 14 | throw new ArgumentException("target_path is required."); |
| 15 | if (!args.TryGetValue("breakpoints", out var bpEl) || bpEl.ValueKind != JsonValueKind.Array) |
| 16 | throw new ArgumentException("breakpoints (array) is required."); |
| 17 | |
| 18 | var list = new List<BreakpointsStorage.BreakpointEntry>(); |
| 19 | foreach (var item in bpEl.EnumerateArray()) |
| 20 | { |
| 21 | if (!McpArgumentHelpers.TryGetPropString(item, "file_path", out var file) || !McpArgumentHelpers.TryGetPropInt(item, "line", out var line) || line < 1) |
| 22 | continue; |
| 23 | McpArgumentHelpers.TryGetPropString(item, "condition", out var condition); |
| 24 | list.Add(new BreakpointsStorage.BreakpointEntry(file!, line, string.IsNullOrWhiteSpace(condition) ? null : condition)); |
| 25 | } |
| 26 | |
| 27 | BreakpointsStorage.SetBreakpoints(workspacePath!, targetPath!, list); |
| 28 | var sb = new StringBuilder(); |
| 29 | sb.AppendLine("# Breakpoints set"); |
| 30 | sb.AppendLine($"# Target: {targetPath}"); |
| 31 | sb.AppendLine($"# File: {BreakpointsStorage.FileName} in workspace"); |
| 32 | sb.AppendLine($"# Count: {list.Count}"); |
| 33 | foreach (var bp in list) |
| 34 | sb.AppendLine($" {bp.File}:{bp.Line}" + (bp.Condition != null ? $" condition=\"{bp.Condition}\"" : "")); |
| 35 | return sb.ToString(); |
| 36 | } |
| 37 | |
| 38 | internal static string HandleListBreakpoints(IReadOnlyDictionary<string, JsonElement> args) |
| 39 | { |
| 40 | if (!McpArgumentHelpers.TryGetString(args, "workspace_path", out var workspacePath) || string.IsNullOrWhiteSpace(workspacePath)) |
| 41 | throw new ArgumentException("workspace_path is required."); |
| 42 | McpArgumentHelpers.TryGetString(args, "target_path", out var targetPath); |
| 43 | |
| 44 | var sb = new StringBuilder(); |
| 45 | sb.AppendLine("# Saved breakpoints"); |
| 46 | if (!string.IsNullOrWhiteSpace(targetPath)) |
| 47 | { |
| 48 | var bps = BreakpointsStorage.GetBreakpoints(workspacePath!, targetPath); |
| 49 | sb.AppendLine($"# Target: {targetPath}"); |
| 50 | sb.AppendLine($"# Count: {bps.Count}"); |
| 51 | foreach (var bp in bps) |
| 52 | sb.AppendLine($" {bp.File}:{bp.Line}" + (bp.Condition != null ? $" condition=\"{bp.Condition}\"" : "")); |
| 53 | } |
| 54 | else |
| 55 | { |
| 56 | var targets = BreakpointsStorage.ListTargets(workspacePath!); |
| 57 | foreach (var (target, bps) in targets) |
| 58 | { |
| 59 | sb.AppendLine($"# Target: {target}"); |
| 60 | foreach (var bp in bps) |
| 61 | sb.AppendLine($" {bp.File}:{bp.Line}" + (bp.Condition != null ? $" condition=\"{bp.Condition}\"" : "")); |
| 62 | sb.AppendLine(); |
| 63 | } |
| 64 | } |
| 65 | return sb.ToString(); |
| 66 | } |
| 67 | |
| 68 | internal static string HandleClearBreakpoints(IReadOnlyDictionary<string, JsonElement> args) |
| 69 | { |
| 70 | if (!McpArgumentHelpers.TryGetString(args, "workspace_path", out var workspacePath) || string.IsNullOrWhiteSpace(workspacePath)) |
| 71 | throw new ArgumentException("workspace_path is required."); |
| 72 | McpArgumentHelpers.TryGetString(args, "target_path", out var targetPath); |
| 73 | BreakpointsStorage.ClearBreakpoints(workspacePath!, targetPath); |
| 74 | return string.IsNullOrWhiteSpace(targetPath) |
| 75 | ? "# All breakpoints cleared for this workspace." |
| 76 | : $"# Breakpoints cleared for target: {targetPath}"; |
| 77 | } |
| 78 | } |
| 79 | |