Documentation
¶
Overview ¶
Package lsp implements the pylon-lsp Language Server.
This is an internal/ package — Go's import rules keep it unreachable from outside the src/go module. Public surface: Run (server.go), wired from src/go/cmd/pylon-lsp/main.go.
Semantic tokens for pylon sources — partial coverage.
Today this emits tokens for three classes the AST already span-tracks:
- `&ref` → variable
- `@ref` → variable + readonly modifier
- `[`, `]`, `(`, `)` → operator (single-char per bracket)
Deferred (require source-scan logic or new AST spans the engine does not track today):
- frontmatter key / number / string tokens
- edge arrows `->`, `<-`, `<->`, `-->`, etc.
- alignment marker dashes flush with brackets
- `| renderer` pipe tags
- `:: name` declaration identifiers
- frontmatter fence `---` lines
The legend reserves space for those classes via the documented growth path below — future commits append entries, never reorder.
Wire format: the server advertises (tokenTypes, tokenModifiers) in the initialize legend; each subsequent textDocument/semanticTokens response is a flat []uint32 whose groups of 5 encode one token as (deltaLine, deltaStartChar, length, tokenType, tokenModifiers). LSP requires source-order emission and disallows inter-token overlap on the same line — encodeTokens asserts both.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Run ¶
func Run() error
Run starts the LSP server on stdio. It blocks until the client closes the connection, then returns. Logging is routed to stderr exclusively; stdout is reserved for LSP wire bytes.
Run does not return until the server stops, so main.go's error-path is exercised only on startup failures.
Types ¶
type Document ¶
type Document struct {
URI string
Version int32
Text string
AST pylon.AST
Diagnostics []pylon.Diagnostic
}
Document is a single open source document cached by the server. Version tracks the LSP text-document version counter; Text is the latest full-sync content.
AST and Diagnostics are computed once (at Open / Change time) and cached so feature handlers stay transport-free: they translate from this already-parsed state rather than re-running the pipeline.
type Handlers ¶
type Handlers struct {
Store *Store
}
Handlers is the transport-free surface every LSP feature attaches to. Each method takes a URI string, reads from the Store, and returns a protocol-shaped response. No glsp.Context reaches here — tests seed a Store and call the methods directly. Today's surface: diagnostics, document symbols, semantic tokens.
func NewHandlers ¶
NewHandlers constructs a Handlers over the given Store.
func (*Handlers) Diagnostics ¶
func (h *Handlers) Diagnostics(uri string) []protocol.Diagnostic
Diagnostics returns the cached pylon diagnostics for uri translated into the LSP protocol shape. Translation only — Parse + Validate ran when the Store.Open / Change notification landed. Always returns a non-nil slice: unknown URIs and clean docs both yield an empty slice, which the publish path forwards directly as a `diagnostics: []` clear.
func (*Handlers) DocumentSymbols ¶
func (h *Handlers) DocumentSymbols(uri string) []protocol.DocumentSymbol
DocumentSymbols returns the outline for uri: every `:: name` declaration as a Variable symbol, plus each frontmatter `data:` series as a Constant named `@key`. Returns nil for unknown URIs; returns an empty slice (not nil) when the document is known but carries no symbols, so callers can distinguish "clean outline" from "unknown document".
Per-series-key spans are not tracked by the frontmatter parser today (Meta.DataSpan covers the whole `data:` section), so every series symbol shares that range. Narrowing is a future refinement that can ride on a later parser change.
func (*Handlers) SemanticTokens ¶
func (h *Handlers) SemanticTokens(uri string) *protocol.SemanticTokens
SemanticTokens returns the LSP-wire-encoded token stream for uri. Partial implementation: brackets plus &/@ references only; see internal/lsp/tokens.go for the legend and deferred-class list. Convention across this package: known clean doc → non-nil empty; unknown URI → also non-nil empty (LSP clients expect a value).
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the URI-keyed document cache. Handlers read under RLock; Open / Change / Close mutate under Lock. Parse + Validate run BEFORE the critical section — the fresh Document is built as a local value and swapped into the map atomically, so the critical section stays short and concurrent readers always observe either the old or the new Document (never a torn state).
func NewStore ¶
func NewStore() *Store
NewStore returns an empty Store ready for didOpen notifications.
func (*Store) Change ¶
Change replaces the full text of an open document. v1 uses full- text sync (no incremental patches), so text is always the complete buffer. A Change on a URI that was never Open'd is treated as an implicit Open — malformed clients shouldn't crash the server.
func (*Store) Get ¶
Get returns a pointer to the cached document for uri, or (nil, false) if none is open. The returned pointer aliases the live entry; handlers must treat it as read-only.