Skip to content

feat: grammar-based value completion behind the experimental flag (#467 #343)#477

Open
SJrX wants to merge 2 commits into
issue-345-7from
issue-345-8
Open

feat: grammar-based value completion behind the experimental flag (#467 #343)#477
SJrX wants to merge 2 commits into
issue-345-7from
issue-345-8

Conversation

@SJrX

@SJrX SJrX commented Jun 21, 2026

Copy link
Copy Markdown
Owner

What

The payoff of the frontier work: grammar-based autocomplete. With the experimental flag on, the value completion for any GrammarOptionValue suggests the literal/choice tokens the grammar could accept at the caret — e.g. typing RestrictAddressFamilies=AF_IN⎉ offers AF_INET / AF_INET6.

Stacked on #475 (issue-345-7). Implements #343 on top of the engine.

How

  • Combinator.nextTokenChoices(prefix) (pure, no IntelliJ): the FIRST set at the end of prefix — the enumerable choices (LiteralChoiceTerminal / FlexibleLiteralChoiceTerminal) from the Stuck values at that offset. "What was expected here" (errors) and "what could come next" (completion) are the same question.
  • UnitFileValueCompletionContributor (kept on the simple extend() path): when the flag is on and the option is grammar-backed, read the value text before the caret and scan split points (largest first) for the tightest word where the grammar expects an enumerable token matching what's typed; then resultSet.withPrefixMatcher(word) + add the choices.

Why the custom prefix matcher

The platform's default prefix is the leaf text up to the caret. For a partial token like ~AF_IN that prefix is ~AF_IN, and no family name starts with it, so everything gets filtered out. Computing the grammar-correct word (here AF_IN) and setting it via withPrefixMatcher fixes this without grammar-specific word-splitting heuristics. This was the subtlety flagged before starting.

Tests

  • NextTokenChoicesTest (pure): empty value offers none/~/families; after ~ offers families but not none/~; after AF_INET offers another family (context-aware).
  • GrammarValueCompletionTest (fixture, flag on): AF_IN⎉AF_INET/AF_INET6; and a subsequent family in a list AF_UNIX AF_IN⎉ → same.

Full suite green; cancellation is polled (ProgressManager.checkCanceled) between split attempts.

Scope / limits

  • Completion fires on COMPLETED_VALUE leaves (existing contributor limitation); values mid-line-continuation aren't covered. Fine for the common case.
  • Only enumerable terminals suggest (literals/choices). Numbers/regex/IP terminals contribute nothing concrete (correctly) — those would need bespoke suggestion logic later.

Refs #467 #343

🤖 Generated with Claude Code

#343)

Cashes in the frontier/expected-set: at the caret, suggest the literal/choice tokens
the grammar could accept next.

- Combinator.nextTokenChoices(prefix): pure FIRST-set computation — the enumerable
  choices (LiteralChoiceTerminal / FlexibleLiteralChoiceTerminal) expected at the end
  of `prefix`, read from the Stuck values at that offset. No IntelliJ types; bounded by
  maxSteps.
- UnitFileValueCompletionContributor: when useGrammarParseEngine is on and the option is
  a GrammarOptionValue, compute completions from the value text before the caret. It
  scans split points (largest first) for the tightest word where the grammar expects an
  enumerable token matching what's typed, then uses resultSet.withPrefixMatcher(word) so
  the platform filters correctly — otherwise a partial token like "~AF_IN" would be the
  prefix and match nothing. Falls back to the original getAutoCompleteOptions path
  otherwise. Polls ProgressManager.checkCanceled between split attempts.

Tests: NextTokenChoicesTest (FIRST set incl. context — after "~" offers families not
"none"; after "AF_INET " offers another family); GrammarValueCompletionTest drives real
completion with the flag on (partial family, and a subsequent family in a list). Full
suite green.

Refs #467 #343

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Test Results

1 130 tests  +5   1 130 ✅ +5   50s ⏱️ +3s
  300 suites +2       0 💤 ±0 
  300 files   +2       0 ❌ ±0 

Results for commit dc47a98. ± Comparison against base commit b41dfdd.

The first cut used "largest split wins", so for a lenient terminal a partial token
like RootImagePolicy=h was treated as a finished partition identifier and completion
offered "=" instead of "home" (and AF_IN-style cases only worked by luck).

Rework addGrammarCompletions to prefer completing a genuine partial: the longest
non-empty trailing word for which the grammar expects an enumerable choice that
STRICTLY extends it (something left to type). Only if there's no such partial do we
fall back to advancing at a fresh boundary (empty value, or after a complete token
like "~" or "root=") with an empty prefix.

This keeps the previously-working cases (empty value, after "partition=", "AF_IN")
and fixes partial-identifier completion. Adds ImagePolicyCompletionTest covering the
empty boundary, partial-identifier completion ("r" -> root/root-verity/...), and the
post-"root=" policy-flag position.

Refs #467 #343

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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