Skip to content

Add support for struct auto-completion#57

Open
JesseHerrick wants to merge 4 commits into
mainfrom
struct-support
Open

Add support for struct auto-completion#57
JesseHerrick wants to merge 4 commits into
mainfrom
struct-support

Conversation

@JesseHerrick
Copy link
Copy Markdown
Member

@JesseHerrick JesseHerrick commented May 4, 2026

#43


Note

Medium Risk
Adds new BEAM CodeIntel protocol ops plus caching and completion-path logic, which can affect editor completion behavior and introduces concurrency/cache invalidation complexity. Failures are mostly handled gracefully, but incorrect inference or cache staleness could degrade completion accuracy/performance.

Overview
Adds Elixir struct field auto-completion to the LSP, covering both struct literals (%Module{...}) and variable.field access.

Extends the BEAM sidecar CodeIntel protocol with new ops to fetch compiled struct fields and to infer a function’s struct return type from the BEAM ExCk chunk, then wires this into server-side completion with a build-root scoped cache, background pre-warming on document open/change, and cache invalidation on reindex/delete/BEAM eviction.

Updates token-based parsing to detect struct key/value cursor contexts, %Module references, variable-to-struct bindings (pattern matches and @spec hints), and simple var = Module.func(...) assignments; completion trigger characters are expanded (including space) to support struct value-position variable suggestions, with extensive new unit/integration tests.

Reviewed by Cursor Bugbot for commit 3dcc64f. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread internal/lsp/server.go
Detail: "variable",
SortText: "000_" + varName,
})
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable sort priority leaks into non-struct completions

Medium Severity

The addVariableCompletion helper unconditionally sets SortText: "000_" + varName, which forces variables to sort before all other completions. This was intended only for struct value positions (where variables are the likely target), but the same helper is used in the regular funcPrefix != "" path too. Previously, variable completions had no SortText and sorted naturally alongside functions. This changes the ordering behavior of all non-struct completions as a side effect.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7823a10. Configure here.

Adds two more sources of struct-type inference for variable
dot-completion:

- @SPEC parameter typespecs: parameters annotated `t()` or `Module.t()`
  resolve to that struct (pattern matches still take precedence).
- ExCk return-type lookup: `var = Mod.func(...)` resolves `var.` against
  the struct returned by the compiled function, queried over a new
  `return_type_struct` op on the persistent BEAM process.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

There are 3 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3dcc64f. Configure here.

Comment thread internal/lsp/elixir.go
}
}
return 0
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused source parameter in countCallArity function

Low Severity

The countCallArity function accepts a source []byte parameter that is never used anywhere in the function body. This adds unnecessary noise to the API and every call site.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3dcc64f. Configure here.

Comment thread internal/lsp/server.go
// Scan the entire file for var = Module.func(...) patterns.
lines := strings.Count(text, "\n")
endCol := len(text)
calls := tf.VariableFunctionCalls(lines, endCol)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prewarming ExCk calls scoped to last function only

Low Severity

prewarmStructFieldsFromText passes lines (last line index) and len(text) (total byte count, not a column) to VariableFunctionCalls. This scopes the scan to only the last function definition in the file because VariableFunctionCalls finds the last def before the offset. Struct module refs from StructModuleRefs correctly scan the whole file, but ExCk-based prewarming misses calls in earlier functions.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3dcc64f. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant