use convert_case::Casing;
use proc_macro2::TokenStream;
use syn::__private::ToTokens;
use syn::{Ident, LitStr};
#[derive(Clone, Debug, PartialEq)]
pub struct FieldExpression {
pub(crate) field: Ident,
pub(crate) syntax_type: OutputFormat,
pub(crate) prefix: String,
pub(crate) suffix: String,
}
impl FieldExpression {
#[cfg(test)]
pub(crate) fn new(field: Ident) -> Self {
Self {
field,
syntax_type: OutputFormat::LitOrIdent,
prefix: "".to_string(),
suffix: "".to_string(),
}
}
pub fn require_neighbours(&self) -> bool {
false
}
pub fn write_output(&self, value: &SelectedValue) -> syn::Result<TokenStream> {
let output = match self.syntax_type {
OutputFormat::IdentConverted(case) => {
let string = format!("{}{}{}", self.prefix, value.0.to_case(case), self.suffix);
let string = if string.is_empty() {
"none".to_string()
} else {
string
};
let mut ident = syn::parse_str::<syn::Ident>(&string)
.map_err(|err| syn::Error::new(self.field.span(), err))?;
ident.set_span(self.field.span());
ident.to_token_stream()
}
OutputFormat::LitStr => {
let string = format!("{}{}{}", self.prefix, value.0, self.suffix);
LitStr::new(&string, self.field.span()).to_token_stream()
}
OutputFormat::LitOrIdent => {
let string = format!("{}{}{}", self.prefix, value.0, self.suffix);
if let Ok(mut lit) = syn::parse_str::<syn::Lit>(&string) {
lit.set_span(self.field.span());
lit.to_token_stream()
} else if let Ok(mut ident) = syn::parse_str::<syn::Ident>(&string) {
ident.set_span(self.field.span());
ident.to_token_stream()
} else {
syn::parse_str(&string)
.map_err(|err| syn::Error::new(self.field.span(), err))?
}
}
};
Ok(output)
}
pub(crate) fn field_ident(&self) -> &Ident {
&self.field
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum OutputFormat {
IdentConverted(convert_case::Case<'static>),
LitStr,
LitOrIdent,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Ord)]
pub struct SelectedValue(pub String);