syn_solidity/stmt/
var_decl.rs1use crate::{Expr, Spanned, Stmt, VariableDeclaration, utils::DebugPunctuated};
2use proc_macro2::Span;
3use std::fmt;
4use syn::{
5 Result, Token, parenthesized,
6 parse::{Parse, ParseStream, discouraged::Speculative},
7 punctuated::Punctuated,
8 token::Paren,
9};
10
11#[derive(Clone)]
16pub struct StmtVarDecl {
17 pub declaration: VarDeclDecl,
18 pub assignment: Option<(Token![=], Expr)>,
19 pub semi_token: Token![;],
20}
21
22impl fmt::Debug for StmtVarDecl {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 f.debug_struct("StmtVarDecl")
25 .field("declaration", &self.declaration)
26 .field("assignment", &self.assignment)
27 .finish()
28 }
29}
30
31impl Parse for StmtVarDecl {
32 fn parse(input: ParseStream<'_>) -> Result<Self> {
33 let declaration: VarDeclDecl = input.parse()?;
34
35 let assignment = if matches!(declaration, VarDeclDecl::Tuple(_)) || input.peek(Token![=]) {
37 Some((input.parse()?, input.parse()?))
38 } else {
39 None
40 };
41
42 let semi_token = input.parse()?;
43
44 Ok(Self { declaration, assignment, semi_token })
45 }
46}
47
48impl Spanned for StmtVarDecl {
49 fn span(&self) -> Span {
50 let span = self.declaration.span();
51 self.assignment.as_ref().and_then(|(_, expr)| expr.span().join(span)).unwrap_or(span)
52 }
53
54 fn set_span(&mut self, span: Span) {
55 self.declaration.set_span(span);
56 if let Some((eq, expr)) = &mut self.assignment {
57 eq.span = span;
58 expr.set_span(span);
59 }
60 self.semi_token.span = span;
61 }
62}
63
64impl StmtVarDecl {
65 pub fn parse_or_expr(input: ParseStream<'_>) -> Result<Stmt> {
66 let speculative_parse = || {
68 let fork = input.fork();
69 match fork.parse() {
70 Ok(var) => {
71 input.advance_to(&fork);
72 Ok(Stmt::VarDecl(var))
73 }
74 Err(_) => input.parse().map(Stmt::Expr),
75 }
76 };
77
78 if input.peek(Paren) {
79 if input.peek2(Token![=]) { speculative_parse() } else { input.parse().map(Stmt::Expr) }
80 } else {
81 speculative_parse()
82 }
83 }
84}
85
86#[derive(Clone, Debug)]
88pub enum VarDeclDecl {
89 VarDecl(VariableDeclaration),
90 Tuple(VarDeclTuple),
91}
92
93impl Parse for VarDeclDecl {
94 fn parse(input: ParseStream<'_>) -> Result<Self> {
95 if input.peek(Paren) {
96 input.parse().map(Self::Tuple)
97 } else {
98 VariableDeclaration::parse_with_name(input).map(Self::VarDecl)
99 }
100 }
101}
102
103impl Spanned for VarDeclDecl {
104 fn span(&self) -> Span {
105 match self {
106 Self::VarDecl(decl) => decl.span(),
107 Self::Tuple(decl) => decl.span(),
108 }
109 }
110
111 fn set_span(&mut self, span: Span) {
112 match self {
113 Self::VarDecl(decl) => decl.set_span(span),
114 Self::Tuple(decl) => decl.set_span(span),
115 }
116 }
117}
118
119#[derive(Clone)]
124pub struct VarDeclTuple {
125 pub paren_token: Paren,
126 pub vars: Punctuated<Option<VariableDeclaration>, Token![,]>,
129}
130
131impl fmt::Debug for VarDeclTuple {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 f.debug_struct("VarDeclTuple").field("vars", DebugPunctuated::new(&self.vars)).finish()
134 }
135}
136
137impl Parse for VarDeclTuple {
138 fn parse(input: ParseStream<'_>) -> Result<Self> {
139 let content;
140 Ok(Self {
141 paren_token: parenthesized!(content in input),
142 vars: content.parse_terminated(Self::parse_var_opt, Token![,])?,
143 })
144 }
145}
146
147impl Spanned for VarDeclTuple {
148 fn span(&self) -> Span {
149 self.paren_token.span.join()
150 }
151
152 fn set_span(&mut self, span: Span) {
153 self.paren_token = Paren(span);
154 }
155}
156
157impl VarDeclTuple {
158 fn parse_var_opt(input: ParseStream<'_>) -> Result<Option<VariableDeclaration>> {
159 if input.peek(Token![,]) { Ok(None) } else { input.parse().map(Some) }
160 }
161}