// Copyright (c) 2026 Petr Balvín (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause // Package lsp implements a Language Server Protocol server for GAsm. It // speaks JSON-RPC 2.0 over any io.Reader/io.Writer pair (normally standard // input/output) and provides completion, hover documentation, document // symbols, diagnostics and semantic-token highlighting — all backed by the // pure-Go lexer, parser, arch and lint packages. It is the vendor-neutral // integration point: any LSP-capable editor can use it with no editor-specific // plugin code. package lsp import "encoding/json" // --- JSON-RPC 2.0 ----------------------------------------------------------- // rpcMessage is the common envelope for every JSON-RPC message. type rpcMessage struct { JSONRPC string `json:"jsonrpc"` ID *json.RawMessage `json:"id,omitempty"` Method string `json:"method,omitempty"` Params json.RawMessage `json:"params,omitempty"` Result any `json:"result,omitempty"` Error *rpcError `json:"error,omitempty"` } type rpcError struct { Code int `json:"code"` Message string `json:"message"` } // JSON-RPC error codes used by LSP. const ( errParse = -32700 errInvalidRequest = -32600 errMethodNotFound = -32601 errInvalidParams = -32602 errInternal = -32603 ) // --- LSP positions and ranges ---------------------------------------------- // Position is a zero-based line/character position, as LSP requires. type Position struct { Line int `json:"line"` Character int `json:"character"` } // Range is a pair of positions. type Range struct { Start Position `json:"start"` End Position `json:"end"` } // Location is a range within a document URI. type Location struct { URI string `json:"uri"` Range Range `json:"range"` } // --- diagnostics ------------------------------------------------------------ // Diagnostic severities (LSP ordering: 1 = error). const ( sevError = 1 sevWarning = 2 sevInformation = 3 sevHint = 4 ) // Diagnostic is one published finding. type Diagnostic struct { Range Range `json:"range"` Severity int `json:"severity"` Code string `json:"code,omitempty"` Source string `json:"source,omitempty"` Message string `json:"message"` } type publishDiagnosticsParams struct { URI string `json:"uri"` Diagnostics []Diagnostic `json:"diagnostics"` } // --- text document synchronisation ----------------------------------------- type textDocumentItem struct { URI string `json:"uri"` LanguageID string `json:"languageId"` Version int `json:"version"` Text string `json:"text"` } type didOpenParams struct { TextDocument textDocumentItem `json:"textDocument"` } type versionedTextDocumentIdentifier struct { URI string `json:"uri"` Version int `json:"version"` } type textDocumentIdentifier struct { URI string `json:"uri"` } type contentChangeEvent struct { Text string `json:"text"` } type didChangeParams struct { TextDocument versionedTextDocumentIdentifier `json:"textDocument"` ContentChanges []contentChangeEvent `json:"contentChanges"` } type didCloseParams struct { TextDocument textDocumentIdentifier `json:"textDocument"` } // --- completion ------------------------------------------------------------- // Completion item kinds (a useful subset). const ( ciFunction = 3 ciField = 5 ciVariable = 6 ciClass = 7 ciModule = 9 ciKeyword = 14 ciConstant = 21 ciStruct = 22 ) // CompletionItem is one completion suggestion. type CompletionItem struct { Label string `json:"label"` Kind int `json:"kind,omitempty"` Detail string `json:"detail,omitempty"` Documentation string `json:"documentation,omitempty"` InsertText string `json:"insertText,omitempty"` } type completionParams struct { TextDocument textDocumentIdentifier `json:"textDocument"` Position Position `json:"position"` } // --- hover ------------------------------------------------------------------ type hoverParams struct { TextDocument textDocumentIdentifier `json:"textDocument"` Position Position `json:"position"` } type definitionParams struct { TextDocument textDocumentIdentifier `json:"textDocument"` Position Position `json:"position"` } // Hover is the hover response. type Hover struct { Contents markupContent `json:"contents"` Range Range `json:"range,omitempty"` } type markupContent struct { Kind string `json:"kind"` Value string `json:"value"` } // --- document symbols ------------------------------------------------------- // Symbol kinds (a useful subset). const ( symFunction = 12 symConstant = 14 symVariable = 13 ) // DocumentSymbol is a hierarchical symbol. type DocumentSymbol struct { Name string `json:"name"` Detail string `json:"detail,omitempty"` Kind int `json:"kind"` Range Range `json:"range"` SelectionRange Range `json:"selectionRange"` Children []DocumentSymbol `json:"children,omitempty"` } type documentSymbolParams struct { TextDocument textDocumentIdentifier `json:"textDocument"` } // --- semantic tokens -------------------------------------------------------- // semanticTokenTypes is the legend of token type names, in index order. The // indices are referenced by the encoder below. var semanticTokenTypes = []string{ "comment", // 0 "keyword", // 1 "function", // 2 "variable", // 3 "type", // 4 "number", // 5 "string", // 6 "operator", // 7 "property", // 8 "namespace", // 9 "macro", // 10 } const ( stComment = 0 stKeyword = 1 stFunction = 2 stVariable = 3 stType = 4 stNumber = 5 stString = 6 stOperator = 7 stProperty = 8 stNamespace = 9 stMacro = 10 ) // SemanticTokensLegend advertises the token classification. type SemanticTokensLegend struct { TokenTypes []string `json:"tokenTypes"` TokenModifiers []string `json:"tokenModifiers"` } // SemanticTokens is the encoded token payload. type SemanticTokens struct { Data []int `json:"data"` } type semanticTokensParams struct { TextDocument textDocumentIdentifier `json:"textDocument"` } // --- initialize ------------------------------------------------------------- type initializeParams struct { RootURI string `json:"rootUri"` } // ServerCapabilities advertises what this server provides. type ServerCapabilities struct { TextDocumentSync int `json:"textDocumentSync"` CompletionProvider map[string]any `json:"completionProvider,omitempty"` HoverProvider bool `json:"hoverProvider,omitempty"` DocumentSymbolProvider bool `json:"documentSymbolProvider,omitempty"` SemanticTokensProvider map[string]any `json:"semanticTokensProvider,omitempty"` DiagnosticProvider map[string]any `json:"diagnosticProvider,omitempty"` } type initializeResult struct { Capabilities ServerCapabilities `json:"capabilities"` ServerInfo map[string]string `json:"serverInfo,omitempty"` }