Skip to content

fix(buildfile-lsp): complete & hover provider_state/target fields mid-edit#117

Merged
raphaelvigee merged 3 commits into
masterfrom
fix-provider-state-lsp-fields
Jun 24, 2026
Merged

fix(buildfile-lsp): complete & hover provider_state/target fields mid-edit#117
raphaelvigee merged 3 commits into
masterfrom
fix-provider-state-lsp-fields

Conversation

@raphaelvigee

Copy link
Copy Markdown
Member

Problem

Hovering or autocompleting the properties of a provider_state(...) call produced nothing while typing. Field-name completion for both provider_state(...) and target(...) rode on the eval-based provenance index, which only exists when the whole BUILD buffer evaluates. Mid-token, the half-written property name is an undefined bareword → eval fails → the index falls back to source_only → no fields. That's exactly the moment completion is wanted.

driver = "..." and heph. member completion never had this problem — they detect context textually, no eval required.

Fix

Detect the enclosing call textually (string/paren-aware scan), the same eval-free approach the working paths already use:

  • provider_state(provider="X", …) — completes and hovers provider X's state-schema fields (the dynamic kwargs the stock starlark_lsp server has no docs for). Hover shows the field's type + doc.
  • target(…) — completes the base target args plus the selected driver's config fields, resolved from the textual driver = "X".

Both now work mid-edit (auto-closed parens, partial token) instead of only on a fully-valid buffer.

Removes the now-dead eval-based StateCall / TargetCall index machinery and the state-provenance capture that only fed it.

Tests

  • completion_mid_edit_offers_state_fields / completion_mid_edit_offers_target_fields — the failing cases, now green.
  • completion_inside_provider_state_offers_state_fields, completion_outside_provider_state_offers_no_state_fields, hover_on_state_field_renders_type_and_doc.
  • Unit tests for the text helpers: enclosing_provider_state_resolves_provider_textually, kwarg_string_extracts_whole_token_value.

lint + cargo test -p plugin-buildfile (95 passed) clean.

🤖 Generated with Claude Code

raphaelvigee and others added 2 commits June 24, 2026 22:32
…-edit

Field-name completion for `provider_state(...)` and `target(...)` relied on
the eval-based provenance index, which only exists when the whole BUILD buffer
evaluates. While typing, a half-written property name is an undefined bareword,
so eval fails, the index falls back to `source_only`, and no fields are offered
— the common case where completion is actually wanted.

Detect the enclosing call textually instead (string/paren-aware scan), the same
eval-free approach `driver = "..."` and `heph.` member completion already use:

- `provider_state(provider="X", …)` → completes & hovers provider X's state
  schema fields (the dynamic kwargs the stock server has no docs for).
- `target(…)` → completes the base args plus the selected driver's config
  fields, resolved from the textual `driver = "X"`.

Removes the now-dead eval-based `StateCall`/`TargetCall` index machinery and the
state provenance capture that only fed it.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Surface red diagnostics for invalid keyword arguments in `target(...)` and
`provider_state(...)` calls, complementing the completion/hover added in this
PR. Two checks, run off the parsed AST (so they work mid-edit, no eval needed):

- Unknown key: a kwarg naming no known field. Only flagged when the complete
  valid set is known — the driver/provider is resolved from a string-literal
  `driver=`/`provider=` and its schema is available — so an unresolved schema
  never yields a false positive.
- Wrong type: a kwarg whose literal value doesn't match the field's declared
  ParamType. Non-literal values (variables, concatenations, calls) carry no
  static type and are left alone. Numeric matching is lenient (an int literal
  satisfies uint/float) to mirror how the engine coerces at eval time.

Diagnostics attach to the offending key (unknown) or value (wrong type) span,
sourced as "heph".

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@raphaelvigee raphaelvigee force-pushed the fix-provider-state-lsp-fields branch from afad42c to 48d7411 Compare June 24, 2026 20:32
Hovering the `target` or `provider_state` callee name showed the stock
`def name(*args, **kwargs) -> None` prototype — both builtins take a raw
`args: &Arguments`, so the Starlark server has no real signature for them.

Render a meaningful one instead, computed once at startup and served by the
hover proxy when the callee name is under the cursor:

- target(name, driver, labels, transitive, **config) -> str
- provider_state(provider, **state) -> None

`target`'s arguments come from `target_base_fields()` (the same source
completion uses, so they never drift); each builtin's real docstring is pulled
from the globals doc and kept.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@raphaelvigee raphaelvigee enabled auto-merge (squash) June 24, 2026 20:57
@raphaelvigee raphaelvigee merged commit 99f7e06 into master Jun 24, 2026
12 checks passed
@raphaelvigee raphaelvigee deleted the fix-provider-state-lsp-fields branch June 24, 2026 21:11
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