1use darling::FromMeta;
2use lazy_static::lazy_static;
3use lib::{Level, Mode};
4use proc_macro::TokenStream;
5use proc_macro_error::{emit_error, emit_warning, proc_macro_error};
6use syn::{parse_macro_input, spanned::Spanned, AttributeArgs};
7
8#[cfg(not(debug_assertions))]
9lazy_static! {
10 static ref MODE: Mode = lib::get_mode().unwrap_or(Mode::Noop);
11}
12
13#[cfg(debug_assertions)]
14lazy_static! {
15 static ref MODE: Mode = lib::get_mode().unwrap_or(Mode::Emit(Level::Warn));
16}
17
18#[proc_macro_error]
21#[proc_macro_attribute]
22pub fn track(args: TokenStream, input: TokenStream) -> TokenStream {
23 let attr_args = parse_macro_input!(args as AttributeArgs);
24
25 let issue: lib::Issue = match Issue::from_list(&attr_args) {
26 Ok(v) => v.into(),
27 Err(e) => {
28 return TokenStream::from(e.write_errors());
29 }
30 };
31
32 match *MODE {
33 Mode::Noop => (),
34 Mode::Pipe => println!(
35 "{}",
36 serde_json::to_string(&issue).expect("serializing issue")
37 ),
38 Mode::Emit(Level::Warn) => match issue.is_closed() {
39 Err(e) => {
40 emit_warning!(
41 attr_args[0].span(),
42 "unable to access {}\n {}",
43 issue.url,
44 e
45 )
46 }
47 Ok(true) => {
48 emit_warning!(attr_args[0].span(), "issue {} has been closed", issue.url)
49 }
50 _ => (),
51 },
52 Mode::Emit(Level::Error) => match issue.is_closed() {
53 Err(e) => {
54 emit_error!(
55 attr_args[0].span(),
56 "unable to access {}\n {}",
57 issue.url,
58 e
59 )
60 }
61 Ok(true) => {
62 emit_error!(attr_args[0].span(), "issue {} has been closed", issue.url)
63 }
64 _ => (),
65 },
66 }
67 input
68}
69
70#[derive(Default, Debug, FromMeta, serde::Serialize)]
71#[darling(default)]
72struct Issue {
73 pub url: String,
74}
75
76impl From<Issue> for lib::Issue {
77 fn from(issue: Issue) -> Self {
78 lib::Issue { url: issue.url }
79 }
80}