pub async fn complete_versions_at_position(
registry: &dyn Registry,
formatter: &dyn SourcePolicy,
parse_result: &dyn ParseResult,
position: Position,
prefix: &str,
operator_chars: &[char],
freshness: FreshnessSettings,
) -> Vec<CompletionItem>Expand description
Version completion resolved by cursor position, not by package name (issue #593).
Finds the dependency in parse_result whose version_range contains position — the
same containment check detect_completion_context used to decide this is a Version
context in the first place — then completes through complete_versions_generic_from
against that dependency’s own crate::Dependency::source. Unlike a name join (the old
per-ecosystem resolve_completion_source pattern this replaces), two dependencies sharing
one PackageName but resolving to different sources never collide: the cursor position
unambiguously identifies which occurrence the user is editing, so each completes against
its own source independently instead of both offering nothing.
Deliberately reuses this module’s own (lenient) position_in_range rather than
crate::lsp_helpers::position_in_range (the two differ at the one-past-range.end
boundary) — using a different predicate here than the one detect_completion_context
used to decide position is even inside a Version context would let this lookup silently
disagree with its own caller and return empty at a boundary the caller already committed to.
§Source-resolvability gate
crate::Registry::get_versions_from’s default/documented contract does not itself fail
closed for a source an ecosystem’s registry does not specifically route (see that method’s
docs) — several concrete Registry implementations forward an unrecognized source (e.g.
Git, Path, an unresolved CustomRegistry) to their default public-registry client
rather than erroring. Gating on formatter’s
SourcePolicy::can_resolve_source
first — the same check crate::lsp_helpers::generate_hover and diagnostics/code-actions
already use — is what keeps that permissive default from leaking a private/non-registry
dependency’s name to a public registry on every keystroke.
§Examples
use deps_core::completion::complete_versions_at_position;
use deps_core::lsp_helpers::SourcePolicy;
use tower_lsp_server::ls_types::Position;
struct DefaultFormatter;
impl SourcePolicy for DefaultFormatter {}
let freshness = deps_core::FreshnessSettings::default();
let position = Position { line: 3, character: 12 };
let items = complete_versions_at_position(
registry,
&DefaultFormatter,
parse_result,
position,
"1.",
&['^', '~'],
freshness,
).await;