derive_deftly_macros/
accum.rs1use super::framework::*;
4use adviseable::*;
5
6#[derive(Debug)]
11pub struct EngineFinalInput {
12 driver: syn::DeriveInput,
13 accum: Accumulated,
14}
15
16#[derive(Debug)]
17pub struct Accumulated {
18 metas: meta::CheckUsed<meta::Accum>,
19}
20
21impl EngineFinalInput {
22 pub fn parse_adviseable_remainder(
23 driver: syn::DeriveInput,
24 input: ParseStream,
25 ) -> AdviseableResult<Self> {
26 let _empty_next_brackets_contents;
27 let _ = bracketed!(_empty_next_brackets_contents in input);
28
29 let accum;
30 let _ = bracketed!(accum in input);
31 let accum = accum.parse()?;
32
33 let _: TokenStream = input.parse()?;
34
35 Ok(AOk(EngineFinalInput { driver, accum }))
36 }
37}
38
39impl Parse for Accumulated {
40 fn parse(input: ParseStream) -> syn::Result<Self> {
41 use meta::CheckUsed as mCU;
42
43 let mut metas = mCU::Check(meta::Accum::default());
44
45 struct Ignore;
46
47 while !input.is_empty() {
48 let kind: syn::Ident = input.parse()?;
49 match if kind == "_meta_used" {
50 if let mCU::Check(m) = &mut metas {
51 match input.parse()? {
52 mCU::Check(y) => m.used.push(y),
53 mCU::Unchecked => metas = mCU::Unchecked,
54 }
55 continue;
56 } else {
57 Ignore
58 }
59 } else if kind == "_meta_recog" {
60 if let mCU::Check(m) = &mut metas {
61 let content;
62 let _brackets = bracketed!(content in input);
63 let input = content;
64 while !input.is_empty() {
65 let allow = match input.parse()? {
66 Some::<proc_macro2::Punct>(p) => {
67 match p.as_char() {
68 '?' => meta::Usage::BOOL_ONLY,
69 '+' => meta::Usage::VALUE_ONLY,
70 _other => return Err(p.error(
71 "unrecognised _meta_recog usage mode",
72 )),
73 }
74 }
75 None => meta::Usage::VALUE,
76 };
77 let desig = input.parse()?;
78 m.recog.update(desig, allow);
79 }
80 continue;
81 } else {
82 Ignore
83 }
84 } else if kind == "error" {
85 metas = mCU::Unchecked;
86 Ignore
87 } else if kind.to_string().starts_with('_') {
88 Ignore
89 } else {
90 return Err(
91 kind.error("unrecognised mandatory accumulation kind")
92 );
93 } {
94 Ignore => {
95 let _: TokenTree = input.parse()?;
96 }
97 }
98 }
99 Ok(Accumulated { metas })
100 }
101}
102
103impl EngineFinalInput {
104 pub fn process(self) -> syn::Result<TokenStream> {
105 let r = Context::call(
106 &self.driver,
107 &dummy_path(), None, |ctx| {
110 if let mCU::Check(m) = &self.accum.metas {
111 for group in &m.used {
112 adviseable_parse2_call(
113 group.content.clone(),
114 |input| {
115 ctx.decode_update_metas_used(input)?;
116 Ok(AOk(()))
117 },
118 )?
119 }
120 }
121
122 let mut errors = ErrorAccumulator::default();
123
124 if let mCU::Check(m) = &self.accum.metas {
125 ctx.check_metas_used(&mut errors, &m.recog);
126 }
127 errors.finish()
128 },
129 );
130
131 let mut out = TokenStream::new();
132
133 match r {
134 Ok(()) => {}
135 Err(e) => e.into_compile_error().to_tokens(&mut out),
136 }
137
138 Ok(out)
139 }
140}