compose_idents/lib.rs
1#![allow(clippy::needless_doctest_main)]
2#![doc = include_str!("../snippets/docs.md")]
3
4mod ast;
5mod core;
6mod deprecation;
7mod error;
8mod eval;
9mod funcs;
10mod interpreter;
11mod parse;
12mod resolve;
13mod unique_id;
14
15use crate::ast::ComposeIdentsArgs;
16use crate::deprecation::DeprecationService;
17use crate::interpreter::Interpreter;
18use proc_macro::TokenStream;
19use std::convert::TryInto;
20use syn::parse_macro_input;
21
22/// Compose identifiers from the provided parts and replace their aliases in the code block.
23///
24/// In addition to replacing identifier aliases it replaces tokens like `%alias%` in string
25/// literals (including in doc-attributes).
26///
27/// # Syntax
28///
29/// ```rust,ignore
30/// use compose_idents::compose_idents;
31///
32/// compose_idents!(
33/// // Alias is defined one or more arguments that are supposed to be concatenated
34/// alias1 = [part1, part2],
35/// // Multiple aliases could be defined
36/// // and they could be composed from arbitrary number of arguments
37/// // Which could be identifiers, strings, numbers, underscores or just arbitrary token
38/// // sequences
39/// alias2 = [part3, _, "part4", _, 1],
40/// // Functions could applied to the arguments, calls to functions could be nested
41/// alias3 = [some_func(part5), outer_func(inner_func(part6))],
42/// // ... more aliases
43/// {
44/// // Code block that uses aliases as identifiers
45/// // The aliases will be replaced with their replacements when the code is expanded
46/// let alias1 = 42;
47///
48/// fn alias2() -> u32 { 42 }
49///
50/// // Aliases could be also used for string-formatting using %alias% syntax
51/// #[doc = "Documentation for %alias3%"]
52/// fn alias3() -> u32 { 42 }
53/// },
54/// );
55/// ```
56///
57/// Semicolons could also be used as separators between the macro arguments for
58/// backwards-compatibility. Mixing separator styles in the same macro invocation is not allowed.
59///
60/// # Reference
61///
62#[doc = include_str!("../snippets/reference_h2.md")]
63#[proc_macro]
64pub fn compose_idents(input: TokenStream) -> TokenStream {
65 let deprecation_service = DeprecationService::scoped();
66 let args = parse_macro_input!(input as ComposeIdentsArgs);
67 let interpreter = Interpreter::new(args, deprecation_service);
68 match interpreter.execute() {
69 Ok(ts) => ts.into(),
70 Err(err) => {
71 let syn_err: syn::Error = err.try_into().unwrap_or_else(|_| {
72 syn::Error::new(proc_macro2::Span::call_site(), "Unknown error")
73 });
74 TokenStream::from(syn_err.into_compile_error())
75 }
76 }
77}