rigortype 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +82 -20
- data/data/core_overlay/numeric.rbs +33 -0
- data/data/core_overlay/pathname.rbs +25 -0
- data/data/core_overlay/string_scanner.rbs +28 -0
- data/data/gem_overlay/activesupport/core_ext.rbs +473 -0
- data/data/vendored_gem_sigs/ast/ast.rbs +130 -0
- data/data/vendored_gem_sigs/bcrypt/bcrypt.rbs +47 -0
- data/data/vendored_gem_sigs/bundler/bundler.rbs +238 -0
- data/data/vendored_gem_sigs/cgi/cgi_extras.rbs +34 -0
- data/data/vendored_gem_sigs/did_you_mean/did_you_mean_extras.rbs +34 -0
- data/data/vendored_gem_sigs/idn-ruby/idn.rbs +54 -0
- data/data/vendored_gem_sigs/mysql2/client.rbs +55 -0
- data/data/vendored_gem_sigs/mysql2/error.rbs +5 -0
- data/data/vendored_gem_sigs/mysql2/result.rbs +31 -0
- data/data/vendored_gem_sigs/mysql2/statement.rbs +5 -0
- data/data/vendored_gem_sigs/nokogiri/nokogiri.rbs +2332 -0
- data/data/vendored_gem_sigs/nokogiri/nokogiri_html5.rbs +47 -0
- data/data/vendored_gem_sigs/pg/pg.rbs +212 -0
- data/data/vendored_gem_sigs/prism/prism_supplement.rbs +44 -0
- data/data/vendored_gem_sigs/redis/errors.rbs +50 -0
- data/data/vendored_gem_sigs/redis/future.rbs +5 -0
- data/data/vendored_gem_sigs/redis/redis.rbs +348 -0
- data/data/vendored_gem_sigs/redis/redis_extras.rbs +130 -0
- data/data/vendored_gem_sigs/rubygems/rubygems_extras.rbs +226 -0
- data/docs/handbook/01-getting-started.md +311 -0
- data/docs/handbook/02-everyday-types.md +337 -0
- data/docs/handbook/03-narrowing.md +359 -0
- data/docs/handbook/04-tuples-and-shapes.md +321 -0
- data/docs/handbook/05-methods-and-blocks.md +339 -0
- data/docs/handbook/06-classes.md +305 -0
- data/docs/handbook/07-rbs-and-extended.md +427 -0
- data/docs/handbook/08-understanding-errors.md +373 -0
- data/docs/handbook/09-plugins.md +241 -0
- data/docs/handbook/10-sorbet.md +347 -0
- data/docs/handbook/11-sig-gen.md +312 -0
- data/docs/handbook/12-lightweight-hkt.md +333 -0
- data/docs/handbook/README.md +275 -0
- data/docs/handbook/appendix-elixir.md +370 -0
- data/docs/handbook/appendix-go.md +399 -0
- data/docs/handbook/appendix-java-csharp.md +470 -0
- data/docs/handbook/appendix-liskov.md +580 -0
- data/docs/handbook/appendix-mypy.md +370 -0
- data/docs/handbook/appendix-phpstan.md +338 -0
- data/docs/handbook/appendix-protocols-and-structural-typing.md +292 -0
- data/docs/handbook/appendix-rust.md +446 -0
- data/docs/handbook/appendix-steep.md +336 -0
- data/docs/handbook/appendix-type-theory.md +1662 -0
- data/docs/handbook/appendix-typeprof.md +416 -0
- data/docs/handbook/appendix-typescript.md +332 -0
- data/docs/install.md +189 -0
- data/docs/llms.txt +72 -0
- data/docs/manual/01-installation.md +342 -0
- data/docs/manual/02-cli-reference.md +557 -0
- data/docs/manual/03-configuration.md +152 -0
- data/docs/manual/04-diagnostics.md +206 -0
- data/docs/manual/05-inspecting-types.md +109 -0
- data/docs/manual/06-baseline.md +104 -0
- data/docs/manual/07-plugins.md +92 -0
- data/docs/manual/08-skills.md +143 -0
- data/docs/manual/09-editor-integration.md +245 -0
- data/docs/manual/10-mcp-server.md +532 -0
- data/docs/manual/11-ci.md +274 -0
- data/docs/manual/12-caching.md +116 -0
- data/docs/manual/13-troubleshooting.md +120 -0
- data/docs/manual/14-rails-quickstart.md +332 -0
- data/docs/manual/15-type-protection-coverage.md +204 -0
- data/docs/manual/16-rbs-extended-annotations.md +190 -0
- data/docs/manual/17-driving-improvement.md +160 -0
- data/docs/manual/README.md +87 -0
- data/docs/manual/ci-templates/README.md +58 -0
- data/docs/manual/plugins/README.md +86 -0
- data/docs/manual/plugins/rigor-actioncable.md +78 -0
- data/docs/manual/plugins/rigor-actionmailer.md +74 -0
- data/docs/manual/plugins/rigor-actionpack.md +80 -0
- data/docs/manual/plugins/rigor-activejob.md +58 -0
- data/docs/manual/plugins/rigor-activerecord.md +102 -0
- data/docs/manual/plugins/rigor-activestorage.md +74 -0
- data/docs/manual/plugins/rigor-activesupport-core-ext.md +86 -0
- data/docs/manual/plugins/rigor-devise.md +70 -0
- data/docs/manual/plugins/rigor-dry-schema.md +56 -0
- data/docs/manual/plugins/rigor-dry-struct.md +60 -0
- data/docs/manual/plugins/rigor-dry-types.md +59 -0
- data/docs/manual/plugins/rigor-dry-validation.md +62 -0
- data/docs/manual/plugins/rigor-factorybot.md +76 -0
- data/docs/manual/plugins/rigor-graphql.md +89 -0
- data/docs/manual/plugins/rigor-hanami.md +83 -0
- data/docs/manual/plugins/rigor-mangrove.md +73 -0
- data/docs/manual/plugins/rigor-minitest.md +86 -0
- data/docs/manual/plugins/rigor-pundit.md +72 -0
- data/docs/manual/plugins/rigor-rails-i18n.md +92 -0
- data/docs/manual/plugins/rigor-rails-routes.md +94 -0
- data/docs/manual/plugins/rigor-rails.md +44 -0
- data/docs/manual/plugins/rigor-rbs-inline.md +83 -0
- data/docs/manual/plugins/rigor-rspec-rails.md +72 -0
- data/docs/manual/plugins/rigor-rspec.md +86 -0
- data/docs/manual/plugins/rigor-shoulda-matchers.md +78 -0
- data/docs/manual/plugins/rigor-sidekiq.md +78 -0
- data/docs/manual/plugins/rigor-sinatra.md +61 -0
- data/docs/manual/plugins/rigor-sorbet.md +63 -0
- data/docs/manual/plugins/rigor-statesman.md +75 -0
- data/docs/manual/plugins/rigor-typescript-utility-types.md +71 -0
- data/exe/rigor +1 -1
- data/lib/rigor/analysis/incremental_session.rb +4 -2
- data/lib/rigor/analysis/run_stats.rb +13 -1
- data/lib/rigor/analysis/runner.rb +54 -12
- data/lib/rigor/cli/check_command.rb +26 -3
- data/lib/rigor/cli/coverage_command.rb +67 -92
- data/lib/rigor/cli/coverage_mutation.rb +149 -0
- data/lib/rigor/cli/docs_command.rb +248 -0
- data/lib/rigor/cli/fused_protection_renderer.rb +67 -0
- data/lib/rigor/cli/fused_protection_report.rb +76 -0
- data/lib/rigor/cli/skill_command.rb +103 -41
- data/lib/rigor/cli/skill_describe.rb +346 -0
- data/lib/rigor/cli.rb +25 -3
- data/lib/rigor/config_audit.rb +152 -0
- data/lib/rigor/configuration.rb +12 -0
- data/lib/rigor/environment/rbs_loader.rb +27 -0
- data/lib/rigor/environment.rb +49 -1
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +140 -38
- data/lib/rigor/inference/method_dispatcher/shape_dispatch.rb +37 -6
- data/lib/rigor/inference/scope_indexer.rb +87 -89
- data/lib/rigor/inference/statement_evaluator.rb +27 -0
- data/lib/rigor/plugin/isolation.rb +5 -5
- data/lib/rigor/plugin/loader.rb +4 -2
- data/lib/rigor/protection/diagnostic_oracle.rb +51 -0
- data/lib/rigor/protection/mutation_scanner.rb +98 -38
- data/lib/rigor/protection/mutator.rb +21 -0
- data/lib/rigor/protection/test_suite_oracle.rb +68 -0
- data/lib/rigor/signature_path_audit.rb +92 -0
- data/lib/rigor/version.rb +1 -1
- data/skills/rigor-ask/SKILL.md +172 -0
- data/skills/rigor-doctor/SKILL.md +87 -0
- data/skills/rigor-editor-setup/SKILL.md +114 -0
- data/skills/rigor-mcp-setup/SKILL.md +117 -0
- data/skills/rigor-monkeypatch-resolve/SKILL.md +79 -0
- data/skills/rigor-next-steps/SKILL.md +113 -0
- data/skills/rigor-plugin-tune/SKILL.md +79 -0
- data/skills/rigor-protection-uplift/SKILL.md +133 -0
- data/skills/rigor-rbs-setup/SKILL.md +128 -0
- data/skills/rigor-upgrade/SKILL.md +79 -0
- metadata +120 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Provided skills
|
|
2
|
+
|
|
3
|
+
Rigor bundles a set of **Agent Skills** — structured workflows an AI
|
|
4
|
+
coding agent (Claude Code and compatible tools) can run on your behalf.
|
|
5
|
+
They live in [`skills/`](../../skills/) and are auto-discovered when an
|
|
6
|
+
agent works inside a project that has Rigor available.
|
|
7
|
+
|
|
8
|
+
Skills are optional. Everything they do, you can do by hand with the
|
|
9
|
+
commands in this manual; a skill drives the workflow end to end.
|
|
10
|
+
|
|
11
|
+
## Start here — two skills to remember
|
|
12
|
+
|
|
13
|
+
You only ever need to remember two skills; the rest are reached through
|
|
14
|
+
them.
|
|
15
|
+
|
|
16
|
+
- **`rigor-next-steps`** — *"what should we do next?"* The single entry
|
|
17
|
+
point: hand it to an agent and it resolves the `rigor` command
|
|
18
|
+
(installing it if missing), onboards an unconfigured project, then asks
|
|
19
|
+
`rigor skill describe` what to do next and routes to the matching skill
|
|
20
|
+
in the catalogue below. The end-to-end workflow it drives is
|
|
21
|
+
[Driving project improvement with `rigor-next-steps`](17-driving-improvement.md).
|
|
22
|
+
- **`rigor-ask`** — *"answer this about Rigor."* Ask anything in plain
|
|
23
|
+
language — why a diagnostic fired or whether it's a false positive, how
|
|
24
|
+
narrowing / refinements / shapes work, what a flag or config key does,
|
|
25
|
+
how Rigor compares to Sorbet / Steep / mypy / PHPStan, whether it
|
|
26
|
+
handles a given gem or framework, or how to type a method. Rigor is
|
|
27
|
+
niche and version-specific, so instead of answering from memory the
|
|
28
|
+
agent **investigates**: it reads the bundled handbook and manual
|
|
29
|
+
**offline** via [`rigor docs`](02-cli-reference.md#rigor-docs) (plus
|
|
30
|
+
`rigor explain` for a diagnostic id) *and*, for a question about your
|
|
31
|
+
code, runs `rigor check` / `annotate` / `type-of` — then answers from
|
|
32
|
+
the page or the inferred type. You never have to remember the command,
|
|
33
|
+
just the question. Available at any point.
|
|
34
|
+
|
|
35
|
+
If you do not know which skill you need, start with `rigor-next-steps`.
|
|
36
|
+
|
|
37
|
+
## The catalogue
|
|
38
|
+
|
|
39
|
+
Every skill below is a destination `rigor-next-steps` (via
|
|
40
|
+
`rigor skill describe`) can route you to. (`rigor-ask`, above, is the
|
|
41
|
+
always-available question skill rather than a routed destination, so it
|
|
42
|
+
is not repeated here.)
|
|
43
|
+
|
|
44
|
+
### Onboarding and foundation
|
|
45
|
+
|
|
46
|
+
- **`rigor-project-init`** — onboards a project from a cold start. It
|
|
47
|
+
detects the stack (Rails, RSpec, dry-rb, …), proposes the matching
|
|
48
|
+
[plugins](07-plugins.md), picks an adoption mode — a
|
|
49
|
+
[baseline](06-baseline.md) snapshot for an existing codebase or a
|
|
50
|
+
zero-diagnostic gate for a clean one — writes a `.rigor.dist.yml`, and
|
|
51
|
+
generates the first baseline. Reach for it when setting Rigor up for
|
|
52
|
+
the first time.
|
|
53
|
+
- **`rigor-rbs-setup`** — installs community RBS for your gems
|
|
54
|
+
(`rbs collection install`) so RBS-less dependencies stop typing as
|
|
55
|
+
`Dynamic`. Rigor auto-detects the resulting `rbs_collection.lock.yaml`.
|
|
56
|
+
- **`rigor-plugin-tune`** — re-matches `Gemfile.lock` to the bundled
|
|
57
|
+
plugin catalogue and enables the plugins for your current stack
|
|
58
|
+
(verifying with `rigor plugins --strict`). Reach for it after adding a
|
|
59
|
+
gem, or for a Rails app whose Rails plugins are not yet enabled.
|
|
60
|
+
|
|
61
|
+
### Improving and reducing
|
|
62
|
+
|
|
63
|
+
- **`rigor-protection-uplift`** — closes the type-protection holes
|
|
64
|
+
`rigor coverage --protection` surfaces: sig-gen first, then the
|
|
65
|
+
minimal hand-RBS residual, under a double gate (the site becomes
|
|
66
|
+
protected *and* `rigor check` gains no new diagnostic). See
|
|
67
|
+
[Type-protection coverage](15-type-protection-coverage.md).
|
|
68
|
+
- **`rigor-baseline-reduce`** — works an existing `.rigor-baseline.yml`
|
|
69
|
+
down rule by rule. It prioritises with `rigor triage`, classifies each
|
|
70
|
+
site as a real bug / safe stylistic finding / false positive, and
|
|
71
|
+
regenerates the baseline. Reach for it to chip away at the backlog.
|
|
72
|
+
- **`rigor-monkeypatch-resolve`** — resolves an `undefined-method`
|
|
73
|
+
cluster that is really your project's own monkey-patches by wiring the
|
|
74
|
+
defining files into `pre_eval:`.
|
|
75
|
+
|
|
76
|
+
### Integration and operations
|
|
77
|
+
|
|
78
|
+
- **`rigor-ci-setup`** — wires Rigor into CI with inline PR/MR
|
|
79
|
+
diagnostics (SARIF / GitHub Actions / GitLab Code Quality / reviewdog).
|
|
80
|
+
See [Running Rigor in CI](11-ci.md).
|
|
81
|
+
- **`rigor-editor-setup`** — wires the bundled `rigor lsp` language
|
|
82
|
+
server into your editor (Neovim, VS Code, Helix, Emacs). See
|
|
83
|
+
[Editor integration](09-editor-integration.md).
|
|
84
|
+
- **`rigor-mcp-setup`** — wires the bundled `rigor mcp` server into an
|
|
85
|
+
AI coding agent (Claude Code, Cursor, Cline, …). See
|
|
86
|
+
[MCP server](10-mcp-server.md).
|
|
87
|
+
|
|
88
|
+
### Maintenance and authoring
|
|
89
|
+
|
|
90
|
+
- **`rigor-upgrade`** — adopts a new Rigor version cleanly: diff against
|
|
91
|
+
the baseline, sort genuine new catches from sig-quality false
|
|
92
|
+
positives, regenerate.
|
|
93
|
+
- **`rigor-doctor`** — validates that the setup is healthy (config
|
|
94
|
+
resolves, plugins load, the baseline is fresh, the RBS environment is
|
|
95
|
+
not broken). See [Troubleshooting](13-troubleshooting.md).
|
|
96
|
+
- **`rigor-plugin-author`** — scaffolds a new Rigor plugin in your own
|
|
97
|
+
repository to teach Rigor an application DSL or metaprogramming
|
|
98
|
+
pattern it cannot infer. Reach for it when no bundled plugin covers a
|
|
99
|
+
framework or DSL your project depends on.
|
|
100
|
+
|
|
101
|
+
## Discovering skills from the CLI
|
|
102
|
+
|
|
103
|
+
The skills ship inside the `rigortype` gem, so they are reachable even
|
|
104
|
+
when Rigor is installed via `mise` / `gem install` with no project-side
|
|
105
|
+
source checkout. The `rigor skill` command surfaces them:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
rigor skill describe # probe the project + recommend the next skill (alias: rigor describe)
|
|
109
|
+
rigor skill --list # name + absolute path for each bundled skill
|
|
110
|
+
rigor skill <name> # print the SKILL.md body (with a references/ header)
|
|
111
|
+
rigor skill --path <name> # one-line absolute SKILL.md path, for a file-reading tool
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`rigor skill describe` is the recommendation engine driven by
|
|
115
|
+
`rigor-next-steps`; `rigor skill rigor-project-init` is the
|
|
116
|
+
canonical way to hand an agent the onboarding workflow without pointing
|
|
117
|
+
it at the repository. The `list` / `print` / `path` verb spellings are
|
|
118
|
+
deprecated (removed in v0.3.0). See [CLI reference](02-cli-reference.md#rigor-skill).
|
|
119
|
+
|
|
120
|
+
## Installing skills into a project
|
|
121
|
+
|
|
122
|
+
In addition to the gem, the user-facing skills are installable via
|
|
123
|
+
[vercel-labs/skills](https://github.com/vercel-labs/skills) — useful for
|
|
124
|
+
dropping the entry point into a project *before* Rigor is installed:
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
# Just the entry point (recommended):
|
|
128
|
+
npx skills add https://github.com/rigortype/rigor/tree/master/skills/rigor-next-steps
|
|
129
|
+
# Or the whole user-facing set:
|
|
130
|
+
npx skills add rigortype/rigor
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
(The contributor-only skills under `.claude/skills/` are marked internal
|
|
134
|
+
and are not installed by a bulk `npx skills add`.)
|
|
135
|
+
|
|
136
|
+
## Running a skill
|
|
137
|
+
|
|
138
|
+
In an agent that supports Agent Skills, invoke the skill by name (in
|
|
139
|
+
Claude Code, `/rigor-next-steps`). The agent reads the skill definition
|
|
140
|
+
(from `skills/` in a source checkout, or via `rigor skill <name>`
|
|
141
|
+
otherwise) and follows it. If your tool does not support skills, each
|
|
142
|
+
skill's `SKILL.md` still reads as a plain checklist you can follow
|
|
143
|
+
yourself.
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Rigor LSP — Editor Integration
|
|
2
|
+
|
|
3
|
+
`rigor lsp` is the in-process Language Server bundled with the
|
|
4
|
+
`rigortype` gem. It speaks the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/)
|
|
5
|
+
over stdio and exposes Rigor's analyzer as a live editor experience —
|
|
6
|
+
diagnostics on every keystroke, hover-to-type, outline view, and
|
|
7
|
+
type-aware completion.
|
|
8
|
+
|
|
9
|
+
This page is the entry point for wiring it into your editor. The
|
|
10
|
+
design + capability matrix lives in
|
|
11
|
+
[`docs/design/20260517-language-server.md`](../design/20260517-language-server.md)
|
|
12
|
+
(v1) and
|
|
13
|
+
[`docs/design/20260517-lsp-hover-completion.md`](../design/20260517-lsp-hover-completion.md)
|
|
14
|
+
(v2). Packaging rationale is in
|
|
15
|
+
[`docs/adr/19-language-server-packaging.md`](../adr/19-language-server-packaging.md).
|
|
16
|
+
|
|
17
|
+
## Features at a glance
|
|
18
|
+
|
|
19
|
+
| LSP method | Behaviour |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `textDocument/publishDiagnostics` | Pushed on every `didChange`, 200ms debounced. Severity / rule / source map directly to Rigor's diagnostic taxonomy. |
|
|
22
|
+
| `textDocument/hover` | Type-aware markdown. Per-node-class dispatch surfaces receiver type + RBS signature for method calls, FQN + singleton type + defined-in path for constants, narrowed type + bound-at for locals, canonical refinement names (`non-empty-string`, …) for `Refined` / `Difference` carriers. |
|
|
23
|
+
| `textDocument/completion` | Method completion after `.` (driven by inferred receiver type), constant-path completion after `::`. Composite receivers (Union → intersection of methods, Tuple / HashShape → ancestor nominal, Refined → underlying nominal) handled. Parse-recovery sentinel makes mid-edit `obj.` / `Foo::` buffers work. |
|
|
24
|
+
| `textDocument/documentSymbol` | Outline tree from Prism AST: `class` / `module` / `def` with nesting. |
|
|
25
|
+
| `workspace/didChangeWatchedFiles` | Invalidates the per-session `Environment` + `Cache::Store` cache so saved files repropagate. |
|
|
26
|
+
| `workspace/didChangeConfiguration` | Same — re-reads `.rigor.yml` / `Gemfile.lock` etc. |
|
|
27
|
+
|
|
28
|
+
## Prerequisites
|
|
29
|
+
|
|
30
|
+
The single prerequisite is **`rigor` on your `PATH`** — the same
|
|
31
|
+
executable `rigor check` and `rigor type-of` already use. Any of the
|
|
32
|
+
install channels in [Installing Rigor](01-installation.md) provide it;
|
|
33
|
+
`mise` is the recommended one because its shims make `rigor` available
|
|
34
|
+
to GUI-launched editors that do not inherit your shell environment.
|
|
35
|
+
|
|
36
|
+
Do **not** add `rigortype` to your project's `Gemfile`. Rigor is a
|
|
37
|
+
tool, not a library — installing it standalone keeps its Ruby version
|
|
38
|
+
and its dependencies out of your application's resolution. See
|
|
39
|
+
[Installing Rigor § Recommended — a runtime version manager](01-installation.md#recommended--a-runtime-version-manager).
|
|
40
|
+
|
|
41
|
+
The LSP server runs as `rigor lsp`, using the same binary as
|
|
42
|
+
`rigor check` / `rigor type-of`. There is no separate gem and no
|
|
43
|
+
addon registration.
|
|
44
|
+
|
|
45
|
+
## CLI
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
rigor lsp [--transport=stdio] [--log=PATH] [--config=PATH]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- `--transport=stdio` — default; only value accepted in v1. TCP /
|
|
52
|
+
Unix-socket transports are queued.
|
|
53
|
+
- `--log=PATH` — wire log + server debug to a file. Without it,
|
|
54
|
+
server-side logs go to stderr.
|
|
55
|
+
- `--config=PATH` — mirrors `rigor check --config=PATH`. Without
|
|
56
|
+
it, `Configuration.discover` walks `.rigor.yml` / `.rigor.dist.yml`
|
|
57
|
+
from the project root.
|
|
58
|
+
|
|
59
|
+
## Editor wiring
|
|
60
|
+
|
|
61
|
+
Every snippet below invokes `rigor lsp` directly, which works as soon
|
|
62
|
+
as `rigor` is on the editor's `PATH` (the `mise` shim path, an
|
|
63
|
+
`asdf` shim, or whatever your install channel set up — see
|
|
64
|
+
[Installing Rigor](01-installation.md)).
|
|
65
|
+
|
|
66
|
+
If you have an older, project-local install that puts `rigortype` in
|
|
67
|
+
the project's `Gemfile`, swap `rigor lsp` for `bundle exec rigor lsp`
|
|
68
|
+
(and add `cwd` / `BUNDLE_GEMFILE` as your editor requires). This is
|
|
69
|
+
a legacy fallback; new installs should not need it.
|
|
70
|
+
|
|
71
|
+
### Neovim — nvim-lspconfig
|
|
72
|
+
|
|
73
|
+
Add a custom server entry. `nvim-lspconfig` doesn't ship a built-in
|
|
74
|
+
preset for Rigor yet, so register it manually:
|
|
75
|
+
|
|
76
|
+
```lua
|
|
77
|
+
local configs = require('lspconfig.configs')
|
|
78
|
+
local lspconfig = require('lspconfig')
|
|
79
|
+
|
|
80
|
+
if not configs.rigor then
|
|
81
|
+
configs.rigor = {
|
|
82
|
+
default_config = {
|
|
83
|
+
cmd = { 'rigor', 'lsp' },
|
|
84
|
+
filetypes = { 'ruby' },
|
|
85
|
+
root_dir = lspconfig.util.root_pattern('.rigor.yml', '.rigor.dist.yml', 'Gemfile', '.git'),
|
|
86
|
+
single_file_support = false,
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
lspconfig.rigor.setup({})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Place this in your `init.lua` (or under `lua/plugins/`). Restart
|
|
95
|
+
Neovim and open a Ruby file inside a Rigor-configured project; you
|
|
96
|
+
should see diagnostics appear on save and hover work via `K`. For a
|
|
97
|
+
legacy bundler-based install, set `cmd = { 'bundle', 'exec', 'rigor', 'lsp' }`.
|
|
98
|
+
|
|
99
|
+
### VS Code — generic LSP client
|
|
100
|
+
|
|
101
|
+
There's no first-party VS Code extension yet. Use a generic
|
|
102
|
+
LSP-client wrapper extension, or write a minimal extension that
|
|
103
|
+
registers the server:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
// extension.ts (minimal example)
|
|
107
|
+
import { workspace, ExtensionContext } from 'vscode';
|
|
108
|
+
import { LanguageClient, ServerOptions, TransportKind } from 'vscode-languageclient/node';
|
|
109
|
+
|
|
110
|
+
let client: LanguageClient;
|
|
111
|
+
|
|
112
|
+
export function activate(context: ExtensionContext) {
|
|
113
|
+
const serverOptions: ServerOptions = {
|
|
114
|
+
command: 'rigor',
|
|
115
|
+
args: ['lsp'],
|
|
116
|
+
transport: TransportKind.stdio,
|
|
117
|
+
};
|
|
118
|
+
client = new LanguageClient(
|
|
119
|
+
'rigor',
|
|
120
|
+
'Rigor Language Server',
|
|
121
|
+
serverOptions,
|
|
122
|
+
{ documentSelector: [{ scheme: 'file', language: 'ruby' }] }
|
|
123
|
+
);
|
|
124
|
+
client.start();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function deactivate() { return client?.stop(); }
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
For a legacy bundler-based install, set `command: 'bundle', args: ['exec', 'rigor', 'lsp']`.
|
|
131
|
+
|
|
132
|
+
Publish as a private extension or run via `--extensionDevelopmentPath`.
|
|
133
|
+
A community-maintained marketplace extension may surface later;
|
|
134
|
+
contributions welcome.
|
|
135
|
+
|
|
136
|
+
### Helix
|
|
137
|
+
|
|
138
|
+
Add to `~/.config/helix/languages.toml`:
|
|
139
|
+
|
|
140
|
+
```toml
|
|
141
|
+
[language-server.rigor]
|
|
142
|
+
command = "rigor"
|
|
143
|
+
args = ["lsp"]
|
|
144
|
+
|
|
145
|
+
[[language]]
|
|
146
|
+
name = "ruby"
|
|
147
|
+
language-servers = ["rigor"]
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Helix auto-detects `.rigor.yml` via its project-root walk. If you
|
|
151
|
+
also use Solargraph / ruby-lsp, list them alongside `rigor` —
|
|
152
|
+
Helix runs multiple servers per language. For a legacy bundler-based
|
|
153
|
+
install, use `command = "bundle"` and `args = ["exec", "rigor", "lsp"]`.
|
|
154
|
+
|
|
155
|
+
### Emacs — Eglot
|
|
156
|
+
|
|
157
|
+
```elisp
|
|
158
|
+
(require 'eglot)
|
|
159
|
+
(add-to-list 'eglot-server-programs
|
|
160
|
+
'(ruby-mode . ("rigor" "lsp")))
|
|
161
|
+
;; Or for ruby-ts-mode (Emacs 30+):
|
|
162
|
+
(add-to-list 'eglot-server-programs
|
|
163
|
+
'(ruby-ts-mode . ("rigor" "lsp")))
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`M-x eglot` in a Ruby buffer to attach. For a legacy bundler-based
|
|
167
|
+
install, replace `("rigor" "lsp")` with `("bundle" "exec" "rigor" "lsp")`.
|
|
168
|
+
|
|
169
|
+
### Emacs — lsp-mode
|
|
170
|
+
|
|
171
|
+
```elisp
|
|
172
|
+
(with-eval-after-load 'lsp-mode
|
|
173
|
+
(lsp-register-client
|
|
174
|
+
(make-lsp-client
|
|
175
|
+
:new-connection (lsp-stdio-connection '("rigor" "lsp"))
|
|
176
|
+
:activation-fn (lsp-activate-on "ruby")
|
|
177
|
+
:server-id 'rigor)))
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
For a legacy bundler-based install, swap the connection list to
|
|
181
|
+
`'("bundle" "exec" "rigor" "lsp")`.
|
|
182
|
+
|
|
183
|
+
## Troubleshooting
|
|
184
|
+
|
|
185
|
+
**The server starts but no diagnostics appear.**
|
|
186
|
+
|
|
187
|
+
- Confirm your project has a `.rigor.yml` or `.rigor.dist.yml` (or
|
|
188
|
+
the LSP root walk finds one). The LSP uses
|
|
189
|
+
`Configuration.discover` — same logic as `rigor check`.
|
|
190
|
+
- Check the LSP log (`--log=/tmp/rigor-lsp.log`) for plugin-load
|
|
191
|
+
errors or RBS-env build failures.
|
|
192
|
+
- Run `rigor check <path>` from the same project root; if it works
|
|
193
|
+
there, the LSP should too. If `rigor check` fails, fix that
|
|
194
|
+
first.
|
|
195
|
+
|
|
196
|
+
**Completion popup is empty.**
|
|
197
|
+
|
|
198
|
+
- Completion only fires on a node with a known type. Receivers
|
|
199
|
+
whose type collapses to `Dynamic[top]` produce no completions.
|
|
200
|
+
Look at `rigor type-of <file>:<line>:<col>` to see what type the
|
|
201
|
+
analyzer assigns the receiver.
|
|
202
|
+
- Mid-edit buffer support is best-effort. If parse fails AND the
|
|
203
|
+
cursor isn't right after `.` / `::`, the v1 LSP returns no
|
|
204
|
+
completions; deeper recovery is queued (see ROADMAP §
|
|
205
|
+
"Editor / IDE integration").
|
|
206
|
+
|
|
207
|
+
**Hover shows `untyped` everywhere.**
|
|
208
|
+
|
|
209
|
+
- The analyzer hasn't loaded your project's RBS. Verify `.rigor.yml`
|
|
210
|
+
has the right `signature_paths:` and `libraries:`. Check the
|
|
211
|
+
LSP log for `RBS::DuplicatedDeclarationError` or similar.
|
|
212
|
+
|
|
213
|
+
**Concurrent LSP sessions conflict.**
|
|
214
|
+
|
|
215
|
+
- They shouldn't — the LSP uses a read-only `Cache::Store` so
|
|
216
|
+
multiple processes against the same project don't race on the
|
|
217
|
+
on-disk cache. If you see corruption, file a bug with the log.
|
|
218
|
+
|
|
219
|
+
## Performance expectations
|
|
220
|
+
|
|
221
|
+
Per LSP v1's design targets (warm session, 5K-file project,
|
|
222
|
+
current laptop):
|
|
223
|
+
|
|
224
|
+
- Cold start (`initialize` → first publish): < 3s.
|
|
225
|
+
- `didChange` → `publishDiagnostics`: p50 < 250ms, p95 < 500ms.
|
|
226
|
+
- `hover`: p95 < 100ms.
|
|
227
|
+
- `documentSymbol`: p95 < 50ms.
|
|
228
|
+
- Memory steady-state: < 600 MB.
|
|
229
|
+
|
|
230
|
+
Cold start is dominated by RBS environment build; warm starts
|
|
231
|
+
(`rigor check`-warmed `.rigor/cache`) land sub-1.5s.
|
|
232
|
+
|
|
233
|
+
## Status + roadmap
|
|
234
|
+
|
|
235
|
+
LSP v1 + v2 landed in v0.1.6 and ship in the `0.1.x` line. Queued
|
|
236
|
+
follow-ups (`textDocument/signatureHelp`, hash-key completion,
|
|
237
|
+
`textDocument/definition`, incremental `didChange` sync, Ractor
|
|
238
|
+
pool dispatch, codeAction / rename / semanticTokens / inlayHint)
|
|
239
|
+
are demand-driven; see ROADMAP § "Editor / IDE integration" for
|
|
240
|
+
the current queue.
|
|
241
|
+
|
|
242
|
+
To request a queued feature or report an LSP issue, open a GitHub
|
|
243
|
+
issue with: the editor + version, the Rigor version
|
|
244
|
+
(`rigor version`), the LSP log (`--log=PATH`), and a minimal
|
|
245
|
+
reproduction.
|