Forge
csharpdeeb25a2
1using Microsoft.CodeAnalysis;
2using Microsoft.CodeAnalysis.CSharp;
3using Microsoft.CodeAnalysis.Text;
4
5namespace CascadeIDE.Services;
6
7public sealed partial class CSharpLanguageService
8{
9 private static readonly SymbolDisplayFormat SignatureFormat = new(
10 typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly,
11 memberOptions: SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeType,
12 parameterOptions: SymbolDisplayParameterOptions.IncludeType | SymbolDisplayParameterOptions.IncludeName,
13 miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
14
15 /// <summary>
16 /// Диагностики по файлу для Problems / MCP: только <b>лексика и синтаксис</b> (парсер Roslyn).
17 /// Полная <c>CSharpCompilation</c> у нас без ссылок на пакеты и соседние файлы проекта — семантические
18 /// ошибки (CS0246 и т.д.) были бы ложными при успешной сборке MSBuild. Семантика — из вывода сборки.
19 /// </summary>
20 public IReadOnlyList<Diagnostic> GetDiagnosticsForFile(string filePath, string sourceText, CancellationToken ct = default)
21 {
22 if (string.IsNullOrEmpty(filePath) || !filePath.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
23 return [];
24 try
25 {
26 var text = SourceText.From(sourceText);
27 var tree = CSharpSyntaxTree.ParseText(text, path: filePath, cancellationToken: ct);
28 var list = new List<Diagnostic>();
29 foreach (var d in tree.GetDiagnostics(ct))
30 {
31 if (d.Location.SourceTree != tree)
32 continue;
33 if (d.Severity == DiagnosticSeverity.Error)
34 list.Add(d);
35 else if (d.Severity == DiagnosticSeverity.Warning && list.Count < 50)
36 list.Add(d);
37 }
38
39 return list;
40 }
41 catch
42 {
43 return [];
44 }
45 }
46
47 /// <summary>Сигнатуры публичных типов и членов в файле (одна строка на объявление) для минимизации контекста.</summary>
48 public IReadOnlyList<string> GetSignatureStringsForFile(string filePath, string sourceText, CancellationToken ct = default)
49 {
50 if (string.IsNullOrEmpty(filePath) || !filePath.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
51 return [];
52 try
53 {
54 var text = SourceText.From(sourceText);
55 var model = GetOrCreateModel(filePath, text, ct);
56 var root = model.SyntaxTree.GetRoot(ct);
57 var list = new List<string>();
58 foreach (var node in root.DescendantNodes())
59 {
60 ct.ThrowIfCancellationRequested();
61 var symbol = model.GetDeclaredSymbol(node, ct);
62 if (symbol is null) continue;
63 if (symbol.DeclaredAccessibility != Accessibility.Public && symbol.ContainingType?.DeclaredAccessibility != Accessibility.Public)
64 continue;
65 var line = symbol.ToDisplayString(SignatureFormat);
66 if (string.IsNullOrEmpty(line)) continue;
67 list.Add(line);
68 if (list.Count >= 200) break;
69 }
70 return list;
71 }
72 catch
73 {
74 return [];
75 }
76 }
77}
78
View only · write via MCP/CIDE