pub trait RequirementResolution: Send + Sync {
// Provided methods
fn version_satisfies_requirement(
&self,
version: &ConcreteVersion,
requirement: &str,
) -> bool { ... }
fn is_requirement_up_to_date(
&self,
requirement: &VersionReq,
latest: &ConcreteVersion,
) -> bool { ... }
fn requirement_is_unresolved(&self, _requirement: &VersionReq) -> bool { ... }
fn requirement_status(
&self,
requirement: &VersionReq,
latest: &ConcreteVersion,
) -> RequirementStatus { ... }
fn requirement_status_for(
&self,
dep: &dyn Dependency,
requirement: &VersionReq,
latest: &ConcreteVersion,
) -> RequirementStatus { ... }
fn compile_requirement(
&self,
_requirement: &VersionReq,
) -> Option<Box<dyn RequirementMatcher>> { ... }
fn requirement_is_undecidable_given_available(
&self,
_requirement: &VersionReq,
_available: &[ConcreteVersion],
) -> bool { ... }
fn manifest_requirement_is_resolved_version(
&self,
dep: &dyn Dependency,
) -> bool { ... }
}Expand description
Requirement parsing, matching, and up-to-date status.
Implementors guarantee every method here is a pure function of its arguments — no network
or filesystem access — since these run on the hot hover/diagnostic path. The default
requirement_status maps
requirement_is_unresolved to its Unresolved variant
and otherwise defers to is_requirement_up_to_date — but
an override of one without the other is not a contract violation: an ecosystem whose
requirement syntax can be unresolved (Maven, Gradle, NuGet, deps-github-actions) overrides
requirement_is_unresolved precisely so requirement_status can distinguish “not yet
decidable” from “decided outdated”, a distinction the boolean method has no variant for.
Callers needing that distinction use requirement_status, not the boolean method.
Provided Methods§
Sourcefn version_satisfies_requirement(
&self,
version: &ConcreteVersion,
requirement: &str,
) -> bool
fn version_satisfies_requirement( &self, version: &ConcreteVersion, requirement: &str, ) -> bool
Check if a version satisfies a requirement string.
General constraint check (e.g. for completion/candidate filtering) — not the
“is this dependency up to date” hook. That is is_requirement_up_to_date below,
which has its own default and its own override points; an ecosystem whose bare
requirement is a floor rather than an auto-following range (see deps-nuget)
overrides that method, not this one.
Sourcefn is_requirement_up_to_date(
&self,
requirement: &VersionReq,
latest: &ConcreteVersion,
) -> bool
fn is_requirement_up_to_date( &self, requirement: &VersionReq, latest: &ConcreteVersion, ) -> bool
Whether an unresolved dependency (no lock-file version) should be reported as
up to date against latest, given its declared requirement.
Default: latest satisfies requirement — correct for range-based ecosystems
(Cargo’s ^1.2, npm’s ~1.2, …) where the declared requirement already
expresses forward compatibility, so a latest it accepts is not “newer” in any
actionable sense. Ecosystems where a bare requirement is a minimum floor rather
than an auto-following range (NuGet’s bare Version="1.0.0") must override this,
since “does the floor accept latest” and “is the pin already latest” are
different questions there.
Sourcefn requirement_is_unresolved(&self, _requirement: &VersionReq) -> bool
fn requirement_is_unresolved(&self, _requirement: &VersionReq) -> bool
Whether requirement could not be resolved to a concrete version constraint (e.g. an
unexpanded property/variable placeholder rather than a real version or range).
Default: always resolvable. Ecosystems whose requirement syntax can contain
unresolved placeholders (Maven’s ${property}, Gradle’s $var/${var}) override
this single predicate; both version_satisfies_requirement’s “treat as satisfied”
short-circuit and requirement_status’s Unresolved variant are derived from it, so
the two can’t drift out of sync with each other.
§Examples
use deps_core::lsp_helpers::RequirementResolution;
use deps_core::VersionReq;
struct DefaultFormatter;
impl RequirementResolution for DefaultFormatter {}
assert!(!DefaultFormatter.requirement_is_unresolved(&VersionReq::new("^1.2")));Sourcefn requirement_status(
&self,
requirement: &VersionReq,
latest: &ConcreteVersion,
) -> RequirementStatus
fn requirement_status( &self, requirement: &VersionReq, latest: &ConcreteVersion, ) -> RequirementStatus
Tri-state variant of is_requirement_up_to_date that distinguishes “confirmed up to
date” from “could not be resolved, so we don’t know.”
Default: Unresolved when requirement_is_unresolved says so, otherwise maps the
boolean result of is_requirement_up_to_date to UpToDate/Outdated. Callers
needing the distinction — inlay hints, in particular — use this instead of
is_requirement_up_to_date so they can tell “verified up to date” apart from
“resolution failed.”
§Examples
use deps_core::lsp_helpers::{RequirementResolution, RequirementStatus};
use deps_core::{ConcreteVersion, VersionReq};
struct DefaultFormatter;
impl RequirementResolution for DefaultFormatter {}
assert_eq!(
DefaultFormatter.requirement_status(&VersionReq::new("^1.2"), &ConcreteVersion::new("1.5.0")),
RequirementStatus::UpToDate
);
assert_eq!(
DefaultFormatter.requirement_status(&VersionReq::new("^1.2"), &ConcreteVersion::new("2.0.0")),
RequirementStatus::Outdated
);Sourcefn requirement_status_for(
&self,
dep: &dyn Dependency,
requirement: &VersionReq,
latest: &ConcreteVersion,
) -> RequirementStatus
fn requirement_status_for( &self, dep: &dyn Dependency, requirement: &VersionReq, latest: &ConcreteVersion, ) -> RequirementStatus
Like requirement_status, but also hands the ecosystem
the dependency itself — for an ecosystem whose requirement text alone is ambiguous
between two shapes with different resolution rules, and which already computed the
disambiguating classification once, at parse time, onto the dependency (deps-gitlab-ci’s
PinStyle, #466 review M-c: a bare "1.2" is Partial under its component: pin
grammar but Branch under its simpler project: ref grammar — indistinguishable from
the text alone).
Default: forwards to requirement_status, ignoring dep
— every other ecosystem’s requirement text alone is unambiguous, so this is a no-op
for them. Callers that already have dep in hand (the diagnostic pipeline’s outdated
rule) call this instead of requirement_status directly, mirroring
Registry::select_latest_matching_with_context’s identical additive-default pattern.
Sourcefn compile_requirement(
&self,
_requirement: &VersionReq,
) -> Option<Box<dyn RequirementMatcher>>
fn compile_requirement( &self, _requirement: &VersionReq, ) -> Option<Box<dyn RequirementMatcher>>
Compiles requirement into a matcher for precise membership testing against a list
of candidate version strings, or None when this ecosystem cannot parse or cannot
model this requirement form — in which case no unsatisfiable-requirement diagnostic
is produced for it.
Distinct from version_satisfies_requirement, which answers the looser “treat as up
to date” question and is deliberately permissive (see that method’s docs). This one
gates a WARNING diagnostic claiming “no published version satisfies this
requirement”, so it must never guess: an ecosystem that has not opted in by
overriding this method emits no such diagnostic at all, rather than one derived from
a loose heuristic.
None has two distinct causes, both correct to suppress the diagnostic for: the
requirement string fails to parse under this ecosystem’s own comparator (deps-cargo,
deps-npm, deps-pypi, deps-swift — .ok() on a fallible parse), or the
requirement parses fine but names a version-space region the fetched available list
structurally cannot contain regardless — a Go pseudo-version, a Composer
dev-branch/@dev flag, a RubyGems exact pin indistinguishable from one that matches
only a yanked release, a malformed Maven/Gradle/NuGet range. Scanning either case would
always decide Some(false) for every candidate, producing a false “no published
version satisfies” verdict instead of correctly suppressing the check. Implementors of
the second (predicate-guard) shape should use
crate::lsp_helpers::compile_requirement_unless, which
centralizes this contract instead of re-deriving it per ecosystem. deps-dart is the
only ecosystem with neither cause: every requirement string is a valid Dart constraint
by construction, so its override is always Some.
Default: None — an ecosystem that has not opted in emits no unsatisfiable-requirement
diagnostics.
§Examples
use deps_core::lsp_helpers::RequirementResolution;
use deps_core::VersionReq;
struct DefaultFormatter;
impl RequirementResolution for DefaultFormatter {}
assert!(
DefaultFormatter
.compile_requirement(&VersionReq::new("^1.2"))
.is_none()
);Sourcefn requirement_is_undecidable_given_available(
&self,
_requirement: &VersionReq,
_available: &[ConcreteVersion],
) -> bool
fn requirement_is_undecidable_given_available( &self, _requirement: &VersionReq, _available: &[ConcreteVersion], ) -> bool
Whether this ecosystem’s registry can silently omit a published version from
available in a way indistinguishable from “never published” — and, if so, whether
requirement names a version-space region that specific omission could explain, given
the versions actually observed in available.
Called by crate::lsp_helpers::requirement_is_unsatisfiable before compiling requirement; returning
true suppresses the “no published version satisfies this requirement” diagnostic for
this dependency, the same as Self::compile_requirement returning None — but,
unlike that method, this one sees available and can therefore narrow the suppression
instead of disabling it for every requirement of a given shape.
Default false — no ecosystem has this problem unless it opts in. deps-bundler
overrides it (see BundlerFormatter::requirement_is_undecidable_given_available and
its helper for the RubyGems-specific rationale and heuristic).
§Examples
use deps_core::lsp_helpers::RequirementResolution;
use deps_core::{ConcreteVersion, VersionReq};
struct DefaultFormatter;
impl RequirementResolution for DefaultFormatter {}
assert!(!DefaultFormatter.requirement_is_undecidable_given_available(
&VersionReq::new("1.6.13"),
&[ConcreteVersion::new("1.6.9"), ConcreteVersion::new("1.6.14")],
));Sourcefn manifest_requirement_is_resolved_version(&self, dep: &dyn Dependency) -> bool
fn manifest_requirement_is_resolved_version(&self, dep: &dyn Dependency) -> bool
Whether dep’s manifest version-requirement line is itself the exact
version already selected — never a range.
True only for a Go require-directive dependency: go.mod’s
require line already holds the module version selected by Go’s
MVS, unlike Cargo/npm where the manifest holds a range and the lock
file holds the pin. When true, hover and inlay hints prefer
Dependency::version_requirement over the lock-file-derived entry
in crate::lsp_helpers::VersionData::resolved, because go.sum is a checksum ledger
that go get/go build only ever append to (only go mod tidy
prunes it) — a stale, no-longer-selected higher version can remain
recorded there after a downgrade and, since go.sum is written sorted
ascending by semver, always sorts last and wins naive
last-occurrence-wins parsing (overridden in deps-go; see #235).
Takes dep (precedent: OsvNaming::osv_package_name) because Go’s
exclude/replace directives are also surfaced as dependencies
whose version_requirement() is not an in-use version (the
excluded version, or the replaced-from version) — the deps-go
override inspects the directive kind and returns true only for
require.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".