foundry_config/
fmt.rs

1//! Configuration specific to the `forge fmt` command and the `forge_fmt` package
2
3use serde::{Deserialize, Serialize};
4
5/// Contains the config and rule set
6#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
7pub struct FormatterConfig {
8    /// Maximum line length where formatter will try to wrap the line
9    pub line_length: usize,
10    /// Number of spaces per indentation level. Ignored if style is Tab
11    pub tab_width: usize,
12    /// Style of indent
13    pub style: IndentStyle,
14    /// Print spaces between brackets
15    pub bracket_spacing: bool,
16    /// Style of uint/int256 types
17    pub int_types: IntTypes,
18    /// Style of multiline function header in case it doesn't fit
19    pub multiline_func_header: MultilineFuncHeaderStyle,
20    /// Style of quotation marks
21    pub quote_style: QuoteStyle,
22    /// Style of underscores in number literals
23    pub number_underscore: NumberUnderscore,
24    /// Style of underscores in hex literals
25    pub hex_underscore: HexUnderscore,
26    /// Style of single line blocks in statements
27    pub single_line_statement_blocks: SingleLineBlockStyle,
28    /// Print space in state variable, function and modifier `override` attribute
29    pub override_spacing: bool,
30    /// Wrap comments on `line_length` reached
31    pub wrap_comments: bool,
32    /// Style of doc comments
33    pub docs_style: DocCommentStyle,
34    /// Globs to ignore
35    pub ignore: Vec<String>,
36    /// Add new line at start and end of contract declarations
37    pub contract_new_lines: bool,
38    /// Sort import statements alphabetically in groups (a group is separated by a newline).
39    pub sort_imports: bool,
40    /// Whether to suppress spaces around the power operator (`**`).
41    pub pow_no_space: bool,
42    /// Whether to compact call args in a single line when possible
43    pub call_compact_args: bool,
44}
45
46/// Style of integer types.
47#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
48#[serde(rename_all = "snake_case")]
49pub enum IntTypes {
50    /// Use the type defined in the source code.
51    Preserve,
52    /// Print the full length `uint256` or `int256`.
53    #[default]
54    Long,
55    /// Print the alias `uint` or `int`.
56    Short,
57}
58
59/// Style of underscores in number literals
60#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
61#[serde(rename_all = "snake_case")]
62pub enum NumberUnderscore {
63    /// Use the underscores defined in the source code
64    #[default]
65    Preserve,
66    /// Remove all underscores
67    Remove,
68    /// Add an underscore every thousand, if greater than 9999
69    /// e.g. 1000 -> 1000 and 10000 -> 10_000
70    Thousands,
71}
72
73impl NumberUnderscore {
74    /// Returns true if the option is `Preserve`
75    #[inline]
76    pub fn is_preserve(self) -> bool {
77        matches!(self, Self::Preserve)
78    }
79
80    /// Returns true if the option is `Remove`
81    #[inline]
82    pub fn is_remove(self) -> bool {
83        matches!(self, Self::Remove)
84    }
85
86    /// Returns true if the option is `Remove`
87    #[inline]
88    pub fn is_thousands(self) -> bool {
89        matches!(self, Self::Thousands)
90    }
91}
92
93/// Style of underscores in hex literals
94#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
95#[serde(rename_all = "snake_case")]
96pub enum HexUnderscore {
97    /// Use the underscores defined in the source code
98    Preserve,
99    /// Remove all underscores
100    #[default]
101    Remove,
102    /// Add underscore as separator between byte boundaries
103    Bytes,
104}
105
106/// Style of doc comments
107#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
108#[serde(rename_all = "snake_case")]
109pub enum DocCommentStyle {
110    /// Preserve the source code style
111    #[default]
112    Preserve,
113    /// Use single-line style (`///`)
114    Line,
115    /// Use block style (`/** .. */`)
116    Block,
117}
118
119/// Style of string quotes
120#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
121#[serde(rename_all = "snake_case")]
122pub enum QuoteStyle {
123    /// Use quotation mark defined in the source code.
124    Preserve,
125    /// Use double quotes where possible.
126    #[default]
127    Double,
128    /// Use single quotes where possible.
129    Single,
130}
131
132impl QuoteStyle {
133    /// Returns the associated quotation mark character.
134    pub const fn quote(self) -> Option<char> {
135        match self {
136            Self::Preserve => None,
137            Self::Double => Some('"'),
138            Self::Single => Some('\''),
139        }
140    }
141}
142
143/// Style of single line blocks in statements
144#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
145#[serde(rename_all = "snake_case")]
146pub enum SingleLineBlockStyle {
147    /// Preserve the original style
148    #[default]
149    Preserve,
150    /// Prefer single line block when possible
151    Single,
152    /// Always use multiline block
153    Multi,
154}
155
156/// Style of function header in case it doesn't fit
157#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
158#[serde(rename_all = "snake_case")]
159pub enum MultilineFuncHeaderStyle {
160    /// Always write function parameters multiline.
161    #[serde(alias = "params_first")] // alias for backwards compatibility
162    ParamsAlways,
163    /// Write function parameters multiline first when there is more than one param.
164    ParamsFirstMulti,
165    /// Write function attributes multiline first.
166    #[default]
167    AttributesFirst,
168    /// If function params or attrs are multiline.
169    /// split the rest
170    All,
171    /// Same as `All` but writes function params multiline even when there is a single param.
172    AllParams,
173}
174
175impl MultilineFuncHeaderStyle {
176    pub fn all(&self) -> bool {
177        matches!(self, Self::All | Self::AllParams)
178    }
179
180    pub fn params_first(&self) -> bool {
181        matches!(self, Self::ParamsAlways | Self::ParamsFirstMulti)
182    }
183
184    pub fn attrib_first(&self) -> bool {
185        matches!(self, Self::AttributesFirst)
186    }
187}
188
189/// Style of indent
190#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
191#[serde(rename_all = "snake_case")]
192pub enum IndentStyle {
193    #[default]
194    Space,
195    Tab,
196}
197
198impl Default for FormatterConfig {
199    fn default() -> Self {
200        Self {
201            line_length: 120,
202            tab_width: 4,
203            style: IndentStyle::Space,
204            bracket_spacing: false,
205            int_types: IntTypes::default(),
206            multiline_func_header: MultilineFuncHeaderStyle::default(),
207            quote_style: QuoteStyle::default(),
208            number_underscore: NumberUnderscore::default(),
209            hex_underscore: HexUnderscore::default(),
210            single_line_statement_blocks: SingleLineBlockStyle::default(),
211            override_spacing: false,
212            wrap_comments: false,
213            ignore: vec![],
214            contract_new_lines: false,
215            sort_imports: false,
216            pow_no_space: false,
217            call_compact_args: true,
218            docs_style: DocCommentStyle::default(),
219        }
220    }
221}