Files
gasm-sdk/lsp/protocol.go
T

395 lines
11 KiB
Go

// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (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"`
}
type referenceParams struct {
TextDocument textDocumentIdentifier `json:"textDocument"`
Position Position `json:"position"`
Context referenceContext `json:"context"`
}
type referenceContext struct {
IncludeDeclaration bool `json:"includeDeclaration"`
}
type renameParams struct {
TextDocument textDocumentIdentifier `json:"textDocument"`
Position Position `json:"position"`
NewName string `json:"newName"`
}
// WorkspaceEdit holds changes across multiple documents.
type WorkspaceEdit struct {
Changes map[string][]TextEdit `json:"changes"`
}
// TextEdit replaces a range with new text.
type TextEdit struct {
Range Range `json:"range"`
NewText string `json:"newText"`
}
type documentFormattingParams struct {
TextDocument textDocumentIdentifier `json:"textDocument"`
Options formattingOptions `json:"options"`
}
type formattingOptions struct {
TabSize int `json:"tabSize"`
InsertSpaces bool `json:"insertSpaces"`
}
type inlayHintParams struct {
TextDocument textDocumentIdentifier `json:"textDocument"`
Range Range `json:"range"`
}
// InlayHint is a hint displayed inline in the editor.
type InlayHint struct {
Position Position `json:"position"`
Label string `json:"label"`
Kind int `json:"kind,omitempty"`
Padding bool `json:"paddingLeft,omitempty"`
Tooltip string `json:"tooltip,omitempty"`
}
const (
inlayHintTypeParameter = 2
)
// Hover is the hover response.
type Hover struct {
Contents markupContent `json:"contents"`
Range Range `json:"range"`
}
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 -------------------------------------------------------------
// 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"`
DefinitionProvider bool `json:"definitionProvider,omitempty"`
ReferencesProvider bool `json:"referencesProvider,omitempty"`
RenameProvider bool `json:"renameProvider,omitempty"`
DocumentSymbolProvider bool `json:"documentSymbolProvider,omitempty"`
DocumentFormattingProvider bool `json:"documentFormattingProvider,omitempty"`
DocumentHighlightProvider bool `json:"documentHighlightProvider,omitempty"`
CodeActionProvider bool `json:"codeActionProvider,omitempty"`
SignatureHelpProvider map[string]any `json:"signatureHelpProvider,omitempty"`
WorkspaceSymbolProvider bool `json:"workspaceSymbolProvider,omitempty"`
SemanticTokensProvider map[string]any `json:"semanticTokensProvider,omitempty"`
InlayHintProvider bool `json:"inlayHintProvider,omitempty"`
DiagnosticProvider map[string]any `json:"diagnosticProvider,omitempty"`
}
// --- code actions -------------------------------------------------------------
type codeActionParams struct {
TextDocument textDocumentIdentifier `json:"textDocument"`
Range Range `json:"range"`
Context codeActionContext `json:"context"`
}
type codeActionContext struct {
Diagnostics []Diagnostic `json:"diagnostics"`
}
// CodeAction represents a quick fix or refactoring.
type CodeAction struct {
Title string `json:"title"`
Kind string `json:"kind,omitempty"`
Edit *WorkspaceEdit `json:"edit,omitempty"`
}
// --- signature help -----------------------------------------------------------
type signatureHelpParams struct {
TextDocument textDocumentIdentifier `json:"textDocument"`
Position Position `json:"position"`
}
// SignatureHelp represents signature information for a function call.
type SignatureHelp struct {
Signatures []SignatureInformation `json:"signatures"`
}
// SignatureInformation represents a function signature.
type SignatureInformation struct {
Label string `json:"label"`
Documentation string `json:"documentation,omitempty"`
Parameters []ParameterInformation `json:"parameters,omitempty"`
}
// ParameterInformation represents a parameter in a signature.
type ParameterInformation struct {
Label string `json:"label"`
}
// --- document highlights ------------------------------------------------------
type documentHighlightParams struct {
TextDocument textDocumentIdentifier `json:"textDocument"`
Position Position `json:"position"`
}
// DocumentHighlight represents a highlight range.
type DocumentHighlight struct {
Range Range `json:"range"`
Kind int `json:"kind,omitempty"`
}
const (
highlightRead = 1
highlightWrite = 2
)
// --- workspace symbols -------------------------------------------------------
type workspaceSymbolParams struct {
Query string `json:"query"`
}
// WorkspaceSymbol represents a symbol found across the workspace.
type WorkspaceSymbol struct {
Name string `json:"name"`
Kind int `json:"kind"`
Location Location `json:"location"`
}
type initializeResult struct {
Capabilities ServerCapabilities `json:"capabilities"`
ServerInfo map[string]string `json:"serverInfo,omitempty"`
}