X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fconfig%2Foptions.rs;h=c0491630c000e2bdd4c5bbbdc87cd80b20a46aa2;hb=612e8d5b9be72713a081370c85cc5bed30b6fae6;hp=c927cffba291c92013d9254100367c29b8d14f7c;hpb=ee6f686cc9aeadc60090dc72a4cbeab6c3156c5a;p=rust.git diff --git a/src/config/options.rs b/src/config/options.rs index c927cffba29..c0491630c00 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -1,11 +1,13 @@ use std::collections::{hash_set, HashSet}; use std::fmt; use std::path::{Path, PathBuf}; +use std::str::FromStr; -use atty; -use config_proc_macro::config_type; +use itertools::Itertools; +use rustfmt_config_proc_macro::config_type; use serde::de::{SeqAccess, Visitor}; -use serde::{Deserialize, Deserializer, Serialize}; +use serde::ser::SerializeSeq; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::config::lists::*; use crate::config::Config; @@ -22,62 +24,6 @@ pub enum NewlineStyle { Native, } -impl NewlineStyle { - fn auto_detect(raw_input_text: &str) -> NewlineStyle { - if let Some(pos) = raw_input_text.find('\n') { - let pos = pos.saturating_sub(1); - if let Some('\r') = raw_input_text.chars().nth(pos) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } else { - NewlineStyle::Native - } - } - - fn native() -> NewlineStyle { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } - - /// Apply this newline style to the formatted text. When the style is set - /// to `Auto`, the `raw_input_text` is used to detect the existing line - /// endings. - /// - /// If the style is set to `Auto` and `raw_input_text` contains no - /// newlines, the `Native` style will be used. - pub(crate) fn apply(self, formatted_text: &mut String, raw_input_text: &str) { - use crate::NewlineStyle::*; - let mut style = self; - if style == Auto { - style = Self::auto_detect(raw_input_text); - } - if style == Native { - style = Self::native(); - } - match style { - Windows => { - let mut transformed = String::with_capacity(2 * formatted_text.capacity()); - for c in formatted_text.chars() { - match c { - '\n' => transformed.push_str("\r\n"), - '\r' => continue, - c => transformed.push(c), - } - } - *formatted_text = transformed; - } - Unix => return, - Native => unreachable!("NewlineStyle::Native"), - Auto => unreachable!("NewlineStyle::Auto"), - } - } -} - #[config_type] /// Where to put the opening brace of items (`fn`, `impl`, etc.). pub enum BraceStyle { @@ -113,10 +59,11 @@ pub enum IndentStyle { #[config_type] /// How to place a list-like items. +/// FIXME: Issue-3581: this should be renamed to ItemsLayout when publishing 2.0 pub enum Density { /// Fit as much on one line as possible. Compressed, - /// Use more lines. + /// Items are placed horizontally if sufficient space, vertically otherwise. Tall, /// Place every item on a separate line. Vertical, @@ -153,6 +100,31 @@ pub fn to_list_tactic(self, len: usize) -> ListTactic { } } +#[config_type] +/// Configuration for import groups, i.e. sets of imports separated by newlines. +pub enum GroupImportsTactic { + /// Keep groups as they are. + Preserve, + /// Discard existing groups, and create new groups for + /// 1. `std` / `core` / `alloc` imports + /// 2. other imports + /// 3. `self` / `crate` / `super` imports + StdExternalCrate, +} + +#[config_type] +/// How to merge imports. +pub enum ImportGranularity { + /// Do not merge imports. + Preserve, + /// Use one `use` statement per crate. + Crate, + /// Use one `use` statement per module. + Module, + /// Use one `use` statement per imported item. + Item, +} + #[config_type] pub enum ReportTactic { Always, @@ -172,6 +144,9 @@ pub enum EmitMode { Coverage, /// Unfancy stdout Checkstyle, + /// Writes the resulting diffs in a JSON format. Returns an empty array + /// `[]` if there were no diffs. + Json, /// Output the changed lines (for internal value only) ModifiedLines, /// Checks if a diff can be generated. If so, rustfmt outputs a diff and @@ -197,7 +172,7 @@ pub enum Color { pub enum Version { /// 1.x.y. When specified, rustfmt will format in the same style as 1.0.0. One, - /// 2.x.y. When specified, rustfmt will formatin the the latest style. + /// 2.x.y. When specified, rustfmt will format in the the latest style. Two, } @@ -205,9 +180,8 @@ impl Color { /// Whether we should use a coloured terminal. pub fn use_colored_tty(self) -> bool { match self { - Color::Always => true, + Color::Always | Color::Auto => true, Color::Never => false, - Color::Auto => atty::is(atty::Stream::Stdout), } } } @@ -247,6 +221,12 @@ pub struct WidthHeuristics { pub single_line_if_else_max_width: usize, } +impl fmt::Display for WidthHeuristics { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + impl WidthHeuristics { // Using this WidthHeuristics means we ignore heuristics. pub fn null() -> WidthHeuristics { @@ -310,16 +290,42 @@ fn default() -> EmitMode { } /// A set of directories, files and modules that rustfmt should ignore. -#[derive(Default, Serialize, Clone, Debug, PartialEq)] +#[derive(Default, Clone, Debug, PartialEq)] pub struct IgnoreList { /// A set of path specified in rustfmt.toml. - #[serde(flatten)] path_set: HashSet, /// A path to rustfmt.toml. - #[serde(skip_serializing)] rustfmt_toml_path: PathBuf, } +impl fmt::Display for IgnoreList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "[{}]", + self.path_set + .iter() + .format_with(", ", |path, f| f(&format_args!( + "{}", + path.to_string_lossy() + ))) + ) + } +} + +impl Serialize for IgnoreList { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.path_set.len()))?; + for e in &self.path_set { + seq.serialize_element(e)?; + } + seq.end() + } +} + impl<'de> Deserialize<'de> for IgnoreList { fn deserialize(deserializer: D) -> Result where @@ -370,7 +376,7 @@ pub fn rustfmt_toml_path(&self) -> &Path { } } -impl ::std::str::FromStr for IgnoreList { +impl FromStr for IgnoreList { type Err = &'static str; fn from_str(_: &str) -> Result { @@ -396,6 +402,10 @@ pub enum Edition { #[doc_hint = "2018"] /// Edition 2018. Edition2018, + #[value = "2021"] + #[doc_hint = "2021"] + /// Edition 2021. + Edition2021, } impl Default for Edition { @@ -404,67 +414,29 @@ fn default() -> Edition { } } -impl Edition { - pub(crate) fn to_libsyntax_pos_edition(self) -> syntax_pos::edition::Edition { - match self { - Edition::Edition2015 => syntax_pos::edition::Edition::Edition2015, - Edition::Edition2018 => syntax_pos::edition::Edition::Edition2018, +impl From for rustc_span::edition::Edition { + fn from(edition: Edition) -> Self { + match edition { + Edition::Edition2015 => Self::Edition2015, + Edition::Edition2018 => Self::Edition2018, + Edition::Edition2021 => Self::Edition2021, } } } -#[test] -fn test_newline_style_auto_detect() { - let lf = "One\nTwo\nThree"; - let crlf = "One\r\nTwo\r\nThree"; - let none = "One Two Three"; - - assert_eq!(NewlineStyle::Unix, NewlineStyle::auto_detect(lf)); - assert_eq!(NewlineStyle::Windows, NewlineStyle::auto_detect(crlf)); - assert_eq!(NewlineStyle::Native, NewlineStyle::auto_detect(none)); -} - -#[test] -fn test_newline_style_auto_apply() { - let auto = NewlineStyle::Auto; - - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One\nTwo\nThree"; - - let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); - assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'"); - - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One\r\nTwo\r\nThree"; - - let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); - assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'"); - - #[cfg(not(windows))] - { - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One Two Three"; - - let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); - assert_eq!( - "One\nTwo\nThree", &out, - "auto-native-unix should detect 'lf'" - ); +impl PartialOrd for Edition { + fn partial_cmp(&self, other: &Edition) -> Option { + rustc_span::edition::Edition::partial_cmp(&(*self).into(), &(*other).into()) } +} - #[cfg(windows)] - { - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One Two Three"; - - let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); - assert_eq!( - "One\r\nTwo\r\nThree", &out, - "auto-native-windows should detect 'crlf'" - ); - } +/// Controls how rustfmt should handle leading pipes on match arms. +#[config_type] +pub enum MatchArmLeadingPipe { + /// Place leading pipes on all match arms + Always, + /// Never emit leading pipes on match arms + Never, + /// Preserve any existing leading pipes + Preserve, }