Skip to content

Language server

csls advertises only capabilities backed by an active implementation. Current language features include:

  • C# compiler and analyzer diagnostics, plus project-aware Razor diagnostics, completion, hover, navigation, rename, and formatting
  • completion with import edits, negotiated snippets, lazy documentation, hover, and signature help
  • definitions, declarations, implementations, references, highlights, links, monikers, and linked editing
  • document and workspace symbols
  • semantic tokens with full and delta responses
  • call hierarchy, type hierarchy, selection ranges, folding ranges, and inlay hints
  • rename, move-to-file refactoring, missing-using, simple-using, and interface implementation quick fixes, import organization, and document, range, on-type, or opt-in save formatting
  • project-aware file creation, rename, folder move, and deletion tracking

Document and workspace diagnostic pulls use the same immutable Roslyn snapshot. Workspace results cover user C# and Razor documents across all loaded projects, exclude build output, include versions for open files, and return unchanged reports when the client already holds the current result. Clients that provide a partial result token receive bounded batches through standard LSP progress notifications. Clients without pull-diagnostic support receive complete versioned push diagnostics after documents open, change, or save. Rapid edits are coalesced, and closing a document clears its published diagnostics.

Compiler and analyzer results are cached by the dependent Roslyn project version. An edit recomputes affected projects on demand while unrelated projects keep their current result identifiers and cached analysis.

Roslyn diagnostics with hidden severity are omitted unless they fade unnecessary code. Diagnostics explicitly raised to information remain visible and use the same hint presentation as the C# extension by default. The presentation can be changed without recomputing analyzer results.

The server tracks open-document versions and applies incremental text changes. Workspace loading supports solutions, projects, file-based apps, loose C# files, multiple roots, and folder changes during a live session. File-based apps are restored and evaluated by the .NET SDK selected for their directory. Package, project, include, property, and SDK directives therefore use the same NuGet, MSBuild, central package management, and global.json behavior as dotnet run. Folder discovery loads shebang apps and directive apps with top-level statements, while an explicit C# file workspace always uses file-based app semantics. Clients that support work-done progress receive one update for each resolved project, including projects discovered through references outside the solution. Files loaded once for each target framework use the best available project flavor for hover and other position-based requests, with a stable fallback when a flavor name has no target framework.

Unity projects are detected by their Assets directory and ProjectSettings/ProjectVersion.txt file. csls loads the generated solution at the project root and skips Unity’s generated Library, Temp, Logs, and UserSettings trees. A normal .NET project in a directory named Library remains discoverable.

Unsaved documents survive reloads when their workspace folder remains active. Standard workspace file-operation notifications refresh project topology from disk. Open unsaved documents follow file and folder renames, while deleted documents and stale diagnostics are removed. Clients that support dynamic file watching receive registrations for C#, Razor, project, solution, SDK, NuGet, and analyzer configuration files. Closed source changes update the current Roslyn solution directly. Project and configuration changes reload the affected workspace while retaining open document overlays.

Completion edits are computed by Roslyn. Clients that advertise snippet support receive snippet insertion text with Roslyn’s final caret position. Method completion adds tab stops for required parameters and leaves optional parameters for signature help. Other clients receive plain text. completionItem/resolve adds Roslyn documentation without changing the edit, sort text, or filter text returned by the original request. Hover, completion resolve, signature help, and parameter help preserve structured C# XML documentation such as references, paragraphs, code, and lists. Markdown is returned only when the client includes it in the corresponding content formats. Inherited method and parameter documentation follows overrides and interface implementations. Razor views and components receive C# member and type completion from their generated project snapshot. Commit edits map back to Razor source, including @using directives required by types from unimported namespaces.

Rename works from C# and from mapped C# expressions in .razor and .cshtml files. A single version-aware workspace edit updates Razor references, Razor-local members, and ordinary C# declarations and references. Rename is rejected when the new identifier would bind to a different symbol in generated Razor code.

Missing-using quick fixes use Roslyn’s project and metadata indexes. Each proposed import is applied to a temporary document, simplified, formatted, and kept only when the unresolved name binds to the selected accessible type. The returned edit includes the current document version when the file is open.

The IDE0063 quick fix converts an applicable using statement to a using declaration and preserves nested statements, comments, directives, async disposal, formatting, and the current open-document version.

Interface implementation quick fixes generate required inherited methods, properties, indexers, events, and static abstract members. Existing and default members are left alone. csls compiles the temporary document and returns the edit only when the selected interface is fully implemented without new compiler errors.

Move to file extracts a top-level class, struct, interface, record, enum, or delegate from a file that contains another declaration. The result creates the matching .cs file before inserting its formatted source and removing the original declaration. The action is offered only when the client supports ordered document changes and create-file resource operations. CLI and MCP previews record both the source hash and the requirement that the target path does not exist before --apply can write either file.

textDocument/moniker returns dotnet identifiers built from canonical assembly identities and Roslyn documentation IDs. Strong-named assembly APIs are unique within the scheme. Unsigned project APIs are unique within their project group, while non-public symbols use project or document scope.

textDocument/linkedEditingRange links matching start and end names in XML documentation, including nested and custom elements. Self-closing, mismatched, and unrelated text do not produce linked ranges.

textDocument/foldingRange returns C# syntax, comment, import, and region folds from the current Roslyn document snapshot. Results honor the client range limit, line-only mode, supported kinds, and collapsed text capability.

Razor views and components use the pinned Microsoft Razor compiler packages. Pull diagnostics include Razor findings and mapped C# compiler or analyzer findings from the owning project. They follow the current unsaved .cshtml or .razor snapshot and return to the persisted file after the editor closes it. Hover uses the same generated project snapshot and maps Roslyn content and ranges back to the Razor source, including symbols made available by _Imports.razor and _ViewImports.cshtml. Definition, declaration, type definition, implementation, and reference requests use that snapshot and map Razor locations back to their source files. Razor formatting indents markup and embedded C#, aligns multiline attributes, and honors the client’s tab, space, newline, and trimming settings. Range formatting updates only the selected lines. On-type formatting updates the local source lines after }, ;, or newline. Content in pre, script, style, and textarea elements is left unchanged. Save formatting uses project settings for C# and stable four-space indentation for Razor and cshtml files.

Configuration is pulled through the standard workspace request when the client supports it. Push-only clients use the same settings and precedence.

Each language-server process creates a private Unix domain socket and a session manifest in the user cache directory. The socket is supported by .NET on Windows, Linux, and macOS. It is not exposed over the network.

The CLI and MCP server authenticate through operating-system file permissions and connect to this socket. This keeps editor requests, terminal commands, and agent requests on one Roslyn workspace.

$/csharp/debugInfo returns the live workspace phase, loaded folders, active requests, queue counters, and cumulative request timings. It bypasses normal request scheduling, so clients and tests can inspect a blocked or shutting-down session without waiting for queued language work.