Skip to main content

GithubActionsFormatter

Struct GithubActionsFormatter 

pub struct GithubActionsFormatter { /* private fields */ }
Expand description

Formatter for GitHub Actions ecosystem LSP responses.

Implementations§

§

impl 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>

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

Source§

fn yanked_message(&self) -> &'static str

Message for yanked/deprecated versions in diagnostics.
Source§

fn yanked_label(&self) -> &'static str

Label for yanked versions in hover.
Source§

fn deprecated_message(&self) -> &'static str

Message for a package-level deprecation/abandonment diagnostic (issue #205). Read more
Source§

fn deprecated_label(&self) -> &'static str

Label for a deprecated package in hover.
§

impl DiagnosticPolicy for GithubActionsFormatter

Source§

fn strict_semver_prerelease_exclusion(&self) -> bool

Whether this ecosystem’s requirement/version syntax follows strict SemVer 2.0.0 pre-release semantics: a pre-release version (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 more
Source§

fn supports_package_rename(&self) -> bool

Whether this ecosystem’s deprecation payload (crate::Deprecation::replacement) is safe to offer as a “Replace with X” rename quickfix. Read more
Source§

fn yanked_diagnostic_applies_to( &self, _dep: &dyn Dependency, _requirement: &VersionReq, ) -> bool

Whether the “requirement satisfiable only by a yanked version” diagnostic (crate::lsp_helpers::requirement_matches_only_yanked) should evaluate requirement at all for this ecosystem. Read more
§

impl OsvNaming for GithubActionsFormatter

§

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>

OSV.dev’s canonical spelling for dep’s package name, or None if this dependency cannot be mapped (e.g. a non-GitHub Swift package). Read more
Source§

fn osv_version_to_native(&self, version: &str) -> String

Converts a version string as it appears in an OSV advisory record (e.g. 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

§

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

Normalize package name for lookup (default: identity).
§

impl PackageRendering for GithubActionsFormatter

§

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

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

Format version string for code action text edit.
§

fn package_url(&self, name: &PackageName) -> String

Get package URL for hover markdown.
Source§

fn format_version_replacing( &self, version: &ConcreteVersion, _current: &str, ) -> String

Format version as a replacement for the existing requirement text current, preserving current’s operator/pin style where the ecosystem supports more than one. Read more
Source§

fn is_position_on_dependency( &self, dep: &dyn Dependency, position: Position, ) -> bool

Detect if cursor position is on a dependency for code actions.
§

impl RequirementResolution for GithubActionsFormatter

§

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

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

Check if a version satisfies a requirement string. Read more
Source§

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.” Read more
Source§

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). Read more
Source§

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. Read more
Source§

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. Read more
Source§

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. Read more
§

impl SourcePolicy for GithubActionsFormatter

Source§

fn can_resolve_source(&self, source: &DependencySource) -> bool

Whether this ecosystem’s registry can resolve version data for source. Read more
Source§

fn source_is_public_registry_content(&self, source: &DependencySource) -> bool

Whether 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 more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> EcosystemFormatter for T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more