syn_solidity/item/
pragma.rs

1use crate::{kw, utils::tts_until_semi, SolIdent, Spanned};
2use proc_macro2::{Span, TokenStream};
3use std::fmt;
4use syn::{
5    parse::{Parse, ParseStream},
6    Result, Token,
7};
8
9/// A pragma directive: `pragma solidity ^0.8.0;`
10#[derive(Clone)]
11pub struct PragmaDirective {
12    pub pragma_token: kw::pragma,
13    pub tokens: PragmaTokens,
14    pub semi_token: Token![;],
15}
16
17impl fmt::Display for PragmaDirective {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        write!(f, "pragma {};", self.tokens)
20    }
21}
22
23impl fmt::Debug for PragmaDirective {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        f.debug_tuple("PragmaDirective").field(&self.tokens).finish()
26    }
27}
28
29impl Parse for PragmaDirective {
30    fn parse(input: ParseStream<'_>) -> Result<Self> {
31        Ok(Self {
32            pragma_token: input.parse()?,
33            tokens: input.parse()?,
34            semi_token: input.parse()?,
35        })
36    }
37}
38
39impl Spanned for PragmaDirective {
40    fn span(&self) -> Span {
41        let span = self.pragma_token.span;
42        span.join(self.semi_token.span).unwrap_or(span)
43    }
44
45    fn set_span(&mut self, span: Span) {
46        self.pragma_token.span = span;
47        self.tokens.set_span(span);
48        self.semi_token.span = span;
49    }
50}
51
52#[derive(Clone, Debug)]
53pub enum PragmaTokens {
54    Version(kw::solidity, TokenStream),
55    Abicoder(kw::abicoder, SolIdent),
56    Experimental(kw::experimental, SolIdent),
57    Verbatim(TokenStream),
58}
59
60impl fmt::Display for PragmaTokens {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        match self {
63            Self::Version(_, version) => write!(f, "solidity {version}"),
64            Self::Abicoder(_, ident) => write!(f, "abicoder {ident}"),
65            Self::Experimental(_, ident) => write!(f, "experimental {ident}"),
66            Self::Verbatim(tokens) => tokens.fmt(f),
67        }
68    }
69}
70
71impl Parse for PragmaTokens {
72    fn parse(input: ParseStream<'_>) -> Result<Self> {
73        if input.peek(kw::solidity) {
74            let solidity = input.parse()?;
75            let version = tts_until_semi(input);
76            Ok(Self::Version(solidity, version))
77        } else if input.peek(kw::abicoder) {
78            let abicoder = input.parse()?;
79            let ident = input.parse()?;
80            Ok(Self::Abicoder(abicoder, ident))
81        } else if input.peek(kw::experimental) {
82            let experimental = input.parse()?;
83            let ident = input.parse()?;
84            Ok(Self::Experimental(experimental, ident))
85        } else {
86            Ok(Self::Verbatim(tts_until_semi(input)))
87        }
88    }
89}
90
91impl Spanned for PragmaTokens {
92    fn span(&self) -> Span {
93        match self {
94            Self::Version(solidity, version) => {
95                let span = solidity.span;
96                span.join(version.span()).unwrap_or(span)
97            }
98            Self::Abicoder(abicoder, ident) => {
99                let span = abicoder.span;
100                span.join(ident.span()).unwrap_or(span)
101            }
102            Self::Experimental(experimental, ident) => {
103                let span = experimental.span;
104                span.join(ident.span()).unwrap_or(span)
105            }
106            Self::Verbatim(tokens) => tokens.span(),
107        }
108    }
109
110    fn set_span(&mut self, span: Span) {
111        match self {
112            Self::Version(solidity, _version) => {
113                solidity.span = span;
114            }
115            Self::Abicoder(abicoder, ident) => {
116                abicoder.span = span;
117                ident.set_span(span);
118            }
119            Self::Experimental(experimental, ident) => {
120                experimental.span = span;
121                ident.set_span(span);
122            }
123            Self::Verbatim(_tokens) => {}
124        }
125    }
126}