1 use proc_macro::TokenStream;
2 use quote::{quote, quote_spanned};
3 use syn::{parse, parse_macro_input, Ident, Token, Visibility};
4 
5 use build_info_common::BuildInfo;
6 
7 mod init_value;
8 use init_value::init_value;
9 
10 struct FunctionSyntax {
11 	definition_crate: Ident,
12 	visibility: Option<Visibility>,
13 	id: Ident,
14 }
15 
16 impl parse::Parse for FunctionSyntax {
parse(input: parse::ParseStream) -> parse::Result<Self>17 	fn parse(input: parse::ParseStream) -> parse::Result<Self> {
18 		let definition_crate = input.parse::<Ident>()?;
19 		let visibility: Option<Visibility> = input.parse().ok();
20 		input.parse::<Token![fn]>()?;
21 		let id = input.parse::<Ident>()?;
22 		Ok(FunctionSyntax {
23 			definition_crate,
24 			visibility,
25 			id,
26 		})
27 	}
28 }
29 
build_info(input: TokenStream, build_info: BuildInfo) -> TokenStream30 pub fn build_info(input: TokenStream, build_info: BuildInfo) -> TokenStream {
31 	let FunctionSyntax {
32 		definition_crate,
33 		visibility,
34 		id,
35 	} = parse_macro_input!(input as FunctionSyntax);
36 	let visibility = visibility.map_or(quote!(), |vis| quote!(#vis));
37 
38 	let mut tokens = proc_macro2::TokenStream::new();
39 	init_value(&build_info, &mut tokens, &definition_crate);
40 
41 	#[allow(clippy::let_and_return)]
42 	let output = quote_spanned! {
43 		proc_macro::Span::mixed_site().into() =>
44 		#visibility fn #id() -> &'static #definition_crate::BuildInfo {
45 			#definition_crate::lazy_static! {
46 				static ref VERSION: #definition_crate::BuildInfo = #tokens;
47 			}
48 			&VERSION
49 		}
50 	};
51 
52 	// println!("{}", output.to_string());
53 	output.into()
54 }
55