Expand description
Completion for the cursor, keyed off the line up to it.
The surface is the canonical cursor context × candidate-kind matrix fixed
by ADR 0093 (design/decisions/0093-completion-surface-contract.md), spec’d
at design/bynk-lsp-spec.md §3.15. complete dispatches the six contexts
it can serve purely (no analysis cache):
consumes <prefix>/consumes U { … }/given …— consumable units and in-scope capabilities (v0.17);- type position (
: T,-> T, inside[ … ]type args) — built-in types, thebynk-surface transparent types, and projecttypedecls; - keyword position (a bare word at a declaration/statement start) — the reserved keywords (with registry docs) and declaration snippets;
- name-receiver
UpperIdent.— sum variants (project + built-inHttpResult/QueueResult), refined/opaqueof/unsafe, capability ops, and built-in type statics (Int.parse/List.empty/Effect.pure/…); - expression position (after
=/(/,/=>/an operator) — the value constructors (Ok/Some/true/…), in-scope type names, and in-scope free functions (the current unit’s ownfns +uses-imported stdlib/project combinators, gated on theusesset) (ADR 0093 D3).
Two further contexts need the analysis overlay and so live handler-side
(main.rs): value-receiver lower. members (kernel methods + record
fields) and in-scope locals/params. They depend on the analysis overlay
(the boundary is ADR 0093 D4), but since slice 4 (ADR 0094) it is
error-tolerant: best-effort partial types are recorded even on a broken
buffer, so they no longer go silent on an unrelated error. Items also carry a
one-line detail eagerly; the richer documentation is filled in lazily by
completionItem/resolve, handler-side (slice 5).
Context detection is lexical (it must work mid-edit, when the buffer rarely
parses); candidates are semantic. Unit/type/capability/member enumeration
parses the project’s .bynk files (and the embedded bynk surface) with
recovery, so it works even while the file the cursor sits in is mid-edit.
Built-ins, keywords, and constructors come from the static bynkc registries
(keywords/builtin_names/firstparty/ast), never the index — first-party
symbols aren’t indexed (the v0.28 finding); the project parse supplies only
project symbols.
Structs§
Enums§
- Completion
Kind - What a candidate refers to — maps to an LSP
CompletionItemKind.
Constants§
- BUILTIN_
STATICS 🔒 - Built-in type statics — real language statics that are not user-declared, so
they come from this small table rather than the project parse. Covers the
numeric parse statics and the JSON codec (v0.22, ADRs 0048/0049), the
collection
emptyconstructors (v0.20b), andEffect.pure(v0.5). The full real set per ADR 0093 D2 — kept complete and drift-tested (builtin_statics_are_reachable). - BUILTIN_
TYPES 🔒 - Built-in type names not declared in any parseable source. Base and generic
types from the language core; collection types from
builtin_names. Docs are drawn from thekeywordsregistry where present (one source of truth). - CONSTRUCTORS 🔒
- The value constructors offered at expression position (ADR 0093 D3) — the
closed set of
Result/Optionvariant constructors and the boolean literals. A value expression can begin with any of these; their docs reuse thekeywordsregistry (one source of truth). - SNIPPETS 🔒
- Declaration snippets (
CompletionItemKind::SNIPPET), as LSP snippet bodies.
Statics§
Functions§
- builtin_
sum_ 🔒variants - Variants of a built-in sum type (
HttpResult/QueueResult), sourced from the AST variant registries so a new variant surfaces in completion for free (ADR 0093 D2/G3). Empty for any other receiver. - capabilities_
of_ 🔒unit - The capability names a unit
exports capability. - complete
- Produce completions for the cursor, given the text of the line up to the cursor, the current document text, and the project source root (if any).
- consumable_
units 🔒 - Consumable unit names: contexts and adapters (plus
bynk), deduplicated. - consumes_
brace_ 🔒unit consumes U { …with the brace still open at the cursor →Some(U).- current_
unit_ 🔒name - The qualified name of the unit the cursor’s document declares, via a recovery
parse (the header survives a mid-edit body).
Nonefor a headerless fragment that names no unit. - expression_
candidates 🔒 - Expression-position candidates: the value constructors plus in-scope type
names (the entry to a static call like
Int.parseor a record construction likeOrder { … }). In-scope values — locals/params, and from slice 3 free functions — are appended by the handler, which owns the analysis cache, so they are not produced here (ADR 0093 D3). - for_
each_ 🔒unit - Parse every project unit, plus the embedded first-party adapters (the
bynksurface and thebynk.cloudflareplatform adapter), and callffor each. Recovery parsing tolerates the in-progress edit at the cursor. - free_
fn_ 🔒signature - Render a free function’s signature for the completion detail, the same way
hover and signature help do (
symbols::type_ref_str) — one format, never divergent. Mirrors signature help: no generic-parameter list. - free_
function_ 🔒candidates - Free-function candidates at expression position: the current unit’s own
top-level
fns plus the freefns of everyuses-imported module (project commons and the embedded stdlib). Gated on theusesset so a combinator is offered only where it is actually in scope (ADR 0093 D3 / G5). - in_
scope_ 🔒capabilities - Capabilities in scope for a
givenclause in the current document: locally declared capabilities, bare names flattened by a bracedconsumes, andU.Capfor each whole-unitconsumes U. - in_
type_ 🔒arg_ list headends inside an unclosed[ …whose opening bracket immediately follows an identifier (a type constructor, e.g.Option[,Result[Int,) — as opposed to a bare list-literal[.- is_
consumes_ 🔒target consumes <partial>with no brace orasyet → completing the target name.- is_
expression_ position - The cursor sits where a value expression is expected — after
=/(/,, a=>lambda arrow, or a binary operator — so in-scope locals are offered (v0.31, ADR 0064). Conservative: covers the common positions, excludes the type arrow->. (The handler also offers locals at keyword position.) - is_
given_ 🔒position - The cursor is inside a
givenlist (aftergiven, before the{body). - is_
keyword_ position - A bare word at a declaration/statement start: the line up to the cursor is
only leading whitespace plus an optional partial identifier (no operators,
colons, or brackets). Fires on an empty line too. Disjoint from
is_type_position, whose triggers (:/->/[) make this false. - is_
qualified_ 🔒name - is_
type_ 🔒position - The cursor sits in a type position: a return type (
-> T), a type annotation/field type (: T), or inside a[ … ]type-argument list. The partial type name being typed is stripped before inspecting the preceding token, so: Optioand-> Effboth qualify. - keyword_
and_ 🔒snippet_ candidates - Keyword-position candidates: the lowercase-initial reserved keywords (the
declaration/statement words — uppercase type/value names like
Int/Somebelong to type/expression position) with their registry docs, plus the declaration snippets. - keyword_
doc 🔒 - The one-line doc for a name in the
keywordsregistry, if present. - member_
candidates 🔒 - Members of a name receiver: built-in type statics, then built-in sum-type
variants, then — from the project and embedded-surface parse — project sum
variants, refined/opaque
of/unsafe, or capability operations. Yields[]when the receiver resolves to none of these (e.g. a plaintype X = Intalias or a record). - member_
receiver 🔒 UpperIdent.<partial>at the cursor →Some("UpperIdent")— a name receiver whose members are statically enumerable (a sum/refined/opaque type or a capability). Conservative: the receiver is a single uppercase-initial identifier, not itself a.-qualified segment (sobynk.cloudflare.anda.B.are excluded) and not a number (so the decimal1.is excluded). A lowercasex.is a value receiver — deferred to slice 3 — and yieldsNone.- type_
candidates 🔒 - Type-position candidates: built-in types (with registry docs), then every
typedeclaration found in the project sources and the embeddedbynksurface (so the transparent surface typesUuid/Method/… come for free). - unit_
items_ 🔒and_ uses - A unit’s top-level items and its
usesclauses, for the kinds that carry free functions. Service/other units contribute neither. - value_
member_ candidates - The members of a typed value receiver: the built-in kernel methods of its type (from the enumerable registry) plus, for a record, its fields.
- value_
receiver_ rewrite - If the cursor (byte
offsetintotext) sits just after a lowercasereceiver.(partial) — a value receiver — return the buffer rewritten so the receiver is a complete expression (the trailing.partialdropped, so the file parses) and the byte offset of the receiver to type. ReturnsNonefor an uppercase name receiver (slice 2), a decimal1., or a.-qualified segment.