1use crate::{Parse, ParseResult, ParseToEnd, Parser, ParserConsumed};
2
3use sway_ast::keywords::{
4 AbiToken, ClassToken, ColonToken, ConfigurableToken, ConstToken, EnumToken, FnToken, ImplToken,
5 ModToken, MutToken, OpenAngleBracketToken, RefToken, SelfToken, SemicolonToken, StorageToken,
6 StructToken, TraitToken, TypeToken, UseToken, WhereToken,
7};
8use sway_ast::{
9 FnArg, FnArgs, FnSignature, ItemConst, ItemEnum, ItemFn, ItemKind, ItemStruct, ItemTrait,
10 ItemTypeAlias, ItemUse, Submodule, TraitType, TypeField,
11};
12use sway_error::parser_error::ParseErrorKind;
13
14mod item_abi;
15mod item_configurable;
16mod item_const;
17mod item_enum;
18mod item_fn;
19mod item_impl;
20mod item_storage;
21mod item_struct;
22mod item_trait;
23mod item_type_alias;
24mod item_use;
25
26impl Parse for ItemKind {
27 fn parse(parser: &mut Parser) -> ParseResult<ItemKind> {
28 let mut visibility = parser.take();
33
34 let kind = if let Some(mut item) = parser.guarded_parse::<ModToken, Submodule>()? {
35 item.visibility = visibility.take();
36 ItemKind::Submodule(item)
37 } else if let Some(mut item) = parser.guarded_parse::<UseToken, ItemUse>()? {
38 item.visibility = visibility.take();
39 ItemKind::Use(item)
40 } else if let Some(mut item) = parser.guarded_parse::<ClassToken, ItemStruct>()? {
41 item.visibility = visibility.take();
42 ItemKind::Struct(item)
43 } else if let Some(mut item) = parser.guarded_parse::<StructToken, ItemStruct>()? {
44 item.visibility = visibility.take();
45 ItemKind::Struct(item)
46 } else if let Some(mut item) = parser.guarded_parse::<EnumToken, ItemEnum>()? {
47 item.visibility = visibility.take();
48 ItemKind::Enum(item)
49 } else if let Some(mut item) = parser.guarded_parse::<FnToken, ItemFn>()? {
50 item.fn_signature.visibility = visibility.take();
51 ItemKind::Fn(item)
52 } else if let Some(mut item) = parser.guarded_parse::<TraitToken, ItemTrait>()? {
53 item.visibility = visibility.take();
54 ItemKind::Trait(item)
55 } else if let Some(item) = parser.guarded_parse::<ImplToken, _>()? {
56 ItemKind::Impl(item)
57 } else if let Some(item) = parser.guarded_parse::<AbiToken, _>()? {
58 ItemKind::Abi(item)
59 } else if let Some(mut item) = parser.guarded_parse::<ConstToken, ItemConst>()? {
60 item.visibility = visibility.take();
61 parser.take::<SemicolonToken>().ok_or_else(|| {
62 parser.emit_error(ParseErrorKind::ExpectedPunct {
63 kinds: vec![sway_types::ast::PunctKind::Semicolon],
64 })
65 })?;
66 ItemKind::Const(item)
67 } else if let Some(item) = parser.guarded_parse::<StorageToken, _>()? {
68 ItemKind::Storage(item)
69 } else if let Some(item) = parser.guarded_parse::<ConfigurableToken, _>()? {
70 ItemKind::Configurable(item)
71 } else if let Some(mut item) = parser.guarded_parse::<TypeToken, ItemTypeAlias>()? {
72 item.visibility = visibility.take();
73 ItemKind::TypeAlias(item)
74 } else {
75 return Err(parser.emit_error(ParseErrorKind::ExpectedAnItem));
76 };
77
78 let _ = parser.ban_visibility_qualifier(&visibility);
80
81 Ok(kind)
82 }
83
84 fn error(
85 spans: Box<[sway_types::Span]>,
86 error: sway_error::handler::ErrorEmitted,
87 ) -> Option<Self>
88 where
89 Self: Sized,
90 {
91 Some(ItemKind::Error(spans, error))
92 }
93}
94
95impl Parse for TypeField {
96 fn parse(parser: &mut Parser) -> ParseResult<TypeField> {
97 let visibility = parser.take();
98 Ok(TypeField {
99 visibility,
100 name: parser.parse()?,
101 colon_token: if parser.peek::<ColonToken>().is_some() {
102 parser.parse()
103 } else {
104 Err(parser.emit_error(ParseErrorKind::MissingColonInEnumTypeField))
105 }?,
106 ty: parser.parse()?,
107 })
108 }
109}
110
111impl ParseToEnd for FnArgs {
112 fn parse_to_end<'a, 'e>(
113 mut parser: Parser<'a, '_>,
114 ) -> ParseResult<(FnArgs, ParserConsumed<'a>)> {
115 let mut ref_self: Option<RefToken> = None;
116 let mut mutable_self: Option<MutToken> = None;
117 if parser.peek::<(MutToken, SelfToken)>().is_some()
118 || parser.peek::<(RefToken, MutToken, SelfToken)>().is_some()
119 {
120 ref_self = parser.take();
121 mutable_self = parser.take();
122 }
123 match parser.take() {
124 Some(self_token) => {
125 match parser.take() {
126 Some(comma_token) => {
127 let (args, consumed) = parser.parse_to_end()?;
128 let fn_args = FnArgs::NonStatic {
129 self_token,
130 ref_self,
131 mutable_self,
132 args_opt: Some((comma_token, args)),
133 };
134 Ok((fn_args, consumed))
135 }
136 None => {
137 let fn_args = FnArgs::NonStatic {
138 self_token,
139 ref_self,
140 mutable_self,
141 args_opt: None,
142 };
143 match parser.check_empty() {
144 Some(consumed) => Ok((fn_args, consumed)),
145 None => Err(parser
146 .emit_error(ParseErrorKind::ExpectedCommaOrCloseParenInFnArgs)),
147 }
148 }
149 }
150 }
151 None => {
152 let (args, consumed) = parser.parse_to_end()?;
153 let fn_args = FnArgs::Static(args);
154 Ok((fn_args, consumed))
155 }
156 }
157 }
158}
159
160impl Parse for FnArg {
161 fn parse(parser: &mut Parser) -> ParseResult<FnArg> {
162 Ok(FnArg {
163 pattern: parser.parse()?,
164 colon_token: parser.parse()?,
165 ty: parser.parse()?,
166 })
167 }
168}
169
170impl Parse for FnSignature {
171 fn parse(parser: &mut Parser) -> ParseResult<FnSignature> {
172 Ok(FnSignature {
173 visibility: parser.take(),
174 fn_token: parser.parse()?,
175 name: parser.parse()?,
176 generics: parser.guarded_parse::<OpenAngleBracketToken, _>()?,
177 arguments: parser.parse()?,
178 return_type_opt: match parser.take() {
179 Some(right_arrow_token) => {
180 let ty = parser.parse()?;
181 Some((right_arrow_token, ty))
182 }
183 None => None,
184 },
185 where_clause_opt: parser.guarded_parse::<WhereToken, _>()?,
186 })
187 }
188}
189
190impl Parse for TraitType {
191 fn parse(parser: &mut Parser) -> ParseResult<TraitType> {
192 let type_token = parser.parse()?;
193 let name = parser.parse()?;
194 let eq_token_opt = parser.take();
195 let ty_opt = match &eq_token_opt {
196 Some(_eq) => Some(parser.parse()?),
197 None => None,
198 };
199 let semicolon_token = parser.peek().unwrap_or_default();
200 Ok(TraitType {
201 type_token,
202 name,
203 eq_token_opt,
204 ty_opt,
205 semicolon_token,
206 })
207 }
208}
209
210#[cfg(test)]
213mod tests {
214 use super::*;
215 use crate::test_utils::parse;
216 use sway_ast::{AttributeDecl, Item, ItemTraitItem};
217
218 type ParameterizedAttr<'a> = (&'a str, Option<Vec<&'a str>>);
220
221 fn attributes(attribute_list: &[AttributeDecl]) -> Vec<Vec<ParameterizedAttr>> {
222 attribute_list
223 .iter()
224 .map(|attr_decl| {
225 attr_decl
226 .attribute
227 .get()
228 .into_iter()
229 .map(|att| {
230 (
231 att.name.as_str(),
232 att.args.as_ref().map(|arg| {
233 arg.get().into_iter().map(|a| a.name.as_str()).collect()
234 }),
235 )
236 })
237 .collect()
238 })
239 .collect()
240 }
241
242 #[test]
243 fn parse_doc_comment() {
244 let item = parse::<Item>(
245 r#"
246 // I will be ignored.
247 //! I will be ignored.
248 /// This is a doc comment.
249 //! I will be ignored.
250 // I will be ignored.
251 fn f() -> bool {
252 false
253 }
254 "#,
255 );
256 assert!(matches!(item.value, ItemKind::Fn(_)));
257 assert_eq!(
258 attributes(&item.attribute_list),
259 vec![[("doc-comment", Some(vec![" This is a doc comment."]))]]
260 );
261 }
262
263 #[test]
264 fn parse_doc_comment_struct() {
265 let item = parse::<Item>(
266 r#"
267 // I will be ignored.
268 //! I will be ignored.
269 /// This is a doc comment.
270 //! I will be ignored.
271 // I will be ignored.
272 struct MyStruct {
273 // I will be ignored.
274 //! I will be ignored.
275 /// This is a doc comment.
276 //! I will be ignored.
277 // I will be ignored.
278 a: bool,
279 }
280 "#,
281 );
282
283 assert!(matches!(item.value, ItemKind::Struct(_)));
285 assert_eq!(
286 attributes(&item.attribute_list),
287 vec![[("doc-comment", Some(vec![" This is a doc comment."]))]]
288 );
289
290 let item = match item.value {
292 ItemKind::Struct(item) => item.fields.inner.into_iter().next().unwrap(),
293 _ => unreachable!(),
294 };
295
296 assert_eq!(
297 attributes(&item.attribute_list),
298 vec![[("doc-comment", Some(vec![" This is a doc comment."]))]]
299 );
300 }
301
302 #[test]
303 fn parse_attributes_none() {
304 let item = parse::<Item>(
305 r#"
306 fn f() -> bool {
307 false
308 }
309 "#,
310 );
311
312 assert!(matches!(item.value, ItemKind::Fn(_)));
313 assert!(item.attribute_list.is_empty());
314 }
315
316 #[test]
317 fn parse_attributes_fn_basic() {
318 let item = parse::<Item>(
319 r#"
320 #[foo]
321 fn f() -> bool {
322 false
323 }
324 "#,
325 );
326
327 assert!(matches!(item.value, ItemKind::Fn(_)));
328 assert_eq!(attributes(&item.attribute_list), vec![[("foo", None)]]);
329 }
330
331 #[test]
332 fn parse_attributes_fn_one_arg_value() {
333 let item = parse::<Item>(
334 r#"
335 #[cfg(target = "evm")]
336 fn f() -> bool {
337 false
338 }
339 "#,
340 );
341
342 assert!(matches!(item.value, ItemKind::Fn(_)));
343 assert_eq!(
344 attributes(&item.attribute_list),
345 vec![[("cfg", Some(vec!["target"]))]]
346 );
347 }
348
349 #[test]
350 fn parse_attributes_fn_two_arg_values() {
351 let item = parse::<Item>(
352 r#"
353 #[cfg(target = "evm", feature = "test")]
354 fn f() -> bool {
355 false
356 }
357 "#,
358 );
359
360 assert!(matches!(item.value, ItemKind::Fn(_)));
361 assert_eq!(
362 attributes(&item.attribute_list),
363 vec![[("cfg", Some(vec!["target", "feature"]))]]
364 );
365 }
366
367 #[test]
368 fn parse_attributes_fn_two_basic() {
369 let item = parse::<Item>(
370 r#"
371 #[foo]
372 #[bar]
373 fn f() -> bool {
374 false
375 }
376 "#,
377 );
378
379 assert!(matches!(item.value, ItemKind::Fn(_)));
380
381 assert_eq!(
382 attributes(&item.attribute_list),
383 vec![[("foo", None)], [("bar", None)]]
384 );
385 }
386
387 #[test]
388 fn parse_attributes_fn_one_arg() {
389 let item = parse::<Item>(
390 r#"
391 #[foo(one)]
392 fn f() -> bool {
393 false
394 }
395 "#,
396 );
397
398 assert!(matches!(item.value, ItemKind::Fn(_)));
399 assert_eq!(
400 attributes(&item.attribute_list),
401 vec![[("foo", Some(vec!["one"]))]]
402 );
403 }
404
405 #[test]
406 fn parse_attributes_fn_empty_parens() {
407 let item = parse::<Item>(
408 r#"
409 #[foo()]
410 fn f() -> bool {
411 false
412 }
413 "#,
414 );
415
416 assert!(matches!(item.value, ItemKind::Fn(_)));
417 assert_eq!(
418 attributes(&item.attribute_list),
419 vec![[("foo", Some(vec![]))]]
420 );
421 }
422
423 #[test]
424 fn parse_attributes_fn_zero_and_one_arg() {
425 let item = parse::<Item>(
426 r#"
427 #[bar]
428 #[foo(one)]
429 fn f() -> bool {
430 false
431 }
432 "#,
433 );
434
435 assert!(matches!(item.value, ItemKind::Fn(_)));
436 assert_eq!(
437 attributes(&item.attribute_list),
438 vec![[("bar", None)], [("foo", Some(vec!["one"]))]]
439 );
440 }
441
442 #[test]
443 fn parse_attributes_fn_one_and_zero_arg() {
444 let item = parse::<Item>(
445 r#"
446 #[foo(one)]
447 #[bar]
448 fn f() -> bool {
449 false
450 }
451 "#,
452 );
453
454 assert!(matches!(item.value, ItemKind::Fn(_)));
455 assert_eq!(
456 attributes(&item.attribute_list),
457 vec![[("foo", Some(vec!["one"]))], [("bar", None)]]
458 );
459 }
460
461 #[test]
462 fn parse_attributes_fn_two_args() {
463 let item = parse::<Item>(
464 r#"
465 #[foo(one, two)]
466 fn f() -> bool {
467 false
468 }
469 "#,
470 );
471
472 assert!(matches!(item.value, ItemKind::Fn(_)));
473 assert_eq!(
474 attributes(&item.attribute_list),
475 vec![[("foo", Some(vec!["one", "two"]))]]
476 );
477 }
478
479 #[test]
480 fn parse_attributes_fn_zero_one_and_three_args() {
481 let item = parse::<Item>(
482 r#"
483 #[bar]
484 #[foo(one)]
485 #[baz(two,three,four)]
486 fn f() -> bool {
487 false
488 }
489 "#,
490 );
491
492 assert!(matches!(item.value, ItemKind::Fn(_)));
493 assert_eq!(
494 attributes(&item.attribute_list),
495 vec![
496 [("bar", None)],
497 [("foo", Some(vec!["one"]))],
498 [("baz", Some(vec!["two", "three", "four"]))]
499 ]
500 );
501 }
502
503 #[test]
504 fn parse_attributes_fn_zero_one_and_three_args_in_one_attribute_decl() {
505 let item = parse::<Item>(
506 r#"
507 #[bar, foo(one), baz(two,three,four)]
508 fn f() -> bool {
509 false
510 }
511 "#,
512 );
513
514 assert!(matches!(item.value, ItemKind::Fn(_)));
515 assert_eq!(
516 attributes(&item.attribute_list),
517 vec![[
518 ("bar", None),
519 ("foo", Some(vec!["one"])),
520 ("baz", Some(vec!["two", "three", "four"]))
521 ]]
522 );
523 }
524
525 #[test]
526 fn parse_attributes_trait() {
527 let item = parse::<Item>(
528 r#"
529 trait T {
530 #[foo(one)]
531 #[bar]
532 fn f() -> bool;
533 } {
534 #[bar(one, two, three)]
535 fn g() -> bool {
536 f()
537 }
538 }
539 "#,
540 );
541
542 assert!(matches!(item.value, ItemKind::Trait(_)));
544 assert_eq!(item.attribute_list.len(), 0);
545
546 if let ItemKind::Trait(item_trait) = item.value {
547 let mut decls = item_trait.trait_items.get().iter();
548
549 let trait_item = decls.next();
550 assert!(trait_item.is_some());
551 let annotated = trait_item.unwrap();
552 if let ItemTraitItem::Fn(_fn_sig, _) = &annotated.value {
553 assert_eq!(
554 attributes(&annotated.attribute_list),
555 vec![[("foo", Some(vec!["one"]))], [("bar", None)]]
556 );
557 }
558
559 assert!(decls.next().is_none());
560
561 assert!(item_trait.trait_defs_opt.is_some());
562 let mut defs = item_trait.trait_defs_opt.as_ref().unwrap().get().iter();
563
564 let g_sig = defs.next();
565 assert!(g_sig.is_some());
566
567 assert_eq!(
568 attributes(&g_sig.unwrap().attribute_list),
569 vec![[("bar", Some(vec!["one", "two", "three"]))],]
570 );
571
572 assert!(defs.next().is_none());
573 } else {
574 panic!("Parsed trait is not a trait.");
575 }
576 }
577
578 #[test]
579 fn parse_attributes_abi() {
580 let item = parse::<Item>(
581 r#"
582 abi A {
583 #[bar(one, two, three)]
584 fn f() -> bool;
585
586 #[foo]
587 fn g() -> u64;
588 } {
589 #[baz(one)]
590 fn h() -> bool {
591 f()
592 }
593 }
594 "#,
595 );
596
597 assert!(matches!(item.value, ItemKind::Abi(_)));
599 assert_eq!(item.attribute_list.len(), 0);
600
601 if let ItemKind::Abi(item_abi) = item.value {
602 let mut decls = item_abi.abi_items.get().iter();
603
604 let f_sig = decls.next();
605 assert!(f_sig.is_some());
606
607 assert_eq!(
608 attributes(&f_sig.unwrap().attribute_list),
609 vec![[("bar", Some(vec!["one", "two", "three"]))],]
610 );
611
612 let g_sig = decls.next();
613 assert!(g_sig.is_some());
614
615 assert_eq!(
616 attributes(&g_sig.unwrap().attribute_list),
617 vec![[("foo", None)],]
618 );
619 assert!(decls.next().is_none());
620
621 assert!(item_abi.abi_defs_opt.is_some());
622 let mut defs = item_abi.abi_defs_opt.as_ref().unwrap().get().iter();
623
624 let h_sig = defs.next();
625 assert!(h_sig.is_some());
626
627 assert_eq!(
628 attributes(&h_sig.unwrap().attribute_list),
629 vec![[("baz", Some(vec!["one"]))],]
630 );
631 assert!(defs.next().is_none());
632 } else {
633 panic!("Parsed ABI is not an ABI.");
634 }
635 }
636
637 #[test]
638 fn parse_attributes_doc_comment() {
639 let item = parse::<Item>(
640 r#"
641 /// This is a doc comment.
642 /// This is another doc comment.
643 fn f() -> bool {
644 false
645 }
646 "#,
647 );
648
649 assert!(matches!(item.value, ItemKind::Fn(_)));
650 assert_eq!(
651 attributes(&item.attribute_list),
652 vec![
653 [("doc-comment", Some(vec![" This is a doc comment."]))],
654 [("doc-comment", Some(vec![" This is another doc comment."]))]
655 ]
656 );
657 }
658}