ruleset-macros 1.0.0

This crate shouldn't be used directly. Check `ruleset`.
Documentation
use crate::replacements::*;
use proc_macro2::TokenStream;
use quote::quote_spanned;
use quote::ToTokens;
use std::fmt::Display;
use syn::parse::Parse;
use syn::spanned::Spanned;
use syn::visit_mut::VisitMut;
use syn::Expr;
use syn::Token;

#[derive(Debug)]
pub enum Consequent {
	Placeholder { original: TokenStream },
	Value { dots: usize, value: Expr, original: TokenStream },
}

impl Parse for Consequent {
	fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
		let mut original = TokenStream::new();

		if let Ok(token) = input.parse::<Token![_]>() {
			original.extend(token.into_token_stream());
			if let Ok(token) = input.parse::<Token![.]>() {
				original.extend(token.into_token_stream());
				let mut dots = 1;
				while let (Ok(token0), Ok(token1)) =
					(input.parse::<Token![_]>(), input.parse::<Token![.]>())
				{
					original.extend(token0.into_token_stream());
					original.extend(token1.into_token_stream());
					dots += 1;
				}
				let mut value = input.parse::<Expr>()?;
				original.extend(value.to_token_stream());
				ReplaceExprTry.visit_expr_mut(&mut value);
				Ok(Self::Value { dots, value, original })
			} else {
				Ok(Self::Placeholder { original })
			}
		} else {
			let mut value = input.parse::<Expr>()?;
			original.extend(value.to_token_stream());
			ReplaceExprTry.visit_expr_mut(&mut value);
			Ok(Self::Value { dots: 0, value, original })
		}
	}
}

impl ToTokens for Consequent {
	fn to_tokens(&self, tokens: &mut TokenStream) {
		match self {
			Self::Placeholder { original } | Self::Value { original, .. } =>
				tokens.extend(original.clone()),
		}
	}
}

impl Display for Consequent {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		Display::fmt(&self.to_token_stream().to_string(), f)
	}
}

impl Consequent {
	pub fn is_placeholder(&self) -> bool { matches!(self, Self::Placeholder { .. }) }

	pub fn len(&self) -> usize {
		match self {
			Self::Placeholder { .. } => 1,
			Self::Value { dots, .. } => *dots + 1,
		}
	}

	pub fn expand(&self, width_override: Option<usize>) -> TokenStream {
		match self {
			Self::Placeholder { .. } => quote_spanned! {
				self.span() =>
				std::option::Option::None
			},
			Self::Value { dots, value, .. } => {
				let width = width_override.unwrap_or_else(|| *dots + 1);
				quote_spanned! {
					self.span() =>
					std::option::Option::Some(ruleset::Consequent::try_from((#width, #value)).unwrap())
				}
			}
		}
	}
}