Implement StyleEditionDefault for each config option

Makes internal changes to define each configuration in terms of the
`StyleEditionDefault` trait, and hard codes `StyleEdition::Edition2015`
anywhere the new `style_edition` is needed.

**Note** users are still unable to configure `style edition`.
This commit is contained in:
Yacin Tmimi 2023-10-08 14:21:10 -04:00
parent 071ca7dc45
commit 7cdb426c05
4 changed files with 335 additions and 158 deletions

View File

@ -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>, bool, $ty, bool)),+
$($i: (Cell<bool>, 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)
}
}
)

View File

@ -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)]

View File

@ -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;
);

View File

@ -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;
}