Skip to content

Latest commit

 

History

History
109 lines (92 loc) · 4.66 KB

File metadata and controls

109 lines (92 loc) · 4.66 KB

The editor — roundhouse lsp

roundhouse lsp serves the analyzer over the Language Server Protocol on stdio. Open a Rails app in an editor with the client attached and every Ruby, ERB and HAML file in it gets whole-app inferred types: hover on @article and see Article; hover on Article.find_by(slug:) and see Article | nil. There are no annotations to write and no server to warm up — the analysis is a whole-app pass that takes about a second on a large codebase and re-runs as you edit.

What you get

  • Hover — the inferred type of the expression under the cursor, and whether it can be nil. On a def line, the method's signature.
  • Inlay hints — inline : Type annotations after assignments. Turn them off without losing hover with "[ruby]": { "editor.inlayHints.enabled": "off" } in VS Code.
  • Go to definition / find references — resolved by the analyzer's bindings, not by name: a local resolves to its exact binding, an instance variable to every read and write across the controller and the views it feeds, a method to its def. F12 on a bare call lands on the definition; references from a def header find the callers.
  • Completion — members after ., instance variables after @, typed keyword arguments inside a call's parentheses, drawn from the inferred receiver type.
  • Diagnostics — in the Problems panel: analysis errors, syntax errors, and static N+1 findings (missing_preload, with the .includes fix). The analyzer's warning ledger (gradual_untyped, unresolved_type — hundreds on a real app) is off by default; the roundhouse.warnings setting turns it on, effective on the next analysis pass. check.md explains each diagnostic kind.
  • Trace CodeLens — ▶ trace GET /rooms/:id · 9 filters · 2 skipped · trace complete above each controller action (on the class line for actions a controller inherits). Click it and the request chain opens as a Markdown document: the route, every before/around/after filter with its guard and what it assigns, the action, the view with its partials, the layout, and a coverage footer saying which hops resolved and what blocks the rest. The document is written under the OS temp directory, never into the app.

VS Code

The client lives in the repository at editors/vscode/. It is not on the Marketplace yet; installing it takes the repository and npm:

git clone https://github.com/rubys/roundhouse
cd roundhouse/editors/vscode
npm install

Then either open that folder in VS Code and press F5 — an Extension Development Host window opens with the client loaded, and File → Open Folder points it at your app — or package it once and install the result in your everyday VS Code:

npx @vscode/vsce package     # writes roundhouse-lsp-client-0.0.1.vsix
code --install-extension roundhouse-lsp-client-0.0.1.vsix

The client activates on Ruby, ERB and HAML files and on any workspace containing config/routes.rb. It finds the server in this order:

  1. the roundhouse.serverPath setting, if set — a path to the roundhouse binary (run as roundhouse lsp) or to a source-built roundhouse-lsp;
  2. a roundhouse on PATH — the snapshot binary from install.md;
  3. for the F5 loop only, the repository's own target/release/roundhouse-lsp.

Nothing else is required: .rb files get the ruby language id from VS Code's built-in grammar. The server's stderr goes to the Output panel's "Roundhouse LSP" channel; that is where to look if hovers never appear.

Other editors

Any LSP client can run it. The server is roundhouse lsp with no arguments, over stdio; the client names the workspace root at initialize, and the root should be the Rails app (the directory holding config/routes.rb). Attach it to the ruby, erb and haml language ids — or just ruby — and everything above except the CodeLens command works with no client-side code. The CodeLens needs the client to forward workspace/executeCommand for roundhouse.traceroute and open the returned file, which most clients do by default.

For Neovim 0.11 or later, for example:

vim.lsp.config('roundhouse', {
  cmd = { 'roundhouse', 'lsp' },
  filetypes = { 'ruby', 'eruby', 'haml' },
  root_markers = { 'config/routes.rb' },
})
vim.lsp.enable('roundhouse')

What it is not

It is not a replacement for ruby-lsp. Roundhouse knows types, effects and request flow; it does not know formatting, refactoring, snippets, or anything about Ruby files that are not part of a Rails app. Running both is fine: they answer different questions, and neither one's diagnostics collide with the other's.