Commit ccd9110
Fix LSP navigation for class fields, enum variants, and methods (#3298)
[Artifacts](https://cloud.codelayer.cloud/tasks/019d31f9-344d-731b-bc97-b0610fd44836/artifacts)
|
[Task](https://cloud.codelayer.cloud/deep/tasks/019d31f9-344d-731b-bc97-b0610fd44836)
## Problem
"Go to Definition" and "Find All References" didn't work for class
fields, enum variants, constructor fields, or methods. Clicking
`p.name`, `Status.Active`, `Person { name: ... }`, or `s.Celebrate()`
did nothing. This made navigating BAML code painful — you had to
manually search for field definitions instead of just ctrl-clicking.
Also: when you misspelled a field like `s.feelin`, the red squiggly
underlined the whole `s.feelin` expression instead of just `feelin`.
## What changed for users
- **Goto-definition** works for field access, enum variants, constructor
fields, and method calls
- **Find All References** on a class field definition finds all usage
sites across the package
- **Document outline** shows real spans for fields/variants (not
zero-width placeholders)
- **Diagnostic squigglies** for unresolved members now highlight just
the member name
- **LSP no longer crashes** on certain edge cases in MIR lowering
(panics replaced with graceful error emission)
## How it works
### The core idea
The type inference layer (TIR) already resolves every `x.foo` during
type checking — it knows whether `foo` is a field, variant, method, or
free function. But that information was thrown away. We now store it as
`MemberResolution` entries and use them in the LSP to navigate.
### Preserving span data (AST + HIR)
Field and variant name spans were dropped during HIR lowering. Two new
source maps fix this:
- **`ItemTreeSourceMap`** (`item_tree.rs`, `builder.rs`,
`semantic_index.rs`, `lib.rs`) — stores class field spans, enum variant
spans, and function name spans. Follows the existing source-map pattern
so it doesn't pollute Salsa cache comparisons.
- **`AstSourceMap::field_access_member_spans`** (`ast.rs`,
`lower_expr_body.rs`, `lower_cst.rs`) — stores the text range of just
the member name token (after the dot) for each `FieldAccess` expression.
Used for narrowing diagnostic spans.
### MemberResolution (TIR)
Renamed `MethodResolution` → `MemberResolution` and added `Field` and
`Variant` variants alongside the existing `Method` and `Free`
(`inference.rs`). The TIR builder (`builder.rs`) now inserts these
during field lookup, variant validation, and method resolution. Added
`resolve_class_loc`/`resolve_enum_loc` helpers.
### Narrower diagnostic spans (TIR)
Added `DiagnosticLocation::ExprMember` (`infer_context.rs`) — at render
time it looks up the member-name span instead of the full expression
span. All 9 `UnresolvedMember` diagnostic sites in `builder.rs` now use
this, so `s.feelin` only underlines `feelin`.
### MIR safety
The new `MemberResolution::Field`/`Variant` variants flow into MIR
lowering. Instead of crashing on unexpected variants (`unreachable!`,
`panic!`), the MIR now emits runtime panic instructions and continues
(`lower.rs`). This keeps the LSP alive.
### LSP goto-definition (`definition.rs`)
When `resolve_name_at` returns `Unknown` (which happens for all dotted
access), we now fall back to `resolve_member_at`, which:
- If cursor is inside a class/enum scope: navigates to the field/variant
definition directly
- If cursor is inside a function: finds the enclosing function, gets its
`ScopeInference`, and searches for the expression at the cursor offset.
Then dispatches based on `MemberResolution` type (field → field def
span, variant → variant def span, method → function name span) or checks
for constructor field keys.
### LSP find-references (`usages.rs`)
When on a class field definition, `find_field_definition_usages` scans
all files in the package. For each function body, it checks
`ScopeInference` for `MemberResolution::Field` matches and also scans
`Object` constructor field keys. Uses a text pre-filter (field name
appears in source) to skip files that can't possibly match.
### LSP outline (`outline.rs`)
Replaced zero-width placeholder spans with real field/variant spans from
`ItemTreeSourceMap`.
### Tests
- Flipped 5 goto-def tests and 1 find-refs test from negative to
positive assertions (`definition_at_tests.rs`, `usages_at_tests.rs`)
- Added 3 new diagnostic span tests: `unresolved_field`,
`unresolved_field_chained_access`,
`unresolved_field_span_should_narrow_to_member` (`inference.rs`)
- Updated 4 inline snapshot byte offsets for narrower spans
(`phase3a.rs`)
- Updated 4 file snapshots (`control_flow` and `format_checks` TIR +
diagnostics)
### Deleted old LSP v1 crates
- **`crates/baml_lsp_actions/`** — 15 source files, fully superseded by
`baml_lsp2_actions`
- **`crates/baml_lsp_actions_tests/`** — 7 source files + 281 test
fixtures
- Removed from `Cargo.toml` workspace members, updated `Cargo.lock`
## Deviations from plan
All 5 planned phases were implemented. Notable additions beyond the
plan:
- **Diagnostic span narrowing**
(`AstSourceMap::field_access_member_spans` +
`DiagnosticLocation::ExprMember`) was not in the plan — discovered the
wide-span issue during implementation
- **`function_name_spans`** in `ItemTreeSourceMap` was needed because
methods aren't top-level symbols, so the planned
`utils::definition_span` approach didn't work
- **MIR panic safety** — plan used `unreachable!` for the new variants,
we made it graceful instead since it runs in the LSP
- **`resolve_enum_loc`** needed more logic than planned for
cross-package namespace lookups
## How to verify
### Manual
- [ ] Ctrl-click `p.name` → jumps to field definition
- [ ] Ctrl-click `Status.Active` → jumps to variant definition
- [ ] Ctrl-click `name` in `Person { name: "..." }` → jumps to field
definition
- [ ] Ctrl-click `s.Celebrate()` → jumps to method definition
- [ ] Right-click field definition → Find All References → finds all
usages
- [ ] Type `s.feelin` → squiggly only on `feelin`
### Automated
```bash
cargo test -p baml_lsp2_actions # 26 tests
cargo test -p baml_tests --lib # 889 tests
```
## Changelog
Fix LSP goto-definition and find-references for class fields, enum
variants, constructor fields, and methods. Narrow unresolved-member
diagnostic spans to just the member name. Remove panics from MIR
lowering for LSP stability. Delete old LSP v1 crates.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 6a2b167 commit ccd9110
333 files changed
Lines changed: 1157 additions & 20959 deletions
File tree
- baml_language
- crates
- baml_compiler2_ast/src
- baml_compiler2_hir/src
- baml_compiler2_mir/src
- baml_compiler2_tir/src
- baml_lsp2_actions_tests/test_files
- semantic_tokens
- syntax/expr
- baml_lsp2_actions/src
- baml_lsp_actions_tests
- src
- test_files
- completion
- inlay_hints
- on_hover
- semantic_tokens
- syntax
- catch
- class
- client
- constraints
- dictionary
- enum
- expr
- functions_v2
- prompt_errors
- tests
- generators
- headers
- hover
- invalid_assignment
- loops
- maps
- match
- misc
- streaming
- strings
- template_string
- throw
- baml_lsp_actions
- src
- completion
- baml_tests
- snapshots
- control_flow
- format_checks
- src/compiler2_tir
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
53 | 52 | | |
54 | 53 | | |
55 | 54 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
| 10 | + | |
9 | 11 | | |
10 | 12 | | |
11 | 13 | | |
| |||
225 | 227 | | |
226 | 228 | | |
227 | 229 | | |
| 230 | + | |
| 231 | + | |
228 | 232 | | |
229 | 233 | | |
230 | 234 | | |
| |||
236 | 240 | | |
237 | 241 | | |
238 | 242 | | |
| 243 | + | |
239 | 244 | | |
240 | 245 | | |
241 | 246 | | |
| |||
262 | 267 | | |
263 | 268 | | |
264 | 269 | | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
265 | 279 | | |
266 | 280 | | |
267 | 281 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
348 | 348 | | |
349 | 349 | | |
350 | 350 | | |
| 351 | + | |
351 | 352 | | |
352 | 353 | | |
353 | 354 | | |
| |||
617 | 618 | | |
618 | 619 | | |
619 | 620 | | |
| 621 | + | |
620 | 622 | | |
621 | 623 | | |
622 | 624 | | |
| |||
831 | 833 | | |
832 | 834 | | |
833 | 835 | | |
| 836 | + | |
834 | 837 | | |
835 | 838 | | |
836 | 839 | | |
| |||
1046 | 1049 | | |
1047 | 1050 | | |
1048 | 1051 | | |
| 1052 | + | |
1049 | 1053 | | |
1050 | 1054 | | |
1051 | 1055 | | |
| |||
Lines changed: 17 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1319 | 1319 | | |
1320 | 1320 | | |
1321 | 1321 | | |
1322 | | - | |
| 1322 | + | |
1323 | 1323 | | |
1324 | 1324 | | |
1325 | 1325 | | |
1326 | 1326 | | |
1327 | | - | |
| 1327 | + | |
1328 | 1328 | | |
1329 | 1329 | | |
1330 | 1330 | | |
| |||
1335 | 1335 | | |
1336 | 1336 | | |
1337 | 1337 | | |
1338 | | - | |
| 1338 | + | |
1339 | 1339 | | |
1340 | 1340 | | |
1341 | 1341 | | |
| |||
1351 | 1351 | | |
1352 | 1352 | | |
1353 | 1353 | | |
1354 | | - | |
1355 | | - | |
1356 | | - | |
| 1354 | + | |
| 1355 | + | |
| 1356 | + | |
1357 | 1357 | | |
1358 | 1358 | | |
1359 | 1359 | | |
1360 | 1360 | | |
1361 | 1361 | | |
1362 | 1362 | | |
| 1363 | + | |
| 1364 | + | |
| 1365 | + | |
| 1366 | + | |
1363 | 1367 | | |
1364 | 1368 | | |
1365 | 1369 | | |
1366 | 1370 | | |
1367 | 1371 | | |
1368 | 1372 | | |
1369 | 1373 | | |
| 1374 | + | |
1370 | 1375 | | |
1371 | 1376 | | |
1372 | 1377 | | |
| |||
1378 | 1383 | | |
1379 | 1384 | | |
1380 | 1385 | | |
| 1386 | + | |
1381 | 1387 | | |
1382 | 1388 | | |
1383 | 1389 | | |
| |||
1386 | 1392 | | |
1387 | 1393 | | |
1388 | 1394 | | |
1389 | | - | |
| 1395 | + | |
| 1396 | + | |
| 1397 | + | |
| 1398 | + | |
| 1399 | + | |
1390 | 1400 | | |
1391 | 1401 | | |
1392 | 1402 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| 47 | + | |
47 | 48 | | |
48 | 49 | | |
49 | 50 | | |
| |||
60 | 61 | | |
61 | 62 | | |
62 | 63 | | |
| 64 | + | |
63 | 65 | | |
64 | 66 | | |
65 | 67 | | |
| |||
129 | 131 | | |
130 | 132 | | |
131 | 133 | | |
| 134 | + | |
132 | 135 | | |
133 | 136 | | |
134 | 137 | | |
| |||
349 | 352 | | |
350 | 353 | | |
351 | 354 | | |
| 355 | + | |
352 | 356 | | |
353 | 357 | | |
354 | 358 | | |
| |||
382 | 386 | | |
383 | 387 | | |
384 | 388 | | |
| 389 | + | |
385 | 390 | | |
386 | 391 | | |
387 | 392 | | |
| |||
428 | 433 | | |
429 | 434 | | |
430 | 435 | | |
| 436 | + | |
431 | 437 | | |
432 | 438 | | |
433 | 439 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
178 | 178 | | |
179 | 179 | | |
180 | 180 | | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
181 | 199 | | |
182 | 200 | | |
183 | 201 | | |
| |||
315 | 333 | | |
316 | 334 | | |
317 | 335 | | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
318 | 367 | | |
319 | 368 | | |
320 | 369 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
36 | | - | |
| 36 | + | |
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| |||
128 | 128 | | |
129 | 129 | | |
130 | 130 | | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
131 | 139 | | |
132 | 140 | | |
133 | 141 | | |
| |||
Lines changed: 4 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| |||
100 | 100 | | |
101 | 101 | | |
102 | 102 | | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
103 | 106 | | |
104 | 107 | | |
105 | 108 | | |
| |||
0 commit comments