diff --git a/src/bin/main.rs b/src/bin/main.rs index ad10b9ede60..3aaf559914e 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -232,7 +232,7 @@ fn execute(opts: &Options) -> Result { let file = PathBuf::from(path); let file = file.canonicalize().unwrap_or(file); - let (config, _) = load_config(Some(file.parent().unwrap()), Some(options))?; + let (config, _, _) = load_config(Some(file.parent().unwrap()), Some(options))?; let toml = config.all_options().to_toml()?; io::stdout().write_all(toml.as_bytes())?; @@ -248,7 +248,7 @@ fn execute(opts: &Options) -> Result { fn format_string(input: String, options: GetOptsOptions) -> Result { // try to read config from local directory - let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; + let (mut config, _, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; if options.check { config.set().emit_mode(EmitMode::Diff); @@ -294,12 +294,15 @@ fn format( options: &GetOptsOptions, ) -> Result { options.verify_file_lines(&files); - let (config, config_path) = load_config(None, Some(options.clone()))?; + let (config, config_path, cargo_path) = load_config(None, Some(options.clone()))?; if config.verbose() == Verbosity::Verbose { if let Some(path) = config_path.as_ref() { println!("Using rustfmt config file {}", path.display()); } + if let Some(path) = cargo_path.as_ref() { + println!("Using cargo config file {}", path.display()); + } } let out = &mut stdout(); @@ -315,7 +318,7 @@ fn format( } else { // Check the file directory if the config-path could not be read or not provided if config_path.is_none() { - let (local_config, config_path) = + let (local_config, config_path, cargo_path) = load_config(Some(file.parent().unwrap()), Some(options.clone()))?; if local_config.verbose() == Verbosity::Verbose { if let Some(path) = config_path { @@ -325,6 +328,13 @@ fn format( file.display() ); } + if let Some(path) = cargo_path { + println!( + "Using cargo config file {} for {}", + path.display(), + file.display() + ); + } } session.override_config(local_config, |sess| { diff --git a/src/config/mod.rs b/src/config/mod.rs index 5041e1e36dd..5e5269279e7 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -217,164 +217,260 @@ impl Config { 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`. + /// Constructs a `Config` from the provided toml file paths. /// /// 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)); - } - } - - Ok(None) + /// the files, otherwise errors. + pub(super) fn from_toml_path( + rustfmt_path: Option<&PathBuf>, + cargo_path: Option<&PathBuf>, + ) -> Result { + let mut rustfmt_toml = None; + if let Some(rustfmt_path) = rustfmt_path { + let mut file = File::open(&rustfmt_path)?; + let mut toml = String::new(); + file.read_to_string(&mut toml)?; + rustfmt_toml = Some(toml); } - match resolve_project_file(dir)? { - None => Ok((Config::default(), None)), - Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + let mut cargo_toml = None; + if let Some(cargo_path) = cargo_path { + let mut file = File::open(&cargo_path)?; + let mut toml = String::new(); + file.read_to_string(&mut toml)?; + cargo_toml = Some(toml); } + + Config::from_toml( + rustfmt_toml.as_ref().map(|s| s.as_str()), + rustfmt_path.map(|p| p.parent().unwrap()), + cargo_toml.as_ref().map(|s| s.as_str()), + ) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } - 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))?; + pub(crate) fn from_toml( + rustfmt_toml: Option<&str>, + rustfmt_toml_dir: Option<&Path>, + cargo_toml: Option<&str>, + ) -> Result { let mut err = String::new(); - let table = parsed - .as_table() - .ok_or_else(|| 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); + + let mut config = if let Some(toml) = rustfmt_toml { + // Parse rustfmt.toml string + let parsed: ::toml::Value = toml + .parse() + .map_err(|e| format!("Could not parse TOML: {}", e))?; + + // Collect warnings for unknown fields + let table = parsed + .as_table() + .ok_or_else(|| 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) } - Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) } - Err(e) => { + + // Map into config object + let parsed_config = parsed.try_into().map_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) + err.to_string() + })?; + + Config::default().fill_from_parsed_config(parsed_config, rustfmt_toml_dir.unwrap()) + } else { + Config::default() + }; + + // Fetch 'edition' from Cargo.toml if not specified by rustfmt.toml + if !config.was_set().edition() { + if let Some(cargo_toml) = cargo_toml { + if let Err(e) = override_edition(cargo_toml, &mut config) { + err.push_str(&e); + } } } + + // Log warnings + if !err.is_empty() { + eprint!("{}", err); + } + + Ok(config) } } /// Loads a config by checking the client-supplied options and if appropriate, the /// file system (including searching the file system for overrides). +/// +/// Returns the loaded config along with the paths to the rustfmt and/or cargo config +/// files that were used to create it, if any. pub fn load_config( file_path: Option<&Path>, options: Option, -) -> Result<(Config, Option), Error> { +) -> Result<(Config, Option, Option), Error> { let over_ride = match options { Some(ref opts) => config_path(opts)?, None => None, }; - let result = if let Some(over_ride) = over_ride { - Config::from_toml_path(over_ride.as_ref()).map(|p| (p, Some(over_ride.to_owned()))) - } else if let Some(file_path) = file_path { - Config::from_resolved_toml_path(file_path) + let result = if let Some(file_path) = file_path { + // Search for matching configs for this path + let (mut rustfmt_path, cargo_path) = resolve_config_files(file_path)?; + if let Some(over_ride) = over_ride { + // Use specified config + rustfmt_path = Some(over_ride); + } + Config::from_toml_path(rustfmt_path.as_ref(), cargo_path.as_ref()) + .map(|p| (p, rustfmt_path, cargo_path)) + } else if let Some(over_ride) = over_ride { + Config::from_toml_path(Some(&over_ride), None).map(|p| (p, Some(over_ride), None)) } else { - Ok((Config::default(), None)) + Ok((Config::default(), None, None)) }; - result.map(|(mut c, p)| { + result.map(|(mut c, rustfmt_path, cargo_path)| { if let Some(options) = options { options.apply_to(&mut c); } - (c, p) + (c, rustfmt_path, cargo_path) }) } +// Search for "best" rustfmt config and cargo config files, in that order. +// +// Return the best files found, or None if they are not found. +fn resolve_config_files(dir: &Path) -> Result<(Option, Option), Error> { + let mut current = if dir.is_relative() { + env::current_dir()?.join(dir) + } else { + dir.to_path_buf() + }; + + current = fs::canonicalize(current)?; + + // Scan up the directory tree for the first rustfmt and cargo configs + let mut rustfmt_toml: Option = None; + let mut cargo_toml: Option = None; + loop { + if rustfmt_toml.is_none() { + match get_rustfmt_toml_path(¤t) { + Ok(Some(path)) => rustfmt_toml = Some(path), + Err(e) => return Err(e), + _ => (), + } + } + + if cargo_toml.is_none() { + match get_cargo_toml_path(¤t) { + Ok(Some(path)) => cargo_toml = Some(path), + Err(e) => return Err(e), + _ => (), + } + } + + // If we found both files, we're done searching. + if rustfmt_toml.is_some() && cargo_toml.is_some() { + break; + } + + // 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 rustfmt_toml.is_none() { + if let Some(home_dir) = dirs::home_dir() { + if let Some(path) = get_rustfmt_toml_path(&home_dir)? { + rustfmt_toml = Some(path); + } + } + } + + // If none was found there either, check in the user's configuration directory. + if rustfmt_toml.is_none() { + if let Some(mut config_dir) = dirs::config_dir() { + config_dir.push("rustfmt"); + if let Some(path) = get_rustfmt_toml_path(&config_dir)? { + rustfmt_toml = Some(path); + } + } + } + + Ok((rustfmt_toml, cargo_toml)) +} + // Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` // // Return the path if a config file exists, empty if no file exists, and Error for IO errors -fn get_toml_path(dir: &Path) -> Result, Error> { +fn get_rustfmt_toml_path(dir: &Path) -> Result, Error> { const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; for config_file_name in &CONFIG_FILE_NAMES { - let config_file = dir.join(config_file_name); - match fs::metadata(&config_file) { - // Only return if it's a file to handle the unlikely situation of a directory named - // `rustfmt.toml`. - Ok(ref md) if md.is_file() => return Ok(Some(config_file)), - // Return the error if it's something other than `NotFound`; otherwise we didn't - // find the project file yet, and continue searching. - Err(e) => { - if e.kind() != ErrorKind::NotFound { - let ctx = format!("Failed to get metadata for config file {:?}", &config_file); - let err = anyhow::Error::new(e).context(ctx); - return Err(Error::new(ErrorKind::Other, err)); - } + if let Some(config_file) = check_config_file(dir, config_file_name)? { + return Ok(Some(config_file)); + } + } + Ok(None) +} + +// Check for the presence of Cargo.toml in `dir` +// +// Return the path if a config file exists, empty if no file exists, and Error for IO errors +fn get_cargo_toml_path(dir: &Path) -> Result, Error> { + check_config_file(dir, &"Cargo.toml") +} + +// Check for the presence of the specified filename in the specified directory +// +// Return the path if a config file exists, empty if no file exists, and Error for IO errors +fn check_config_file(dir: &Path, file_name: &str) -> Result, Error> { + let config_file = dir.join(file_name); + match fs::metadata(&config_file) { + // Only return if it's a file to handle the unlikely situation of a directory named + // `rustfmt.toml`. + Ok(ref md) if md.is_file() => return Ok(Some(config_file)), + // Return the error if it's something other than `NotFound`; otherwise we didn't + // find the project file yet, and continue searching. + Err(e) => { + if e.kind() != ErrorKind::NotFound { + let ctx = format!("Failed to get metadata for config file {:?}", &config_file); + let err = anyhow::Error::new(e).context(ctx); + return Err(Error::new(ErrorKind::Other, err)); } - _ => {} } + _ => {} } Ok(None) } +// Assigns the "edition" value provided by the provided Cargo.toml content, if any +fn override_edition(cargo_toml: &str, config: &mut Config) -> Result<(), String> { + let parsed_cargo: ::toml::Value = cargo_toml + .parse() + .map_err(|e| format!("Could not parse TOML: {}", e))?; + let table_cargo = parsed_cargo + .as_table() + .ok_or_else(|| String::from("Parsed config was not table"))?; + if let Some(package) = table_cargo.get("package") { + let table_package = package + .as_table() + .ok_or("Warning: Cargo.toml package is not a table")?; + if let Some(edition) = table_package.get("edition") { + let edition_str = edition + .as_str() + .ok_or("Warning: Cargo.toml edition is not a string")?; + config.override_value("edition", edition_str); + } + } + Ok(()) +} + fn config_path(options: &dyn CliOptions) -> Result, Error> { let config_path_not_found = |path: &str| -> Result, Error> { Err(Error::new( @@ -391,7 +487,7 @@ fn config_path(options: &dyn CliOptions) -> Result, Error> { match options.config_path() { Some(path) if !path.exists() => config_path_not_found(path.to_str().unwrap()), Some(path) if path.is_dir() => { - let config_file_path = get_toml_path(path)?; + let config_file_path = get_rustfmt_toml_path(path)?; if config_file_path.is_some() { Ok(config_file_path) } else { @@ -409,6 +505,11 @@ mod test { use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test}; + // Common case for use by tests + fn config_from_toml(rustfmt_toml: &str) -> Result { + Config::from_toml(Some(rustfmt_toml), Some(Path::new("")), None) + } + #[allow(dead_code)] mod mock { use super::super::*; @@ -489,7 +590,7 @@ mod test { #[test] fn test_was_set() { - let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap(); + let config = config_from_toml("hard_tabs = true").unwrap(); assert_eq!(config.was_set().hard_tabs(), true); assert_eq!(config.was_set().verbose(), false); @@ -525,7 +626,7 @@ mod test { #[test] fn test_empty_string_license_template_path() { let toml = r#"license_template_path = """#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert!(config.license_template.is_none()); } @@ -533,7 +634,7 @@ mod test { #[test] fn test_valid_license_template_path() { let toml = r#"license_template_path = "tests/license-template/lt.txt""#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert!(config.license_template.is_some()); } @@ -541,7 +642,7 @@ mod test { #[test] fn test_override_existing_license_with_no_license() { let toml = r#"license_template_path = "tests/license-template/lt.txt""#; - let mut config = Config::from_toml(toml, Path::new("")).unwrap(); + let mut config = config_from_toml(toml).unwrap(); assert!(config.license_template.is_some()); config.override_value("license_template_path", ""); assert!(config.license_template.is_none()); @@ -658,7 +759,7 @@ make_backup = false #[nightly_only_test] #[test] fn test_unstable_from_toml() { - let config = Config::from_toml("unstable_features = true", Path::new("")).unwrap(); + let config = config_from_toml("unstable_features = true").unwrap(); assert_eq!(config.was_set().unstable_features(), true); assert_eq!(config.unstable_features(), true); } @@ -674,7 +775,7 @@ make_backup = false unstable_features = true merge_imports = true "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.imports_granularity(), ImportGranularity::Crate); } @@ -686,7 +787,7 @@ make_backup = false merge_imports = true imports_granularity = "Preserve" "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.imports_granularity(), ImportGranularity::Preserve); } @@ -697,7 +798,7 @@ make_backup = false unstable_features = true merge_imports = true "#; - let mut config = Config::from_toml(toml, Path::new("")).unwrap(); + let mut config = config_from_toml(toml).unwrap(); config.override_value("imports_granularity", "Preserve"); assert_eq!(config.imports_granularity(), ImportGranularity::Preserve); } @@ -709,7 +810,7 @@ make_backup = false unstable_features = true imports_granularity = "Module" "#; - let mut config = Config::from_toml(toml, Path::new("")).unwrap(); + let mut config = config_from_toml(toml).unwrap(); config.override_value("merge_imports", "true"); // no effect: the new option always takes precedence assert_eq!(config.imports_granularity(), ImportGranularity::Module); @@ -726,7 +827,7 @@ make_backup = false use_small_heuristics = "Default" max_width = 200 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.array_width(), 120); assert_eq!(config.attr_fn_like_width(), 140); assert_eq!(config.chain_width(), 120); @@ -742,7 +843,7 @@ make_backup = false use_small_heuristics = "Max" max_width = 120 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.array_width(), 120); assert_eq!(config.attr_fn_like_width(), 120); assert_eq!(config.chain_width(), 120); @@ -758,7 +859,7 @@ make_backup = false use_small_heuristics = "Off" max_width = 100 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.array_width(), usize::max_value()); assert_eq!(config.attr_fn_like_width(), usize::max_value()); assert_eq!(config.chain_width(), usize::max_value()); @@ -780,7 +881,7 @@ make_backup = false struct_lit_width = 30 struct_variant_width = 34 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.array_width(), 20); assert_eq!(config.attr_fn_like_width(), 40); assert_eq!(config.chain_width(), 20); @@ -802,7 +903,7 @@ make_backup = false struct_lit_width = 30 struct_variant_width = 34 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.array_width(), 20); assert_eq!(config.attr_fn_like_width(), 40); assert_eq!(config.chain_width(), 20); @@ -824,7 +925,7 @@ make_backup = false struct_lit_width = 30 struct_variant_width = 34 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.array_width(), 20); assert_eq!(config.attr_fn_like_width(), 40); assert_eq!(config.chain_width(), 20); @@ -840,7 +941,7 @@ make_backup = false max_width = 90 fn_call_width = 95 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.fn_call_width(), 90); } @@ -850,7 +951,7 @@ make_backup = false max_width = 80 attr_fn_like_width = 90 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.attr_fn_like_width(), 80); } @@ -860,7 +961,7 @@ make_backup = false max_width = 78 struct_lit_width = 90 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.struct_lit_width(), 78); } @@ -870,7 +971,7 @@ make_backup = false max_width = 80 struct_variant_width = 90 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.struct_variant_width(), 80); } @@ -880,7 +981,7 @@ make_backup = false max_width = 60 array_width = 80 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.array_width(), 60); } @@ -890,7 +991,7 @@ make_backup = false max_width = 80 chain_width = 90 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.chain_width(), 80); } @@ -900,7 +1001,7 @@ make_backup = false max_width = 70 single_line_if_else_max_width = 90 "#; - let config = Config::from_toml(toml, Path::new("")).unwrap(); + let config = config_from_toml(toml).unwrap(); assert_eq!(config.single_line_if_else_max_width(), 70); } diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 579778edbe7..738319787c8 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -57,7 +57,7 @@ fn get_files(input: &str) -> Vec<&str> { } fn fmt_files(files: &[&str]) -> i32 { - let (config, _) = + let (config, _, _) = load_config::(Some(Path::new(".")), None).expect("couldn't load config"); let mut exit_code = 0; diff --git a/src/ignore_path.rs b/src/ignore_path.rs index 7738eee0a76..6e94ac95e3c 100644 --- a/src/ignore_path.rs +++ b/src/ignore_path.rs @@ -42,8 +42,12 @@ mod test { #[nightly_only_test] #[test] fn test_ignore_path_set() { - let config = - Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new("")).unwrap(); + let config = Config::from_toml( + Some(r#"ignore = ["foo.rs", "bar_dir/*"]"#), + Some(Path::new("")), + None, + ) + .unwrap(); let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap(); assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs")))); diff --git a/src/parse/session.rs b/src/parse/session.rs index 624fed0d2de..f19de1358a0 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -344,7 +344,9 @@ mod tests { } fn get_ignore_list(config: &str) -> IgnoreList { - Config::from_toml(config, Path::new("")).unwrap().ignore() + Config::from_toml(Some(config), Some(Path::new("")), None) + .unwrap() + .ignore() } #[test] diff --git a/src/test/mod.rs b/src/test/mod.rs index 4191e3e96b0..79821077b9e 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -694,7 +694,7 @@ fn idempotent_check( ) -> Result { let sig_comments = read_significant_comments(filename); let config = if let Some(ref config_file_path) = opt_config { - Config::from_toml_path(config_file_path).expect("`rustfmt.toml` not found") + Config::from_toml_path(Some(config_file_path), None).expect("`rustfmt.toml` not found") } else { read_config(filename) }; @@ -737,7 +737,8 @@ fn get_config(config_file: Option<&Path>) -> Config { .read_to_string(&mut def_config) .expect("Couldn't read config"); - Config::from_toml(&def_config, Path::new("tests/config/")).expect("invalid TOML") + Config::from_toml(Some(&def_config), Some(Path::new("tests/config/")), None) + .expect("invalid TOML") } // Reads significant comments of the form: `// rustfmt-key: value` into a hash map.