sway_parse/item/
item_impl.rs1use 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 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 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}