sway_ast/item/
mod.rs

1use sway_error::handler::ErrorEmitted;
2
3use crate::priv_prelude::*;
4
5pub mod item_abi;
6pub mod item_configurable;
7pub mod item_const;
8pub mod item_enum;
9pub mod item_fn;
10pub mod item_impl;
11pub mod item_storage;
12pub mod item_struct;
13pub mod item_trait;
14pub mod item_type_alias;
15pub mod item_use;
16
17pub type Item = Annotated<ItemKind>;
18
19impl Spanned for Item {
20    fn span(&self) -> Span {
21        match self.attributes.first() {
22            Some(attr0) => Span::join(attr0.span(), &self.value.span()),
23            None => self.value.span(),
24        }
25    }
26}
27
28#[allow(clippy::large_enum_variant)]
29#[derive(Clone, Debug, Serialize)]
30pub enum ItemKind {
31    Submodule(Submodule),
32    Use(ItemUse),
33    Struct(ItemStruct),
34    Enum(ItemEnum),
35    Fn(ItemFn),
36    Trait(ItemTrait),
37    Impl(ItemImpl),
38    Abi(ItemAbi),
39    Const(ItemConst),
40    Storage(ItemStorage),
41    Configurable(ItemConfigurable),
42    TypeAlias(ItemTypeAlias),
43    // to handle parser recovery: Error represents an incomplete item
44    Error(Box<[Span]>, #[serde(skip_serializing)] ErrorEmitted),
45}
46
47impl ItemKind {
48    /// [ItemKind]'s friendly name string used for various reportings.
49    ///
50    /// Note that all friendly names are lowercase.
51    /// This is also the case for names containing acronyms like ABI.
52    /// For contexts in which acronyms need to be uppercase, like
53    /// e.g., error reporting, use `friendly_name_with_acronym` instead.
54    pub fn friendly_name(&self) -> &'static str {
55        use ItemKind::*;
56        match self {
57            Submodule(_) => "submodule (`mod`)",
58            Use(_) => "import (`use`)",
59            Struct(_) => "struct declaration",
60            Enum(_) => "enum declaration",
61            Fn(_) => "function declaration",
62            Trait(_) => "trait declaration",
63            Impl(item_impl) => match item_impl.trait_opt {
64                Some(_) => "ABI or trait implementation",
65                None => "inherent implementation",
66            },
67            Abi(_) => "abi declaration",
68            Const(_) => "constant declaration",
69            Storage(_) => "contract storage declaration",
70            Configurable(_) => "configurable declaration",
71            TypeAlias(_) => "type alias declaration",
72            Error(..) => "error",
73        }
74    }
75
76    pub fn friendly_name_with_acronym(&self) -> &'static str {
77        match self.friendly_name() {
78            "abi declaration" => "ABI declaration",
79            friendly_name => friendly_name,
80        }
81    }
82}
83
84impl Spanned for ItemKind {
85    fn span(&self) -> Span {
86        match self {
87            ItemKind::Submodule(item_mod) => item_mod.span(),
88            ItemKind::Use(item_use) => item_use.span(),
89            ItemKind::Struct(item_struct) => item_struct.span(),
90            ItemKind::Enum(item_enum) => item_enum.span(),
91            ItemKind::Fn(item_fn) => item_fn.span(),
92            ItemKind::Trait(item_trait) => item_trait.span(),
93            ItemKind::Impl(item_impl) => item_impl.span(),
94            ItemKind::Abi(item_abi) => item_abi.span(),
95            ItemKind::Const(item_const) => item_const.span(),
96            ItemKind::Storage(item_storage) => item_storage.span(),
97            ItemKind::Configurable(item_configurable) => item_configurable.span(),
98            ItemKind::TypeAlias(item_type_alias) => item_type_alias.span(),
99            ItemKind::Error(spans, _) => Span::join_all(spans.iter().cloned()),
100        }
101    }
102}
103
104#[derive(Clone, Debug, Serialize)]
105pub struct TypeField {
106    pub visibility: Option<PubToken>,
107    pub name: Ident,
108    pub colon_token: ColonToken,
109    pub ty: Ty,
110}
111
112impl Spanned for TypeField {
113    fn span(&self) -> Span {
114        let start = match &self.visibility {
115            Some(pub_token) => pub_token.span(),
116            None => self.name.span(),
117        };
118        let end = self.ty.span();
119        Span::join(start, &end)
120    }
121}
122
123#[derive(Clone, Debug, Serialize)]
124pub enum FnArgs {
125    Static(Punctuated<FnArg, CommaToken>),
126    NonStatic {
127        self_token: SelfToken,
128        ref_self: Option<RefToken>,
129        mutable_self: Option<MutToken>,
130        args_opt: Option<(CommaToken, Punctuated<FnArg, CommaToken>)>,
131    },
132}
133
134impl FnArgs {
135    /// Returns all the [FnArg]s, from the function signature defined by `self`.
136    ///
137    /// If the `self` is [FnArgs::NonStatic], the first `self` argument is not
138    /// returned, because it is not an [FnArg].
139    pub fn args(&self) -> Vec<&FnArg> {
140        match self {
141            Self::Static(punctuated) => punctuated.iter().collect(),
142            Self::NonStatic { args_opt, .. } => args_opt
143                .as_ref()
144                .map_or(vec![], |(_comma_token, punctuated)| {
145                    punctuated.iter().collect()
146                }),
147        }
148    }
149
150    /// Returns all the [FnArg]s, from the function signature defined by `self`.
151    ///
152    /// If the `self` is [FnArgs::NonStatic], the first `self` argument is not
153    /// returned, because it is not an [FnArg].
154    pub fn args_mut(&mut self) -> Vec<&mut FnArg> {
155        match self {
156            Self::Static(punctuated) => punctuated.iter_mut().collect(),
157            Self::NonStatic { args_opt, .. } => args_opt
158                .as_mut()
159                .map_or(vec![], |(_comma_token, punctuated)| {
160                    punctuated.iter_mut().collect()
161                }),
162        }
163    }
164}
165
166#[derive(Clone, Debug, Serialize)]
167pub struct FnArg {
168    pub pattern: Pattern,
169    pub colon_token: ColonToken,
170    pub ty: Ty,
171}
172
173impl Spanned for FnArg {
174    fn span(&self) -> Span {
175        Span::join(self.pattern.span(), &self.ty.span())
176    }
177}
178
179#[derive(Clone, Debug, Serialize)]
180pub struct FnSignature {
181    pub visibility: Option<PubToken>,
182    pub fn_token: FnToken,
183    pub name: Ident,
184    pub generics: Option<GenericParams>,
185    pub arguments: Parens<FnArgs>,
186    pub return_type_opt: Option<(RightArrowToken, Ty)>,
187    pub where_clause_opt: Option<WhereClause>,
188}
189
190impl Spanned for FnSignature {
191    fn span(&self) -> Span {
192        let start = match &self.visibility {
193            Some(pub_token) => pub_token.span(),
194            None => self.fn_token.span(),
195        };
196        let end = match &self.where_clause_opt {
197            Some(where_clause) => where_clause.span(),
198            None => match &self.return_type_opt {
199                Some((_right_arrow, ty)) => ty.span(),
200                None => self.arguments.span(),
201            },
202        };
203        Span::join(start, &end)
204    }
205}
206
207#[derive(Clone, Debug, Serialize)]
208pub struct TraitType {
209    pub name: Ident,
210    pub type_token: TypeToken,
211    pub eq_token_opt: Option<EqToken>,
212    pub ty_opt: Option<Ty>,
213    pub semicolon_token: SemicolonToken,
214}
215
216impl Spanned for TraitType {
217    fn span(&self) -> Span {
218        let start = self.type_token.span();
219        let end = match &self.ty_opt {
220            Some(ty_opt) => ty_opt.span(),
221            None => self.name.span(),
222        };
223        Span::join(start, &end)
224    }
225}