Forge
markdowndeeb25a2
1# План: языковые сервисы C# (гибридный подход)
2
3Зафиксировано решение использовать **вариант C — гибрид**: in-process Roslyn для быстрых сценариев, LSP (OmniSharp) для полного решения.
4
5## Цель
6
7- **Отзывчивость:** ввод и простые действия не ждут поднятия внешнего процесса.
8- **Полнота по решению:** диагностика, Go to Definition, Find References, рефакторинги по всему решению — без собственного MSBuildWorkspace, за счёт готового language server.
9
10## Текущее состояние (база)
11
12- **In-process Roslyn** (один файл, кэш):
13 - `CSharpLanguageService`: completion (члены после `.`, ключевые слова, LookupSymbols), signature help, подсветка вхождений в текущем файле.
14 - Кэш по (path, textHash, line, column); сброс при смене файла/решения.
15 - `EditorIntelligence`: триггеры (`.` / Ctrl+Space), debounce, Popup для completion и signature, IBackgroundRenderer для highlight вхождений в текущем файле (без дублирования диагностик в intelligence).
16- **Диагностики по всем открытым `.cs`:** `WorkspaceDiagnosticsCoordinator` — debounce ~400 ms, кэш по пути, событие `DiagnosticsChanged`, список для панели Problems (`ProblemsPanelViewModel`). В `CSharpLanguageService.GetDiagnosticsForFile` — **только парсер** (синтаксис/лексика), без семантики однофайловой «скретч»-компиляции, чтобы не было ложных CS0246 при успешном `dotnet build`.
17- **Редактор:** на каждой вкладке `DockDocumentView` ставит `EditorDiagnosticBackgroundRenderer` + подписка на координатор (не только активная вкладка); tooltip по наведению на полосу (`HitTest`).
18- **LSP (выбор провайдера):** настройки `CSharpLspProvider` (ParseOnly / OmniSharp / CSharpLs / Custom), stdio JSON-RPC, `CSharpLspDiagnosticsHost` + `WorkspaceDiagnosticsCoordinator.SetLspDiagnosticsHost`. Перезапуск при смене решения или настроек.
19- **Контракт:** `Services/Lsp/ILspDiagnosticSource.cs`.
20- Редактор: AvaloniaEdit, TextMate для подсветки синтаксиса.
21- Загрузка решения и файлов — в фоне (LoadSolutionAsync, LoadFileContentAsync).
22
23## Этапы плана
24
25### Этап 1 — Укрепление текущего in-process (при необходимости)
26
27- [ ] При желании: расширить completion (например, больше контекстов, фильтрация по вводу).
28- [ ] Сохранить текущее поведение: без открытого решения или до старта LSP всё работает как сейчас.
29
30### Этап 2 — LSP-клиент в CascadeIDE
31
32- [ ] Подключить **OmniSharp.Extensions.LanguageClient** (NuGet) для роли LSP-клиента.
33- [ ] Запуск **OmniSharp-Roslyn** (или другого C# LSP-сервера) как дочернего процесса при открытии решения (.sln / .csproj); обмен по stdio (JSON-RPC).
34- [ ] Инициализация сессии: `initialize` + `initialized`, привязка к корню решения (workspace folder).
35- [ ] Отправка документов: при открытии/изменении файла — `textDocument/didOpen`, `textDocument/didChange` и т.д.
36
37### Этап 3 — Использование LSP по решению
38
39- [ ] **Диагностика:** подписка на `textDocument/publishDiagnostics`, отображение подчёркиваний/списка ошибок в редакторе (или панель проблем).
40- [ ] **Completion:** при открытом решении и готовом LSP — запрос `textDocument/completion` (можно дублировать или постепенно переключать с in-process на LSP для файлов из решения).
41- [ ] **Go to Definition / Find References:** запросы к LSP, навигация по результатам (открытие файла, позиция в редакторе).
42- [ ] По желанию: Hover, Signature Help от LSP для файлов решения.
43
44### Этап 4 — Правило «когда что»
45
46- [ ] Чёткое правило: **если открыто решение и LSP запущен и готов — используем LSP** для completion/diagnostics/definition/references по этому решению.
47- [ ] **Иначе** (файл без решения, LSP ещё не поднят, ошибка подключения) — только in-process Roslyn (текущая логика).
48- [ ] При смене решения — перезапуск LSP (новый процесс на новое решение), сброс кэша in-process.
49
50### Этап 5 (опционально) — Отладка (DAP)
51
52- [x] Встроенная отладка через **netcoredbg** (протокол DAP по stdio): общий клиент в `DotnetDebug.Core` (`DapClient`), сессия в IDE — `Services/IdeDapDebugSession` (паритет с `dotnet-debug-mcp`).
53- [x] Команды MCP/IDE: `debug_launch`, `debug_attach`, `debug_continue`, шаги, стек/переменные — см. `IdeCommands` и `IdeMcpCommandExecutor.Handlers.DapDebug.cs`.
54- [x] UI: меню **Отладка**, горячие клавиши F5 / Shift+F5 / F10 / F11 / Shift+F11; диалоги выбора цели (.dll/.exe) и PID для attach (`MainWindow.Dialogs.axaml.cs`).
55- Примечание: отдельный NuGet **OmniSharp.Extensions.DebugAdapter.Client** не используется — достаточно общего DAP-клиента и netcoredbg, как в MCP.
56
57## Зависимости и ссылки
58
59- **OmniSharp-Roslyn:** https://github.com/OmniSharp/omnisharp-roslyn (C# language server, LSP по stdio).
60- **OmniSharp csharp-language-server-protocol:** https://github.com/OmniSharp/csharp-language-server-protocol (LSP на C#; для этапов 2–4).
61- **RoslynPad** (внешний ориентир, **не** NuGet-зависимость): https://github.com/roslynpad/roslynpad — продукт на Roslyn + редактор (AvalonEdit / Avalonia), где **уже** есть **autocomplete, code fixes** и сопутствующий набор; у нас аналогичные возможности **только наращиваются**. Смотреть на готовую реализацию того, что у нас **ещё** предстоит довести; не форк и не drop-in для AvaloniaEdit в CascadeIDE.
62- **netcoredbg** (внешний процесс): путь через `NETCOREDBG_PATH` или `PATH`; см. также `Financial/software/open/dotnet-debug-mcp`.
63
64## Документ
65
66- Создан: 2026-02.
67- Обновлять по мере выполнения этапов и смены приоритетов.
68
69
View only · write via MCP/CIDE