diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md index fae64574..e177eee6 100644 --- a/THIRD-PARTY-NOTICES.md +++ b/THIRD-PARTY-NOTICES.md @@ -66,6 +66,8 @@ Copied into the VSIX at `bin/all/` alongside the sidecar executable. | Serilog | 4.4.0 | Apache-2.0 | Serilog Contributors | | Serilog.Sinks.File | 7.0.0 | Apache-2.0 | Serilog Contributors | | Outcome | 1.0.0 | MIT | Christian Findlay | +| Microsoft.CodeAnalysis.Razor.Compiler and Microsoft.AspNetCore.Razor.Utilities.Shared (the Razor compiler, copied from the .NET SDK) | 10.0.0-preview.26377.103 (SDK 10.0.303) | MIT | .NET Foundation and Contributors | +| Microsoft.Extensions.ObjectPool (copied from the .NET SDK with the Razor compiler) | 10.0.1 | MIT | .NET Foundation and Contributors | > `Microsoft.Build`, `Microsoft.Build.Framework`, and `Microsoft.NET.StringTools` > are referenced **compile-time only** (`ExcludeAssets="runtime"`); MSBuildLocator diff --git a/coverage-thresholds.json b/coverage-thresholds.json index ffb1b25d..89bada40 100644 --- a/coverage-thresholds.json +++ b/coverage-thresholds.json @@ -12,7 +12,7 @@ "language": "dotnet" }, "sharplsp-sidecar-csharp": { - "threshold": 95, + "threshold": 95.39, "language": "dotnet" }, "sharplsp-sidecar-fsharp": { diff --git a/docs/plans/RAZOR-PLAN.md b/docs/plans/RAZOR-PLAN.md new file mode 100644 index 00000000..66e28729 --- /dev/null +++ b/docs/plans/RAZOR-PLAN.md @@ -0,0 +1,89 @@ +# Razor and Blazor Implementation Plan + +**Spec:** [RAZOR-SPEC.md](../specs/RAZOR-SPEC.md) + +## Context + +SharpLsp has not supported `.razor` or `.cshtml` files until now. Research confirmed three things ([RAZOR-RESEARCH]): + +- The SDK's own Razor source generator already runs inside the C# sidecar's design-time workspace. +- Its enhanced `#line` directives map every C# fragment back to Razor. +- The public compiler IR supplies everything the mapping misses. + +So the C# sidecar owns Razor end to end, the host routes the documents to it, and the editors sync and forward HTML. + +The phases below are in dependency order. Each item is checked only when a test that exercises it passes. + +## TODO + +### Phase 1: Foundation + +- [x] Fixture solution `src/sharplsp/tests/fixtures/razor/` with `BlazorApp`, `Widgets` (RCL), `PagesApp` (Pages + MVC) and `Domain` (F#), isolated by its own `Directory.Build.props` ([RAZOR-TESTING]) +- [x] Host: add `LangId::Razor` for `.razor` and `.cshtml`, owned by the C# sidecar ([RAZOR-ARCHITECTURE-ROUTING]) +- [x] Host: route `documentSymbol`, `foldingRange` and `linkedEditingRange` for Razor to the sidecar, and answer `selectionRange` empty +- [x] Host: add `<` and `@` completion triggers, and short-circuit them for C# and F# documents +- [x] Host: publish Razor diagnostics under the source `sharplsp-razor` +- [x] Sidecar: bundle the Razor compiler from the build SDK, and list it in `THIRD-PARTY-NOTICES.md` ([RAZOR-ARCHITECTURE-ENGINE]) +- [x] Sidecar: find Razor files as additional documents, and sync their text in every framework context, including the pending-edit replay ([RAZOR-ARCHITECTURE-DOCUMENTS]) +- [x] Sidecar: build the C# projection — find the generated document by its checksum pragma, and build the verified span map in both directions ([RAZOR-ARCHITECTURE-PROJECTION]) + - [x] Verify the checksum lookup, the mappings that never map (hidden, fileless, foreign, outside either text), carets at a fragment's end, and rename's check that a span holds the old name — `RazorProjectionTests`: 6 passing cases over hand-written generator output +- [x] Sidecar: build the Razor engine per project — configuration from the analyzer and parse options, an in-memory file system, tag helpers per compilation, the capture pass and markup facts + - [x] Verify configuration fallbacks, target-path metadata, current file/import reads, missing files, missing paths, cancellation and failure recovery — `RazorEngineSettingsTests`: 12 passing cases; settings, filesystem and engine each have 100% line coverage +- [x] Sidecar: build the HTML projection and the markup-context tokenizer ([RAZOR-ARCHITECTURE-HTML]) + - [x] HTML projection from compiler IR, preserving offsets/newlines and current unsaved text — `RazorHtmlProjectionTests`: 19 passing fixture cases (Blazor and MVC, comments, UTF-16, incomplete tags, unsaved edits) + - [x] HTML markup-context tokenizer — `HtmlMarkupContextTests`: 36 passing cases with 100% line coverage, including malformed start/end tag recovery; the three character-reconsumption regressions were verified failing before the fix and pass unchanged afterward + - [x] Host: `sharplsp/razor/htmlProjection` answers `{ text }`, or `null` for a file no project lists — `test_full_stack_razor_routing_session` + - [x] Verify `sharplsp/razor/htmlProjection` through editor integration — `razor-lsp.test.ts`: the projection keeps the editor's offsets, line breaks and unsaved text, and feeds VS Code's HTML completion and hover + +**Validation (2026-10-20):** the Release sidecar solution builds with zero warnings and errors; 671 C#, 440 F# and 125 Common tests pass, and all three coverage gates pass. C# coverage is 96.39%, with all 1,530 new C# executable lines covered. `RazorSidecarTests` exercises the real IPC contract and malformed-request recovery; `RazorCompletionEditsTests` covers mapped edits, import deduplication, aliases, static imports and LF/CRLF insertion. + +**Editor validation (2026-10-20):** the final Razor chunk passes all 6 cases, the workspace chunk passes all 446 cases (including server-start lifecycle), the debugger chunk passes all 80 cases, and editor lint and formatting pass. The debugger group-outcome test that previously timed out passes unchanged in the full chunk in 6.5 seconds. + +**Template validation (2026-10-20):** the real host and sidecars run over a fresh `dotnet new blazor` app (.NET 10). Its files report no errors and keep their shape in the HTML projection. Hover, definition, references, member completion and signature help answer on its real code: layouts, `@inherits`, `@Body`, `NavLinkMatch`, `@Assets`, `typeof(Program)`. The one false report found was usings marked unnecessary: every using in `_Imports.razor`, and, as review showed, a component's usings that only its markup needs. Razor files no longer report unnecessary usings (`Import_files_never_report_their_usings_as_unnecessary`, `Components_never_report_a_using_their_markup_may_need_as_unnecessary`). + +### Phase 2: C# Inside Razor + +- [ ] Diagnostics: C# diagnostics from projections, `RZ` diagnostics from facts, and Razor files in solution-wide diagnostics ([RAZOR-FEATURES-DIAGNOSTICS]) +- [x] Hover at mapped positions ([RAZOR-FEATURES-HOVER]) +- [ ] Definition, type definition, declaration and implementation from mapped positions, with generated component classes landing in their `.razor` file ([RAZOR-FEATURES-DEFINITION]) +- [x] References and document highlights across projections, with hidden scaffolding dropped ([RAZOR-FEATURES-REFERENCES]) +- [x] C# completion, with mapped edits and `using` → `@using` ([RAZOR-FEATURES-COMPLETION]) +- [x] Signature help ([RAZOR-FEATURES-SIGNATURE-HELP]) +- [x] Semantic tokens for C# fragments ([RAZOR-FEATURES-SEMANTIC-TOKENS]) +- [ ] Rename and prepareRename — Razor usages and `@code` declarations, from `.cs` and `.razor` origins ([RAZOR-FEATURES-RENAME]) + +### Phase 3: Blazor Markup + +- [ ] Component tags: hover, definition, references, highlights and linked editing +- [ ] Component attributes and `@bind-X`: hover, definition, references and rename +- [ ] Directive attributes and directives: hover +- [ ] Completion: components, parameters (with `[EditorRequired]` first), `@bind-X`, directive attributes and their parameters, and directives +- [ ] Semantic tokens for markup: component tags, attributes, directive attributes and directives +- [ ] Folding ranges and document symbols ([RAZOR-FEATURES-STRUCTURE]) + +### Phase 4: Razor Pages and MVC + +- [ ] `@model`, `@inject`, `@section` and `@functions` through the projection ([RAZOR-MVC]) +- [ ] Tag helper elements and attributes: hover and completion +- [ ] `_ViewImports.cshtml` imports resolved by the engine + +### Phase 5: Editors + +- [x] VS Code: sync `razor` and `aspnetcorerazor` documents, and activate on `onLanguage:razor` ([RAZOR-EDITORS]) — `razor-lsp.test.ts`: a Razor file opens as Razor, and its unsaved edits reach the server +- [x] VS Code: forward HTML completion and hover over `sharplsp/razor/htmlProjection` ([RAZOR-FEATURES-HTML]) — `razor-lsp.test.ts`: element names and HTML hovers in markup, C# completion and hover in code +- [x] VS Code: add a `razor` end-to-end chunk on both platforms — `test-chunks.json`, in both matrices +- [x] Zed: Razor language registration (Zed has no built-in Razor grammar) — `the_server_attaches_to_the_csharp_fsharp_and_razor_languages` + +### Phase 6: F# + +- [ ] Hover, completion and definition from Razor into F# types of a referenced F# project ([RAZOR-FSHARP]) +- [ ] F#-origin rename that includes Razor usages, mapped back from the projections + +### Deferred ([RAZOR-FEATURES-DEFERRED]) + +- [ ] Razor formatting +- [ ] Selection ranges +- [ ] Code actions: extract a block to code-behind, extract a component, generate an event handler, add `@using` +- [ ] Inlay hints, code lens, and call and type hierarchy from Razor positions +- [ ] `.razor.css` and `.razor.js` collocation awareness +- [ ] Blazor WebAssembly debugging and Razor Hot Reload diff --git a/docs/specs/DESIGN-SYSTEM.md b/docs/specs/DESIGN-SYSTEM.md index 2cf5196c..61b5471c 100644 --- a/docs/specs/DESIGN-SYSTEM.md +++ b/docs/specs/DESIGN-SYSTEM.md @@ -137,9 +137,26 @@ Screenshots and video of a SharpLsp feature show the real extension, never a moc - Every autoplaying video pauses and shows its controls under `prefers-reduced-motion: reduce`. - Every video ships a WebP poster, the films and the recordings alike. - **Narration.** A walkthrough may be narrated (`kit/sound/`). Its reviewed script (`films/.narration.json`) is spoken by Kokoro-82M through `kokoro-js` on the capturing machine, never by a speech service or the operating system's voices, whose licences forbid publishing. Each line starts just after its scene's cut, and a scene holds its last frame until its line ends. The music is an original score synthesised from code (`kit/sound/score.mjs`), so no film carries licensed or sampled music, and it ducks under the voice. A narrated film ships AAC in its MP4 and Opus in its WebM, plays unmuted with controls, and carries WebVTT captions in every site language (`..vtt`, the page's own language shown by default), listed under `captions` in the catalogue. -- **One catalogue.** Every video on the site is declared once in `src/website/src/_data/videos.json`: encodings, size, length, upload date, and its label and caption in each language. Pages place a video with the `{% video "" %}` shortcode (`src/website/video-figure.js`) and never repeat `