feat: LSP language features over the obligation core (#222 Phase D)#719
Conversation
vera lsp now serves the four standard features, all computed by pure backing functions in vera/lsp/features.py over one Analysis bundle (parse -> typecheck-with-artifacts -> warm incremental verify), with all verification serialised through the server's single VerificationSession under a lock (Z3 contexts are not thread-safe). - publishDiagnostics on didOpen/didChange: parse/transform errors (single-diagnostic short-circuit, matching the CLI), type-check diagnostics, verification diagnostics, plus a synthesised per-function verification-tier Hint computed from the obligation stream (decision R3: the verifier stays silent about successes; the Hint is LSP-layer presentation — 'fn: Tier 1 — all contracts proven by Z3' / 'Tier 3 — N of M obligations fall back to runtime checks'; suppressed for functions with violated obligations). didClose clears squiggles. - Hover: type of the smallest recorded expression span under the cursor, from the new checker side-table. - Definition: @T.n -> the parameter it names via slots.slot_table (De Bruijn most-recent-first); indices binding through let/match return None (documented signature-level scope; #181 owns full binding resolution). - Completion: at a typed hole (or immediately after it), the in-scope bindings with their types, innermost first; '?' added as a trigger character. Checker (#222 Phase D artifacts, decision R4 — opt-in, zero cost for existing callers): - typecheck_with_artifacts() returns (diagnostics, CheckArtifacts) with a Span->pretty-type side-table and structured HoleSite records. - _synth_expr is now a thin recording wrapper over _synth_expr_impl (the dispatcher; walker-coverage marker travels with it — checker verified green), so every synthesis including recursion is recorded. - _check_hole's binding collection factored into _collect_scope_bindings(), shared by the W001 fix hint and the LSP completion payload. Tier plumbing: - Diagnostic gains tier: int | None (surfaced in to_dict() only when set — schema-additive); the verifier's six Tier-3 fallback warnings (E520-E525) now carry tier=3; the LSP diagnostic puts it in data. Tests (tests/test_lsp.py 30 -> 44): parse-error path, type-error short-circuit, tier in diagnostic data, tier-Hint synthesis + violated-suppression, hover (smallest span / off-expression / parse error), definition (most-recent-parameter jump, out-of-range None, off-slot None), hole completion (inside/after/away). Validation: mypy strict clean (68 files), ruff S clean, 978 adjacent suite tests green (obligations + verifier + checker + errors), doc counts consistent (4,264 tests). Part of #222 (Phase D). Release prep follows before the PR. Co-Authored-By: Claude <noreply@anthropic.invalid>
Version bump across all tracked sites, CHANGELOG cut, HISTORY row, footer count, site assets. Skip-changelog: the CHANGELOG cut for 0.0.164 IS this commit's changelog change. Co-Authored-By: Claude <noreply@anthropic.invalid>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughVersion 0.0.164 ships Phase D LSP language features: diagnostic tiering, on-demand expression-type and hole-site artifact collection during type checking, and complete LSP handlers (hover, go-to-definition for slot references, typed-hole completion) integrated into a thread-safe server with per-URI analysis caching. ChangesPhase D LSP Language Features
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #719 +/- ##
========================================
Coverage 90.95% 90.96%
========================================
Files 67 68 +1
Lines 24434 24630 +196
Branches 292 292
========================================
+ Hits 22225 22404 +179
- Misses 2202 2219 +17
Partials 7 7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@vera/lsp/features.py`:
- Around line 218-240: definition_at() currently uses the outer `decl` as
`enclosing`, causing slots inside nested `where`/inner functions to resolve
against the top-level function's params; update the logic so when you find an
`ast.SlotRef` in the `walk_nodes(decl)` loop you set `enclosing` to the
innermost `ast.FnDecl` that actually contains that node (e.g., by walking the
node's parent chain or using a helper like `find_enclosing_fn(node)`), then
break out—ensure you still break both loops only after assigning the correct
`enclosing` and keep using `slot_table(enclosing.params)` and
`positions[slot.index]` as before.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: df90fba5-f7f4-4391-8dc0-209844f545fd
⛔ Files ignored due to path filters (5)
docs/index.htmlis excluded by!docs/**docs/index.mdis excluded by!docs/**docs/llms-full.txtis excluded by!docs/**docs/llms.txtis excluded by!docs/**uv.lockis excluded by!**/*.lock,!uv.lock
📒 Files selected for processing (14)
CHANGELOG.mdHISTORY.mdREADME.mdROADMAP.mdTESTING.mdpyproject.tomltests/test_lsp.pyvera/__init__.pyvera/checker/core.pyvera/checker/expressions.pyvera/errors.pyvera/lsp/features.pyvera/lsp/server.pyvera/verifier.py
…und 1) CodeRabbit round 1 (valid, Major): definition_at bound 'enclosing' to the first top-level FnDecl whose subtree contained the cursor, so a slot inside a where-block function jumped to the OUTER function's parameter list. Now the innermost FnDecl containing the cursor (by smallest span) wins, and the SlotRef is located within it. New test pins a where-block helper: the slot jumps to helper's signature line, not outer's. Co-Authored-By: Claude <noreply@anthropic.invalid>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
README.md (1)
211-213:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd the Phase D LSP capabilities to the v0.0.164 feature summary.
The project-status feature list for this release omits the shipped LSP-facing items (tiered diagnostics, hover,
@T.ngo-to-definition, typed-hole completion), so the README is incomplete for the externally visible Phase D scope.As per coding guidelines, README v0.0.164 should keep the top-line LSP/agent-facing feature list aligned with Phase D deliverables.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` around lines 211 - 213, Update the v0.0.164 feature summary in README.md to include the Phase D LSP/agent-facing capabilities that were shipped: add "tiered diagnostics", "hover", "`@T.n` go-to-definition", and "typed-hole completion" (or similarly phrased LSP features) to the top-line feature list alongside the existing items (e.g., the line listing typed De Bruijn indices, algebraic effects, built-ins, etc.) so the externally visible release notes accurately reflect the Phase D deliverables.Source: Coding guidelines
vera/lsp/features.py (1)
93-96:⚠️ Potential issue | 🟠 MajorFix LSP diagnostic loss for import-resolution failures
vera/lsp/features.py::analyzeappends onlyresult.verify_diagnosticsfromsession.verify_source(...). However,VerificationSession.verify_sourceplaces import-resolution/typecheck errors intoresult.check_diagnosticsand returns early withok=Falsewhen any error-severity diagnostics exist—so resolver errors (e.g. “Cannot resolve import …”) can be silently dropped (common when an unused import points at a missing module andtypecheck_with_artifactsonly emits warnings). Fix by also appendingresult.check_diagnostics(orresult.diagnostics) when publishing LSP diagnostics.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@vera/lsp/features.py` around lines 93 - 96, The analyze logic currently only appends result.verify_diagnostics from session.verify_source, which can drop import-resolution/typecheck errors placed in result.check_diagnostics; update the code in vera/lsp/features.py inside analyze (the block using check_diags and calling session.verify_source) to also append result.check_diagnostics (or simply result.diagnostics) to analysis.diagnostics so resolver/typecheck errors are published, i.e. extend analysis.diagnostics with both verify and check diagnostics returned by session.verify_source.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_lsp.py`:
- Around line 444-468: Move the test function
test_slot_in_where_block_resolves_to_inner_params out of the TestHoleCompletion
class and into the TestDefinition class (after the existing
test_position_not_on_slot_is_none); this test exercises definition_at resolution
(not completion_at), so cut the whole def
test_slot_in_where_block_resolves_to_inner_params(...) and paste it into
TestDefinition to keep tests grouped by the symbol under test.
---
Outside diff comments:
In `@README.md`:
- Around line 211-213: Update the v0.0.164 feature summary in README.md to
include the Phase D LSP/agent-facing capabilities that were shipped: add "tiered
diagnostics", "hover", "`@T.n` go-to-definition", and "typed-hole completion"
(or similarly phrased LSP features) to the top-line feature list alongside the
existing items (e.g., the line listing typed De Bruijn indices, algebraic
effects, built-ins, etc.) so the externally visible release notes accurately
reflect the Phase D deliverables.
In `@vera/lsp/features.py`:
- Around line 93-96: The analyze logic currently only appends
result.verify_diagnostics from session.verify_source, which can drop
import-resolution/typecheck errors placed in result.check_diagnostics; update
the code in vera/lsp/features.py inside analyze (the block using check_diags and
calling session.verify_source) to also append result.check_diagnostics (or
simply result.diagnostics) to analysis.diagnostics so resolver/typecheck errors
are published, i.e. extend analysis.diagnostics with both verify and check
diagnostics returned by session.verify_source.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 22d6fb59-4ace-4192-9b81-8b930a446f0b
📒 Files selected for processing (5)
README.mdROADMAP.mdTESTING.mdtests/test_lsp.pyvera/lsp/features.py
CodeRabbit round 2 (valid): the test was appended at the file tail, which placed it inside TestHoleCompletion. It validates definition_at and now sits with the other definition tests. No logic changes. Co-Authored-By: Claude <noreply@anthropic.invalid>
Summary
Phase D of the #222 plan: language features over the obligation core.
vera lspnow serves the four standard features the issue body asked for, each a pure backing function invera/lsp/features.pyover oneAnalysisbundle (parse → typecheck-with-artifacts → warm incremental verify), with all verification serialised through the server's singleVerificationSessionunder a lock (Z3 contexts are not thread-safe). This PR does not finish #222 — Phase E (vera/speculativeEdit) follows; the issue stays open.Features
@T.n→ the parameter it names viaslots.slot_table(De Bruijn most-recent-first —@Nat.0jumps to the second@Natparameter). References binding throughlet/matchreturn None: signature-level scope by design, full binding resolution belongs to #181's refactoring engine.?registered as a trigger character.Compiler-side plumbing (both opt-in / additive)
typecheck_with_artifacts): aSpan→ pretty-type side-table recorded by a thin_synth_exprwrapper over the renamed_synth_expr_impldispatcher (every synthesis, including recursion, flows through it; the# WALKER_COVERAGEmarker travels with the impl —check_walker_coverage.pyverified green), plus structuredHoleSiterecords via the binding-collection now factored out of_check_holeinto_collect_scope_bindings()(shared by the W001 fix hint and the completion payload). Zero cost for existing callers — collection is off unless the artifact entry point is used.Diagnostic.tier: int | None(into_dict()only when set — schema-additive for--jsonconsumers); the verifier's six Tier-3 fallback warnings (E520–E525) carrytier=3, and the LSP diagnostic surfaces it indata.Verification
tests/test_lsp.py30 → 44: parse-error path, type-error verification short-circuit,tier=3in E520 diagnostic data, tier-Hint synthesis + violated-suppression, hover (smallest span / off-expression / parse-error), definition (most-recent-parameter jump pinned, out-of-range None, off-slot None), hole completion (inside / immediately-after / away).mypy vera/strict clean (68 files); ruff S clean; full non-stress suite green via pre-commit on both commits; doc counts consistent (4,264 tests).Release prep (in this PR per workflow)
v0.0.164 across all tracked sites, CHANGELOG cut, HISTORY.md single-sentence row, site assets, tag on branch.
Part of #222 (Phase D of the phased plan — Phase E follows in its own PR).
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests
Documentation