This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Ruby LSP is a Language Server Protocol implementation for Ruby, providing IDE features across different editors. The project consists of:
- Core Ruby LSP gem (language server implementation)
- Ruby Indexer (code indexing for navigation)
- VS Code extension (TypeScript frontend)
- Documentation site (Jekyll-based)
# Run all tests
bundle exec rake
# Run specific test file
bin/test test/requests/completion_test.rb
# Run tests matching a pattern
bin/test test/requests/completion_test.rb test_name_pattern
# Type check with Sorbet
bundle exec srb tc
# Lint with RuboCop
bin/rubocop
# Auto-fix RuboCop violations
bin/rubocop -acd vscode
yarn install # Install dependencies
yarn run lint # Lint TypeScript code
yarn run test # Run extension testsexe/ruby-lsp- Main language server executableexe/ruby-lsp-check- Validation toolexe/ruby-lsp-launcher- Experimental launcher
The server (lib/ruby_lsp/server.rb) processes LSP messages and delegates to:
- Requests (
lib/ruby_lsp/requests/) - Handle specific LSP features - Listeners (
lib/ruby_lsp/listeners/) - Analyze Ruby code for the specific feature - Response Builders (
lib/ruby_lsp/response_builders/) - Construct LSP responses
- Document Store (
lib/ruby_lsp/document.rb) - Manages open documents and parsed ASTs - Ruby Indexer (
lib/ruby_indexer/) - Indexes Ruby code for navigation features - Addon System (
lib/ruby_lsp/addon.rb) - Extensibility framework for third-party addons
- Visitor Pattern: AST traversal using Prism parser visitors
- Request/Response: Each LSP feature implemented as a request class
- Type Safety: Sorbet signatures throughout (strict for lib/, test for tests)
lib/ruby_lsp/server.rb- Main LSP server handling all client requests and message routinglib/ruby_lsp/base_server.rb- Abstract base with core LSP infrastructure (message I/O, worker threads)lib/ruby_lsp/global_state.rb- Central configuration and state management (formatters, linters, client capabilities)lib/ruby_lsp/store.rb- Document storage and lifecycle management
lib/ruby_lsp/document.rb- Abstract base for all document types (versioning, edits, encoding)lib/ruby_lsp/ruby_document.rb- Ruby source file handling with Prism parsinglib/ruby_lsp/erb_document.rb- ERB template file handlinglib/ruby_lsp/rbs_document.rb- RBS type definition file handling
lib/ruby_lsp/addon.rb- Extension framework for third-party add-onslib/ruby_lsp/node_context.rb- AST node context information (nesting, scope)lib/ruby_lsp/type_inferrer.rb- Type inference functionalitylib/ruby_lsp/client_capabilities.rb- Client feature capability tracking
graph TD
Client[VS Code/Editor Client]
Server[server.rb<br/>Main LSP Server]
BaseServer[base_server.rb<br/>Message I/O & Threading]
GlobalState[global_state.rb<br/>Configuration & State]
Store[store.rb<br/>Document Manager]
RubyDoc[ruby_document.rb<br/>Ruby Files]
ERBDoc[erb_document.rb<br/>ERB Templates]
RBSDoc[rbs_document.rb<br/>RBS Types]
Requests[requests/*<br/>Feature Handlers]
Listeners[listeners/*<br/>AST Analyzers]
Indexer[ruby_indexer/*<br/>Symbol Index]
Addon[addon.rb<br/>Extension System]
NodeContext[node_context.rb<br/>AST Context]
Client <-->|LSP Protocol| Server
Server -.->|inherits| BaseServer
Server --> GlobalState
Server --> Store
Server --> Requests
Server --> Addon
GlobalState --> Requests
Document --> Requests
Store --> RubyDoc
Store --> ERBDoc
Store --> RBSDoc
RubyDoc -.->|inherits| Document[document.rb]
ERBDoc -.->|inherits| Document
RBSDoc -.->|inherits| Document
Requests --> Listeners
Requests --> NodeContext
Listeners --> Indexer
Addon -->|extends| Requests
style Server fill:#f9f,stroke:#333,stroke-width:4px
style GlobalState fill:#9ff,stroke:#333,stroke-width:2px
style Store fill:#9ff,stroke:#333,stroke-width:2px
style Indexer fill:#ff9,stroke:#333,stroke-width:2px
Tests use expectation-based patterns:
# Tests typically follow this structure:
def test_feature_name
source = <<~RUBY
# Ruby code to test
RUBY
with_server(source) do |server, _uri|
# Make LSP request
# Assert response
end
endTest fixtures are in test/fixtures/ and expectations in test/expectations/.
- Create request class in
lib/ruby_lsp/requests/ - Register in
lib/ruby_lsp/executor.rb - Add tests in
test/requests/ - Update VS Code extension if needed
The Ruby Indexer (lib/ruby_indexer/) handles:
- Building symbol tables for classes, modules, methods, and constants
- Resolving constant references and method calls
- Finding definitions across files
- Providing completion candidates for constants and methods
- Dealing with inheritance and ancestor linearization
Ruby LSP uses Sorbet (typed: strict) with inline RBS annotations for static typechecking.
Key Guidelines:
- Use RBS inline annotations (
#:) exclusively - never use RBI stylesig { } - Place type annotations immediately before method definitions or after variable assignments
- Run
bundle exec srb tcto ensure typechecking passes
Common RBS Patterns:
# Method signatures (placed above method definition)
#: (String name) -> void
def process(name)
# ...
end
# Variable annotations (placed after assignment)
@documents = {} #: Hash[URI::Generic, Document]
# Attribute type declarations (placed above attribute)
#: String?
attr_reader :parent_class
# Generic types
#: [T] () { (String) -> T } -> T
def with_cache(&block)
# ...
end
# Union and nullable types
result = nil #: (String | Symbol)?Type Syntax Reference: https://sorbet.org/docs/rbs-support