Skip to main content
Version: 0.1

Language Server (LSP)

The G# Language Server is a .NET process that speaks the Language Server Protocol over JSON-RPC. Editors normally start it over stdin/stdout; it can also connect to a named pipe or Unix domain socket for clients that manage transport separately.

Starting the server

Build the server from the repository when developing it locally:

dotnet build src/LanguageServer

By default, the server reads LSP messages from standard input and writes responses and notifications to standard output.

dotnet out/bin/Debug/LanguageServer/GSharp.LanguageServer.dll

Recognized command-line arguments are:

ArgumentBehavior
--pipe=<name>Connect to a Windows named pipe or Unix domain socket instead of stdio.
--logEnable protocol logging to the server's default debug log path. In current Unix source that default is /tmp/gsharp-lsp-debug.log.
--log=<path>Enable protocol logging to a specific file.

VS Code exposes logging through gsharp.server.log and gsharp.server.logPath.

Advertised capabilities

The server capability factory enables the following:

CapabilityLSP surface
Text synchronizationOpen/close, full-document changes, save with text.
DiagnosticstextDocument/diagnostic pull requests (live as-you-type), with workspace/diagnostic/refresh for cross-file edits; falls back to textDocument/publishDiagnostics for push-only clients.
HovertextDocument/hover.
DefinitiontextDocument/definition.
Type definitiontextDocument/typeDefinition.
ImplementationtextDocument/implementation.
ReferencestextDocument/references.
Document highlightstextDocument/documentHighlight.
Document symbolstextDocument/documentSymbol.
Workspace symbolsworkspace/symbol.
FormattingtextDocument/formatting, textDocument/rangeFormatting, and textDocument/onTypeFormatting.
Folding rangestextDocument/foldingRange.
Selection rangestextDocument/selectionRange.
Linked editingtextDocument/linkedEditingRange.
CompletiontextDocument/completion, triggered on ..
Signature helptextDocument/signatureHelp, triggered by ( and ,.
RenametextDocument/prepareRename and textDocument/rename.
Code actionstextDocument/codeAction, currently refactor/rewrite-style actions.
Code lensestextDocument/codeLens, currently reference-count lenses for declarations.
Semantic tokensFull and range semantic tokens.
Inlay hintstextDocument/inlayHint, currently parameter-name hints at call sites.

Diagnostics lifecycle

The server keeps the active document parsed in memory and, when it belongs to a discovered .gsproj, updates the project state on open/change/save. Diagnostics are served through the LSP pull model: the editor requests textDocument/diagnostic as the user types and on save, and the server runs the full pipeline — syntax, global-scope semantic analysis, and the binding pass — on every pull, so binding errors appear live rather than only on save. Each report carries a resultId; unchanged results return an unchanged report so the client reuses existing squiggles. The binding pass runs off the handler gate and supports cancellation, keeping interactive requests responsive, and cross-file edits in multi-file projects trigger a debounced workspace/diagnostic/refresh. Push-only clients (no pull-diagnostic capability) fall back to textDocument/publishDiagnostics on open/change/save.

Workspace and project awareness

During initialize, the server attempts best-effort workspace discovery from the root path or root URI. It tracks .gsproj and .gs file changes, registers source files with projects, and can fall back to an implicit project for single-file editing. Symbol operations use the active document or the current project compilation when available.

Feature notes and limitations

  • Completion is scope-aware and dot-triggered, but the implementation remains much simpler than mature .NET language services.
  • Formatting is a lexer-based whole-document formatter with a canonical whitespace pass; current implementation uses two-space indentation internally.
  • Rename, linked editing, references, CodeLens, implementation, and type-definition results are computed from the compiler's semantic lookup model and are strongest for symbols in the current project/document model.
  • The server serializes handlers through a single gate so edits and reads are processed in order, not incrementally in parallel.

Connecting an editor

An editor client needs to launch the server, speak standard LSP framing, and register .gs documents as the gsharp language. VS Code does this through the bundled extension. Other editors can use stdio with the default server command or --pipe=<name> if the editor prefers a socket/pipe transport.