diff --git a/src/config/config_type.rs b/src/config/config_type.rs index f7cff1a1729..41d6cdab104 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -70,15 +70,15 @@ macro_rules! create_config { // // - $i: the ident name of the option // - $ty: the type of the option value - // - $def: the default value of the option // - $stb: true if the option is stable // - $dstring: description of the option - ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( + ($($i:ident: $ty:ty, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( #[cfg(test)] use std::collections::HashSet; use std::io::Write; use serde::{Deserialize, Serialize}; + use $crate::config::style_edition::StyleEditionDefault; #[derive(Clone)] #[allow(unreachable_pub)] @@ -89,7 +89,7 @@ pub struct Config { // - 1: true if the option was manually initialized // - 2: the option value // - 3: true if the option is unstable - $($i: (Cell, bool, $ty, bool)),+ + $($i: (Cell, bool, <$ty as StyleEditionDefault>::ConfigType, bool)),+ } // Just like the Config struct but with each property wrapped @@ -100,7 +100,7 @@ pub struct Config { #[derive(Deserialize, Serialize, Clone)] #[allow(unreachable_pub)] pub struct PartialConfig { - $(pub $i: Option<$ty>),+ + $(pub $i: Option<<$ty as StyleEditionDefault>::ConfigType>),+ } // Macro hygiene won't allow us to make `set_$i()` methods on Config @@ -114,7 +114,7 @@ pub struct PartialConfig { impl<'a> ConfigSetter<'a> { $( #[allow(unreachable_pub)] - pub fn $i(&mut self, value: $ty) { + pub fn $i(&mut self, value: <$ty as StyleEditionDefault>::ConfigType) { (self.0).$i.2 = value; match stringify!($i) { "max_width" @@ -153,12 +153,28 @@ pub fn $i(&self) -> bool { impl Config { $( #[allow(unreachable_pub)] - pub fn $i(&self) -> $ty { + pub fn $i(&self) -> <$ty as StyleEditionDefault>::ConfigType { self.$i.0.set(true); self.$i.2.clone() } )+ + #[allow(unreachable_pub)] + pub fn default_with_style_edition(style_edition: StyleEdition) -> Config { + Config { + $( + $i: ( + Cell::new(false), + false, + <$ty as StyleEditionDefault>::style_edition_default( + style_edition + ), + $stb + ), + )+ + } + } + #[allow(unreachable_pub)] pub fn set(&mut self) -> ConfigSetter<'_> { ConfigSetter(self) @@ -212,7 +228,9 @@ pub(crate) fn is_valid_name(name: &str) -> bool { pub fn is_valid_key_val(key: &str, val: &str) -> bool { match key { $( - stringify!($i) => val.parse::<$ty>().is_ok(), + stringify!($i) => { + val.parse::<<$ty as StyleEditionDefault>::ConfigType>().is_ok() + } )+ _ => false, } @@ -246,11 +264,15 @@ pub fn override_value(&mut self, key: &str, val: &str) match key { $( stringify!($i) => { - let option_value = val.parse::<$ty>() - .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", - stringify!($i), - val, - stringify!($ty))); + let value = val.parse::<<$ty as StyleEditionDefault>::ConfigType>() + .expect( + &format!( + "Failed to parse override for {} (\"{}\") as a {}", + stringify!($i), + val, + stringify!(<$ty as StyleEditionDefault>::ConfigType) + ) + ); // Users are currently allowed to set unstable // options/variants via the `--config` options override. @@ -261,7 +283,7 @@ pub fn override_value(&mut self, key: &str, val: &str) // For now, do not validate whether the option or value is stable, // just always set it. self.$i.1 = true; - self.$i.2 = option_value; + self.$i.2 = value; } )+ _ => panic!("Unknown config key in override: {}", key) @@ -301,6 +323,7 @@ pub fn is_hidden_option(name: &str) -> bool { #[allow(unreachable_pub)] pub fn print_docs(out: &mut dyn Write, include_unstable: bool) { + let style_edition = StyleEdition::Edition2015; use std::cmp; let max = 0; $( let max = cmp::max(max, stringify!($i).len()+1); )+ @@ -317,14 +340,17 @@ pub fn print_docs(out: &mut dyn Write, include_unstable: bool) { } name_out.push_str(name_raw); name_out.push(' '); - let mut default_str = format!("{}", $def); + let default_value = <$ty as StyleEditionDefault>::style_edition_default( + style_edition + ); + let mut default_str = format!("{}", default_value); if default_str.is_empty() { default_str = String::from("\"\""); } writeln!(out, "{}{} Default: {}{}", name_out, - <$ty>::doc_hint(), + <<$ty as StyleEditionDefault>::ConfigType>::doc_hint(), default_str, if !$stb { " (unstable)" } else { "" }).unwrap(); $( @@ -480,9 +506,13 @@ fn set_hide_parse_errors(&mut self) { #[allow(unreachable_pub)] /// Returns `true` if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { + let style_edition = StyleEdition::Edition2015; $( + let default_value = <$ty as StyleEditionDefault>::style_edition_default( + style_edition + ); if let stringify!($i) = key { - return self.$i.1 && self.$i.2 == $def; + return self.$i.1 && self.$i.2 == default_value; } )+ false @@ -492,11 +522,7 @@ pub fn is_default(&self, key: &str) -> bool { // Template for the default configuration impl Default for Config { fn default() -> Config { - Config { - $( - $i: (Cell::new(false), false, $def, $stb), - )+ - } + Config::default_with_style_edition(StyleEdition::Edition2015) } } ) diff --git a/src/config/mod.rs b/src/config/mod.rs index eb92b8f6eeb..b38ca2b8dec 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -10,9 +10,7 @@ #[allow(unreachable_pub)] pub use crate::config::file_lines::{FileLines, FileName, Range}; #[allow(unreachable_pub)] -pub use crate::config::lists::*; -#[allow(unreachable_pub)] -pub use crate::config::macro_names::{MacroSelector, MacroSelectors}; +pub use crate::config::macro_names::MacroSelector; #[allow(unreachable_pub)] pub use crate::config::options::*; @@ -34,161 +32,168 @@ // `name: value type, default value, is stable, description;` create_config! { // Fundamental stuff - max_width: usize, 100, true, "Maximum width of each line"; - hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; - tab_spaces: usize, 4, true, "Number of spaces per tab"; - newline_style: NewlineStyle, NewlineStyle::Auto, true, "Unix or Windows line endings"; - indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items"; + max_width: MaxWidth, true, "Maximum width of each line"; + hard_tabs: HardTabs, true, "Use tab characters for indentation, spaces for alignment"; + tab_spaces: TabSpaces, true, "Number of spaces per tab"; + newline_style: NewlineStyleConfig, true, "Unix or Windows line endings"; + indent_style: IndentStyleConfig, false, "How do we indent expressions or items"; // Width Heuristics - use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \ + use_small_heuristics: UseSmallHeuristics, true, "Whether to use different \ formatting for items and expressions if they satisfy a heuristic notion of 'small'"; - width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, - "'small' heuristic values"; - fn_call_width: usize, 60, true, "Maximum width of the args of a function call before \ + width_heuristics: WidthHeuristicsConfig, false, "'small' heuristic values"; + fn_call_width: FnCallWidth, true, "Maximum width of the args of a function call before \ falling back to vertical formatting."; - attr_fn_like_width: usize, 70, true, "Maximum width of the args of a function-like \ + attr_fn_like_width: AttrFnLikeWidth, true, "Maximum width of the args of a function-like \ attributes before falling back to vertical formatting."; - struct_lit_width: usize, 18, true, "Maximum width in the body of a struct lit before \ + struct_lit_width: StructLitWidth, true, "Maximum width in the body of a struct lit before \ falling back to vertical formatting."; - struct_variant_width: usize, 35, true, "Maximum width in the body of a struct variant before \ - falling back to vertical formatting."; - array_width: usize, 60, true, "Maximum width of an array literal before falling \ + struct_variant_width: StructVariantWidth, true, "Maximum width in the body of a struct variant \ + before falling back to vertical formatting."; + array_width: ArrayWidth, true, "Maximum width of an array literal before falling \ back to vertical formatting."; - chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line."; - single_line_if_else_max_width: usize, 50, true, "Maximum line length for single line if-else \ - expressions. A value of zero means always break if-else expressions."; - single_line_let_else_max_width: usize, 50, true, "Maximum line length for single line \ - let-else statements. A value of zero means always format the divergent `else` block \ - over multiple lines."; + chain_width: ChainWidth, true, "Maximum length of a chain to fit on a single line."; + single_line_if_else_max_width: SingleLineIfElseMaxWidth, true, "Maximum line length for single \ + line if-else expressions. A value of zero means always break if-else expressions."; + single_line_let_else_max_width: SingleLineLetElseMaxWidth, true, "Maximum line length for \ + single line let-else statements. A value of zero means always format the divergent `else` \ + block over multiple lines."; // Comments. macros, and strings - wrap_comments: bool, false, false, "Break comments to fit on the line"; - format_code_in_doc_comments: bool, false, false, "Format the code snippet in doc comments."; - doc_comment_code_block_width: usize, 100, false, "Maximum width for code snippets in doc \ - comments. No effect unless format_code_in_doc_comments = true"; - comment_width: usize, 80, false, + wrap_comments: WrapComments, false, "Break comments to fit on the line"; + format_code_in_doc_comments: FormatCodeInDocComments, false, "Format the code snippet in \ + doc comments."; + doc_comment_code_block_width: DocCommentCodeBlockWidth, false, "Maximum width for code \ + snippets in doc comments. No effect unless format_code_in_doc_comments = true"; + comment_width: CommentWidth, false, "Maximum length of comments. No effect unless wrap_comments = true"; - normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; - normalize_doc_attributes: bool, false, false, "Normalize doc attributes as doc comments"; - format_strings: bool, false, false, "Format string literals where necessary"; - format_macro_matchers: bool, false, false, + normalize_comments: NormalizeComments, false, "Convert /* */ comments to // comments where \ + possible"; + normalize_doc_attributes: NormalizeDocAttributes, false, "Normalize doc attributes as doc \ + comments"; + format_strings: FormatStrings, false, "Format string literals where necessary"; + format_macro_matchers: FormatMacroMatchers, false, "Format the metavariable matching patterns in macros"; - format_macro_bodies: bool, true, false, "Format the bodies of declarative macro definitions"; - skip_macro_invocations: MacroSelectors, MacroSelectors::default(), false, + format_macro_bodies: FormatMacroBodies, false, + "Format the bodies of declarative macro definitions"; + skip_macro_invocations: SkipMacroInvocations, false, "Skip formatting the bodies of macros invoked with the following names."; - hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false, - "Format hexadecimal integer literals"; + hex_literal_case: HexLiteralCaseConfig, false, "Format hexadecimal integer literals"; // Single line expressions and items - empty_item_single_line: bool, true, false, + empty_item_single_line: EmptyItemSingleLine, false, "Put empty-body functions and impls on a single line"; - struct_lit_single_line: bool, true, false, + struct_lit_single_line: StructLitSingleLine, false, "Put small struct literals on a single line"; - fn_single_line: bool, false, false, "Put single-expression functions on a single line"; - where_single_line: bool, false, false, "Force where-clauses to be on a single line"; + fn_single_line: FnSingleLine, false, "Put single-expression functions on a single line"; + where_single_line: WhereSingleLine, false, "Force where-clauses to be on a single line"; // Imports - imports_indent: IndentStyle, IndentStyle::Block, false, "Indent of imports"; - imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; - imports_granularity: ImportGranularity, ImportGranularity::Preserve, false, + imports_indent: ImportsIndent, false, "Indent of imports"; + imports_layout: ImportsLayout, false, "Item layout inside a import block"; + imports_granularity: ImportsGranularityConfig, false, "Merge or split imports to the provided granularity"; - group_imports: GroupImportsTactic, GroupImportsTactic::Preserve, false, + group_imports: GroupImportsTacticConfig, false, "Controls the strategy for how imports are grouped together"; - merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)"; + merge_imports: MergeImports, false, "(deprecated: use imports_granularity instead)"; // Ordering - reorder_imports: bool, true, true, "Reorder import and extern crate statements alphabetically"; - reorder_modules: bool, true, true, "Reorder module statements alphabetically in group"; - reorder_impl_items: bool, false, false, "Reorder impl items"; + reorder_imports: ReorderImports, true, "Reorder import and extern crate statements \ + alphabetically"; + reorder_modules: ReorderModules, true, "Reorder module statements alphabetically in group"; + reorder_impl_items: ReorderImplItems, false, "Reorder impl items"; // Spaces around punctuation - type_punctuation_density: TypeDensity, TypeDensity::Wide, false, + type_punctuation_density: TypePunctuationDensity, false, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; - space_before_colon: bool, false, false, "Leave a space before the colon"; - space_after_colon: bool, true, false, "Leave a space after the colon"; - spaces_around_ranges: bool, false, false, "Put spaces around the .. and ..= range operators"; - binop_separator: SeparatorPlace, SeparatorPlace::Front, false, + space_before_colon: SpaceBeforeColon, false, "Leave a space before the colon"; + space_after_colon: SpaceAfterColon, false, "Leave a space after the colon"; + spaces_around_ranges: SpacesAroundRanges, false, "Put spaces around the .. and ..= range \ + operators"; + binop_separator: BinopSeparator, false, "Where to put a binary operator when a binary expression goes multiline"; // Misc. - remove_nested_parens: bool, true, true, "Remove nested parens"; - combine_control_expr: bool, true, false, "Combine control expressions with function calls"; - short_array_element_width_threshold: usize, 10, true, + remove_nested_parens: RemoveNestedParens, true, "Remove nested parens"; + combine_control_expr: CombineControlExpr, false, "Combine control expressions with function \ + calls"; + short_array_element_width_threshold: ShortArrayElementWidthThreshold, true, "Width threshold for an array element to be considered short"; - overflow_delimited_expr: bool, false, false, + overflow_delimited_expr: OverflowDelimitedExpr, false, "Allow trailing bracket/brace delimited expressions to overflow"; - struct_field_align_threshold: usize, 0, false, + struct_field_align_threshold: StructFieldAlignThreshold, false, "Align struct fields if their diffs fits within threshold"; - enum_discrim_align_threshold: usize, 0, false, + enum_discrim_align_threshold: EnumDiscrimAlignThreshold, false, "Align enum variants discrims, if their diffs fit within threshold"; - match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ - the same line with the pattern of arms"; - match_arm_leading_pipes: MatchArmLeadingPipe, MatchArmLeadingPipe::Never, true, + match_arm_blocks: MatchArmBlocks, false, "Wrap the body of arms in blocks when it does not fit \ + on the same line with the pattern of arms"; + match_arm_leading_pipes: MatchArmLeadingPipeConfig, true, "Determines whether leading pipes are emitted on match arms"; - force_multiline_blocks: bool, false, false, + force_multiline_blocks: ForceMultilineBlocks, false, "Force multiline closure bodies and match arms to be wrapped in a block"; - fn_args_layout: Density, Density::Tall, true, + fn_args_layout: FnArgsLayout, true, "(deprecated: use fn_params_layout instead)"; - fn_params_layout: Density, Density::Tall, true, + fn_params_layout: FnParamsLayout, true, "Control the layout of parameters in function signatures."; - brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; - control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, + brace_style: BraceStyleConfig, false, "Brace style for items"; + control_brace_style: ControlBraceStyleConfig, false, "Brace style for control flow constructs"; - trailing_semicolon: bool, true, false, + trailing_semicolon: TrailingSemicolon, false, "Add trailing semicolon after break, continue and return"; - trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, + trailing_comma: TrailingComma, false, "How to handle trailing commas for lists"; - match_block_trailing_comma: bool, false, true, + match_block_trailing_comma: MatchBlockTrailingComma, true, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; - blank_lines_upper_bound: usize, 1, false, + blank_lines_upper_bound: BlankLinesUpperBound, false, "Maximum number of blank lines which can be put between items"; - blank_lines_lower_bound: usize, 0, false, + blank_lines_lower_bound: BlankLinesLowerBound, false, "Minimum number of blank lines which must be put between items"; - edition: Edition, Edition::Edition2015, true, "The edition of the parser (RFC 2052)"; - version: Version, Version::One, false, "Version of formatting rules"; - inline_attribute_width: usize, 0, false, + edition: EditionConfig, true, "The edition of the parser (RFC 2052)"; + version: VersionConfig, false, "Version of formatting rules"; + inline_attribute_width: InlineAttributeWidth, false, "Write an item and its attribute on the same line \ if their combined width is below a threshold"; - format_generated_files: bool, true, false, "Format generated files"; - generated_marker_line_search_limit: usize, 5, false, "Number of lines to check for a \ - `@generated` marker when `format_generated_files` is enabled"; + format_generated_files: FormatGeneratedFiles, false, "Format generated files"; + generated_marker_line_search_limit: GeneratedMarkerLineSearchLimit, false, "Number of lines to \ + check for a `@generated` marker when `format_generated_files` is enabled"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) - merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; - use_try_shorthand: bool, false, true, "Replace uses of the try! macro by the ? shorthand"; - use_field_init_shorthand: bool, false, true, "Use field initialization shorthand if possible"; - force_explicit_abi: bool, true, true, "Always print the abi for extern items"; - condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ - in tuple patterns"; + merge_derives: MergeDerives, true, "Merge multiple `#[derive(...)]` into a single one"; + use_try_shorthand: UseTryShorthand, true, "Replace uses of the try! macro by the ? shorthand"; + use_field_init_shorthand: UseFieldInitShorthand, true, "Use field initialization shorthand if \ + possible"; + force_explicit_abi: ForceExplicitAbi, true, "Always print the abi for extern items"; + condense_wildcard_suffixes: CondenseWildcardSuffixes, false, "Replace strings of _ wildcards \ + by a single .. in tuple patterns"; // Control options (changes the operation of rustfmt, rather than the formatting) - color: Color, Color::Auto, false, + color: ColorConfig, false, "What Color option to use when none is supplied: Always, Never, Auto"; - required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, + required_version: RequiredVersion, false, "Require a specific version of rustfmt"; - unstable_features: bool, false, false, + unstable_features: UnstableFeatures, false, "Enables unstable features. Only available on nightly channel"; - disable_all_formatting: bool, false, true, "Don't reformat anything"; - skip_children: bool, false, false, "Don't reformat out of line modules"; - hide_parse_errors: bool, false, false, "(deprecated: use show_parse_errors instead)"; - show_parse_errors: bool, true, false, "Show errors from the parser (unstable)"; - error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width"; - error_on_unformatted: bool, false, false, + disable_all_formatting: DisableAllFormatting, true, "Don't reformat anything"; + skip_children: SkipChildren, false, "Don't reformat out of line modules"; + hide_parse_errors: HideParseErrors, false, "Hide errors from the parser"; + show_parse_errors: ShowParseErrors, false, "Show errors from the parser (unstable)"; + error_on_line_overflow: ErrorOnLineOverflow, false, "Error if unable to get all lines within \ + max_width"; + error_on_unformatted: ErrorOnUnformatted, false, "Error if unable to get comments or string literals within max_width, \ or they are left with trailing whitespaces"; - ignore: IgnoreList, IgnoreList::default(), false, + ignore: Ignore, false, "Skip formatting the specified files and directories"; // Not user-facing - verbose: Verbosity, Verbosity::Normal, false, "How much to information to emit to the user"; - file_lines: FileLines, FileLines::all(), false, + verbose: Verbose, false, "How much to information to emit to the user"; + file_lines: FileLinesConfig, false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; - emit_mode: EmitMode, EmitMode::Files, false, + emit_mode: EmitModeConfig, false, "What emit Mode to use when none is supplied"; - make_backup: bool, false, false, "Backup changed files"; - print_misformatted_file_names: bool, false, true, + make_backup: MakeBackup, false, "Backup changed files"; + print_misformatted_file_names: PrintMisformattedFileNames, true, "Prints the names of mismatched files that were formatted. Prints the names of \ files that would be formatted when used with `--check` mode. "; } @@ -420,12 +425,13 @@ mod test { use super::*; use std::str; - use crate::config::macro_names::MacroName; + use crate::config::macro_names::{MacroName, MacroSelectors}; use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test}; #[allow(dead_code)] mod mock { use super::super::*; + use crate::config_option_with_style_edition_default; use rustfmt_config_proc_macro::config_type; #[config_type] @@ -436,66 +442,66 @@ pub(crate) enum PartiallyUnstableOption { V3, } + config_option_with_style_edition_default!( + StableOption, bool, _ => false; + UnstableOption, bool, _ => false; + PartiallyUnstable, PartiallyUnstableOption, _ => PartiallyUnstableOption::V1; + ); + create_config! { // Options that are used by the generated functions - max_width: usize, 100, true, "Maximum width of each line"; - required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, - "Require a specific version of rustfmt."; - ignore: IgnoreList, IgnoreList::default(), false, - "Skip formatting the specified files and directories."; - verbose: Verbosity, Verbosity::Normal, false, - "How much to information to emit to the user"; - file_lines: FileLines, FileLines::all(), false, + max_width: MaxWidth, true, "Maximum width of each line"; + required_version: RequiredVersion, false, "Require a specific version of rustfmt."; + ignore: Ignore, false, "Skip formatting the specified files and directories."; + verbose: Verbose, false, "How much to information to emit to the user"; + file_lines: FileLinesConfig, false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; // merge_imports deprecation - imports_granularity: ImportGranularity, ImportGranularity::Preserve, false, - "Merge imports"; - merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)"; + imports_granularity: ImportsGranularityConfig, false, "Merge imports"; + merge_imports: MergeImports, false, "(deprecated: use imports_granularity instead)"; // fn_args_layout renamed to fn_params_layout - fn_args_layout: Density, Density::Tall, true, - "(deprecated: use fn_params_layout instead)"; - fn_params_layout: Density, Density::Tall, true, + fn_args_layout: FnArgsLayout, true, "(deprecated: use fn_params_layout instead)"; + fn_params_layout: FnParamsLayout, true, "Control the layout of parameters in a function signatures."; // hide_parse_errors renamed to show_parse_errors - hide_parse_errors: bool, false, false, + hide_parse_errors: HideParseErrors, false, "(deprecated: use show_parse_errors instead)"; - show_parse_errors: bool, true, false, + show_parse_errors: ShowParseErrors, false, "Show errors from the parser (unstable)"; // Width Heuristics - use_small_heuristics: Heuristics, Heuristics::Default, true, + use_small_heuristics: UseSmallHeuristics, true, "Whether to use different formatting for items and \ expressions if they satisfy a heuristic notion of 'small'."; - width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, - "'small' heuristic values"; + width_heuristics: WidthHeuristicsConfig, false, "'small' heuristic values"; - fn_call_width: usize, 60, true, "Maximum width of the args of a function call before \ + fn_call_width: FnCallWidth, true, "Maximum width of the args of a function call before \ falling back to vertical formatting."; - attr_fn_like_width: usize, 70, true, "Maximum width of the args of a function-like \ - attributes before falling back to vertical formatting."; - struct_lit_width: usize, 18, true, "Maximum width in the body of a struct lit before \ - falling back to vertical formatting."; - struct_variant_width: usize, 35, true, "Maximum width in the body of a struct \ + attr_fn_like_width: AttrFnLikeWidth, true, "Maximum width of the args of a \ + function-like attributes before falling back to vertical formatting."; + struct_lit_width: StructLitWidth, true, "Maximum width in the body of a struct lit \ + before falling back to vertical formatting."; + struct_variant_width: StructVariantWidth, true, "Maximum width in the body of a struct \ variant before falling back to vertical formatting."; - array_width: usize, 60, true, "Maximum width of an array literal before falling \ + array_width: ArrayWidth, true, "Maximum width of an array literal before falling \ back to vertical formatting."; - chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line."; - single_line_if_else_max_width: usize, 50, true, "Maximum line length for single \ - line if-else expressions. A value of zero means always break if-else expressions."; - single_line_let_else_max_width: usize, 50, false, "Maximum line length for single \ - line let-else statements. A value of zero means always format the divergent \ - `else` block over multiple lines."; + chain_width: ChainWidth, true, "Maximum length of a chain to fit on a single line."; + single_line_if_else_max_width: SingleLineIfElseMaxWidth, true, "Maximum line length \ + for single line if-else expressions. A value of zero means always break if-else \ + expressions."; + single_line_let_else_max_width: SingleLineLetElseMaxWidth, false, "Maximum line length \ + for single line let-else statements. A value of zero means always format the \ + divergent `else` block over multiple lines."; // Options that are used by the tests - stable_option: bool, false, true, "A stable option"; - unstable_option: bool, false, false, "An unstable option"; - partially_unstable_option: PartiallyUnstableOption, PartiallyUnstableOption::V1, true, - "A partially unstable option"; + stable_option: StableOption, true, "A stable option"; + unstable_option: UnstableOption, false, "An unstable option"; + partially_unstable_option: PartiallyUnstable, true, "A partially unstable option"; } #[cfg(test)] diff --git a/src/config/options.rs b/src/config/options.rs index 3c5c713a33a..e674aba86f8 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -11,7 +11,9 @@ use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use crate::config::file_lines::FileLines; use crate::config::lists::*; +use crate::config::macro_names::MacroSelectors; use crate::config::Config; #[config_type] @@ -494,3 +496,146 @@ pub enum StyleEdition { /// [Edition 2024](). Edition2024, } + +/// Defines unit structs to implement `StyleEditionDefault` for. +#[macro_export] +macro_rules! config_option_with_style_edition_default { + ($name:ident, $config_ty:ty, _ => $default:expr) => { + #[allow(unreachable_pub)] + pub struct $name; + $crate::style_edition_default!($name, $config_ty, _ => $default); + }; + ($name:ident, $config_ty:ty, Edition2024 => $default_2024:expr, _ => $default_2015:expr) => { + pub struct $name; + $crate::style_edition_default!( + $name, + $config_ty, + Edition2024 => $default_2024, + _ => $default_2015 + ); + }; + ( + $($name:ident, $config_ty:ty, $(Edition2024 => $default_2024:expr,)? _ => $default:expr);* + $(;)* + ) => { + $( + config_option_with_style_edition_default!( + $name, $config_ty, $(Edition2024 => $default_2024,)? _ => $default + ); + )* + }; +} + +// TODO(ytmimi) Some of the configuration values have a `Config` suffix, while others don't. +// I chose to add a `Config` suffix in cases where a type for the config option was already +// defined. For example, `NewlineStyle` and `NewlineStyleConfig`. There was some discussion +// about using the `Config` suffix more consistently. +config_option_with_style_edition_default!( + // Fundamental stuff + MaxWidth, usize, _ => 100; + HardTabs, bool, _ => false; + TabSpaces, usize, _ => 4; + NewlineStyleConfig, NewlineStyle, _ => NewlineStyle::Auto; + IndentStyleConfig, IndentStyle, _ => IndentStyle::Block; + + // Width Heuristics + UseSmallHeuristics, Heuristics, _ => Heuristics::Default; + WidthHeuristicsConfig, WidthHeuristics, _ => WidthHeuristics::scaled(100); + FnCallWidth, usize, _ => 60; + AttrFnLikeWidth, usize, _ => 70; + StructLitWidth, usize, _ => 18; + StructVariantWidth, usize, _ => 35; + ArrayWidth, usize, _ => 60; + ChainWidth, usize, _ => 60; + SingleLineIfElseMaxWidth, usize, _ => 50; + SingleLineLetElseMaxWidth, usize, _ => 50; + + // Comments. macros, and strings + WrapComments, bool, _ => false; + FormatCodeInDocComments, bool, _ => false; + DocCommentCodeBlockWidth, usize, _ => 100; + CommentWidth, usize, _ => 80; + NormalizeComments, bool, _ => false; + NormalizeDocAttributes, bool, _ => false; + FormatStrings, bool, _ => false; + FormatMacroMatchers, bool, _ => false; + FormatMacroBodies, bool, _ => true; + SkipMacroInvocations, MacroSelectors, _ => MacroSelectors::default(); + HexLiteralCaseConfig, HexLiteralCase, _ => HexLiteralCase::Preserve; + + // Single line expressions and items + EmptyItemSingleLine, bool, _ => true; + StructLitSingleLine, bool, _ => true; + FnSingleLine, bool, _ => false; + WhereSingleLine, bool, _ => false; + + // Imports + ImportsIndent, IndentStyle, _ => IndentStyle::Block; + ImportsLayout, ListTactic, _ => ListTactic::Mixed; + ImportsGranularityConfig, ImportGranularity, _ => ImportGranularity::Preserve; + GroupImportsTacticConfig, GroupImportsTactic, _ => GroupImportsTactic::Preserve; + MergeImports, bool, _ => false; + + // Ordering + ReorderImports, bool, _ => true; + ReorderModules, bool, _ => true; + ReorderImplItems, bool, _ => false; + + // Spaces around punctuation + TypePunctuationDensity, TypeDensity, _ => TypeDensity::Wide; + SpaceBeforeColon, bool, _ => false; + SpaceAfterColon, bool, _ => true; + SpacesAroundRanges, bool, _ => false; + BinopSeparator, SeparatorPlace, _ => SeparatorPlace::Front; + + // Misc. + RemoveNestedParens, bool, _ => true; + CombineControlExpr, bool, _ => true; + ShortArrayElementWidthThreshold, usize, _ => 10; + OverflowDelimitedExpr, bool, _ => false; + StructFieldAlignThreshold, usize, _ => 0; + EnumDiscrimAlignThreshold, usize, _ => 0; + MatchArmBlocks, bool, _ => true; + MatchArmLeadingPipeConfig, MatchArmLeadingPipe, _ => MatchArmLeadingPipe::Never; + ForceMultilineBlocks, bool, _ => false; + FnArgsLayout, Density, _ => Density::Tall; + FnParamsLayout, Density, _ => Density::Tall; + BraceStyleConfig, BraceStyle, _ => BraceStyle::SameLineWhere; + ControlBraceStyleConfig, ControlBraceStyle, _ => ControlBraceStyle::AlwaysSameLine; + TrailingSemicolon, bool, _ => true; + TrailingComma, SeparatorTactic, _ => SeparatorTactic::Vertical; + MatchBlockTrailingComma, bool, _ => false; + BlankLinesUpperBound, usize, _ => 1; + BlankLinesLowerBound, usize, _ => 0; + EditionConfig, Edition, _ => Edition::Edition2015; + VersionConfig, Version, Edition2024 => Version::Two, _ => Version::One; + InlineAttributeWidth, usize, _ => 0; + FormatGeneratedFiles, bool, _ => true; + GeneratedMarkerLineSearchLimit, usize, _ => 5; + + // Options that can change the source code beyond whitespace/blocks (somewhat linty things) + MergeDerives, bool, _ => true; + UseTryShorthand, bool, _ => false; + UseFieldInitShorthand, bool, _ => false; + ForceExplicitAbi, bool, _ => true; + CondenseWildcardSuffixes, bool, _ => false; + + // Control options (changes the operation of rustfmt, rather than the formatting) + ColorConfig, Color, _ => Color::Auto; + RequiredVersion, String, _ => env!("CARGO_PKG_VERSION").to_owned(); + UnstableFeatures, bool, _ => false; + DisableAllFormatting, bool, _ => false; + SkipChildren, bool, _ => false; + HideParseErrors, bool, _ => false; + ShowParseErrors, bool, _ => true; + ErrorOnLineOverflow, bool, _ => false; + ErrorOnUnformatted, bool, _ => false; + Ignore, IgnoreList, _ => IgnoreList::default(); + + // Not user-facing + Verbose, Verbosity, _ => Verbosity::Normal; + FileLinesConfig, FileLines, _ => FileLines::all(); + EmitModeConfig, EmitMode, _ => EmitMode::Files; + MakeBackup, bool, _ => false; + PrintMisformattedFileNames, bool, _ => false; +); diff --git a/src/config/style_edition.rs b/src/config/style_edition.rs index 7b3ea3bc119..c34eca9c8e1 100644 --- a/src/config/style_edition.rs +++ b/src/config/style_edition.rs @@ -2,7 +2,7 @@ /// Defines the default value for the given style edition #[allow(dead_code)] -pub(crate) trait StyleEditionDefault { +pub trait StyleEditionDefault { type ConfigType; fn style_edition_default(style_edition: StyleEdition) -> Self::ConfigType; }