swayfmt/module/
mod.rs

1use crate::{
2    comments::write_comments,
3    formatter::*,
4    utils::map::byte_span::{self, ByteSpan, LeafSpans},
5};
6use std::fmt::Write;
7use sway_ast::{
8    keywords::{
9        ContractToken, Keyword, LibraryToken, PredicateToken, ScriptToken, SemicolonToken, Token,
10    },
11    Item, ItemKind, Module, ModuleKind,
12};
13use sway_types::Spanned;
14
15pub(crate) mod item;
16pub(crate) mod submodule;
17
18impl Format for Module {
19    fn format(
20        &self,
21        formatted_code: &mut FormattedCode,
22        formatter: &mut Formatter,
23    ) -> Result<(), FormatterError> {
24        write_comments(formatted_code, 0..self.span().start(), formatter)?;
25        self.kind.format(formatted_code, formatter)?;
26        writeln!(formatted_code, "{}", SemicolonToken::AS_STR)?;
27
28        // Format comments between module kind declaration and rest of items
29        if !self.items.is_empty() {
30            write_comments(
31                formatted_code,
32                0..self.items.first().unwrap().span().start(),
33                formatter,
34            )?;
35        }
36
37        let iter = self.items.iter();
38        let mut prev_item: Option<&Item> = None;
39        for item in iter.clone() {
40            if let Some(prev_item) = prev_item {
41                write_comments(
42                    formatted_code,
43                    prev_item.span().end()..item.span().start(),
44                    formatter,
45                )?;
46            }
47
48            item.format(formatted_code, formatter)?;
49            if let ItemKind::Submodule { .. } = item.value {
50                // Do not print a newline after a submodule
51            } else {
52                writeln!(formatted_code)?;
53            }
54
55            prev_item = Some(item);
56        }
57
58        if let Some(prev_item) = prev_item {
59            write_comments(
60                formatted_code,
61                prev_item.span().end()..self.span().end(),
62                formatter,
63            )?;
64        }
65
66        Ok(())
67    }
68}
69
70impl Format for ModuleKind {
71    fn format(
72        &self,
73        formatted_code: &mut FormattedCode,
74        _formatter: &mut Formatter,
75    ) -> Result<(), FormatterError> {
76        match self {
77            ModuleKind::Script { script_token: _ } => {
78                write!(formatted_code, "{}", ScriptToken::AS_STR)?
79            }
80            ModuleKind::Contract { contract_token: _ } => {
81                write!(formatted_code, "{}", ContractToken::AS_STR)?
82            }
83            ModuleKind::Predicate { predicate_token: _ } => {
84                write!(formatted_code, "{}", PredicateToken::AS_STR)?
85            }
86            ModuleKind::Library { library_token: _ } => {
87                write!(formatted_code, "{}", LibraryToken::AS_STR)?;
88            }
89        };
90
91        Ok(())
92    }
93}
94
95impl LeafSpans for Module {
96    fn leaf_spans(&self) -> Vec<ByteSpan> {
97        let mut collected_spans = vec![byte_span::STARTING_BYTE_SPAN];
98        collected_spans.append(&mut self.kind.leaf_spans());
99        collected_spans.push(ByteSpan::from(self.semicolon_token.span()));
100        collected_spans.append(&mut self.items.leaf_spans());
101        collected_spans
102    }
103}
104
105impl LeafSpans for ModuleKind {
106    fn leaf_spans(&self) -> Vec<ByteSpan> {
107        match self {
108            ModuleKind::Script { script_token } => {
109                vec![ByteSpan::from(script_token.span())]
110            }
111            ModuleKind::Contract { contract_token } => {
112                vec![ByteSpan::from(contract_token.span())]
113            }
114            ModuleKind::Predicate { predicate_token } => {
115                vec![ByteSpan::from(predicate_token.span())]
116            }
117            ModuleKind::Library { library_token } => {
118                vec![ByteSpan::from(library_token.span())]
119            }
120        }
121    }
122}