lsp

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 10, 2026 License: MIT Imports: 2 Imported by: 0

README ΒΆ

LSP - Language Server Protocol Library for Go

A Go library for implementing Language Server Protocol (LSP) servers with protocol-agnostic core types optimized for CLI tools and server implementations.

Key Features

  • Protocol-Agnostic Core Types: Work with UTF-8 byte offsets naturally in Go
  • CLI-First Design: Use LSP data structures in CLI tools without protocol overhead
  • Reusable Providers: Write business logic once, use in both CLI and LSP server
  • Automatic UTF-16 Conversion: Adapters handle protocol conversion at boundaries per LSP spec requirements
  • Full LSP Support: Implements LSP 3.16, 3.17, and 3.18

New to LSP? Check out the LSP Primer - a guide mapping VS Code features (like squiggles, auto-complete, and go-to-definition) to LSP capabilities.

Quick Start

1. CLI Tool (No LSP Server)
import "github.com/SCKelemen/lsp/core"

func lintFile(content string) []core.Diagnostic {
    var diagnostics []core.Diagnostic
    severity := core.SeverityWarning

    // Work naturally with UTF-8 byte offsets
    for i := 0; i < len(content); i++ {
        if content[i] == '\t' {
            pos := core.ByteOffsetToPosition(content, i)
            diagnostics = append(diagnostics, core.Diagnostic{
                Range: core.Range{
                    Start: pos,
                    End:   core.Position{Line: pos.Line, Character: pos.Character + 1},
                },
                Severity: &severity,
                Message:  "Use spaces instead of tabs",
            })
        }
    }
    return diagnostics
}
2. Reusable Provider
// Write once, use in CLI and LSP server
type TabFixProvider struct{}

func (p *TabFixProvider) ProvideCodeFixes(ctx core.CodeFixContext) []core.CodeAction {
    // Your fix logic using UTF-8 offsets
    return actions
}

// Use in CLI tool
registry := core.NewCodeFixRegistry()
registry.Register(&TabFixProvider{})
fixes := registry.ProvideCodeFixes(ctx)

// Same provider works in LSP server - just convert at boundaries
3. LSP Server Handler
import (
    "github.com/SCKelemen/lsp"
    "github.com/SCKelemen/lsp/adapter"
    "github.com/SCKelemen/lsp/core"
    protocol "github.com/SCKelemen/lsp/protocol"
)

func (s *Server) TextDocumentDidOpen(
    context *lsp.Context,
    params *protocol.DidOpenTextDocumentParams,
) error {
    uri := string(params.TextDocument.URI)
    content := params.TextDocument.Text

    // Business logic with core types (UTF-8)
    diagnostics := s.validate(uri, content)

    // Convert to protocol at boundary
    protocolDiags := adapter.CoreToProtocolDiagnostics(diagnostics, content)

    // Send to client
    context.Notify(...)
    return nil
}

πŸ“š Comprehensive Feature Guides

Complete guides for implementing LSP features from scratch to production:

Core Features

➑️ VALIDATORS.md - Diagnostic Providers

  • Writing validators that detect code issues
  • Testing with Unicode content
  • Composing multiple validators
  • Integration with LSP servers

➑️ CODE_ACTIONS.md - Code Action Providers

  • Quick fixes for diagnostics
  • Refactoring actions (extract, inline, rewrite)
  • Source actions (organize imports, fix all)
  • Workspace edits and multiple file changes
Navigation & Information

➑️ NAVIGATION.md - Definition & Hover Providers

  • Go-to-definition across files
  • Hover information with markdown
  • Finding references and implementations
  • Type definitions and declarations

➑️ SYMBOLS.md - Document Symbol Providers

  • Hierarchical document structure
  • Outline and breadcrumb navigation
  • Symbol kinds (functions, classes, variables)
  • Tree-based symbol representation
Editor Features

➑️ FOLDING.md - Folding Range Providers

  • Collapsible code regions
  • Multiple folding strategies (braces, indentation, regions)
  • Comments, imports, and function folding
  • Language-agnostic folding patterns

➑️ FORMATTING.md - Formatting Providers

  • Document-wide formatting
  • Range formatting for selections
  • Formatting options (tabs, spaces, whitespace)
  • Integration with language formatters

Each guide includes:

  • βœ… Step-by-step implementation
  • βœ… Complete working examples
  • βœ… Comprehensive test patterns
  • βœ… LSP server integration
  • βœ… UTF-8/UTF-16 conversion details

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      Your Business Logic            β”‚
β”‚       (core/ package)                β”‚
β”‚   UTF-8 offsets, Go-friendly types  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β”œβ”€ CLI Tools: Direct use
             β”‚
             └─ LSP Server: Convert at boundaries
                      ↓
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚   Adapter Functions   β”‚
          β”‚    (adapter/ package) β”‚
          β”‚    UTF-8 ↔ UTF-16     β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      ↓
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚   Protocol Types      β”‚
          β”‚   (protocol/ package) β”‚
          β”‚   JSON-RPC/LSP Spec   β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why Core Types?

LSP uses UTF-16 (per specification), but Go strings are UTF-8. Core types use UTF-8 for natural Go string handling:

content := "hello δΈ–η•Œ"  // δΈ–η•Œ is 3 bytes in UTF-8, 1 code unit in UTF-16

// Core types: direct indexing
pos := core.ByteOffsetToPosition(content, 8)  // Natural UTF-8 offset

// Protocol types: need conversion
protocolPos := adapter.CoreToProtocolPosition(pos, content)

Core Packages

core/

Protocol-agnostic types using UTF-8:

  • types.go: Position, Range, Location, Diagnostic
  • language_features.go: FoldingRange, TextEdit, DocumentSymbol, CodeAction, WorkspaceEdit
  • codefix.go: Provider interfaces (CodeFixProvider, DiagnosticProvider, etc.)
  • document.go: DocumentManager for managing documents in memory
  • encoding.go: UTF-8 ↔ UTF-16 conversion utilities
protocol/

LSP protocol types with UTF-16 offsets (JSON-RPC):

  • Full LSP 3.16, 3.17, and 3.18 protocol type definitions
  • Message types, request/response structures
  • Server and client capabilities
adapter/

Conversion functions between core (UTF-8) and protocol (UTF-16) types:

  • Position and range conversions
  • Diagnostic, completion, and workspace edit conversions
  • Support for all LSP 3.16, 3.17, and 3.18 features
examples/

Complete working examples for CLI tools and LSP servers

Provider Interfaces

Write providers that work with core types:

type DiagnosticProvider interface {
    ProvideDiagnostics(uri, content string) []Diagnostic
}

type CodeFixProvider interface {
    ProvideCodeFixes(ctx CodeFixContext) []CodeAction
}

type FoldingRangeProvider interface {
    ProvideFoldingRanges(uri, content string) []FoldingRange
}

// ... and more (hover, definition, formatting, etc.)

β†’ See comprehensive feature guides above for complete implementation details

Traditional LSP Server (Original Functionality)

This library still supports traditional LSP server usage:

package main

import (
	"github.com/SCKelemen/lsp"
	protocol "github.com/SCKelemen/lsp/protocol"
	"github.com/SCKelemen/lsp/server"
	"github.com/tliron/commonlog"
	_ "github.com/tliron/commonlog/simple"
)

const lsName = "my language"

var (
	version string = "0.0.1"
	handler protocol.Handler
)

func main() {
	commonlog.Configure(1, nil)

	handler = protocol.Handler{
		Initialize:  initialize,
		Initialized: initialized,
		Shutdown:    shutdown,
		SetTrace:    setTrace,
	}

	server := server.NewServer(&handler, lsName, false)
	server.RunStdio()
}

func initialize(context *lsp.Context, params *protocol.InitializeParams) (any, error) {
	capabilities := handler.CreateServerCapabilities()
	return protocol.InitializeResult{
		Capabilities: capabilities,
		ServerInfo: &protocol.InitializeResultServerInfo{
			Name:    lsName,
			Version: &version,
		},
	}, nil
}

func initialized(context *lsp.Context, params *protocol.InitializedParams) error {
	return nil
}

func shutdown(context *lsp.Context) error {
	protocol.SetTraceValue(protocol.TraceValueOff)
	return nil
}

func setTrace(context *lsp.Context, params *protocol.SetTraceParams) error {
	protocol.SetTraceValue(params.Value)
	return nil
}

Documentation

Feature Implementation Guides
Architecture & Reference

Testing

# Run all tests
go test ./core/... ./adapter/... ./examples/...

# Test specific package
go test ./core/... -v

# Run adapter tests
go test ./adapter/... -v

# Build examples
go build ./examples/...

License

BearWare 1.0 - See LICENSE file for details.

Attribution

Forked from tliron/glsp by Tal Liron.

Major architectural improvements in this fork:

  • Added core types with UTF-8 byte offsets
  • Created adapter packages for protocol conversion
  • Added provider interfaces for reusable business logic
  • Comprehensive documentation and examples for CLI and server usage
  • Document manager for stateful document tracking
  • Full support for LSP 3.16, 3.17, and 3.18

References

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

This section is empty.

Types ΒΆ

type CallFunc ΒΆ

type CallFunc func(method string, params any, result any)

type Context ΒΆ

type Context struct {
	Method  string
	Params  json.RawMessage
	Notify  NotifyFunc
	Call    CallFunc
	Context contextpkg.Context // can be nil
}

type Handler ΒΆ

type Handler interface {
	Handle(context *Context) (result any, validMethod bool, validParams bool, err error)
}

type NotifyFunc ΒΆ

type NotifyFunc func(method string, params any)

Directories ΒΆ

Path Synopsis
Package adapter_3_16 provides conversion functions between core types and protocol_3_16 types.
Package adapter_3_16 provides conversion functions between core types and protocol_3_16 types.
Package core provides diagnostic types for reporting errors, warnings, and hints.
Package core provides diagnostic types for reporting errors, warnings, and hints.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL