Forge
csharpdeeb25a2
1using CascadeIDE.Services;
2using Microsoft.CodeAnalysis;
3
4namespace CascadeIDE.Features.Editor.Application.Monaco;
5
6/// <summary>Diagnostic strips → line-first CECB decorations and EOL inlays.</summary>
7public static class MonacoEditorDiagnosticsMapper
8{
9 private const int MaxInlineMessageLength = 120;
10
11 public static IReadOnlyList<CideEditorDecoration> ToDecorations(IReadOnlyList<EditorDiagnosticStrip> strips)
12 {
13 if (strips.Count == 0)
14 return Array.Empty<CideEditorDecoration>();
15
16 var list = new List<CideEditorDecoration>(strips.Count);
17 foreach (var group in strips.GroupBy(s => s.Line1).OrderBy(g => g.Key))
18 {
19 var items = group.ToList();
20 var primary = items.OrderByDescending(s => SeverityRank(s.Severity)).First();
21 var className = primary.Severity switch
22 {
23 DiagnosticSeverity.Error => "squiggly-error",
24 DiagnosticSeverity.Warning => "squiggly-warning",
25 _ => "squiggly-info",
26 };
27 var hover = items.Count == 1
28 ? $"{primary.Id}: {primary.Message}"
29 : string.Join("\n", items.Select(s => $"{s.Id}: {s.Message}"));
30
31 list.Add(new CideEditorDecoration(
32 StartOffset: 0,
33 Length: 0,
34 ClassName: className,
35 HoverMessage: hover,
36 IsWholeLine: true,
37 StartLine: group.Key,
38 StartColumn: 1,
39 EndLine: group.Key));
40 }
41
42 return list;
43 }
44
45 /// <summary>Trailing diagnostic labels at EOL (VS / Error Lens style).</summary>
46 public static IReadOnlyList<CideEditorInlayHint> ToDiagnosticInlays(IReadOnlyList<EditorDiagnosticStrip> strips)
47 {
48 if (strips.Count == 0)
49 return Array.Empty<CideEditorInlayHint>();
50
51 var list = new List<CideEditorInlayHint>(strips.Count);
52 foreach (var group in strips.GroupBy(s => s.Line1).OrderBy(g => g.Key))
53 {
54 var items = group.ToList();
55 var primary = items.OrderByDescending(s => SeverityRank(s.Severity)).First();
56 var label = FormatInlineLabel(primary, items.Count);
57 var kind = primary.Severity switch
58 {
59 DiagnosticSeverity.Error => "diagnostic-error",
60 DiagnosticSeverity.Warning => "diagnostic-warning",
61 _ => "diagnostic-info",
62 };
63 list.Add(new CideEditorInlayHint(group.Key, 1, label, kind, AtEndOfLine: true));
64 }
65
66 return list;
67 }
68
69 private static string FormatInlineLabel(EditorDiagnosticStrip primary, int countOnLine)
70 {
71 var message = primary.Message.Trim();
72 if (message.Length > MaxInlineMessageLength)
73 message = message[..(MaxInlineMessageLength - 1)] + "…";
74
75 var label = $" {primary.Id}: {message}";
76 if (countOnLine > 1)
77 label += $" (+{countOnLine - 1})";
78 return label;
79 }
80
81 private static int SeverityRank(DiagnosticSeverity severity) => severity switch
82 {
83 DiagnosticSeverity.Error => 3,
84 DiagnosticSeverity.Warning => 2,
85 DiagnosticSeverity.Info => 1,
86 _ => 0,
87 };
88}
89
View only · write via MCP/CIDE