use super::*;
#[derive(Debug, Clone, PartialEq)]
pub enum ParameterKind {
Export,
Normal,
Variadic(VariadicType),
}
#[derive(Debug, Clone, PartialEq)]
pub enum VariadicType {
OneOrMore,
ZeroOrMore,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Parameter {
pub content: String,
pub default_value: Option<String>,
pub kind: ParameterKind,
pub name: String,
pub range: lsp::Range,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct ParameterJson {
pub default_value: Option<String>,
pub name: String,
}
impl From<Parameter> for ParameterJson {
fn from(parameter: Parameter) -> Self {
ParameterJson {
name: parameter.name,
default_value: parameter.default_value,
}
}
}
impl Parameter {
#[must_use]
pub fn parse(text: &str, range: lsp::Range) -> Option<Self> {
let parts: Vec<&str> = text.split('=').collect();
let (param_name, default_value) = if parts.len() > 1 {
(
parts[0].trim(),
Some(parts[1..].join("=").trim().to_string()),
)
} else {
(text.trim(), None)
};
if param_name.is_empty() {
return None;
}
let (name, kind) = if let Some(stripped) = param_name.strip_prefix('$') {
(stripped.to_string(), ParameterKind::Export)
} else if let Some(stripped) = param_name.strip_prefix('+') {
(
stripped.to_string(),
ParameterKind::Variadic(VariadicType::OneOrMore),
)
} else if let Some(stripped) = param_name.strip_prefix('*') {
(
stripped.to_string(),
ParameterKind::Variadic(VariadicType::ZeroOrMore),
)
} else {
(param_name.to_string(), ParameterKind::Normal)
};
if name.is_empty() {
return None;
}
Some(Parameter {
name: name.trim().into(),
kind,
default_value,
content: text.trim().to_string(),
range,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_normal_parameter() {
let input = "target";
let range = lsp::Range::at(0, 0, 0, 6);
let param = Parameter::parse(input, range).unwrap();
assert_eq!(
param,
Parameter {
name: "target".to_string(),
kind: ParameterKind::Normal,
default_value: None,
content: "target".to_string(),
range,
}
);
}
#[test]
fn parse_parameter_with_default() {
let input = "tests=\"default\"";
let range = lsp::Range::at(0, 0, 0, 15);
let param = Parameter::parse(input, range).unwrap();
assert_eq!(
param,
Parameter {
name: "tests".to_string(),
kind: ParameterKind::Normal,
default_value: Some("\"default\"".to_string()),
content: "tests=\"default\"".to_string(),
range,
}
);
}
#[test]
fn parse_parameter_with_complex_default() {
let input = "triple=(arch + \"-unknown-unknown\")";
let range = lsp::Range::at(0, 0, 0, 32);
let param = Parameter::parse(input, range).unwrap();
assert_eq!(
param,
Parameter {
name: "triple".to_string(),
kind: ParameterKind::Normal,
default_value: Some("(arch + \"-unknown-unknown\")".to_string()),
content: "triple=(arch + \"-unknown-unknown\")".to_string(),
range,
}
);
}
#[test]
fn parse_export_parameter() {
let input = "$bar";
let range = lsp::Range::at(0, 0, 0, 4);
let param = Parameter::parse(input, range).unwrap();
assert_eq!(
param,
Parameter {
name: "bar".to_string(),
kind: ParameterKind::Export,
default_value: None,
content: "$bar".to_string(),
range,
}
);
}
#[test]
fn parse_variadic_one_or_more_parameter() {
let input = "+FILES";
let range = lsp::Range::at(0, 0, 0, 6);
let param = Parameter::parse(input, range).unwrap();
assert_eq!(
param,
Parameter {
name: "FILES".to_string(),
kind: ParameterKind::Variadic(VariadicType::OneOrMore),
default_value: None,
content: "+FILES".to_string(),
range,
}
);
}
#[test]
fn parse_variadic_zero_or_more_parameter() {
let input = "*FLAGS";
let range = lsp::Range::at(0, 0, 0, 6);
let param = Parameter::parse(input, range).unwrap();
assert_eq!(
param,
Parameter {
name: "FLAGS".to_string(),
kind: ParameterKind::Variadic(VariadicType::ZeroOrMore),
default_value: None,
content: "*FLAGS".to_string(),
range,
}
);
}
#[test]
fn parse_variadic_with_default() {
let input = "+FLAGS='-q'";
let range = lsp::Range::at(0, 0, 0, 12);
let param = Parameter::parse(input, range).unwrap();
assert_eq!(
param,
Parameter {
name: "FLAGS".to_string(),
kind: ParameterKind::Variadic(VariadicType::OneOrMore),
default_value: Some("'-q'".to_string()),
content: "+FLAGS='-q'".to_string(),
range,
}
);
}
#[test]
fn invalid_parameter_input() {
let range = lsp::Range::at(0, 0, 0, 0);
assert_eq!(Parameter::parse("", range), None);
assert_eq!(Parameter::parse("$", range), None);
assert_eq!(Parameter::parse("+", range), None);
assert_eq!(Parameter::parse("*", range), None);
}
}