sway_parse/item/
item_impl.rs

1use crate::{Parse, ParseResult, Parser};
2
3use sway_ast::attribute::Annotated;
4use sway_ast::keywords::{
5    ConstToken, FnToken, OpenAngleBracketToken, SemicolonToken, TypeToken, WhereToken,
6};
7use sway_ast::{Braces, GenericParams, ItemImpl, ItemImplItem, PubToken, Ty};
8use sway_error::parser_error::ParseErrorKind;
9
10impl Parse for ItemImplItem {
11    fn parse(parser: &mut Parser) -> ParseResult<ItemImplItem> {
12        if parser.peek::<FnToken>().is_some()
13            || (parser.peek::<PubToken>().is_some() && parser.peek_next::<FnToken>().is_some())
14        {
15            let fn_decl = parser.parse()?;
16            Ok(ItemImplItem::Fn(fn_decl))
17        } else if parser.peek::<ConstToken>().is_some()
18            || (parser.peek::<PubToken>().is_some() && parser.peek_next::<ConstToken>().is_some())
19        {
20            let const_decl = parser.parse()?;
21            parser.parse::<SemicolonToken>()?;
22            Ok(ItemImplItem::Const(const_decl))
23        } else if let Some(_type_keyword) = parser.peek::<TypeToken>() {
24            let type_decl = parser.parse()?;
25            parser.parse::<SemicolonToken>()?;
26            Ok(ItemImplItem::Type(type_decl))
27        } else {
28            Err(parser.emit_error(ParseErrorKind::ExpectedAnItem))
29        }
30    }
31}
32
33impl Parse for ItemImpl {
34    fn parse(parser: &mut Parser) -> ParseResult<ItemImpl> {
35        let impl_token = parser.parse()?;
36        let generic_params_opt = parser.guarded_parse::<OpenAngleBracketToken, GenericParams>()?;
37        let ty = parser.parse::<Ty>()?;
38        let (trait_opt, ty) = match parser.take() {
39            Some(for_token) => match ty {
40                Ty::Path(path_type) => (Some((path_type, for_token)), parser.parse()?),
41                _ => {
42                    return Err(parser.emit_error(ParseErrorKind::ExpectedPathType));
43                }
44            },
45            None => (None, ty),
46        };
47        let where_clause_opt = parser.guarded_parse::<WhereToken, _>()?;
48        let contents: Braces<Vec<Annotated<ItemImplItem>>> = parser.parse()?;
49        if trait_opt.is_some() {
50            for annotated in contents.get().iter() {
51                if let ItemImplItem::Fn(item_fn) = &annotated.value {
52                    parser.ban_visibility_qualifier(&item_fn.fn_signature.visibility)?;
53                }
54            }
55        }
56        Ok(ItemImpl {
57            impl_token,
58            generic_params_opt,
59            trait_opt,
60            ty,
61            where_clause_opt,
62            contents,
63        })
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70    use crate::test_utils::parse;
71    use assert_matches::*;
72
73    #[test]
74    fn parse_impl_ptr() {
75        let item = parse::<ItemImpl>(
76            r#"
77            impl __ptr[T] {}
78            "#,
79        );
80        assert_matches!(item.ty, Ty::Ptr { .. });
81    }
82
83    #[test]
84    fn parse_impl_for_ptr() {
85        let item = parse::<ItemImpl>(
86            r#"
87            impl Foo for __ptr[T] {}
88            "#,
89        );
90        assert_matches!(item.ty, Ty::Ptr { .. });
91    }
92
93    #[test]
94    fn parse_impl_slice() {
95        // deprecated syntax
96        let item = parse::<ItemImpl>("impl __slice[T] {}");
97        assert_matches!(
98            item.ty,
99            Ty::Slice {
100                slice_token: Some(..),
101                ty: _
102            }
103        );
104
105        // "new" syntax
106        let item = parse::<ItemImpl>("impl [T] {}");
107        assert_matches!(
108            item.ty,
109            Ty::Slice {
110                slice_token: None,
111                ty: _
112            }
113        );
114
115        let item = parse::<ItemImpl>("impl &[T] {}");
116        assert_matches!(item.ty, Ty::Ref { ty, .. } if matches!(&*ty, Ty::Slice { .. }));
117    }
118
119    #[test]
120    fn parse_impl_for_slice() {
121        let item = parse::<ItemImpl>(
122            r#"
123            impl Foo for __slice[T] {}
124            "#,
125        );
126        assert_matches!(item.ty, Ty::Slice { .. });
127    }
128
129    #[test]
130    fn parse_impl_ref() {
131        let item = parse::<ItemImpl>(
132            r#"
133            impl &T {}
134            "#,
135        );
136        assert_matches!(
137            item.ty,
138            Ty::Ref {
139                mut_token: None,
140                ..
141            }
142        );
143    }
144
145    #[test]
146    fn parse_impl_for_ref() {
147        let item = parse::<ItemImpl>(
148            r#"
149            impl Foo for &T {}
150            "#,
151        );
152        assert_matches!(
153            item.ty,
154            Ty::Ref {
155                mut_token: None,
156                ..
157            }
158        );
159    }
160
161    #[test]
162    fn parse_impl_mut_ref() {
163        let item = parse::<ItemImpl>(
164            r#"
165            impl &mut T {}
166            "#,
167        );
168        assert_matches!(
169            item.ty,
170            Ty::Ref {
171                mut_token: Some(_),
172                ..
173            }
174        );
175    }
176
177    #[test]
178    fn parse_impl_for_mut_ref() {
179        let item = parse::<ItemImpl>(
180            r#"
181            impl Foo for &mut T {}
182            "#,
183        );
184        assert_matches!(
185            item.ty,
186            Ty::Ref {
187                mut_token: Some(_),
188                ..
189            }
190        );
191    }
192}