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