diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 4d09eea7c47..14c2dcbb8db 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -93,19 +93,6 @@ macro_rules! create_config { $(pub $i: Option<$ty>),+ } - impl PartialConfig { - pub fn to_toml(&self) -> Result { - // Non-user-facing options can't be specified in TOML - let mut cloned = self.clone(); - cloned.file_lines = None; - cloned.verbose = None; - cloned.width_heuristics = None; - - ::toml::to_string(&cloned) - .map_err(|e| format!("Could not output config: {}", e)) - } - } - // Macro hygiene won't allow us to make `set_$i()` methods on Config // for each item, so this struct is used to give the API to set values: // `config.set().option(false)`. It's pretty ugly. Consider replacing @@ -139,23 +126,6 @@ macro_rules! create_config { } impl Config { - pub(crate) fn version_meets_requirement(&self) -> bool { - if self.was_set().required_version() { - let version = env!("CARGO_PKG_VERSION"); - let required_version = self.required_version(); - if version != required_version { - println!( - "Error: rustfmt version ({}) doesn't match the required version ({})", - version, - required_version, - ); - return false; - } - } - - true - } - $( pub fn $i(&self) -> $ty { self.$i.0.set(true); @@ -213,37 +183,6 @@ macro_rules! create_config { } } - pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { - let parsed: ::toml::Value = - toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; - let mut err: String = String::new(); - { - let table = parsed - .as_table() - .ok_or(String::from("Parsed config was not table"))?; - for key in table.keys() { - if !Config::is_valid_name(key) { - let msg = &format!("Warning: Unknown configuration option `{}`\n", key); - err.push_str(msg) - } - } - } - match parsed.try_into() { - Ok(parsed_config) => { - if !err.is_empty() { - eprint!("{}", err); - } - Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) - } - Err(e) => { - err.push_str("Error: Decoding config file failed:\n"); - err.push_str(format!("{}\n", e).as_str()); - err.push_str("Please check your config file."); - Err(err) - } - } - } - pub fn used_options(&self) -> PartialConfig { PartialConfig { $( @@ -287,82 +226,6 @@ macro_rules! create_config { } } - /// Constructs a `Config` from the toml file specified at `file_path`. - /// - /// This method only looks at the provided path, for a method that - /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. - /// - /// Returns a `Config` if the config could be read and parsed from - /// the file, otherwise errors. - pub(super) fn from_toml_path(file_path: &Path) -> Result { - let mut file = File::open(&file_path)?; - let mut toml = String::new(); - file.read_to_string(&mut toml)?; - Config::from_toml(&toml, file_path.parent().unwrap()) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) - } - - /// Resolves the config for input in `dir`. - /// - /// Searches for `rustfmt.toml` beginning with `dir`, and - /// recursively checking parents of `dir` if no config file is found. - /// If no config file exists in `dir` or in any parent, a - /// default `Config` will be returned (and the returned path will be empty). - /// - /// Returns the `Config` to use, and the path of the project file if there was - /// one. - pub(super) fn from_resolved_toml_path( - dir: &Path, - ) -> Result<(Config, Option), Error> { - /// Try to find a project file in the given directory and its parents. - /// Returns the path of a the nearest project file if one exists, - /// or `None` if no project file was found. - fn resolve_project_file(dir: &Path) -> Result, Error> { - let mut current = if dir.is_relative() { - env::current_dir()?.join(dir) - } else { - dir.to_path_buf() - }; - - current = fs::canonicalize(current)?; - - loop { - match get_toml_path(¤t) { - Ok(Some(path)) => return Ok(Some(path)), - Err(e) => return Err(e), - _ => () - } - - // If the current directory has no parent, we're done searching. - if !current.pop() { - break; - } - } - - // If nothing was found, check in the home directory. - if let Some(home_dir) = dirs::home_dir() { - if let Some(path) = get_toml_path(&home_dir)? { - return Ok(Some(path)); - } - } - - // If none was found ther either, check in the user's configuration directory. - if let Some(mut config_dir) = dirs::config_dir() { - config_dir.push("rustfmt"); - if let Some(path) = get_toml_path(&config_dir)? { - return Ok(Some(path)); - } - } - - return Ok(None); - } - - match resolve_project_file(dir)? { - None => Ok((Config::default(), None)), - Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), - } - } - pub fn is_hidden_option(name: &str) -> bool { const HIDE_OPTIONS: [&str; 4] = ["verbose", "verbose_diff", "file_lines", "width_heuristics"]; diff --git a/src/config/mod.rs b/src/config/mod.rs index 785d61749a4..0790a3be2a6 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -150,6 +150,142 @@ create_config! { make_backup: bool, false, false, "Backup changed files"; } +impl PartialConfig { + pub fn to_toml(&self) -> Result { + // Non-user-facing options can't be specified in TOML + let mut cloned = self.clone(); + cloned.file_lines = None; + cloned.verbose = None; + cloned.width_heuristics = None; + + ::toml::to_string(&cloned).map_err(|e| format!("Could not output config: {}", e)) + } +} + +impl Config { + pub(crate) fn version_meets_requirement(&self) -> bool { + if self.was_set().required_version() { + let version = env!("CARGO_PKG_VERSION"); + let required_version = self.required_version(); + if version != required_version { + println!( + "Error: rustfmt version ({}) doesn't match the required version ({})", + version, required_version, + ); + return false; + } + } + + true + } + + /// Constructs a `Config` from the toml file specified at `file_path`. + /// + /// This method only looks at the provided path, for a method that + /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. + /// + /// Returns a `Config` if the config could be read and parsed from + /// the file, otherwise errors. + pub(super) fn from_toml_path(file_path: &Path) -> Result { + let mut file = File::open(&file_path)?; + let mut toml = String::new(); + file.read_to_string(&mut toml)?; + Config::from_toml(&toml, file_path.parent().unwrap()) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + } + + /// Resolves the config for input in `dir`. + /// + /// Searches for `rustfmt.toml` beginning with `dir`, and + /// recursively checking parents of `dir` if no config file is found. + /// If no config file exists in `dir` or in any parent, a + /// default `Config` will be returned (and the returned path will be empty). + /// + /// Returns the `Config` to use, and the path of the project file if there was + /// one. + pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + /// Try to find a project file in the given directory and its parents. + /// Returns the path of a the nearest project file if one exists, + /// or `None` if no project file was found. + fn resolve_project_file(dir: &Path) -> Result, Error> { + let mut current = if dir.is_relative() { + env::current_dir()?.join(dir) + } else { + dir.to_path_buf() + }; + + current = fs::canonicalize(current)?; + + loop { + match get_toml_path(¤t) { + Ok(Some(path)) => return Ok(Some(path)), + Err(e) => return Err(e), + _ => (), + } + + // If the current directory has no parent, we're done searching. + if !current.pop() { + break; + } + } + + // If nothing was found, check in the home directory. + if let Some(home_dir) = dirs::home_dir() { + if let Some(path) = get_toml_path(&home_dir)? { + return Ok(Some(path)); + } + } + + // If none was found ther either, check in the user's configuration directory. + if let Some(mut config_dir) = dirs::config_dir() { + config_dir.push("rustfmt"); + if let Some(path) = get_toml_path(&config_dir)? { + return Ok(Some(path)); + } + } + + return Ok(None); + } + + match resolve_project_file(dir)? { + None => Ok((Config::default(), None)), + Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + } + } + + pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { + let parsed: ::toml::Value = toml + .parse() + .map_err(|e| format!("Could not parse TOML: {}", e))?; + let mut err: String = String::new(); + { + let table = parsed + .as_table() + .ok_or(String::from("Parsed config was not table"))?; + for key in table.keys() { + if !Config::is_valid_name(key) { + let msg = &format!("Warning: Unknown configuration option `{}`\n", key); + err.push_str(msg) + } + } + } + match parsed.try_into() { + Ok(parsed_config) => { + if !err.is_empty() { + eprint!("{}", err); + } + Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) + } + Err(e) => { + err.push_str("Error: Decoding config file failed:\n"); + err.push_str(format!("{}\n", e).as_str()); + err.push_str("Please check your config file."); + Err(err) + } + } + } +} + /// Loads a config by checking the client-supplied options and if appropriate, the /// file system (including searching the file system for overrides). pub fn load_config(