compose-idents 0.3.0

A Rust macro for generating new identifiers (names of variables, functions, traits, etc) by concatenating one or more arbitrary parts and applying other manipulations.
Documentation
use crate::ast::{AliasSpec, ComposeItemSpec, LoopSpec};
use crate::util::deprecation::DeprecationService;
use crate::util::unique_id::next_unique_id;
use syn::parse::{Parse, ParseStream};
use syn::Token;

impl Parse for ComposeItemSpec {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let loops = if input.peek(Token![for]) {
            Some(input.parse::<LoopSpec>()?)
        } else {
            None
        };

        let spec = if input.peek(syn::Ident) {
            Some(input.parse::<AliasSpec>()?)
        } else {
            None
        };

        let deprecation_service = DeprecationService::scoped();
        if let Some(spec) = &spec {
            if spec.is_comma_used().is_some_and(|v| !v) {
                deprecation_service.add_semicolon_separator_warning();
            }
        }

        let has_comma = input.peek(Token![,]);
        let has_semicolon = input.peek(Token![;]);
        let has_separator = has_comma || has_semicolon;

        if has_separator {
            if spec.is_some() {
                if has_comma {
                    let _ = input.parse::<Token![,]>()?;
                } else {
                    let _ = input.parse::<Token![;]>()?;
                }
            } else if loops.is_some() {
                return Err(input
                    .error("Trailing separator after loops is not allowed in #[compose_item]."));
            }
        }

        Ok(ComposeItemSpec::new(
            next_unique_id(),
            loops.map(std::rc::Rc::new),
            spec.map(std::rc::Rc::new),
        ))
    }
}