1use proc_macro2::{Ident, Punct, Spacing, TokenStream};
19use quote::{quote, quote_spanned, ToTokens};
20
21use crate::parse::*;
22
23pub struct Changes {
24 pub exterior: TokenStream,
25 pub interior: TokenStream,
26 pub exempt: Vec<Ident>,
27}
28
29impl Changes {
30 pub fn from_input(input: &Input, only: bool) -> Changes {
31 let mut exempt = Vec::new();
32 let mut ext = TokenStream::new();
33 let mut int = TokenStream::new();
34
35 for d in &input.assigned {
36 let mu = &d.mu;
37 let mut int_upvar = d.upvar.clone();
38 if only {
39 make_mixed!(int_upvar);
40 }
41 ext.extend(quote!(let #mu #int_upvar = ));
42 match &d.ty {
43 DirectiveType::Clone(sp) => {
44 let sp = *sp;
45 let ext_upvar = &d.upvar;
46 ext.extend(quote_spanned![sp=> ::core::clone::Clone::clone(&#ext_upvar)]);
47 }
48 DirectiveType::With(expr) => {
49 (&expr).to_tokens(&mut ext);
50 }
51 DirectiveType::Ref(sp, mu) => {
52 let mut ref_punc = Punct::new('&', Spacing::Alone);
53 ref_punc.set_span(*sp);
54 let ext_upvar = &d.upvar;
55 ext.extend(quote!(#ref_punc #mu #ext_upvar));
56 }
57 }
58 ext.extend(quote!(;));
59 }
60
61 for d in &input.all {
62 let upvar = &d.upvar;
63 exempt.push(upvar.clone());
64 int.extend(quote!(let _ = &#upvar;));
65 }
66
67 Changes {
68 exterior: ext,
69 interior: int,
70 exempt,
71 }
72 }
73}