syn_solidity/stmt/
try.rs

1use crate::{Block, Expr, ParameterList, Returns, SolIdent, Spanned, kw};
2use proc_macro2::Span;
3use std::fmt;
4use syn::{
5    Result, Token, parenthesized,
6    parse::{Parse, ParseStream},
7    token::Paren,
8};
9
10/// A try statement: `try fooBar(42) catch { ... }`.
11///
12/// Solidity reference:
13/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.tryStatement>
14#[derive(Clone)]
15pub struct StmtTry {
16    pub try_token: Token![try],
17    pub expr: Box<Expr>,
18    pub returns: Option<Returns>,
19    /// The try block.
20    pub block: Block,
21    /// The list of catch clauses. Cannot be parsed empty.
22    pub catch: Vec<CatchClause>,
23}
24
25impl fmt::Debug for StmtTry {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        f.debug_struct("StmtTry")
28            .field("expr", &self.expr)
29            .field("returns", &self.returns)
30            .field("block", &self.block)
31            .field("catch", &self.catch)
32            .finish()
33    }
34}
35
36impl Parse for StmtTry {
37    fn parse(input: ParseStream<'_>) -> Result<Self> {
38        Ok(Self {
39            try_token: input.parse()?,
40            expr: input.parse()?,
41            returns: input.call(Returns::parse_opt)?,
42            block: input.parse()?,
43            catch: {
44                let mut catch = Vec::new();
45                let mut first = true;
46                while first || input.peek(kw::catch) {
47                    first = false;
48                    catch.push(input.parse()?);
49                }
50                catch
51            },
52        })
53    }
54}
55
56impl Spanned for StmtTry {
57    fn span(&self) -> Span {
58        let span = self.try_token.span;
59        span.join(self.block.span()).unwrap_or(span)
60    }
61
62    fn set_span(&mut self, span: Span) {
63        self.try_token.span = span;
64        self.block.set_span(span);
65    }
66}
67
68/// A catch clause of a [`StmtTry`]: `catch  { ... }`.
69///
70/// Solidity reference:
71/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.tryStatement>
72#[derive(Clone)]
73pub struct CatchClause {
74    pub catch_token: kw::catch,
75    pub name: Option<SolIdent>,
76    pub paren_token: Option<Paren>,
77    pub list: ParameterList,
78    pub block: Block,
79}
80
81impl fmt::Debug for CatchClause {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        f.debug_struct("CatchClause")
84            .field("name", &self.name)
85            .field("list", &self.list)
86            .field("block", &self.block)
87            .finish()
88    }
89}
90
91impl Parse for CatchClause {
92    fn parse(input: ParseStream<'_>) -> Result<Self> {
93        let catch_token = input.parse()?;
94        let name = input.call(SolIdent::parse_opt)?;
95        let (paren_token, list) = if input.peek(Paren) {
96            let content;
97            (Some(parenthesized!(content in input)), content.parse()?)
98        } else {
99            (None, ParameterList::new())
100        };
101        let block = input.parse()?;
102        Ok(Self { catch_token, name, paren_token, list, block })
103    }
104}
105
106impl Spanned for CatchClause {
107    fn span(&self) -> Span {
108        let span = self.catch_token.span;
109        span.join(self.block.span()).unwrap_or(span)
110    }
111
112    fn set_span(&mut self, span: Span) {
113        self.catch_token.span = span;
114        self.block.set_span(span);
115    }
116}