use crate::config::IgnoreTarget;
use crate::config::Level;
use crate::domain::action::identity::ActionId;
use crate::domain::file::actions::Located as LocatedAction;
use crate::domain::file::site::{JobId, StepIndex, WorkflowPath};
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Diagnostic<Id> {
pub rule: Id,
pub level: Level,
pub message: String,
pub workflow: Option<WorkflowPath>,
pub job: Option<JobId>,
pub step: Option<StepIndex>,
pub line: Option<u32>,
}
impl<Id> Diagnostic<Id> {
pub fn new<S: Into<String>>(rule: Id, level: Level, message: S) -> Self {
Self {
rule,
level,
message: message.into(),
workflow: None,
job: None,
step: None,
line: None,
}
}
#[must_use]
pub fn with_workflow(mut self, workflow: WorkflowPath) -> Self {
self.workflow = Some(workflow);
self
}
#[must_use]
pub fn with_job(mut self, job: JobId) -> Self {
self.job = Some(job);
self
}
#[must_use]
pub fn with_step(mut self, step: StepIndex) -> Self {
self.step = Some(step);
self
}
#[must_use]
pub fn with_line(mut self, line: Option<u32>) -> Self {
self.line = line;
self
}
}
fn workflow_axis(diag_workflow: Option<&WorkflowPath>, target: &IgnoreTarget) -> bool {
let Some(target_workflow) = &target.workflow else {
return true;
};
diag_workflow.is_some_and(|w| w.as_str().ends_with(target_workflow.as_str()))
}
fn job_axis<Id>(diag: &Diagnostic<Id>, target: &IgnoreTarget) -> bool {
let Some(target_job) = &target.job else {
return true;
};
diag.job
.as_ref()
.is_some_and(|j| j.as_str() == target_job.as_str())
}
fn action_axis(diag_action: Option<&ActionId>, target: &IgnoreTarget) -> bool {
let Some(target_action) = &target.action else {
return true;
};
diag_action.is_some_and(|id| id.as_str() == target_action.as_str())
}
pub fn matches_ignore_workflow<Id>(diag: &Diagnostic<Id>, target: &IgnoreTarget) -> bool {
target.action.is_none()
&& workflow_axis(diag.workflow.as_ref(), target)
&& job_axis(diag, target)
}
pub fn matches_ignore_action<Id>(
diag: &Diagnostic<Id>,
target: &IgnoreTarget,
action: &LocatedAction,
) -> bool {
diag.workflow.is_some()
&& action_axis(Some(&action.action.id), target)
&& workflow_axis(diag.workflow.as_ref(), target)
&& target.job.is_none()
}
pub fn matches_ignore<Id>(
diag: &Diagnostic<Id>,
target: &IgnoreTarget,
located_actions: &[LocatedAction],
) -> bool {
let Some(diag_workflow) = &diag.workflow else {
return false;
};
let diag_action = located_actions
.iter()
.find(|loc| loc.site.file == *diag_workflow)
.map(|loc| &loc.action.id);
action_axis(diag_action, target)
&& workflow_axis(Some(diag_workflow), target)
&& target.job.is_none()
}