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    /// Style that determines if a broken list, should keep its elements together on their own
43    /// line, before breaking individually.
44    pub prefer_compact: PreferCompact,
45    /// Keep single imports on a single line even if they exceed line length.
46    pub single_line_imports: bool,
47}
48
49/// Style of integer types.
50#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
51#[serde(rename_all = "snake_case")]
52pub enum IntTypes {
53    /// Use the type defined in the source code.
54    Preserve,
55    /// Print the full length `uint256` or `int256`.
56    #[default]
57    Long,
58    /// Print the alias `uint` or `int`.
59    Short,
60}
61
62/// Style of underscores in number literals
63#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
64#[serde(rename_all = "snake_case")]
65pub enum NumberUnderscore {
66    /// Use the underscores defined in the source code
67    #[default]
68    Preserve,
69    /// Remove all underscores
70    Remove,
71    /// Add an underscore every thousand, if greater than 9999
72    /// e.g. 1000 -> 1000 and 10000 -> 10_000
73    Thousands,
74}
75
76impl NumberUnderscore {
77    /// Returns true if the option is `Preserve`
78    #[inline]
79    pub fn is_preserve(self) -> bool {
80        matches!(self, Self::Preserve)
81    }
82
83    /// Returns true if the option is `Remove`
84    #[inline]
85    pub fn is_remove(self) -> bool {
86        matches!(self, Self::Remove)
87    }
88
89    /// Returns true if the option is `Remove`
90    #[inline]
91    pub fn is_thousands(self) -> bool {
92        matches!(self, Self::Thousands)
93    }
94}
95
96/// Style of underscores in hex literals
97#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
98#[serde(rename_all = "snake_case")]
99pub enum HexUnderscore {
100    /// Use the underscores defined in the source code
101    Preserve,
102    /// Remove all underscores
103    #[default]
104    Remove,
105    /// Add underscore as separator between byte boundaries
106    Bytes,
107}
108
109/// Style of doc comments
110#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
111#[serde(rename_all = "snake_case")]
112pub enum DocCommentStyle {
113    /// Preserve the source code style
114    #[default]
115    Preserve,
116    /// Use single-line style (`///`)
117    Line,
118    /// Use block style (`/** .. */`)
119    Block,
120}
121
122/// Style of string quotes
123#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
124#[serde(rename_all = "snake_case")]
125pub enum QuoteStyle {
126    /// Use quotation mark defined in the source code.
127    Preserve,
128    /// Use double quotes where possible.
129    #[default]
130    Double,
131    /// Use single quotes where possible.
132    Single,
133}
134
135impl QuoteStyle {
136    /// Returns the associated quotation mark character.
137    pub const fn quote(self) -> Option<char> {
138        match self {
139            Self::Preserve => None,
140            Self::Double => Some('"'),
141            Self::Single => Some('\''),
142        }
143    }
144}
145
146/// Style of single line blocks in statements
147#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
148#[serde(rename_all = "snake_case")]
149pub enum SingleLineBlockStyle {
150    /// Preserve the original style
151    #[default]
152    Preserve,
153    /// Prefer single line block when possible
154    Single,
155    /// Always use multiline block
156    Multi,
157}
158
159/// Style of function header in case it doesn't fit
160#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
161#[serde(rename_all = "snake_case")]
162pub enum MultilineFuncHeaderStyle {
163    /// Always write function parameters multiline.
164    #[serde(alias = "params_first")] // alias for backwards compatibility
165    ParamsAlways,
166    /// Write function parameters multiline first when there is more than one param.
167    ParamsFirstMulti,
168    /// Write function attributes multiline first.
169    #[default]
170    AttributesFirst,
171    /// If function params or attrs are multiline.
172    /// split the rest
173    All,
174    /// Same as `All` but writes function params multiline even when there is a single param.
175    AllParams,
176}
177
178impl MultilineFuncHeaderStyle {
179    pub fn all(&self) -> bool {
180        matches!(self, Self::All | Self::AllParams)
181    }
182
183    pub fn params_first(&self) -> bool {
184        matches!(self, Self::ParamsAlways | Self::ParamsFirstMulti)
185    }
186
187    pub fn attrib_first(&self) -> bool {
188        matches!(self, Self::AttributesFirst)
189    }
190}
191
192/// Style that determines if a broken list, should keep its elements together on their own line,
193/// before breaking individually.
194#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
195#[serde(rename_all = "snake_case")]
196pub enum PreferCompact {
197    /// All elements are preferred consistent.
198    None,
199    /// Calls are preferred compact. Events and errors break consistently.
200    Calls,
201    /// Events are preferred compact. Calls and errors break consistently.
202    Events,
203    /// Errors are preferred compact. Calls and events break consistently.
204    Errors,
205    /// Events and errors are preferred compact. Calls break consistently.
206    EventsErrors,
207    /// All elements are preferred compact.
208    #[default]
209    All,
210}
211
212impl PreferCompact {
213    pub fn calls(&self) -> bool {
214        matches!(self, Self::All | Self::Calls)
215    }
216
217    pub fn events(&self) -> bool {
218        matches!(self, Self::All | Self::Events | Self::EventsErrors)
219    }
220
221    pub fn errors(&self) -> bool {
222        matches!(self, Self::All | Self::Errors | Self::EventsErrors)
223    }
224}
225
226/// Style of indent
227#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
228#[serde(rename_all = "snake_case")]
229pub enum IndentStyle {
230    #[default]
231    Space,
232    Tab,
233}
234
235impl Default for FormatterConfig {
236    fn default() -> Self {
237        Self {
238            line_length: 120,
239            tab_width: 4,
240            style: IndentStyle::Space,
241            bracket_spacing: false,
242            int_types: IntTypes::default(),
243            multiline_func_header: MultilineFuncHeaderStyle::default(),
244            quote_style: QuoteStyle::default(),
245            number_underscore: NumberUnderscore::default(),
246            hex_underscore: HexUnderscore::default(),
247            single_line_statement_blocks: SingleLineBlockStyle::default(),
248            override_spacing: false,
249            wrap_comments: false,
250            ignore: vec![],
251            contract_new_lines: false,
252            sort_imports: false,
253            pow_no_space: false,
254            prefer_compact: PreferCompact::default(),
255            docs_style: DocCommentStyle::default(),
256            single_line_imports: false,
257        }
258    }
259}