racket-langserver
The racket-langserver is a Language Server Protocol implementation for Racket. This project seeks to use DrRacket’s public APIs to provide functionality that mimics DrRacket’s code tools as closely as possible.
1 Installation and usage
A Racket runtime is a prerequisite, so before using racket-langserver, ensure that a Racket runtime is installed. You can install from the official download page or install one from your package manager.
First, install an LSP runtime for your editor.
Next, install the package via raco:
raco pkg install racket-langserver
To update the racket-langserver useraco pkg update racket-langserver
Once it is installed, you can configure your editor to use a custom LSP client for Racket (and all installed module languages, e.g. Rhombus) files (usually .rkt), and set the command for the custom client to
racket -l racket-langserver
You may need to restart your LSP runtime or your editor for racket-langserver to start.
1.1 VSCode
Use the Magic Racket extension.
2 Interfaces
| (require racket-langserver/interfaces) | |
| package: racket-langserver | |
This module provides the data types used by the LSP protocol layer and the doc library API. Structs defined here are generated by define-json-struct, which is basically struct with JSON encode/decode support.
To convert a struct value to a JSON-compatible hasheq, use jsexpr-encode from racket-langserver/json-util. Nested struct values are encoded recursively.
2.1 Position and Range
struct
(struct Pos (line char) #:transparent) line : exact-nonnegative-integer? char : exact-nonnegative-integer?
2.2 Edit Payloads
2.3 Query Responses
struct
(struct DocumentHighlight (range) #:transparent) range : Range?
struct
(struct CompletionItem (label) #:transparent) label : string?
struct
(struct CompletionList (isIncomplete items) #:transparent) isIncomplete : boolean? items : (listof CompletionItem?)
struct
(struct SignatureInformation (label documentation) #:transparent) label : string? documentation : string?
struct
(struct SignatureHelp (signatures) #:transparent) signatures : (listof SignatureInformation?)
value
Name |
| Code |
File |
| 1 |
Module |
| 2 |
Namespace |
| 3 |
Package |
| 4 |
Class |
| 5 |
Method |
| 6 |
Property |
| 7 |
Field |
| 8 |
Constructor |
| 9 |
Enum |
| 10 |
Interface |
| 11 |
Function |
| 12 |
Variable |
| 13 |
Constant |
| 14 |
String |
| 15 |
Number |
| 16 |
Boolean |
| 17 |
Array |
| 18 |
Object |
| 19 |
Key |
| 20 |
Null |
| 21 |
EnumMember |
| 22 |
Struct |
| 23 |
Event |
| 24 |
Operator |
| 25 |
TypeParameter |
| 26 |
Access named constants via SymbolKind-Constant, SymbolKind-String, SymbolKind-Variable, etc.
struct
(struct SymbolInformation (name kind location) #:transparent) name : string? kind : SymbolKind? location : Location?
struct
(struct CodeAction (title kind diagnostics isPreferred edit) #:transparent) title : string? kind : string? diagnostics : (listof Diagnostic?) isPreferred : boolean? edit : WorkspaceEdit?
Name |
| Code |
Error |
| 1 |
Warning |
| 2 |
Information |
| 3 |
Hint |
| 4 |
Access named constants via DiagnosticSeverity-Error, DiagnosticSeverity-Warning, etc.
struct
(struct Diagnostic (range severity source message) #:transparent) range : Range? severity : DiagnosticSeverity? source : string? message : string?
2.4 Formatting Options
struct
(struct FormattingOptions ( tab-size insert-spaces trim-trailing-whitespace insert-final-newline trim-final-newlines key) #:transparent) tab-size : exact-nonnegative-integer? insert-spaces : boolean? trim-trailing-whitespace : boolean? insert-final-newline : boolean? trim-final-newlines : boolean? key : (or/c false/c hash?)
The tab-size and insert-spaces fields are required in protocol payloads. The remaining fields (trim-trailing-whitespace, insert-final-newline, trim-final-newlines, key) are optional in the JSON payload; absent fields are represented as an internal undef sentinel rather than #f. Test for an absent optional field with undef? from interfaces.rkt.
The corresponding JSON field names use camelCase: tabSize, insertSpaces, trimTrailingWhitespace, insertFinalNewline, trimFinalNewlines.
Not all generated accessors are exported. Public callers should rely on FormattingOptions-tab-size and FormattingOptions-trim-trailing-whitespace.
2.5 Semantic Tokens
struct
(struct SemanticToken (start end type modifiers) #:transparent) start : exact-nonnegative-integer? end : exact-nonnegative-integer? type : SemanticTokenType? modifiers : SemanticTokenModifier?
value
Name |
| Value |
variable |
| "variable" |
function |
| "function" |
string |
| "string" |
number |
| "number" |
regexp |
| "regexp" |
Name |
| Value |
definition |
| "definition" |
3 Doc Library
| (require racket-langserver/doc) | package: racket-langserver |
The doc library provides single-threaded document helpers for representing and querying Racket source documents. All functions operate on document values that satisfy Doc? without touching the network or a thread scheduler, making them suitable for direct testing and reuse.
3.1 Document State
procedure
uri : string? text : string? version : exact-nonnegative-integer? = 0
procedure
(doc-get-text doc) → string?
doc : Doc?
procedure
(doc-apply-edits! doc edits) → void?
doc : Doc? edits : (listof TextEdit?)
procedure
(doc-apply-edit! doc range text) → void?
doc : Doc? range : Range? text : string?
procedure
(doc-reset! doc new-text) → void?
doc : Doc? new-text : string?
procedure
(doc-update-version! doc new-ver) → void?
doc : Doc? new-ver : exact-nonnegative-integer?
procedure
(doc-update-uri! doc new-uri) → void?
doc : Doc? new-uri : string?
procedure
(doc-copy-text-buffer doc) → (is-a?/c lsp-editor%)
doc : Doc?
3.2 Positions and Ranges
All position helpers below work in terms of absolute character offsets (zero-based integer indices into the document text) as well as LSP Pos structs (line/character pairs).
procedure
(doc-pos->abs-pos doc pos) → exact-nonnegative-integer?
doc : Doc? pos : Pos?
procedure
(doc-abs-pos->pos doc abs-pos) → Pos?
doc : Doc? abs-pos : exact-nonnegative-integer?
procedure
(doc-line-start-abs-pos doc line) → exact-nonnegative-integer?
doc : Doc? line : exact-nonnegative-integer?
procedure
(doc-line-end-abs-pos doc line) → exact-nonnegative-integer?
doc : Doc? line : exact-nonnegative-integer?
procedure
doc : Doc?
procedure
(doc-find-containing-paren doc pos)
→ (or/c exact-nonnegative-integer? #f) doc : Doc? pos : exact-nonnegative-integer?
3.3 Trace and Expansion
These functions manage check-syntax expansion and the resulting trace.
procedure
(doc-expand! doc) → boolean?
doc : Doc?
procedure
(doc-update-trace! doc new-trace new-version) → void? doc : Doc? new-trace : (is-a?/c build-trace%) new-version : exact-nonnegative-integer?
procedure
(doc-trace-latest? doc) → boolean?
doc : Doc?
procedure
(doc-walk-text trace text) → void?
trace : (is-a?/c build-trace%) text : string?
3.4 Token and Symbol Utilities
Lexer-derived token and symbol helpers. These do not require an up-to-date trace except where noted.
procedure
(doc-get-symbols doc)
→ (interval-map-of (list/c string? SymbolKind?)) doc : Doc?
procedure
(doc-range-tokens doc range) → (listof SemanticToken?)
doc : Doc? range : Range?
procedure
(doc-guess-token doc pos) → string?
doc : Doc? pos : exact-nonnegative-integer?
3.5 Query Functions
These return structured LSP responses. Most require an up-to-date trace; call doc-expand! first or check doc-trace-latest?. Exceptions are noted in individual entries.
procedure
(doc-completion doc pos) → CompletionList?
doc : Doc? pos : Pos?
procedure
(doc-references doc uri pos include-decl?)
→ (or/c (listof Location?) #f) doc : Doc? uri : string? pos : Pos? include-decl? : boolean?
The include-decl? parameter is accepted for API compatibility with the LSP protocol but is not currently used in the implementation; the declaration site is always included when the binding is in the same file.
procedure
(doc-highlights doc pos) → (or/c (listof DocumentHighlight?) #f)
doc : Doc? pos : Pos?
procedure
(doc-rename doc uri pos new-name) → (or/c WorkspaceEdit? #f)
doc : Doc? uri : string? pos : Pos? new-name : string?
procedure
(doc-prepare-rename doc pos) → (or/c Range? #f)
doc : Doc? pos : Pos?
procedure
(doc-signature-help doc pos) → (or/c SignatureHelp? #f)
doc : Doc? pos : Pos?
procedure
(doc-code-action doc range) → (listof CodeAction?)
doc : Doc? range : Range?
procedure
(doc-diagnostics doc) → (listof Diagnostic?)
doc : Doc?
procedure
(doc-symbols doc uri) → (listof SymbolInformation?)
doc : Doc? uri : string?
3.6 Formatting
procedure
(doc-format-edits doc fmt-range #:formatting-options opts [ #:on-type? on-type?]) → (or/c (listof TextEdit?) #f) doc : Doc? fmt-range : Range? opts : FormattingOptions? on-type? : boolean? = #f
When on-type? is #t, blank lines are indented too. This mode is intended for on-type formatting triggered by pressing Enter.
Formatting is performed on an internal copy of the document; the doc is not mutated by this call. Pass the result to doc-apply-edits! to apply the edits.