syn_solidity/stmt/
try.rs

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