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(attributes: &[AttributeDecl]) -> Vec<Vec<ParameterizedAttr>> {
222 attributes
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 //! This is a misplaced inner doc comment.
248 /// This is an outer doc comment.
249 //! This is a misplaced inner doc comment.
250 // I will be ignored.
251 /// This is an outer doc comment.
252 // I will be ignored.
253 fn f() -> bool {
254 false
255 }
256 "#,
257 );
258 assert!(matches!(item.value, ItemKind::Fn(_)));
259 assert_eq!(
260 attributes(&item.attributes),
261 vec![
262 [(
263 "doc-comment",
264 Some(vec![" This is a misplaced inner doc comment."])
265 )],
266 [("doc-comment", Some(vec![" This is an outer doc comment."]))],
267 [(
268 "doc-comment",
269 Some(vec![" This is a misplaced inner doc comment."])
270 )],
271 [("doc-comment", Some(vec![" This is an outer doc comment."]))],
272 ]
273 );
274 }
275
276 #[test]
277 fn parse_doc_comment_struct() {
278 let item = parse::<Item>(
279 r#"
280 // I will be ignored.
281 //! This is a misplaced inner doc comment.
282 /// This is an outer doc comment.
283 //! This is a misplaced inner doc comment.
284 // I will be ignored.
285 /// This is an outer doc comment.
286 // I will be ignored.
287 struct MyStruct {
288 // I will be ignored.
289 //! This is a misplaced inner doc comment.
290 /// This is an outer doc comment.
291 //! This is a misplaced inner doc comment.
292 // I will be ignored.
293 /// This is an outer doc comment.
294 // I will be ignored.
295 a: bool,
296 }
297 "#,
298 );
299
300 assert!(matches!(item.value, ItemKind::Struct(_)));
302 assert_eq!(
303 attributes(&item.attributes),
304 vec![
305 [(
306 "doc-comment",
307 Some(vec![" This is a misplaced inner doc comment."])
308 )],
309 [("doc-comment", Some(vec![" This is an outer doc comment."]))],
310 [(
311 "doc-comment",
312 Some(vec![" This is a misplaced inner doc comment."])
313 )],
314 [("doc-comment", Some(vec![" This is an outer doc comment."]))],
315 ]
316 );
317
318 let item = match item.value {
320 ItemKind::Struct(item) => item.fields.inner.into_iter().next().unwrap(),
321 _ => unreachable!(),
322 };
323
324 assert_eq!(
325 attributes(&item.attributes),
326 vec![
327 [(
328 "doc-comment",
329 Some(vec![" This is a misplaced inner doc comment."])
330 )],
331 [("doc-comment", Some(vec![" This is an outer doc comment."]))],
332 [(
333 "doc-comment",
334 Some(vec![" This is a misplaced inner doc comment."])
335 )],
336 [("doc-comment", Some(vec![" This is an outer doc comment."]))],
337 ]
338 );
339 }
340
341 #[test]
342 fn parse_attributes_none() {
343 let item = parse::<Item>(
344 r#"
345 fn f() -> bool {
346 false
347 }
348 "#,
349 );
350
351 assert!(matches!(item.value, ItemKind::Fn(_)));
352 assert!(item.attributes.is_empty());
353 }
354
355 #[test]
356 fn parse_attributes_fn_basic() {
357 let item = parse::<Item>(
358 r#"
359 #[foo]
360 fn f() -> bool {
361 false
362 }
363 "#,
364 );
365
366 assert!(matches!(item.value, ItemKind::Fn(_)));
367 assert_eq!(attributes(&item.attributes), vec![[("foo", None)]]);
368 }
369
370 #[test]
371 fn parse_attributes_fn_one_arg_value() {
372 let item = parse::<Item>(
373 r#"
374 #[cfg(target = "evm")]
375 fn f() -> bool {
376 false
377 }
378 "#,
379 );
380
381 assert!(matches!(item.value, ItemKind::Fn(_)));
382 assert_eq!(
383 attributes(&item.attributes),
384 vec![[("cfg", Some(vec!["target"]))]]
385 );
386 }
387
388 #[test]
389 fn parse_attributes_fn_two_arg_values() {
390 let item = parse::<Item>(
391 r#"
392 #[cfg(target = "evm", feature = "test")]
393 fn f() -> bool {
394 false
395 }
396 "#,
397 );
398
399 assert!(matches!(item.value, ItemKind::Fn(_)));
400 assert_eq!(
401 attributes(&item.attributes),
402 vec![[("cfg", Some(vec!["target", "feature"]))]]
403 );
404 }
405
406 #[test]
407 fn parse_attributes_fn_two_basic() {
408 let item = parse::<Item>(
409 r#"
410 #[foo]
411 #[bar]
412 fn f() -> bool {
413 false
414 }
415 "#,
416 );
417
418 assert!(matches!(item.value, ItemKind::Fn(_)));
419
420 assert_eq!(
421 attributes(&item.attributes),
422 vec![[("foo", None)], [("bar", None)]]
423 );
424 }
425
426 #[test]
427 fn parse_attributes_fn_one_arg() {
428 let item = parse::<Item>(
429 r#"
430 #[foo(one)]
431 fn f() -> bool {
432 false
433 }
434 "#,
435 );
436
437 assert!(matches!(item.value, ItemKind::Fn(_)));
438 assert_eq!(
439 attributes(&item.attributes),
440 vec![[("foo", Some(vec!["one"]))]]
441 );
442 }
443
444 #[test]
445 fn parse_attributes_fn_empty_parens() {
446 let item = parse::<Item>(
447 r#"
448 #[foo()]
449 fn f() -> bool {
450 false
451 }
452 "#,
453 );
454
455 assert!(matches!(item.value, ItemKind::Fn(_)));
456 assert_eq!(attributes(&item.attributes), vec![[("foo", Some(vec![]))]]);
457 }
458
459 #[test]
460 fn parse_attributes_fn_zero_and_one_arg() {
461 let item = parse::<Item>(
462 r#"
463 #[bar]
464 #[foo(one)]
465 fn f() -> bool {
466 false
467 }
468 "#,
469 );
470
471 assert!(matches!(item.value, ItemKind::Fn(_)));
472 assert_eq!(
473 attributes(&item.attributes),
474 vec![[("bar", None)], [("foo", Some(vec!["one"]))]]
475 );
476 }
477
478 #[test]
479 fn parse_attributes_fn_one_and_zero_arg() {
480 let item = parse::<Item>(
481 r#"
482 #[foo(one)]
483 #[bar]
484 fn f() -> bool {
485 false
486 }
487 "#,
488 );
489
490 assert!(matches!(item.value, ItemKind::Fn(_)));
491 assert_eq!(
492 attributes(&item.attributes),
493 vec![[("foo", Some(vec!["one"]))], [("bar", None)]]
494 );
495 }
496
497 #[test]
498 fn parse_attributes_fn_two_args() {
499 let item = parse::<Item>(
500 r#"
501 #[foo(one, two)]
502 fn f() -> bool {
503 false
504 }
505 "#,
506 );
507
508 assert!(matches!(item.value, ItemKind::Fn(_)));
509 assert_eq!(
510 attributes(&item.attributes),
511 vec![[("foo", Some(vec!["one", "two"]))]]
512 );
513 }
514
515 #[test]
516 fn parse_attributes_fn_zero_one_and_three_args() {
517 let item = parse::<Item>(
518 r#"
519 #[bar]
520 #[foo(one)]
521 #[baz(two,three,four)]
522 fn f() -> bool {
523 false
524 }
525 "#,
526 );
527
528 assert!(matches!(item.value, ItemKind::Fn(_)));
529 assert_eq!(
530 attributes(&item.attributes),
531 vec![
532 [("bar", None)],
533 [("foo", Some(vec!["one"]))],
534 [("baz", Some(vec!["two", "three", "four"]))]
535 ]
536 );
537 }
538
539 #[test]
540 fn parse_attributes_fn_zero_one_and_three_args_in_one_attribute_decl() {
541 let item = parse::<Item>(
542 r#"
543 #[bar, foo(one), baz(two,three,four)]
544 fn f() -> bool {
545 false
546 }
547 "#,
548 );
549
550 assert!(matches!(item.value, ItemKind::Fn(_)));
551 assert_eq!(
552 attributes(&item.attributes),
553 vec![[
554 ("bar", None),
555 ("foo", Some(vec!["one"])),
556 ("baz", Some(vec!["two", "three", "four"]))
557 ]]
558 );
559 }
560
561 #[test]
562 fn parse_attributes_trait() {
563 let item = parse::<Item>(
564 r#"
565 trait T {
566 #[foo(one)]
567 #[bar]
568 fn f() -> bool;
569 } {
570 #[bar(one, two, three)]
571 fn g() -> bool {
572 f()
573 }
574 }
575 "#,
576 );
577
578 assert!(matches!(item.value, ItemKind::Trait(_)));
580 assert_eq!(item.attributes.len(), 0);
581
582 if let ItemKind::Trait(item_trait) = item.value {
583 let mut decls = item_trait.trait_items.get().iter();
584
585 let trait_item = decls.next();
586 assert!(trait_item.is_some());
587 let annotated = trait_item.unwrap();
588 if let ItemTraitItem::Fn(_fn_sig, _) = &annotated.value {
589 assert_eq!(
590 attributes(&annotated.attributes),
591 vec![[("foo", Some(vec!["one"]))], [("bar", None)]]
592 );
593 }
594
595 assert!(decls.next().is_none());
596
597 assert!(item_trait.trait_defs_opt.is_some());
598 let mut defs = item_trait.trait_defs_opt.as_ref().unwrap().get().iter();
599
600 let g_sig = defs.next();
601 assert!(g_sig.is_some());
602
603 assert_eq!(
604 attributes(&g_sig.unwrap().attributes),
605 vec![[("bar", Some(vec!["one", "two", "three"]))],]
606 );
607
608 assert!(defs.next().is_none());
609 } else {
610 panic!("Parsed trait is not a trait.");
611 }
612 }
613
614 #[test]
615 fn parse_attributes_abi() {
616 let item = parse::<Item>(
617 r#"
618 abi A {
619 #[bar(one, two, three)]
620 fn f() -> bool;
621
622 #[foo]
623 fn g() -> u64;
624 } {
625 #[baz(one)]
626 fn h() -> bool {
627 f()
628 }
629 }
630 "#,
631 );
632
633 assert!(matches!(item.value, ItemKind::Abi(_)));
635 assert_eq!(item.attributes.len(), 0);
636
637 if let ItemKind::Abi(item_abi) = item.value {
638 let mut decls = item_abi.abi_items.get().iter();
639
640 let f_sig = decls.next();
641 assert!(f_sig.is_some());
642
643 assert_eq!(
644 attributes(&f_sig.unwrap().attributes),
645 vec![[("bar", Some(vec!["one", "two", "three"]))],]
646 );
647
648 let g_sig = decls.next();
649 assert!(g_sig.is_some());
650
651 assert_eq!(
652 attributes(&g_sig.unwrap().attributes),
653 vec![[("foo", None)],]
654 );
655 assert!(decls.next().is_none());
656
657 assert!(item_abi.abi_defs_opt.is_some());
658 let mut defs = item_abi.abi_defs_opt.as_ref().unwrap().get().iter();
659
660 let h_sig = defs.next();
661 assert!(h_sig.is_some());
662
663 assert_eq!(
664 attributes(&h_sig.unwrap().attributes),
665 vec![[("baz", Some(vec!["one"]))],]
666 );
667 assert!(defs.next().is_none());
668 } else {
669 panic!("Parsed ABI is not an ABI.");
670 }
671 }
672
673 #[test]
674 fn parse_attributes_doc_comment() {
675 let item = parse::<Item>(
676 r#"
677 /// This is a doc comment.
678 /// This is another doc comment.
679 fn f() -> bool {
680 false
681 }
682 "#,
683 );
684
685 assert!(matches!(item.value, ItemKind::Fn(_)));
686 assert_eq!(
687 attributes(&item.attributes),
688 vec![
689 [("doc-comment", Some(vec![" This is a doc comment."]))],
690 [("doc-comment", Some(vec![" This is another doc comment."]))]
691 ]
692 );
693 }
694}