Struct GithubActionsFormatter
pub struct GithubActionsFormatter { /* private fields */ }Expand description
Formatter for GitHub Actions ecosystem LSP responses.
Implementations§
§impl GithubActionsFormatter
impl GithubActionsFormatter
pub fn new(
tag_index: Arc<DashMap<PackageName, Arc<TagIndex>>>,
) -> GithubActionsFormatter
pub fn new( tag_index: Arc<DashMap<PackageName, Arc<TagIndex>>>, ) -> GithubActionsFormatter
Creates a new formatter over an already-populated (or empty) [TagIndex] map,
the same shared handle crate::registry::GithubActionsRegistry::tag_index
returns.
tag_index stays pub(crate) (critic M1): this constructor is the intended
external construction path — a seeded TagIndex for a doctest/integration test
goes through [crate::registry::TagIndex]’s own already-pub fields, not
through widening this struct’s field visibility.
§Examples
use dashmap::DashMap;
use deps_github_actions::GithubActionsFormatter;
use deps_github_actions::registry::TagIndex;
use deps_core::PackageName;
use std::sync::Arc;
let tag_index = Arc::new(DashMap::new());
let mut index = TagIndex::default();
index.tag_to_sha.insert("v4".to_string(), "a".repeat(40));
tag_index.insert(PackageName::new("actions/checkout"), Arc::new(index));
let formatter = GithubActionsFormatter::new(tag_index);
assert_eq!(
formatter.sha_pin_replacement_for(&PackageName::new("actions/checkout"), "v4"),
Some(format!("{} # v4", "a".repeat(40)))
);pub fn sha_pin_replacement_for(
&self,
name: &PackageName,
tag: &str,
) -> Option<String>
pub fn sha_pin_replacement_for( &self, name: &PackageName, tag: &str, ) -> Option<String>
Looks up tag’s commit SHA for name in the shared [TagIndex], returning the
{sha} # {tag} replacement text a “Pin to commit SHA” code action (issue #473)
writes — None on a cache miss (no TagIndex entry for name, or no entry for
this specific tag).
Deliberately separate from Self::format_version_replacing_for’s
PinStyle::Tag branch: that branch bumps to the latest tag (outdated-version
semantics — “update v3 to v4”), while this pins the current tag to its own
SHA (mutability semantics — “harden v4 to <sha> # v4”). The two operations
are independent (a step can need either, both, or neither) and must never be
conflated behind one method.
§Examples
use dashmap::DashMap;
use deps_github_actions::GithubActionsFormatter;
use deps_github_actions::registry::TagIndex;
use deps_core::PackageName;
use std::sync::Arc;
let tag_index = Arc::new(DashMap::new());
let mut index = TagIndex::default();
index.tag_to_sha.insert("v4".to_string(), "a".repeat(40));
tag_index.insert(PackageName::new("actions/checkout"), Arc::new(index));
let formatter = GithubActionsFormatter::new(tag_index);
// Miss: no entry for this tag.
assert_eq!(
formatter.sha_pin_replacement_for(&PackageName::new("actions/checkout"), "v5"),
None
);Trait Implementations§
§impl DiagnosticMessages for GithubActionsFormatter
impl DiagnosticMessages for GithubActionsFormatter
Source§fn yanked_message(&self) -> &'static str
fn yanked_message(&self) -> &'static str
Source§fn yanked_label(&self) -> &'static str
fn yanked_label(&self) -> &'static str
Source§fn deprecated_message(&self) -> &'static str
fn deprecated_message(&self) -> &'static str
Source§fn deprecated_label(&self) -> &'static str
fn deprecated_label(&self) -> &'static str
§impl DiagnosticPolicy for GithubActionsFormatter
impl DiagnosticPolicy for GithubActionsFormatter
Source§fn strict_semver_prerelease_exclusion(&self) -> bool
fn strict_semver_prerelease_exclusion(&self) -> bool
X.Y.Z-pre) is excluded from matching
requirement unless requirement itself pins to the same X.Y.Z tuple with a
pre-release tag — the rule Cargo’s semver crate and npm’s node-semver both
implement, and that compile_requirement’s matcher inherits from its underlying
comparator. Read moreSource§fn supports_package_rename(&self) -> bool
fn supports_package_rename(&self) -> bool
crate::Deprecation::replacement)
is safe to offer as a “Replace with X” rename quickfix. Read moreSource§fn yanked_diagnostic_applies_to(
&self,
_dep: &dyn Dependency,
_requirement: &VersionReq,
) -> bool
fn yanked_diagnostic_applies_to( &self, _dep: &dyn Dependency, _requirement: &VersionReq, ) -> bool
crate::lsp_helpers::requirement_matches_only_yanked) should evaluate requirement
at all for this ecosystem. Read more§impl OsvNaming for GithubActionsFormatter
impl OsvNaming for GithubActionsFormatter
§fn osv_version(&self, version: &str) -> String
fn osv_version(&self, version: &str) -> String
Rewrites a native tag string into the spelling OSV.dev’s SEMVER range matching
expects: unprefixed (verified live against GHSA-mrrh-fwg8-r2c3, whose ranges
carry no v prefix regardless of the affected repository’s own tagging
convention).
osv_version_to_native is deliberately left at its default identity: adding a v
prefix unconditionally, the way deps-go does for module versions, would be wrong
for a GitHub Actions repository that tags without one — and
format_version_replacing_for’s match_v_prefix_style already reconciles the
prefix against the dependency’s own declared pin style downstream, so no native
version ever reaches the manifest with the wrong style regardless of what this
method returns.
Source§fn osv_package_name(&self, dep: &dyn Dependency) -> Option<String>
fn osv_package_name(&self, dep: &dyn Dependency) -> Option<String>
dep’s package name, or None if
this dependency cannot be mapped (e.g. a non-GitHub Swift package). Read moreSource§fn osv_version_to_native(&self, version: &str) -> String
fn osv_version_to_native(&self, version: &str) -> String
crate::osv::Advisory::fixed_versions) into this ecosystem’s
own version namespace, as used in manifests and by the registry. Read more§impl PackageNaming for GithubActionsFormatter
impl PackageNaming for GithubActionsFormatter
§fn validate_package_name(&self, name: &str) -> Result<(), InvalidPackageName>
fn validate_package_name(&self, name: &str) -> Result<(), InvalidPackageName>
Accepts crate::is_valid_github_identity’s owner/repo shape, or either of the
two non-registry uses: forms crate::parser::classify_uses_value recognizes by
the same leading literals: a local composite action path (./x, .\x,
DependencySource::Path) or a Docker image reference (docker://x, carried as a
DependencySource::Url — GitHub Actions has no dedicated Docker source variant).
The non-registry forms matter here for the same reason a bare local-package name
matters to SwiftFormatter::validate_package_name (#402 critique C1): a Path- or
Docker-uses:-sourced GithubActionsDependency keeps its raw uses: value as
name() verbatim rather than an owner/repo coordinate, and
deps_core::lsp_helpers::diagnostics’s R5a “unknown package” rule runs
validate_package_name unconditionally — even for a source this formatter’s
can_resolve_source (default, unoverridden) already treats as non-resolvable.
Without accepting these two literal prefixes, every workflow step using a local
action or a Docker image would be flagged “Invalid package name” instead of
producing no diagnostic at all, as before this override existed.
In the current codebase this method’s Err arm is unreachable from any live call
path: classify_uses_value already discards a malformed owner/repo uses: value
as Malformed before a Registry- or reusable-workflow-sourced dependency is ever
constructed, and GithubActionsFormatter’s supports_package_rename (default,
unoverridden false) skips deps_core::lsp_helpers::code_actions’s
build_replacement_action — the only other call site — before it reaches this
method. The override exists for parity with every other GitHub-identifier-shaped
or coordinate-shaped ecosystem formatter (deps-swift, and the #402/#375 sweep) and
as a defensive gate for any future caller that constructs a name without going
through classify_uses_value, not because a malformed name reaches it today.
§Errors
Returns InvalidPackageName when name is none of the three accepted shapes.
§fn normalize_package_name(&self, name: &PackageName) -> String
fn normalize_package_name(&self, name: &PackageName) -> String
§impl PackageRendering for GithubActionsFormatter
impl PackageRendering for GithubActionsFormatter
§fn format_version_replacing_for(
&self,
dep: &dyn Dependency,
version: &ConcreteVersion,
current: &str,
) -> String
fn format_version_replacing_for( &self, dep: &dyn Dependency, version: &ConcreteVersion, current: &str, ) -> String
Tag → the latest tag, preserving current’s v-prefix style. SHA → looks up the
new SHA for version’s tag in the shared [TagIndex]; on a miss, returns
dep.version_literal().unwrap_or(current) — byte-identical to the raw declared
span, so every shared no-op guard (comparing against exactly that text)
suppresses the action instead of emitting a destructive downgrade-to-tag edit
(B1). Branch → current unchanged, for the same reason.
§fn suppress_package_url(&self, source: &DependencySource) -> bool
fn suppress_package_url(&self, source: &DependencySource) -> bool
Suppresses the hover heading link for a local composite action (./x,
DependencySource::Path) and a Docker image ref (docker://...) — neither has a
dependency name that Self::package_url can turn into a real URL, so without this
override hover renders a dead [name]() link instead of a plain heading (#474).
A reusable-workflow call (owner/repo/.github/workflows/x.yml@ref) is a
DependencySource::Url too, but its url is always built from a valid
owner/repo identity (see crate::parser’s is_reusable_workflow branch) and so is
left unsuppressed; a Docker ref’s url is the raw docker://... value and never
matches that shape.
§fn format_version_for_text_edit(&self, version: &ConcreteVersion) -> String
fn format_version_for_text_edit(&self, version: &ConcreteVersion) -> String
§fn package_url(&self, name: &PackageName) -> String
fn package_url(&self, name: &PackageName) -> String
Source§fn format_version_replacing(
&self,
version: &ConcreteVersion,
_current: &str,
) -> String
fn format_version_replacing( &self, version: &ConcreteVersion, _current: &str, ) -> String
version as a replacement for the existing requirement text
current, preserving current’s operator/pin style where the
ecosystem supports more than one. Read moreSource§fn is_position_on_dependency(
&self,
dep: &dyn Dependency,
position: Position,
) -> bool
fn is_position_on_dependency( &self, dep: &dyn Dependency, position: Position, ) -> bool
§impl RequirementResolution for GithubActionsFormatter
impl RequirementResolution for GithubActionsFormatter
§fn is_requirement_up_to_date(
&self,
requirement: &VersionReq,
latest: &ConcreteVersion,
) -> bool
fn is_requirement_up_to_date( &self, requirement: &VersionReq, latest: &ConcreteVersion, ) -> bool
A major-only or major.minor requirement (v4) is up to date while latest’s
corresponding leading components match; a full version is compared component-for-
component. v/V is normalized off both sides first. An unparseable requirement
(a bare SHA or branch name — neither is dot-separated all-digit) returns true,
never a false “outdated”: Self::requirement_is_unresolved is what actually
gates those out of the diagnostic/inlay-hint path; this is only the fallback for a
caller (the “Update N outdated” code lens) that does not consult that hook first.
§fn requirement_is_unresolved(&self, requirement: &VersionReq) -> bool
fn requirement_is_unresolved(&self, requirement: &VersionReq) -> bool
A bare SHA or branch ref is recognizable from the requirement string alone: a
40-character hex string is a SHA, and anything not shaped like a tag (an optional
v/V followed by a digit) is treated as a branch — the “honest unknown” side,
since neither can be resolved to a concrete version without a TagIndex lookup
this pure predicate has no access to.
Source§fn version_satisfies_requirement(
&self,
version: &ConcreteVersion,
requirement: &str,
) -> bool
fn version_satisfies_requirement( &self, version: &ConcreteVersion, requirement: &str, ) -> bool
Source§fn requirement_status(
&self,
requirement: &VersionReq,
latest: &ConcreteVersion,
) -> RequirementStatus
fn requirement_status( &self, requirement: &VersionReq, latest: &ConcreteVersion, ) -> RequirementStatus
is_requirement_up_to_date that distinguishes “confirmed up to
date” from “could not be resolved, so we don’t know.” Read moreSource§fn 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
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). Read moreSource§fn compile_requirement(
&self,
_requirement: &VersionReq,
) -> Option<Box<dyn RequirementMatcher>>
fn compile_requirement( &self, _requirement: &VersionReq, ) -> Option<Box<dyn RequirementMatcher>>
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. Read moreSource§fn requirement_is_undecidable_given_available(
&self,
_requirement: &VersionReq,
_available: &[ConcreteVersion],
) -> bool
fn requirement_is_undecidable_given_available( &self, _requirement: &VersionReq, _available: &[ConcreteVersion], ) -> bool
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. Read moreSource§fn manifest_requirement_is_resolved_version(&self, dep: &dyn Dependency) -> bool
fn manifest_requirement_is_resolved_version(&self, dep: &dyn Dependency) -> bool
dep’s manifest version-requirement line is itself the exact
version already selected — never a range. Read more§impl SourcePolicy for GithubActionsFormatter
impl SourcePolicy for GithubActionsFormatter
Source§fn can_resolve_source(&self, source: &DependencySource) -> bool
fn can_resolve_source(&self, source: &DependencySource) -> bool
source. Read moreSource§fn source_is_public_registry_content(&self, source: &DependencySource) -> bool
fn source_is_public_registry_content(&self, source: &DependencySource) -> bool
source’s content is exactly the default public registry’s — safe to treat
as such for OSV vulnerability scanning, cache-key signature construction, and hover
heading links. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for GithubActionsFormatter
impl !UnwindSafe for GithubActionsFormatter
impl Freeze for GithubActionsFormatter
impl Send for GithubActionsFormatter
impl Sync for GithubActionsFormatter
impl Unpin for GithubActionsFormatter
impl UnsafeUnpin for GithubActionsFormatter
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T> EcosystemFormatter for Twhere
T: PackageNaming + PackageRendering + RequirementResolution + DiagnosticMessages + DiagnosticPolicy + SourcePolicy + OsvNaming,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more