diff --git a/src/config/mod.rs b/src/config/mod.rs index 3b77902fa2a..da7adea5a74 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -271,12 +271,21 @@ pub(crate) fn version_meets_requirement(&self) -> bool { /// /// 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 { + pub(super) fn from_toml_path( + file_path: &Path, + edition: Option, + style_edition: Option, + ) -> 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)) + Config::from_toml_for_style_edition( + &toml, + file_path.parent().unwrap(), + edition, + style_edition, + ) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } /// Resolves the config for input in `dir`. @@ -288,7 +297,11 @@ pub(super) fn from_toml_path(file_path: &Path) -> Result { /// /// 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> { + pub(super) fn from_resolved_toml_path( + dir: &Path, + edition: Option, + style_edition: Option, + ) -> Result<(Config, Option), Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of the nearest project file if one exists, /// or `None` if no project file was found. @@ -333,12 +346,26 @@ fn resolve_project_file(dir: &Path) -> Result, Error> { } match resolve_project_file(dir)? { - None => Ok((Config::default(), None)), - Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + None => Ok(( + Config::default_for_possible_style_edition(style_edition, edition), + None, + )), + Some(path) => Config::from_toml_path(&path, edition, style_edition) + .map(|config| (config, Some(path))), } } - pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { + #[allow(dead_code)] + pub(super) fn from_toml(toml: &str, dir: &Path) -> Result { + Self::from_toml_for_style_edition(toml, dir, None, None) + } + + pub(crate) fn from_toml_for_style_edition( + toml: &str, + dir: &Path, + edition: Option, + style_edition: Option, + ) -> Result { let parsed: ::toml::Value = toml .parse() .map_err(|e| format!("Could not parse TOML: {}", e))?; @@ -358,7 +385,7 @@ pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { if !err.is_empty() { eprint!("{err}"); } - Ok(parsed_config.to_parsed_config(None, None, dir)) + Ok(parsed_config.to_parsed_config(style_edition, edition, dir)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); @@ -376,21 +403,21 @@ pub fn load_config( file_path: Option<&Path>, options: Option, ) -> Result<(Config, Option), Error> { - let (over_ride, _edition, _style_edition) = match options { - Some(ref opts) => ( - config_path(opts)?, - opts.edition(), - opts.style_edition(), - ), + let (over_ride, edition, style_edition) = match options { + Some(ref opts) => (config_path(opts)?, opts.edition(), opts.style_edition()), None => (None, 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()))) + Config::from_toml_path(over_ride.as_ref(), edition, style_edition) + .map(|p| (p, Some(over_ride.to_owned()))) } else if let Some(file_path) = file_path { - Config::from_resolved_toml_path(file_path) + Config::from_resolved_toml_path(file_path, edition, style_edition) } else { - Ok((Config::default(), None)) + Ok(( + Config::default_for_possible_style_edition(style_edition, edition), + None, + )) }; result.map(|(mut c, p)| { diff --git a/src/test/mod.rs b/src/test/mod.rs index 7c563801c32..96706efb161 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -6,14 +6,17 @@ use std::mem; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use std::str::Chars; +use std::str::{Chars, FromStr}; use std::thread; use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle}; use crate::formatting::{ReportedErrors, SourceFile}; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; -use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session}; +use crate::{ + is_nightly_channel, Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, + StyleEdition, +}; use rustfmt_config_proc_macro::nightly_only_test; @@ -710,13 +713,22 @@ fn print_mismatches String>( fn read_config(filename: &Path) -> Config { let sig_comments = read_significant_comments(filename); + let (edition, style_edition) = get_editions_from_comments(&sig_comments); // Look for a config file. If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with // the same name as the test file. let mut config = if !sig_comments.is_empty() { - get_config(sig_comments.get("config").map(Path::new)) + get_config( + sig_comments.get("config").map(Path::new), + edition, + style_edition, + ) } else { - get_config(filename.with_extension("toml").file_name().map(Path::new)) + get_config( + filename.with_extension("toml").file_name().map(Path::new), + edition, + style_edition, + ) }; for (key, val) in &sig_comments { @@ -747,13 +759,28 @@ enum IdempotentCheckError { Parse, } +fn get_editions_from_comments( + comments: &HashMap, +) -> (Option, Option) { + ( + comments + .get("edition") + .map(|e| Edition::from_str(e).expect(&format!("invalid edition value: '{}'", e))), + comments.get("style_edition").map(|se| { + StyleEdition::from_str(se).expect(&format!("invalid style_edition value: '{}'", se)) + }), + ) +} + fn idempotent_check( filename: &PathBuf, opt_config: &Option, ) -> 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") + let (edition, style_edition) = get_editions_from_comments(&sig_comments); + Config::from_toml_path(config_file_path, edition, style_edition) + .expect("`rustfmt.toml` not found") } else { read_config(filename) }; @@ -777,14 +804,18 @@ fn idempotent_check( // Reads test config file using the supplied (optional) file name. If there's no file name or the // file doesn't exist, just return the default config. Otherwise, the file must be read // successfully. -fn get_config(config_file: Option<&Path>) -> Config { +fn get_config( + config_file: Option<&Path>, + edition: Option, + style_edition: Option, +) -> Config { let config_file_name = match config_file { - None => return Default::default(), + None => return Config::default_for_possible_style_edition(style_edition, edition), Some(file_name) => { let mut full_path = PathBuf::from("tests/config/"); full_path.push(file_name); if !full_path.exists() { - return Default::default(); + return Config::default_for_possible_style_edition(style_edition, edition); }; full_path } @@ -796,7 +827,13 @@ 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_for_style_edition( + &def_config, + Path::new("tests/config/"), + edition, + style_edition, + ) + .expect("invalid TOML") } // Reads significant comments of the form: `// rustfmt-key: value` into a hash map.