yarte_parser/
stmt_local.rs

1use proc_macro2::TokenStream;
2use quote::{quote, ToTokens};
3use syn::{
4    parse::{Parse, ParseStream},
5    punctuated::Punctuated,
6    token::Semi,
7    Expr, Local, Pat, PatOr, PatType, Result, Token, Type,
8};
9
10#[derive(Debug, PartialEq)]
11pub struct StmtLocal {
12    pub let_token: Token![let],
13    pub pat: Pat,
14    pub init: Option<(Token![=], Box<Expr>)>,
15}
16
17// Duplicated https://github.com/dtolnay/syn/blob/master/src/stmt.rs#L216
18impl Parse for StmtLocal {
19    fn parse(input: ParseStream) -> Result<Self> {
20        Ok(StmtLocal {
21            let_token: input.parse()?,
22            pat: {
23                let leading_vert: Option<Token![|]> = input.parse()?;
24                let mut pat: Pat = input.parse()?;
25                if leading_vert.is_some()
26                    || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=])
27                {
28                    let mut cases = Punctuated::new();
29                    cases.push_value(pat);
30                    while input.peek(Token![|])
31                        && !input.peek(Token![||])
32                        && !input.peek(Token![|=])
33                    {
34                        let punct = input.parse()?;
35                        cases.push_punct(punct);
36                        let pat: Pat = input.parse()?;
37                        cases.push_value(pat);
38                    }
39                    pat = Pat::Or(PatOr {
40                        attrs: Vec::new(),
41                        leading_vert,
42                        cases,
43                    });
44                }
45                if input.peek(Token![:]) {
46                    let colon_token: Token![:] = input.parse()?;
47                    let ty: Type = input.parse()?;
48                    pat = Pat::Type(PatType {
49                        attrs: Vec::new(),
50                        pat: Box::new(pat),
51                        colon_token,
52                        ty: Box::new(ty),
53                    });
54                }
55                pat
56            },
57            init: {
58                if input.peek(Token![=]) {
59                    let eq_token: Token![=] = input.parse()?;
60                    let init: Expr = input.parse()?;
61                    Some((eq_token, Box::new(init)))
62                } else {
63                    None
64                }
65            },
66        })
67    }
68}
69
70impl ToTokens for StmtLocal {
71    fn to_tokens(&self, tokens: &mut TokenStream) {
72        let StmtLocal {
73            let_token,
74            pat,
75            init,
76        } = self;
77        if let Some((eq, init)) = init {
78            tokens.extend(quote!(#let_token #pat #eq #init));
79        } else {
80            tokens.extend(quote!(#let_token #pat));
81        }
82    }
83}
84
85// Use for no duplicate code in generator
86impl Into<Local> for StmtLocal {
87    fn into(self) -> Local {
88        Local {
89            let_token: self.let_token,
90            attrs: Vec::new(),
91            pat: self.pat,
92            init: self.init,
93            semi_token: Semi::default(),
94        }
95    }
96}
97
98impl From<Local> for StmtLocal {
99    fn from(local: Local) -> Self {
100        StmtLocal {
101            let_token: local.let_token,
102            pat: local.pat,
103            init: local.init,
104        }
105    }
106}
107
108impl Into<crate::Local> for StmtLocal {
109    fn into(self) -> crate::Local {
110        crate::Local(self.into())
111    }
112}