Skip to main content

Module extract

Module extract 

Source
Expand description

v0.213 (ADR 0239): textDocument/codeAction extract-variable — CodeActionKind::REFACTOR_EXTRACT. The smallest expression node whose span fully contains the requested selection is bound to a fresh let inserted immediately above its enclosing statement (or block tail), and the selection’s span is replaced with the new name.

text is whatever snapshot the caller passes in — for code_action that’s the last committed analysis round’s snapshot (ADR 0235’s stale-while-revalidate posture), not necessarily the very latest keystroke. Like crate::structure, this reparses that snapshot fresh each call — no cached AST is retained in Analysis, and extraction is selection-driven the same way folding/selection ranges are.

Track #800 settles as: plan_function reuses the exact same smallest-containing-expression selection algorithm, but lifts the expression into a new top-level fn (threading its free identifiers as parameters) rather than a local let. It is capability-free-only — fn has no given clause to propagate a capability-using body into, unlike Handler/Provider (that language-change question is deliberately not taken on here) — so it declines whenever the selection’s site carries any recorded [Requirement], covered or not.

#813 extends plan_function to a contiguous run of one or more full statements (optionally including the block’s tail), not just one expression — offered when the selection’s span aligns exactly with statement boundaries (whitespace-trimmed at either end, so a real “select these lines” gesture matches); a selection that doesn’t align falls back to the single-expression algorithm above unchanged. A run that stops before the tail synthesises a fn … -> () — or -> Effect[()] when the run itself performs an effect, so ~>/do/<- stay legal in the lifted body — with no explicit tail, the same implicit-unit-tail shape the parser already synthesises for any statements-only block (v0.146, ADR 0170); the call site becomes let _ = …(…) (or do …(…) in the effectful case) rather than a bare expression, since Bynk has no expression-statement form. It declines whenever a := (Cell store write) statement falls inside the run — a lifted top-level fn has no store fields to write, so this always fails to typecheck, not merely a conservative guess — or whenever a binding the run introduces is still referenced later in the same block: lifting it away would strand that reference.

Structs§

FunctionPlan
#2100 slice 2: a planned extract-function — the new fn’s name and the two edits (insert the fn, replace the selection with its call).
FunctionRefusal
#2100 slice 2: why extract-function is not offered for a selection. reason is Some when the selection is a real candidate the user should be told about (a client that supports it shows a disabled action with the reason); None when there is simply nothing to extract there.
FunctionTarget
#2100 slice 2: what a listed extract-function action’s data names.

Functions§

extract_variable
Extract-variable actions for the requested range. Only offered for a genuine selection (requested.start != requested.end) — a bare cursor offers nothing, the refactor-vs-quickfix posture other editors take.
function_listed
#2100 slice 2: the listed extract-function action for a selection — no edit yet (codeAction/resolve computes and re-checks it), or, when the selection is refused for a reason worth telling and the client supports it, a disabled action carrying that reason. None otherwise.
plan_function
#2100 slice 2: the extract-function plan for requested, or why there is none. Extracted functions stay capability-free (a fn has no given clause), and a selection containing ? is refused: lifted into a new fn, the ? would return from that fn instead of the one it was written in.