Documentation
¶
Overview ¶
Package lsp provides Language Server Protocol integration for Trace.
The LSP layer provides accurate type information, references, and rename capabilities by communicating with external language servers (gopls, pyright, etc.).
Architecture ¶
The package uses a hybrid approach where Tree-sitter handles fast graph building while LSP servers handle accuracy-critical queries like type resolution, references, and rename operations.
┌─────────────────────────────────────────────────────────────────────────────┐ │ Trace Service │ │ │ │ Graph Queries (Tree-sitter) ◄── Query Router ──► LSP Queries │ │ Fast ~1ms, ~90% accuracy Accurate ~50ms, ~100% │ └─────────────────────────────────────────────────────────────────────────────┘
Components ¶
- Manager: Orchestrates multiple language server instances
- Server: Manages individual LSP server processes
- Protocol: Handles JSON-RPC communication
- Operations: Provides high-level LSP operations (definition, references, etc.)
Thread Safety ¶
All exported types are safe for concurrent use.
Example ¶
mgr := lsp.NewManager("/path/to/project", lsp.DefaultManagerConfig())
defer mgr.ShutdownAll(context.Background())
ops := lsp.NewOperations(mgr)
locs, err := ops.Definition(ctx, "/path/to/file.go", 10, 5)
Index ¶
- Constants
- Variables
- func URIToPath(uri string) string
- type ClientCapabilities
- type ConfigRegistry
- func (r *ConfigRegistry) Extensions() []string
- func (r *ConfigRegistry) Get(language string) (LanguageConfig, bool)
- func (r *ConfigRegistry) GetByExtension(ext string) (LanguageConfig, bool)
- func (r *ConfigRegistry) LanguageForExtension(ext string) (string, bool)
- func (r *ConfigRegistry) Languages() []string
- func (r *ConfigRegistry) Register(config LanguageConfig)
- type DefinitionCapabilities
- type DidChangeTextDocumentParams
- type DidCloseTextDocumentParams
- type DidOpenTextDocumentParams
- type HoverCapabilities
- type HoverInfo
- type HoverResult
- type InitializeParams
- type InitializeResult
- type LSPError
- type LanguageConfig
- type Location
- type LocationLink
- type Manager
- func (m *Manager) Config() ManagerConfig
- func (m *Manager) Configs() *ConfigRegistry
- func (m *Manager) Get(language string) *Server
- func (m *Manager) GetOrSpawn(ctx context.Context, language string) (*Server, error)
- func (m *Manager) IsAvailable(language string) bool
- func (m *Manager) ReleaseFile(ctx context.Context, filePath string) error
- func (m *Manager) ReopenFile(ctx context.Context, filePath string, content string, languageID string) error
- func (m *Manager) RootPath() string
- func (m *Manager) RunningServers() []string
- func (m *Manager) Shutdown(ctx context.Context, language string) error
- func (m *Manager) ShutdownAll(ctx context.Context) error
- func (m *Manager) StartIdleMonitor()
- type ManagerConfig
- type MarkupContent
- type Notification
- type Operations
- func (o *Operations) CloseDocument(ctx context.Context, filePath string) error
- func (o *Operations) Definition(ctx context.Context, filePath string, line, col int) ([]Location, error)
- func (o *Operations) Hover(ctx context.Context, filePath string, line, col int) (*HoverInfo, error)
- func (o *Operations) IsAvailable(filePath string) bool
- func (o *Operations) Manager() *Manager
- func (o *Operations) OpenDocument(ctx context.Context, filePath, content string) error
- func (o *Operations) PathToURI(path string) string
- func (o *Operations) PrepareRename(ctx context.Context, filePath string, line, col int) (*PrepareRenameResult, error)
- func (o *Operations) References(ctx context.Context, filePath string, line, col int, includeDecl bool) ([]Location, error)
- func (o *Operations) Rename(ctx context.Context, filePath string, line, col int, newName string) (*WorkspaceEdit, error)
- func (o *Operations) SummarizeWorkspaceEdit(edit *WorkspaceEdit) WorkspaceEditSummary
- func (o *Operations) URIToPath(uri string) string
- func (o *Operations) ValidateWorkspaceEdit(edit *WorkspaceEdit) error
- func (o *Operations) WorkspaceSymbol(ctx context.Context, language, query string) ([]SymbolInformation, error)
- type Position
- type PrepareRenameParams
- type PrepareRenameResult
- type Protocol
- type Range
- type ReferenceContext
- type ReferenceParams
- type ReferencesCapabilities
- type RenameCapabilities
- type RenameParams
- type Request
- type Response
- type ResponseError
- type Server
- func (s *Server) Capabilities() ServerCapabilities
- func (s *Server) Language() string
- func (s *Server) LastUsed() time.Time
- func (s *Server) Notify(method string, params interface{}) error
- func (s *Server) Request(ctx context.Context, method string, params interface{}) (*Response, error)
- func (s *Server) RootPath() string
- func (s *Server) Shutdown(ctx context.Context) error
- func (s *Server) Start(ctx context.Context) error
- func (s *Server) State() ServerState
- type ServerCapabilities
- type ServerInfo
- type ServerState
- type SymbolInformation
- type SymbolKind
- type SymbolTag
- type TextDocumentClientCapabilities
- type TextDocumentContentChangeEvent
- type TextDocumentEdit
- type TextDocumentIdentifier
- type TextDocumentItem
- type TextDocumentPositionParams
- type TextDocumentSyncClientCapabilities
- type TextEdit
- type VersionedTextDocumentIdentifier
- type WorkspaceClientCapabilities
- type WorkspaceEdit
- type WorkspaceEditClientCapabilities
- type WorkspaceEditSummary
- type WorkspaceFolder
- type WorkspaceSymbolClientCapabilities
- type WorkspaceSymbolParams
Constants ¶
const JSONRPCVersion = "2.0"
JSONRPCVersion is the JSON-RPC version used by LSP.
Variables ¶
var ( // ErrServerNotRunning indicates the LSP server is not in a ready state. ErrServerNotRunning = errors.New("lsp server not running") // ErrServerNotInstalled indicates the LSP server binary was not found. ErrServerNotInstalled = errors.New("lsp server not installed") // ErrUnsupportedLanguage indicates no LSP configuration exists for the language. ErrUnsupportedLanguage = errors.New("no lsp configuration for language") // ErrInitializeFailed indicates the LSP initialize handshake failed. ErrInitializeFailed = errors.New("lsp initialize failed") // ErrRequestTimeout indicates the LSP request exceeded the timeout. ErrRequestTimeout = errors.New("lsp request timeout") // ErrServerCrashed indicates the LSP server process terminated unexpectedly. ErrServerCrashed = errors.New("lsp server crashed") // ErrInvalidResponse indicates the LSP response could not be parsed. ErrInvalidResponse = errors.New("invalid lsp response") // ErrServerAlreadyStarted indicates Start was called on an already running server. ErrServerAlreadyStarted = errors.New("server already started") )
Sentinel errors for LSP operations.
Functions ¶
Types ¶
type ClientCapabilities ¶
type ClientCapabilities struct {
// TextDocument describes text document capabilities.
TextDocument TextDocumentClientCapabilities `json:"textDocument,omitempty"`
// Workspace describes workspace capabilities.
Workspace WorkspaceClientCapabilities `json:"workspace,omitempty"`
}
ClientCapabilities describes what the client supports.
type ConfigRegistry ¶
type ConfigRegistry struct {
// contains filtered or unexported fields
}
ConfigRegistry manages LSP configurations for different languages.
Thread Safety: Safe for concurrent use.
func NewConfigRegistry ¶
func NewConfigRegistry() *ConfigRegistry
NewConfigRegistry creates a registry with default configurations.
Description:
Creates a new configuration registry pre-populated with configurations for common languages: Go (gopls), Python (pyright), TypeScript, and JavaScript.
Outputs:
*ConfigRegistry - The configured registry
func (*ConfigRegistry) Extensions ¶
func (r *ConfigRegistry) Extensions() []string
Extensions returns all file extensions mapped to a language.
Description:
Returns a slice of all file extensions that have configurations.
Outputs:
[]string - File extensions including dots
Thread Safety:
Safe for concurrent use.
func (*ConfigRegistry) Get ¶
func (r *ConfigRegistry) Get(language string) (LanguageConfig, bool)
Get returns the configuration for a language.
Description:
Looks up the configuration for the specified language identifier.
Inputs:
language - The language identifier (e.g., "go", "python")
Outputs:
LanguageConfig - The configuration (zero value if not found) bool - True if the configuration was found
Thread Safety:
Safe for concurrent use.
func (*ConfigRegistry) GetByExtension ¶
func (r *ConfigRegistry) GetByExtension(ext string) (LanguageConfig, bool)
GetByExtension returns the configuration for a file extension.
Description:
Looks up the configuration for the language that handles the given file extension.
Inputs:
ext - The file extension including dot (e.g., ".go", ".py")
Outputs:
LanguageConfig - The configuration (zero value if not found) bool - True if the configuration was found
Thread Safety:
Safe for concurrent use.
func (*ConfigRegistry) LanguageForExtension ¶
func (r *ConfigRegistry) LanguageForExtension(ext string) (string, bool)
LanguageForExtension returns the language identifier for a file extension.
Description:
Maps a file extension to its language identifier.
Inputs:
ext - The file extension including dot (e.g., ".go")
Outputs:
string - The language identifier (empty if not found) bool - True if a mapping was found
Thread Safety:
Safe for concurrent use.
func (*ConfigRegistry) Languages ¶
func (r *ConfigRegistry) Languages() []string
Languages returns all registered language names.
Description:
Returns a slice of all language identifiers that have configurations.
Outputs:
[]string - Language identifiers
Thread Safety:
Safe for concurrent use.
func (*ConfigRegistry) Register ¶
func (r *ConfigRegistry) Register(config LanguageConfig)
Register adds or updates a language configuration.
Description:
Registers a language server configuration. If a configuration already exists for the language, it is replaced. Also updates the extension mapping for quick lookups.
Inputs:
config - The language configuration to register
Thread Safety:
Safe for concurrent use.
type DefinitionCapabilities ¶
type DefinitionCapabilities struct {
// DynamicRegistration indicates dynamic registration is supported.
DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
// LinkSupport indicates LocationLink support.
LinkSupport bool `json:"linkSupport,omitempty"`
}
DefinitionCapabilities describes go-to-definition support.
type DidChangeTextDocumentParams ¶
type DidChangeTextDocumentParams struct {
// TextDocument is the document that changed.
TextDocument VersionedTextDocumentIdentifier `json:"textDocument"`
// ContentChanges is the list of changes.
ContentChanges []TextDocumentContentChangeEvent `json:"contentChanges"`
}
DidChangeTextDocumentParams contains params for textDocument/didChange.
type DidCloseTextDocumentParams ¶
type DidCloseTextDocumentParams struct {
// TextDocument is the document that was closed.
TextDocument TextDocumentIdentifier `json:"textDocument"`
}
DidCloseTextDocumentParams contains params for textDocument/didClose.
type DidOpenTextDocumentParams ¶
type DidOpenTextDocumentParams struct {
// TextDocument is the document that was opened.
TextDocument TextDocumentItem `json:"textDocument"`
}
DidOpenTextDocumentParams contains params for textDocument/didOpen.
type HoverCapabilities ¶
type HoverCapabilities struct {
// DynamicRegistration indicates dynamic registration is supported.
DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
// ContentFormat describes supported content formats.
ContentFormat []string `json:"contentFormat,omitempty"`
}
HoverCapabilities describes hover support.
type HoverInfo ¶
type HoverInfo struct {
// Content is the hover text (documentation, type info, etc.)
Content string `json:"content"`
// Kind is the content format ("plaintext" or "markdown").
Kind string `json:"kind"`
// Range is the range this hover applies to (optional).
Range *Range `json:"range,omitempty"`
}
HoverInfo contains parsed hover information.
type HoverResult ¶
type HoverResult struct {
// Contents is the hover content.
Contents MarkupContent `json:"contents"`
// Range is the range this hover applies to.
Range *Range `json:"range,omitempty"`
}
HoverResult contains hover information.
type InitializeParams ¶
type InitializeParams struct {
// ProcessID is the process ID of the parent process.
ProcessID int `json:"processId"`
// RootURI is the root URI of the workspace (preferred over rootPath).
RootURI string `json:"rootUri"`
// RootPath is the root path of the workspace (deprecated).
RootPath string `json:"rootPath,omitempty"`
// Capabilities describes what the client supports.
Capabilities ClientCapabilities `json:"capabilities"`
// InitializationOptions are custom initialization options.
InitializationOptions interface{} `json:"initializationOptions,omitempty"`
// Trace sets the initial trace setting.
Trace string `json:"trace,omitempty"`
// WorkspaceFolders are the workspace folders if supported.
WorkspaceFolders []WorkspaceFolder `json:"workspaceFolders,omitempty"`
}
InitializeParams contains initialization parameters.
type InitializeResult ¶
type InitializeResult struct {
// Capabilities describes what the server supports.
Capabilities ServerCapabilities `json:"capabilities"`
// ServerInfo contains optional server information.
ServerInfo *ServerInfo `json:"serverInfo,omitempty"`
}
InitializeResult contains the server's response to initialize.
type LSPError ¶
type LSPError struct {
// Code is the JSON-RPC error code.
Code int
// Message is the error message from the server.
Message string
// Data contains optional additional data about the error.
Data interface{}
}
LSPError represents an error returned by the language server via JSON-RPC.
LSP error codes follow the JSON-RPC spec plus LSP-specific codes:
- -32700: Parse error
- -32600: Invalid request
- -32601: Method not found
- -32602: Invalid params
- -32603: Internal error
- -32099 to -32000: Server error (reserved)
- -32802: Server not initialized
- -32801: Unknown error code
- -32800: Request cancelled
func (*LSPError) IsMethodNotFound ¶
IsMethodNotFound returns true if the method is not supported by the server.
func (*LSPError) IsParseError ¶
IsParseError returns true if this is a JSON-RPC parse error.
func (*LSPError) IsRequestCancelled ¶
IsRequestCancelled returns true if the request was cancelled.
func (*LSPError) IsServerNotInitialized ¶
IsServerNotInitialized returns true if the server is not initialized.
type LanguageConfig ¶
type LanguageConfig struct {
// Language is the language identifier (e.g., "go", "python").
Language string
// Command is the executable name or path.
Command string
// Args are command-line arguments to pass to the server.
Args []string
// Extensions are file extensions this server handles (e.g., ".go").
Extensions []string
// RootFiles are files that indicate a project root (e.g., "go.mod").
RootFiles []string
// InitializationOptions are custom options passed during initialize.
InitializationOptions interface{}
}
LanguageConfig contains configuration for an LSP server.
type Location ¶
type Location struct {
// URI is the document URI (file:// scheme).
URI string `json:"uri"`
// Range is the range within the document.
Range Range `json:"range"`
}
Location represents a location in a document.
type LocationLink ¶
type LocationLink struct {
// OriginSelectionRange is the span in the source that was used.
OriginSelectionRange *Range `json:"originSelectionRange,omitempty"`
// TargetURI is the target document URI.
TargetURI string `json:"targetUri"`
// TargetRange is the full range of the target (for highlighting).
TargetRange Range `json:"targetRange"`
// TargetSelectionRange is the precise range to reveal.
TargetSelectionRange Range `json:"targetSelectionRange"`
}
LocationLink represents a link between a source and target location.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages LSP server instances for multiple languages.
Description:
Provides lazy startup of language servers as needed, with idle timeout and graceful shutdown. Each language has at most one server instance per workspace.
Thread Safety:
Safe for concurrent use.
func NewManager ¶
func NewManager(rootPath string, config ManagerConfig) *Manager
NewManager creates a new LSP manager.
Description:
Creates a manager for the given workspace root. The manager will lazily start language servers as needed and shut them down after the idle timeout.
Inputs:
rootPath - Absolute path to the workspace root config - Manager configuration
Outputs:
*Manager - The configured manager
func (*Manager) Config ¶
func (m *Manager) Config() ManagerConfig
Config returns the manager configuration.
func (*Manager) Configs ¶
func (m *Manager) Configs() *ConfigRegistry
Configs returns the language configuration registry.
Description:
Returns the registry so callers can register custom language configurations.
Thread Safety:
The returned registry is safe for concurrent use.
func (*Manager) Get ¶
Get returns a server for the language if one is running.
Description:
Returns the server if it exists and is ready, otherwise returns nil. Does not start a new server.
Inputs:
language - The language identifier
Outputs:
*Server - The server if running and ready, nil otherwise
Thread Safety:
Safe for concurrent use.
func (*Manager) GetOrSpawn ¶
GetOrSpawn returns a server for the language, starting it if needed.
Description:
Returns an existing server if one is running and ready, otherwise starts a new server. Uses double-check locking to ensure only one server is started per language even under concurrent requests.
Inputs:
ctx - Context for cancellation and startup timeout language - The language identifier (e.g., "go", "python")
Outputs:
*Server - The ready server error - Non-nil if the language is unsupported or server failed to start
Errors:
ErrUnsupportedLanguage - No configuration for the language ErrServerNotInstalled - Server binary not found ErrInitializeFailed - Server initialization failed
Thread Safety:
Safe for concurrent use.
func (*Manager) IsAvailable ¶
IsAvailable checks if an LSP server is available for a language.
Description:
Checks if the language is supported and the server binary is installed. Does not start the server.
Inputs:
language - The language identifier
Outputs:
bool - True if the language is supported and server is installed
Thread Safety:
Safe for concurrent use.
func (*Manager) ReleaseFile ¶
ReleaseFile notifies all running LSP servers to close a file.
Description:
Sends textDocument/didClose notifications to all running LSP servers for the given file path. This is needed on Windows before atomic file writes (os.Rename) because LSP servers may hold file handles open, blocking the rename operation.
Inputs:
ctx - Context for cancellation and timeout filePath - Absolute path to the file to release
Outputs:
error - Non-nil if any server notification failed (best-effort)
Thread Safety:
Safe for concurrent use.
func (*Manager) ReopenFile ¶
func (m *Manager) ReopenFile(ctx context.Context, filePath string, content string, languageID string) error
ReopenFile notifies all running LSP servers to reopen a file.
Description:
Sends textDocument/didOpen notifications to all running LSP servers for the given file path with the new content. This is called after atomic file writes on Windows to restore LSP server awareness of the file.
Inputs:
ctx - Context for cancellation and timeout filePath - Absolute path to the file to reopen content - The new file content to send to servers languageID - The language identifier (e.g., "go", "python")
Outputs:
error - Non-nil if any server notification failed (best-effort)
Thread Safety:
Safe for concurrent use.
func (*Manager) RunningServers ¶
RunningServers returns languages with running servers.
Description:
Returns a list of language identifiers for servers that are currently in the ready state.
Outputs:
[]string - Language identifiers
Thread Safety:
Safe for concurrent use.
func (*Manager) Shutdown ¶
Shutdown shuts down a specific language server.
Description:
Gracefully shuts down the server for the given language. No-op if no server is running for the language.
Inputs:
ctx - Context for shutdown timeout language - The language identifier
Outputs:
error - Non-nil if shutdown encountered errors
Thread Safety:
Safe for concurrent use.
func (*Manager) ShutdownAll ¶
ShutdownAll shuts down all servers and stops the manager.
Description:
Gracefully shuts down all running servers. After this call, GetOrSpawn will return an error.
Inputs:
ctx - Context for shutdown timeout
Outputs:
error - Non-nil if any shutdown encountered errors (last error returned)
Thread Safety:
Safe for concurrent use. Multiple calls are idempotent.
func (*Manager) StartIdleMonitor ¶
func (m *Manager) StartIdleMonitor()
StartIdleMonitor starts the idle server cleanup goroutine.
Description:
Starts a background goroutine that periodically checks for idle servers and shuts them down. The check interval is half the idle timeout. Does nothing if IdleTimeout is 0.
Thread Safety:
Safe for concurrent use. Multiple calls start multiple monitors (not recommended).
type ManagerConfig ¶
type ManagerConfig struct {
// IdleTimeout is how long a server can be idle before being shut down.
// Set to 0 to disable idle shutdown.
IdleTimeout time.Duration
// StartupTimeout is the maximum time to wait for a server to start.
StartupTimeout time.Duration
// RequestTimeout is the default timeout for LSP requests.
RequestTimeout time.Duration
}
ManagerConfig configures the LSP manager.
func DefaultManagerConfig ¶
func DefaultManagerConfig() ManagerConfig
DefaultManagerConfig returns sensible defaults for the manager.
Description:
Returns a configuration with: - IdleTimeout: 10 minutes - StartupTimeout: 30 seconds - RequestTimeout: 10 seconds
type MarkupContent ¶
type MarkupContent struct {
// Kind is the type of markup: "plaintext" or "markdown".
Kind string `json:"kind"`
// Value is the actual content.
Value string `json:"value"`
}
MarkupContent represents documentation content.
type Notification ¶
type Notification struct {
// JSONRPC is the protocol version, always "2.0".
JSONRPC string `json:"jsonrpc"`
// Method is the method to invoke.
Method string `json:"method"`
// Params contains the method parameters.
Params interface{} `json:"params,omitempty"`
}
Notification represents a JSON-RPC notification (no ID, no response).
type Operations ¶
type Operations struct {
// contains filtered or unexported fields
}
Operations provides high-level LSP operations.
Description:
Wraps the Manager to provide convenient methods for common LSP operations like go-to-definition, find-references, hover, and rename. Automatically determines the language from file extensions and handles server startup as needed.
Thread Safety:
Safe for concurrent use.
func NewOperations ¶
func NewOperations(manager *Manager) *Operations
NewOperations creates an Operations instance.
Inputs:
manager - The LSP manager to use for server management
Outputs:
*Operations - The operations wrapper
func (*Operations) CloseDocument ¶
func (o *Operations) CloseDocument(ctx context.Context, filePath string) error
CloseDocument notifies the server that a document was closed.
Description:
Sends a textDocument/didClose notification.
Inputs:
filePath - Absolute path to the file
Outputs:
error - Non-nil on failure
func (*Operations) Definition ¶
func (o *Operations) Definition(ctx context.Context, filePath string, line, col int) ([]Location, error)
Definition returns the definition location(s) for a symbol.
Description:
Sends a textDocument/definition request to the appropriate language server and returns the location(s) of the symbol's definition.
Inputs:
ctx - Context for cancellation and timeout filePath - Absolute path to the file line - 1-indexed line number col - 0-indexed column number (character offset)
Outputs:
[]Location - Definition location(s), may be empty if not found error - Non-nil on failure
Errors:
ErrUnsupportedLanguage - No LSP configuration for file extension ErrServerNotInstalled - Server binary not found ErrRequestTimeout - Request timed out
Example:
locs, err := ops.Definition(ctx, "/project/main.go", 10, 5)
if err != nil {
return err
}
for _, loc := range locs {
fmt.Printf("Definition at %s:%d\n", URIToPath(loc.URI), loc.Range.Start.Line+1)
}
func (*Operations) Hover ¶
Hover returns type and documentation info for a symbol.
Description:
Sends a textDocument/hover request to get documentation and type information for the symbol at the given position.
Inputs:
ctx - Context for cancellation and timeout filePath - Absolute path to the file line - 1-indexed line number col - 0-indexed column number
Outputs:
*HoverInfo - Hover information, nil if no hover available error - Non-nil on failure
Example:
info, err := ops.Hover(ctx, "/project/main.go", 10, 5)
if err != nil {
return err
}
if info != nil {
fmt.Println(info.Content)
}
func (*Operations) IsAvailable ¶
func (o *Operations) IsAvailable(filePath string) bool
IsAvailable checks if LSP operations are available for a file.
Description:
Checks if the file extension is supported and the server binary is installed.
Inputs:
filePath - Path to check (only extension is used)
Outputs:
bool - True if LSP operations are available
func (*Operations) Manager ¶
func (o *Operations) Manager() *Manager
Manager returns the underlying manager.
func (*Operations) OpenDocument ¶
func (o *Operations) OpenDocument(ctx context.Context, filePath, content string) error
OpenDocument notifies the server that a document was opened.
Description:
Sends a textDocument/didOpen notification. This is required before most LSP operations will work on a file.
Inputs:
filePath - Absolute path to the file content - The file content
Outputs:
error - Non-nil on failure
func (*Operations) PathToURI ¶
func (o *Operations) PathToURI(path string) string
PathToURI converts a file path to a file:// URI.
Description:
Convenience method for converting file paths to LSP URIs.
func (*Operations) PrepareRename ¶
func (o *Operations) PrepareRename(ctx context.Context, filePath string, line, col int) (*PrepareRenameResult, error)
PrepareRename checks if rename is valid at the given position.
Description:
Sends a textDocument/prepareRename request to check if the symbol at the given position can be renamed and returns the range and placeholder text.
Inputs:
ctx - Context for cancellation and timeout filePath - Absolute path to the file line - 1-indexed line number col - 0-indexed column number
Outputs:
*PrepareRenameResult - The range and placeholder, nil if not renameable error - Non-nil on failure
func (*Operations) References ¶
func (o *Operations) References(ctx context.Context, filePath string, line, col int, includeDecl bool) ([]Location, error)
References returns all references to a symbol.
Description:
Sends a textDocument/references request to find all locations that reference the symbol at the given position.
Inputs:
ctx - Context for cancellation and timeout filePath - Absolute path to the file line - 1-indexed line number col - 0-indexed column number includeDecl - Whether to include the declaration in results
Outputs:
[]Location - Reference locations, may be empty error - Non-nil on failure
Example:
refs, err := ops.References(ctx, "/project/main.go", 10, 5, true)
if err != nil {
return err
}
fmt.Printf("Found %d references\n", len(refs))
func (*Operations) Rename ¶
func (o *Operations) Rename(ctx context.Context, filePath string, line, col int, newName string) (*WorkspaceEdit, error)
Rename computes edits for renaming a symbol.
Description:
Sends a textDocument/rename request to compute all edits needed to rename the symbol at the given position. Returns the edits but does NOT apply them - the caller is responsible for applying the edits.
Inputs:
ctx - Context for cancellation and timeout filePath - Absolute path to the file line - 1-indexed line number col - 0-indexed column number newName - The new name for the symbol
Outputs:
*WorkspaceEdit - Edits to apply for the rename error - Non-nil on failure
Example:
edit, err := ops.Rename(ctx, "/project/main.go", 10, 5, "newName")
if err != nil {
return err
}
for uri, edits := range edit.Changes {
fmt.Printf("File %s: %d edits\n", URIToPath(uri), len(edits))
}
func (*Operations) SummarizeWorkspaceEdit ¶
func (o *Operations) SummarizeWorkspaceEdit(edit *WorkspaceEdit) WorkspaceEditSummary
SummarizeWorkspaceEdit creates a summary of a workspace edit.
Description:
Analyzes a WorkspaceEdit returned by LSP Rename and produces a summary showing which files are affected and how many edits each will receive. This is useful for presenting rename previews to users.
Inputs:
edit - The workspace edit to summarize
Outputs:
WorkspaceEditSummary - Summary of the edit
Example:
edit, err := ops.Rename(ctx, "/project/main.go", 10, 5, "newName")
if err != nil {
return err
}
summary := ops.SummarizeWorkspaceEdit(edit)
fmt.Printf("Rename will affect %d files with %d total edits\n",
summary.FileCount, summary.TotalEdits)
func (*Operations) URIToPath ¶
func (o *Operations) URIToPath(uri string) string
URIToPath converts a file:// URI to a file path.
Description:
Convenience method for converting LSP URIs to file paths.
func (*Operations) ValidateWorkspaceEdit ¶
func (o *Operations) ValidateWorkspaceEdit(edit *WorkspaceEdit) error
ValidateWorkspaceEdit checks if a workspace edit can be safely applied.
Description:
Performs basic validation on a workspace edit to ensure it references valid files and has reasonable edit ranges. This does NOT check if the files actually exist or are writable.
Important:
The Rename operation returns edits but does NOT apply them. The caller is responsible for: 1. Reviewing the edits with the user 2. Creating backups if needed 3. Applying the edits atomically 4. Handling any conflicts or errors
Inputs:
edit - The workspace edit to validate
Outputs:
error - Non-nil if the edit has obvious problems
func (*Operations) WorkspaceSymbol ¶
func (o *Operations) WorkspaceSymbol(ctx context.Context, language, query string) ([]SymbolInformation, error)
WorkspaceSymbol finds symbols matching a query in the workspace.
Description:
Sends a workspace/symbol request to find symbols matching the query across the entire workspace.
Inputs:
ctx - Context for cancellation and timeout language - The language to query (determines which server to use) query - The symbol query (empty string returns all symbols)
Outputs:
[]SymbolInformation - Matching symbols error - Non-nil on failure
Example:
symbols, err := ops.WorkspaceSymbol(ctx, "go", "Handler")
if err != nil {
return err
}
for _, sym := range symbols {
fmt.Printf("%s (%s)\n", sym.Name, sym.Location.URI)
}
type Position ¶
type Position struct {
// Line is the 0-indexed line number.
Line int `json:"line"`
// Character is the 0-indexed character offset within the line.
Character int `json:"character"`
}
Position represents a position in a text document. Line and character are 0-indexed per LSP specification.
type PrepareRenameParams ¶
type PrepareRenameParams struct {
TextDocumentPositionParams
}
PrepareRenameParams contains prepare rename request parameters.
type PrepareRenameResult ¶
type PrepareRenameResult struct {
// Range is the range of the string to rename.
Range Range `json:"range"`
// Placeholder is the text of the string to rename.
Placeholder string `json:"placeholder"`
}
PrepareRenameResult contains the result of a prepare rename request.
type Protocol ¶
type Protocol struct {
// contains filtered or unexported fields
}
Protocol handles JSON-RPC communication over stdin/stdout.
Description:
Implements the LSP base protocol using Content-Length headers. Manages request/response correlation and supports notifications.
Thread Safety:
Safe for concurrent use. Multiple goroutines can send requests and notifications simultaneously.
func NewProtocol ¶
NewProtocol creates a new protocol handler.
Description:
Creates a protocol handler that communicates over the provided reader (server stdout) and writer (server stdin).
Inputs:
r - Reader for server responses (e.g., stdout pipe) w - Writer for client requests (e.g., stdin pipe)
Outputs:
*Protocol - The protocol handler
func (*Protocol) Close ¶
func (p *Protocol) Close()
Close marks the protocol as closed.
Description:
Marks the protocol as closed to prevent further sends. Cancels all pending requests with an error response. Does not close underlying readers/writers.
Thread Safety:
Safe for concurrent use.
func (*Protocol) ReadLoop ¶
ReadLoop reads messages from the server and dispatches responses.
Description:
Continuously reads messages from the server. Responses are matched to pending requests. Notifications are ignored. Call this in a goroutine after starting the server.
Inputs:
ctx - Context for cancellation
Outputs:
error - Non-nil if reading fails or context is cancelled
Thread Safety:
Must be called from a single goroutine. Safe to run while other goroutines call SendRequest/SendNotification.
func (*Protocol) SendNotification ¶
SendNotification sends a notification (no response expected).
Description:
Sends a JSON-RPC notification to the server. Notifications do not expect a response.
Inputs:
method - The LSP method to invoke (e.g., "initialized") params - Method parameters (will be JSON-marshaled)
Outputs:
error - Non-nil if sending failed
Thread Safety:
Safe for concurrent use.
func (*Protocol) SendRequest ¶
func (p *Protocol) SendRequest(ctx context.Context, method string, params interface{}) (*Response, error)
SendRequest sends a request and waits for the response.
Description:
Sends a JSON-RPC request to the server and blocks until a response is received or the context is cancelled.
Inputs:
ctx - Context for cancellation and timeout method - The LSP method to invoke (e.g., "textDocument/definition") params - Method parameters (will be JSON-marshaled)
Outputs:
*Response - The server's response error - Non-nil if sending failed, timeout, or server returned error
Thread Safety:
Safe for concurrent use.
type Range ¶
type Range struct {
// Start is the inclusive start position.
Start Position `json:"start"`
// End is the exclusive end position.
End Position `json:"end"`
}
Range represents a range in a text document.
type ReferenceContext ¶
type ReferenceContext struct {
// IncludeDeclaration indicates whether to include the declaration.
IncludeDeclaration bool `json:"includeDeclaration"`
}
ReferenceContext contains options for find references requests.
type ReferenceParams ¶
type ReferenceParams struct {
TextDocumentPositionParams
// Context contains additional context for the request.
Context ReferenceContext `json:"context"`
}
ReferenceParams extends TextDocumentPositionParams for find references.
type ReferencesCapabilities ¶
type ReferencesCapabilities struct {
// DynamicRegistration indicates dynamic registration is supported.
DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
}
ReferencesCapabilities describes find-references support.
type RenameCapabilities ¶
type RenameCapabilities struct {
// DynamicRegistration indicates dynamic registration is supported.
DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
// PrepareSupport indicates prepareRename is supported.
PrepareSupport bool `json:"prepareSupport,omitempty"`
}
RenameCapabilities describes rename support.
type RenameParams ¶
type RenameParams struct {
TextDocumentPositionParams
// NewName is the new name to rename the symbol to.
NewName string `json:"newName"`
}
RenameParams contains rename request parameters.
type Request ¶
type Request struct {
// JSONRPC is the protocol version, always "2.0".
JSONRPC string `json:"jsonrpc"`
// ID is the request identifier. Omit for notifications.
ID int64 `json:"id,omitempty"`
// Method is the method to invoke.
Method string `json:"method"`
// Params contains the method parameters.
Params interface{} `json:"params,omitempty"`
}
Request represents a JSON-RPC request.
type Response ¶
type Response struct {
// JSONRPC is the protocol version, always "2.0".
JSONRPC string `json:"jsonrpc"`
// ID is the request identifier this response corresponds to.
ID int64 `json:"id"`
// Result contains the method result (mutually exclusive with Error).
Result json.RawMessage `json:"result,omitempty"`
// Error contains error information (mutually exclusive with Result).
Error *ResponseError `json:"error,omitempty"`
}
Response represents a JSON-RPC response.
type ResponseError ¶
type ResponseError struct {
// Code is the error code.
Code int `json:"code"`
// Message is a short description of the error.
Message string `json:"message"`
// Data contains additional error information.
Data interface{} `json:"data,omitempty"`
}
ResponseError represents a JSON-RPC error.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server represents a running LSP server process.
Description:
Manages the lifecycle of an LSP server process, including starting, initializing, and shutting down. Provides methods for sending requests and notifications to the server.
Thread Safety:
Safe for concurrent use after Start() returns successfully.
func NewServer ¶
func NewServer(config LanguageConfig, rootPath string) *Server
NewServer creates a new server instance (not started).
Description:
Creates a server instance configured for the given language. The server is not started; call Start to begin the process.
Inputs:
config - Language configuration for the server rootPath - Absolute path to the workspace root
Outputs:
*Server - The configured (but not started) server
func (*Server) Capabilities ¶
func (s *Server) Capabilities() ServerCapabilities
Capabilities returns the server's capabilities.
Description:
Returns the capabilities reported by the server during initialization. Returns zero value if the server hasn't been initialized.
func (*Server) LastUsed ¶
LastUsed returns when the server was last used.
Thread Safety:
Safe for concurrent use.
func (*Server) Notify ¶
Notify sends an LSP notification.
Description:
Sends a notification to the server. Notifications do not expect a response. Updates the last-used timestamp.
Inputs:
method - The LSP method to invoke params - Method parameters
Outputs:
error - Non-nil if server not ready or send failed
Thread Safety:
Safe for concurrent use.
func (*Server) Request ¶
Request sends an LSP request and waits for the response.
Description:
Sends a request to the server and blocks until a response is received or the context is cancelled. Updates the last-used timestamp.
Inputs:
ctx - Context for cancellation and timeout method - The LSP method to invoke params - Method parameters
Outputs:
*Response - The server's response error - Non-nil if server not ready, send failed, or timeout
Thread Safety:
Safe for concurrent use.
func (*Server) Shutdown ¶
Shutdown gracefully shuts down the server.
Description:
Sends shutdown and exit messages to the server, then waits for the process to terminate. If the server doesn't respond, it is killed.
Inputs:
ctx - Context for cancellation and timeout
Outputs:
error - Non-nil if shutdown encountered errors (server is still stopped)
Thread Safety:
Safe for concurrent use. Multiple calls are idempotent.
func (*Server) Start ¶
Start starts the LSP server process and initializes it.
Description:
Starts the server process, establishes communication, and performs the LSP initialize handshake. On success, the server is ready to receive requests.
Inputs:
ctx - Context for cancellation and timeout
Outputs:
error - Non-nil if the server failed to start or initialize
Errors:
ErrServerNotInstalled - Server binary not found ErrServerAlreadyStarted - Start called on a non-uninitialized server ErrInitializeFailed - LSP initialize handshake failed
Thread Safety:
Safe for concurrent use, but only the first caller will start the server.
func (*Server) State ¶
func (s *Server) State() ServerState
State returns the current server state.
Thread Safety:
Safe for concurrent use.
type ServerCapabilities ¶
type ServerCapabilities struct {
// TextDocumentSync describes how documents are synced.
TextDocumentSync interface{} `json:"textDocumentSync,omitempty"`
// DefinitionProvider indicates textDocument/definition is supported.
DefinitionProvider interface{} `json:"definitionProvider,omitempty"`
// ReferencesProvider indicates textDocument/references is supported.
ReferencesProvider interface{} `json:"referencesProvider,omitempty"`
// HoverProvider indicates textDocument/hover is supported.
HoverProvider interface{} `json:"hoverProvider,omitempty"`
// RenameProvider indicates textDocument/rename is supported.
RenameProvider interface{} `json:"renameProvider,omitempty"`
// WorkspaceSymbolProvider indicates workspace/symbol is supported.
WorkspaceSymbolProvider interface{} `json:"workspaceSymbolProvider,omitempty"`
}
ServerCapabilities describes what the server supports.
func (*ServerCapabilities) HasDefinitionProvider ¶
func (c *ServerCapabilities) HasDefinitionProvider() bool
HasDefinitionProvider returns true if definition is supported.
func (*ServerCapabilities) HasHoverProvider ¶
func (c *ServerCapabilities) HasHoverProvider() bool
HasHoverProvider returns true if hover is supported.
func (*ServerCapabilities) HasReferencesProvider ¶
func (c *ServerCapabilities) HasReferencesProvider() bool
HasReferencesProvider returns true if references is supported.
func (*ServerCapabilities) HasRenameProvider ¶
func (c *ServerCapabilities) HasRenameProvider() bool
HasRenameProvider returns true if rename is supported.
func (*ServerCapabilities) HasWorkspaceSymbolProvider ¶
func (c *ServerCapabilities) HasWorkspaceSymbolProvider() bool
HasWorkspaceSymbolProvider returns true if workspace/symbol is supported.
type ServerInfo ¶
type ServerInfo struct {
// Name is the server's name.
Name string `json:"name"`
// Version is the server's version.
Version string `json:"version,omitempty"`
}
ServerInfo contains information about the server.
type ServerState ¶
type ServerState int
ServerState represents the lifecycle state of an LSP server.
const ( // ServerStateUninitialized is the initial state before Start is called. ServerStateUninitialized ServerState = iota // ServerStateStarting means the server process is starting. ServerStateStarting // ServerStateReady means the server is initialized and ready for requests. ServerStateReady // ServerStateStopping means the server is shutting down. ServerStateStopping // ServerStateStopped means the server has terminated. ServerStateStopped )
func (ServerState) String ¶
func (s ServerState) String() string
String returns a human-readable state name.
type SymbolInformation ¶
type SymbolInformation struct {
// Name is the symbol's name.
Name string `json:"name"`
// Kind is the symbol kind (function, class, etc.).
Kind SymbolKind `json:"kind"`
// Tags are additional attributes (deprecated, etc.).
Tags []SymbolTag `json:"tags,omitempty"`
// Location is where the symbol is defined.
Location Location `json:"location"`
// ContainerName is the name of the containing symbol.
ContainerName string `json:"containerName,omitempty"`
}
SymbolInformation represents information about a symbol.
type SymbolKind ¶
type SymbolKind int
SymbolKind represents the kind of a symbol.
const ( SymbolKindFile SymbolKind = 1 SymbolKindModule SymbolKind = 2 SymbolKindNamespace SymbolKind = 3 SymbolKindPackage SymbolKind = 4 SymbolKindClass SymbolKind = 5 SymbolKindMethod SymbolKind = 6 SymbolKindProperty SymbolKind = 7 SymbolKindField SymbolKind = 8 SymbolKindConstructor SymbolKind = 9 SymbolKindEnum SymbolKind = 10 SymbolKindInterface SymbolKind = 11 SymbolKindFunction SymbolKind = 12 SymbolKindVariable SymbolKind = 13 SymbolKindConstant SymbolKind = 14 SymbolKindString SymbolKind = 15 SymbolKindNumber SymbolKind = 16 SymbolKindBoolean SymbolKind = 17 SymbolKindArray SymbolKind = 18 SymbolKindObject SymbolKind = 19 SymbolKindKey SymbolKind = 20 SymbolKindNull SymbolKind = 21 SymbolKindEnumMember SymbolKind = 22 SymbolKindStruct SymbolKind = 23 SymbolKindEvent SymbolKind = 24 SymbolKindOperator SymbolKind = 25 SymbolKindTypeParameter SymbolKind = 26 )
Symbol kinds as defined by the LSP specification.
type SymbolTag ¶
type SymbolTag int
SymbolTag represents additional symbol attributes.
const (
SymbolTagDeprecated SymbolTag = 1
)
Symbol tags as defined by the LSP specification.
type TextDocumentClientCapabilities ¶
type TextDocumentClientCapabilities struct {
// Synchronization describes document sync capabilities.
Synchronization *TextDocumentSyncClientCapabilities `json:"synchronization,omitempty"`
// Definition describes go-to-definition support.
Definition *DefinitionCapabilities `json:"definition,omitempty"`
// References describes find-references support.
References *ReferencesCapabilities `json:"references,omitempty"`
// Hover describes hover support.
Hover *HoverCapabilities `json:"hover,omitempty"`
// Rename describes rename support.
Rename *RenameCapabilities `json:"rename,omitempty"`
}
TextDocumentClientCapabilities describes text document capabilities.
type TextDocumentContentChangeEvent ¶
type TextDocumentContentChangeEvent struct {
// Range is the range that got replaced. Omit for full document sync.
Range *Range `json:"range,omitempty"`
// RangeLength is the length of the range that got replaced (deprecated).
RangeLength *int `json:"rangeLength,omitempty"`
// Text is the new text for the range or full document.
Text string `json:"text"`
}
TextDocumentContentChangeEvent describes a content change event.
type TextDocumentEdit ¶
type TextDocumentEdit struct {
// TextDocument identifies the document.
TextDocument VersionedTextDocumentIdentifier `json:"textDocument"`
// Edits is the list of edits.
Edits []TextEdit `json:"edits"`
}
TextDocumentEdit describes edits to a specific document version.
type TextDocumentIdentifier ¶
type TextDocumentIdentifier struct {
// URI is the document's URI.
URI string `json:"uri"`
}
TextDocumentIdentifier identifies a text document by URI.
type TextDocumentItem ¶
type TextDocumentItem struct {
// URI is the document's URI.
URI string `json:"uri"`
// LanguageID is the language identifier (e.g., "go", "python").
LanguageID string `json:"languageId"`
// Version is the version number of this document.
Version int `json:"version"`
// Text is the content of the document.
Text string `json:"text"`
}
TextDocumentItem represents a text document with its content.
type TextDocumentPositionParams ¶
type TextDocumentPositionParams struct {
// TextDocument is the document identifier.
TextDocument TextDocumentIdentifier `json:"textDocument"`
// Position is the position within the document.
Position Position `json:"position"`
}
TextDocumentPositionParams identifies a position in a text document.
type TextDocumentSyncClientCapabilities ¶
type TextDocumentSyncClientCapabilities struct {
// DynamicRegistration indicates dynamic registration is supported.
DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
// WillSave indicates willSave notifications are supported.
WillSave bool `json:"willSave,omitempty"`
// WillSaveWaitUntil indicates willSaveWaitUntil requests are supported.
WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitempty"`
// DidSave indicates didSave notifications are supported.
DidSave bool `json:"didSave,omitempty"`
}
TextDocumentSyncClientCapabilities describes sync capabilities.
type TextEdit ¶
type TextEdit struct {
// Range is the range to replace.
Range Range `json:"range"`
// NewText is the replacement text.
NewText string `json:"newText"`
}
TextEdit represents a single text change.
type VersionedTextDocumentIdentifier ¶
type VersionedTextDocumentIdentifier struct {
TextDocumentIdentifier
// Version is the version number. Null means the version is known.
Version *int `json:"version"`
}
VersionedTextDocumentIdentifier identifies a specific version of a document.
type WorkspaceClientCapabilities ¶
type WorkspaceClientCapabilities struct {
// ApplyEdit indicates applyEdit requests are supported.
ApplyEdit bool `json:"applyEdit,omitempty"`
// WorkspaceEdit describes workspace edit capabilities.
WorkspaceEdit *WorkspaceEditClientCapabilities `json:"workspaceEdit,omitempty"`
// Symbol describes workspace symbol capabilities.
Symbol *WorkspaceSymbolClientCapabilities `json:"symbol,omitempty"`
}
WorkspaceClientCapabilities describes workspace capabilities.
type WorkspaceEdit ¶
type WorkspaceEdit struct {
// Changes is a map from URI to list of text edits.
Changes map[string][]TextEdit `json:"changes,omitempty"`
// DocumentChanges are versioned document edits (preferred over Changes).
DocumentChanges []TextDocumentEdit `json:"documentChanges,omitempty"`
}
WorkspaceEdit represents changes to many resources.
type WorkspaceEditClientCapabilities ¶
type WorkspaceEditClientCapabilities struct {
// DocumentChanges indicates documentChanges are supported.
DocumentChanges bool `json:"documentChanges,omitempty"`
}
WorkspaceEditClientCapabilities describes workspace edit capabilities.
type WorkspaceEditSummary ¶
type WorkspaceEditSummary struct {
// FileCount is the number of files affected by the edit.
FileCount int
// TotalEdits is the total number of text edits across all files.
TotalEdits int
// Files is a map from file path to the number of edits in that file.
Files map[string]int
}
WorkspaceEditSummary provides a human-readable summary of a workspace edit.
type WorkspaceFolder ¶
type WorkspaceFolder struct {
// URI is the folder URI.
URI string `json:"uri"`
// Name is the name of the folder.
Name string `json:"name"`
}
WorkspaceFolder represents a workspace folder.
type WorkspaceSymbolClientCapabilities ¶
type WorkspaceSymbolClientCapabilities struct {
// DynamicRegistration indicates dynamic registration is supported.
DynamicRegistration bool `json:"dynamicRegistration,omitempty"`
}
WorkspaceSymbolClientCapabilities describes workspace symbol capabilities.
type WorkspaceSymbolParams ¶
type WorkspaceSymbolParams struct {
// Query is a non-empty query string to filter symbols.
Query string `json:"query"`
}
WorkspaceSymbolParams contains workspace symbol query parameters.