rustfmt_wrapper/config/
mod.rs

1// Copyright 2022 Oxide Computer Company
2
3use serde::Serialize;
4
5// Process the configuration options lifted from the rustfmt repo. Note that
6// the default value is ignored, but left in to simplify updates.
7macro_rules! create_config {
8    ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => {
9        /// `rustfmt` configuration.
10        ///
11        /// See the [`rustfmt` documentation](https://rust-lang.github.io/rustfmt)
12        /// for the descriptions of these stable and non-stable options.
13        #[derive(Serialize, Default)]
14        pub struct Config {
15            $(
16                $(
17                    #[doc = $dstring]
18                )*
19                #[serde(skip_serializing_if = "Option::is_none")]
20                pub $i: Option<$ty>,
21            )*
22        }
23
24        impl Config {
25            pub(crate) fn unstable(&self) -> bool {
26                false
27                $(
28                    // Not stable and explicitly set.
29                    || (!$stb && self.$i.is_some())
30                )*
31            }
32
33            pub(crate) fn list_unstable(&self) -> String {
34                let mut list = Vec::new();
35                $(
36                    if !$stb && self.$i.is_some() {
37                        list.push(stringify!($i));
38                    }
39                )*
40                list.join(", ")
41            }
42        }
43    };
44}
45
46// Per https://github.com/rust-lang/rustfmt/blob/master/src/config/mod.rs
47// ... skipping the section titled "Not user-facing" and "Control options".
48//
49// This macro defines configuration options used in rustfmt. Each option
50// is defined as follows:
51//
52// `name: value type, default value, is stable, description;`
53create_config! {
54    // Fundamental stuff
55    max_width: usize, 100, true, "Maximum width of each line";
56    hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment";
57    tab_spaces: usize, 4, true, "Number of spaces per tab";
58    newline_style: NewlineStyle, NewlineStyle::Auto, true, "Unix or Windows line endings";
59    indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items";
60
61    // Width Heuristics
62    use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \
63        formatting for items and expressions if they satisfy a heuristic notion of 'small'";
64    fn_call_width: usize, 60, true, "Maximum width of the args of a function call before \
65        falling back to vertical formatting.";
66    attr_fn_like_width: usize, 70, true, "Maximum width of the args of a function-like \
67        attributes before falling back to vertical formatting.";
68    struct_lit_width: usize, 18, true, "Maximum width in the body of a struct lit before \
69        falling back to vertical formatting.";
70    struct_variant_width: usize, 35, true, "Maximum width in the body of a struct variant before \
71        falling back to vertical formatting.";
72    array_width: usize, 60, true,  "Maximum width of an array literal before falling \
73        back to vertical formatting.";
74    chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line.";
75    single_line_if_else_max_width: usize, 50, true, "Maximum line length for single line if-else \
76        expressions. A value of zero means always break if-else expressions.";
77
78    // Comments. macros, and strings
79    wrap_comments: bool, false, false, "Break comments to fit on the line";
80    format_code_in_doc_comments: bool, false, false, "Format the code snippet in doc comments.";
81    doc_comment_code_block_width: usize, 100, false, "Maximum width for code snippets in doc \
82        comments. No effect unless format_code_in_doc_comments = true";
83    comment_width: usize, 80, false,
84        "Maximum length of comments. No effect unless wrap_comments = true";
85    normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible";
86    normalize_doc_attributes: bool, false, false, "Normalize doc attributes as doc comments";
87    format_strings: bool, false, false, "Format string literals where necessary";
88    format_macro_matchers: bool, false, false,
89        "Format the metavariable matching patterns in macros";
90    format_macro_bodies: bool, true, false, "Format the bodies of macros";
91    hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
92        "Format hexadecimal integer literals";
93
94    // Single line expressions and items
95    empty_item_single_line: bool, true, false,
96        "Put empty-body functions and impls on a single line";
97    struct_lit_single_line: bool, true, false,
98        "Put small struct literals on a single line";
99    fn_single_line: bool, false, false, "Put single-expression functions on a single line";
100    where_single_line: bool, false, false, "Force where-clauses to be on a single line";
101
102    // Imports
103    imports_indent: IndentStyle, IndentStyle::Block, false, "Indent of imports";
104    imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block";
105    imports_granularity: ImportGranularity, ImportGranularity::Preserve, false,
106        "Merge or split imports to the provided granularity";
107    group_imports: GroupImportsTactic, GroupImportsTactic::Preserve, false,
108        "Controls the strategy for how imports are grouped together";
109    merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)";
110
111    // Ordering
112    reorder_imports: bool, true, true, "Reorder import and extern crate statements alphabetically";
113    reorder_modules: bool, true, true, "Reorder module statements alphabetically in group";
114    reorder_impl_items: bool, false, false, "Reorder impl items";
115
116    // Spaces around punctuation
117    type_punctuation_density: TypeDensity, TypeDensity::Wide, false,
118        "Determines if '+' or '=' are wrapped in spaces in the punctuation of types";
119    space_before_colon: bool, false, false, "Leave a space before the colon";
120    space_after_colon: bool, true, false, "Leave a space after the colon";
121    spaces_around_ranges: bool, false, false, "Put spaces around the  .. and ..= range operators";
122    binop_separator: SeparatorPlace, SeparatorPlace::Front, false,
123        "Where to put a binary operator when a binary expression goes multiline";
124
125    // Misc.
126    remove_nested_parens: bool, true, true, "Remove nested parens";
127    combine_control_expr: bool, true, false, "Combine control expressions with function calls";
128    short_array_element_width_threshold: usize, 10, true,
129        "Width threshold for an array element to be considered short";
130    overflow_delimited_expr: bool, false, false,
131        "Allow trailing bracket/brace delimited expressions to overflow";
132    struct_field_align_threshold: usize, 0, false,
133        "Align struct fields if their diffs fits within threshold";
134    enum_discrim_align_threshold: usize, 0, false,
135        "Align enum variants discrims, if their diffs fit within threshold";
136    match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \
137        the same line with the pattern of arms";
138    match_arm_leading_pipes: MatchArmLeadingPipe, MatchArmLeadingPipe::Never, true,
139        "Determines whether leading pipes are emitted on match arms";
140    force_multiline_blocks: bool, false, false,
141        "Force multiline closure bodies and match arms to be wrapped in a block";
142    fn_args_layout: Density, Density::Tall, true,
143        "Control the layout of arguments in a function";
144    brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items";
145    control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false,
146        "Brace style for control flow constructs";
147    trailing_semicolon: bool, true, false,
148        "Add trailing semicolon after break, continue and return";
149    trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false,
150        "How to handle trailing commas for lists";
151    match_block_trailing_comma: bool, false, true,
152        "Put a trailing comma after a block based match arm (non-block arms are not affected)";
153    blank_lines_upper_bound: usize, 1, false,
154        "Maximum number of blank lines which can be put between items";
155    blank_lines_lower_bound: usize, 0, false,
156        "Minimum number of blank lines which must be put between items";
157    edition: Edition, Edition::Edition2015, true, "The edition of the parser (RFC 2052)";
158    version: Version, Version::One, false, "Version of formatting rules";
159    inline_attribute_width: usize, 0, false,
160        "Write an item and its attribute on the same line \
161        if their combined width is below a threshold";
162    format_generated_files: bool, true, false, "Format generated files";
163
164    // Options that can change the source code beyond whitespace/blocks (somewhat linty things)
165    merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
166    use_try_shorthand: bool, false, true, "Replace uses of the try! macro by the ? shorthand";
167    use_field_init_shorthand: bool, false, true, "Use field initialization shorthand if possible";
168    force_explicit_abi: bool, true, true, "Always print the abi for extern items";
169    condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \
170                                                     in tuple patterns";
171
172    // Control options (changes the operation of rustfmt, rather than the formatting)
173    // [..] deleted
174
175    // Not user-facing
176    // [..] deleted
177}
178
179macro_rules! make_enum {
180    ($name:ident $(, $v:ident)+) => {
181        #[derive(Serialize)]
182        pub enum $name {
183            $( $v, )*
184        }
185    };
186}
187
188make_enum!(NewlineStyle, Auto, Windows, Unix, Native);
189make_enum!(IndentStyle, Visual, Block);
190make_enum!(Heuristics, Off, Max, Default);
191make_enum!(HexLiteralCase, Preserve, Upper, Lower);
192make_enum!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed);
193make_enum!(ImportGranularity, Preserve, Crate, Module, Item, One);
194make_enum!(GroupImportsTactic, Preserve, StdExternalCrate, One);
195make_enum!(TypeDensity, Compressed, Wide);
196make_enum!(SeparatorPlace, Front, Back);
197make_enum!(MatchArmLeadingPipe, Always, Never, Preserve);
198make_enum!(Density, Compressed, Tall, Vertical);
199make_enum!(BraceStyle, AlwaysNextLine, PreferSameLine, SameLineWhere);
200make_enum!(
201    ControlBraceStyle,
202    AlwaysSameLine,
203    ClosingNextLine,
204    AlwaysNextLine
205);
206make_enum!(SeparatorTactic, Always, Never, Vertical);
207make_enum!(Version, One, Two);
208
209#[derive(Serialize)]
210pub enum Edition {
211    #[serde(rename = "2015")]
212    Edition2015,
213    #[serde(rename = "2018")]
214    Edition2018,
215    #[serde(rename = "2021")]
216    Edition2021,
217    #[serde(rename = "2024")]
218    Edition2024,
219}