use super::RstestDetectionOptions;
use crate::attributes::Attribute;
use std::collections::BTreeSet;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ParameterBinding {
Ident(String),
Unsupported,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RstestParameter {
binding: ParameterBinding,
attributes: Vec<Attribute>,
}
impl RstestParameter {
#[must_use]
pub fn new(binding: ParameterBinding, attributes: Vec<Attribute>) -> Self {
Self {
binding,
attributes,
}
}
#[must_use]
pub fn ident(name: impl Into<String>) -> Self {
Self::new(ParameterBinding::Ident(name.into()), Vec::new())
}
#[must_use]
pub fn unsupported() -> Self {
Self::new(ParameterBinding::Unsupported, Vec::new())
}
#[must_use]
pub const fn binding(&self) -> &ParameterBinding {
&self.binding
}
#[must_use]
pub fn attributes(&self) -> &[Attribute] {
&self.attributes
}
#[must_use]
pub fn binding_name(&self) -> Option<&str> {
match &self.binding {
ParameterBinding::Ident(name) => Some(name),
ParameterBinding::Unsupported => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RstestParameterKind {
FixtureLocal { name: String },
Provider,
UnsupportedPattern,
}
#[must_use]
pub fn classify_rstest_parameter(
parameter: &RstestParameter,
options: &RstestDetectionOptions,
) -> RstestParameterKind {
match parameter.binding() {
ParameterBinding::Ident(name) => {
if parameter_has_provider_attribute(parameter.attributes(), options) {
RstestParameterKind::Provider
} else {
RstestParameterKind::FixtureLocal { name: name.clone() }
}
}
ParameterBinding::Unsupported => RstestParameterKind::UnsupportedPattern,
}
}
#[must_use]
pub fn fixture_local_names(
parameters: &[RstestParameter],
options: &RstestDetectionOptions,
) -> BTreeSet<String> {
parameters
.iter()
.filter_map(
|parameter| match classify_rstest_parameter(parameter, options) {
RstestParameterKind::FixtureLocal { name } => Some(name),
RstestParameterKind::Provider | RstestParameterKind::UnsupportedPattern => None,
},
)
.collect()
}
fn parameter_has_provider_attribute(
attributes: &[Attribute],
options: &RstestDetectionOptions,
) -> bool {
attributes.iter().any(|attribute| {
options.provider_param_attributes().iter().any(|candidate| {
attribute
.path()
.matches(candidate.segments().iter().map(String::as_str))
})
})
}