diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 14cb63db7d5..d2eb9f8e4f9 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -18,7 +18,7 @@ extern crate env_logger; extern crate getopts; use rustfmt::{run, run_from_stdin}; -use rustfmt::config::{Config, WriteMode}; +use rustfmt::config::{Config, PartialConfig, WriteMode}; use std::env; use std::fs::{self, File}; @@ -30,7 +30,7 @@ use getopts::{Matches, Options}; /// Rustfmt operations. enum Operation { /// Format files and their child modules. - Format(Vec, WriteMode), + Format(Vec), /// Print the help message. Help, // Print version information @@ -40,7 +40,7 @@ enum Operation { /// Invalid program input, including reason. InvalidInput(String), /// No file specified, read from stdin - Stdin(String, WriteMode), + Stdin(String), } /// Try to find a project file in the given directory and its parents. Returns the path of a the @@ -92,12 +92,24 @@ fn resolve_config(dir: &Path) -> io::Result<(Config, Option)> { let mut file = try!(File::open(&path)); let mut toml = String::new(); try!(file.read_to_string(&mut toml)); - Ok((Config::from_toml(&toml), Some(path))) + let parsed_config: PartialConfig = toml::decode_str(&toml).expect("Failed to parse config"); + Ok((Config::from(parsed_config), Some(path))) } -fn update_config(config: &mut Config, matches: &Matches) { - config.verbose = matches.opt_present("verbose"); - config.skip_children = matches.opt_present("skip-children"); +fn partial_config_from_options(matches: &Matches) -> PartialConfig { + let mut config = PartialConfig::new(); + if matches.opt_present("skip_children") { + config.skip_children = Some(true); + } + if matches.opt_present("verbose") { + config.verbose = Some(true); + } + if let Some(mode) = matches.opt_str("write-mode") { + config.write_mode = Some(mode.parse() + .expect(&format!("Unrecognized write mode: {}", mode))); + } + + config } fn execute() -> i32 { @@ -142,27 +154,30 @@ fn execute() -> i32 { Config::print_docs(); 0 } - Operation::Stdin(input, write_mode) => { + Operation::Stdin(input) => { // try to read config from local directory - let (config, _) = resolve_config(&env::current_dir().unwrap()) - .expect("Error resolving config"); + let (mut config, _) = resolve_config(&env::current_dir().unwrap()) + .expect("Error resolving config"); - run_from_stdin(input, write_mode, &config); + // WriteMode is always Plain for Stdin. + config = config.merge(&PartialConfig::from(WriteMode::Plain)); + + run_from_stdin(input, &config); 0 } - Operation::Format(files, write_mode) => { + Operation::Format(files) => { for file in files { let (mut config, path) = resolve_config(file.parent().unwrap()) .expect(&format!("Error resolving config for {}", file.display())); + config = config.merge(&partial_config_from_options(&matches)); if let Some(path) = path { println!("Using rustfmt config file {} for {}", path.display(), file.display()); } - update_config(&mut config, &matches); - run(&file, write_mode, &config); + run(&file, &config); } 0 } @@ -220,21 +235,11 @@ fn determine_operation(matches: &Matches) -> Operation { Err(e) => return Operation::InvalidInput(e.to_string()), } - // WriteMode is always plain for Stdin - return Operation::Stdin(buffer, WriteMode::Plain); + return Operation::Stdin(buffer); } - let write_mode = match matches.opt_str("write-mode") { - Some(mode) => { - match mode.parse() { - Ok(mode) => mode, - Err(..) => return Operation::InvalidInput("Unrecognized write mode".into()), - } - } - None => WriteMode::Default, - }; let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); - Operation::Format(files, write_mode) + Operation::Format(files) } diff --git a/src/config.rs b/src/config.rs index 48b7a06e538..4f0c850404e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -121,9 +121,6 @@ configuration_option_enum! { ReportTactic: } configuration_option_enum! { WriteMode: - // Used internally to represent when no option is given - // Treated as Replace. - Default, // Backsup the original file and overwrites the orignal. Replace, // Overwrites original file without backup. @@ -196,41 +193,118 @@ macro_rules! create_config { $(pub $i: $ty),+ } - // Just like the Config struct but with each property wrapped - // as Option. This is used to parse a rustfmt.toml that doesn't - // specity all properties of `Config`. - // We first parse into `ParsedConfig`, then create a default `Config` - // and overwrite the properties with corresponding values from `ParsedConfig` + /// Equivalent to `Config` except that each field is wrapped in an `Option`. + /// + /// This can be decoded into from TOML, and then later merged into a `Config` or another + /// `PartialConfig`. + /// + /// # Examples + /// + /// Decode a TOML value into a `PartialConfig`: + /// + /// ```ignore + /// extern crate toml; + /// use config::{Config, PartialConfig}; + /// let toml_str = r#" + /// ideal_width = 72 + /// "#; + /// + /// let partial: PartialConfig = toml::decode_str(toml_str); + /// ``` + /// + /// Later, merge the `PartialConfig` into the default `Config`: + /// + /// ```ignore + /// # extern crate toml; + /// # use config::{Config, PartialConfig}; + /// # let toml_str = r#" + /// # ideal_width = 72 + /// # "#; + /// + /// let partial: PartialConfig = toml::decode_str(toml_str); + /// let config = Config::Default().merge(partial); + /// assert_eq!(72, config.ideal_width); + /// ``` #[derive(RustcDecodable, Clone)] - pub struct ParsedConfig { + pub struct PartialConfig { $(pub $i: Option<$ty>),+ } + impl PartialConfig { + + /// Create a `PartialConfig` with all fields set to `None`. + pub fn new() -> PartialConfig { + PartialConfig { + $( + $i: None, + )+ + } + + } + + /// Merge `other` into `self, overwriting fields in `self` with any non-`None` fields + /// in `other`. + pub fn merge(&mut self, other: &PartialConfig) -> &mut PartialConfig { + $( + if other.$i.is_some() { + self.$i = other.$i.clone(); + } + )+ + self + } + } + + impl Default for PartialConfig { + fn default() -> PartialConfig { + PartialConfig::new() + } + } + + // Convenience impl. + impl From for PartialConfig { + fn from(write_mode: WriteMode) -> PartialConfig { + PartialConfig { + write_mode: Some(write_mode), ..PartialConfig::default() + } + } + } + + // Convenience impl. + impl From> for PartialConfig { + fn from(write_mode: Option) -> PartialConfig { + PartialConfig { + write_mode: write_mode, ..PartialConfig::default() + } + } + } + + /// Applies settings in `partial` on top of the default `Config`. + impl From for Config { + fn from(partial: PartialConfig) -> Config { + Config::default().merge(&partial) + } + } + + /// Applies settings in `partial` on top of the default `Config`. + impl<'a> From<&'a PartialConfig> for Config { + fn from(partial: &'a PartialConfig) -> Config { + Config::default().merge(partial) + } + } + impl Config { - fn fill_from_parsed_config(mut self, parsed: ParsedConfig) -> Config { + /// Merge `partial` into `self, overwriting fields in `self` with any non-`None` fields + /// in `partial`. + pub fn merge(mut self, partial: &PartialConfig) -> Config { $( - if let Some(val) = parsed.$i { + if let Some(val) = partial.$i { self.$i = val; } )+ self } - pub fn from_toml(toml: &str) -> Config { - let parsed = toml.parse().unwrap(); - let parsed_config:ParsedConfig = match toml::decode(parsed) { - Some(decoded) => decoded, - None => { - println!("Decoding config file failed. Config:\n{}", toml); - let parsed: toml::Value = toml.parse().unwrap(); - println!("\n\nParsed:\n{:?}", parsed); - panic!(); - } - }; - Config::default().fill_from_parsed_config(parsed_config) - } - pub fn override_value(&mut self, key: &str, val: &str) { match key { $( @@ -344,6 +418,40 @@ create_config! { match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; - write_mode: WriteMode, WriteMode::Default, + write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; } + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_config_merge_overrides() { + let config = Config::default().merge(&PartialConfig { + ideal_width: Some(37), + ..PartialConfig::default() + }); + assert_eq!(37, config.ideal_width); + } + + #[test] + fn test_partial_config_merge_overrides() { + let mut config = PartialConfig::default(); + config.merge(&PartialConfig { ideal_width: Some(37), ..PartialConfig::default() }); + assert_eq!(Some(37), config.ideal_width); + } + + #[test] + fn test_config_merge_does_not_override_if_none() { + let mut config = Config { ideal_width: 37, ..Config::default() }; + config = config.merge(&PartialConfig::new()); + assert_eq!(37, config.ideal_width); + } + + #[test] + fn test_partial_config_merge_does_not_override_if_none() { + let mut config = PartialConfig { ideal_width: Some(37), ..PartialConfig::default() }; + config.merge(&PartialConfig::new()); + assert_eq!(Some(37), config.ideal_width); + } +} diff --git a/src/expr.rs b/src/expr.rs index 8e76001e731..b9dbd8b8401 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -427,7 +427,7 @@ impl Rewrite for ast::Block { return Some(user_str); } - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); visitor.block_indent = context.block_indent; let prefix = match self.rules { @@ -954,9 +954,7 @@ impl Rewrite for ast::Arm { let attr_str = if !attrs.is_empty() { // We only use this visitor for the attributes, should we use it for // more? - let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session, - context.config, - None); + let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session, context.config); attr_visitor.block_indent = context.block_indent; attr_visitor.last_pos = attrs[0].span.lo; if attr_visitor.visit_attrs(attrs) { diff --git a/src/filemap.rs b/src/filemap.rs index 61ad573f702..f41915b8cff 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -31,18 +31,14 @@ pub fn append_newlines(file_map: &mut FileMap) { } } -pub fn write_all_files(file_map: &FileMap, - mut out: T, - mode: WriteMode, - config: &Config) - -> Result<(), io::Error> +pub fn write_all_files(file_map: &FileMap, mut out: T, config: &Config) -> Result<(), io::Error> where T: Write { - output_header(&mut out, mode).ok(); + output_header(&mut out, config.write_mode).ok(); for filename in file_map.keys() { - try!(write_file(&file_map[filename], filename, &mut out, mode, config)); + try!(write_file(&file_map[filename], filename, &mut out, config)); } - output_footer(&mut out, mode).ok(); + output_footer(&mut out, config.write_mode).ok(); Ok(()) } @@ -87,7 +83,6 @@ pub fn write_system_newlines(writer: T, pub fn write_file(text: &StringBuffer, filename: &str, out: &mut T, - mode: WriteMode, config: &Config) -> Result, io::Error> where T: Write @@ -114,7 +109,7 @@ pub fn write_file(text: &StringBuffer, Ok(make_diff(&ori, &fmt, 3)) } - match mode { + match config.write_mode { WriteMode::Replace => { if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { if fmt != ori { @@ -157,9 +152,6 @@ pub fn write_file(text: &StringBuffer, |line_num| format!("\nDiff at line {}:", line_num)); } } - WriteMode::Default => { - unreachable!("The WriteMode should NEVER Be default at this point!"); - } WriteMode::Checkstyle => { let diff = try!(create_diff(filename, text, config)); try!(output_checkstyle_file(out, filename, diff)); diff --git a/src/items.rs b/src/items.rs index 2ff52148f6a..d7c16c4561c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -530,7 +530,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; if !items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); visitor.block_indent = context.block_indent.block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); diff --git a/src/lib.rs b/src/lib.rs index ad9322ab649..53afb9b194e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,7 @@ use std::fmt; use issues::{BadIssueSeeker, Issue}; use filemap::FileMap; use visitor::FmtVisitor; -use config::{Config, WriteMode}; +use config::Config; #[macro_use] mod utils; @@ -264,8 +264,7 @@ impl fmt::Display for FormatReport { fn fmt_ast(krate: &ast::Crate, parse_session: &ParseSess, main_file: &Path, - config: &Config, - mode: WriteMode) + config: &Config) -> FileMap { let mut file_map = FileMap::new(); for (path, module) in modules::list_files(krate, parse_session.codemap()) { @@ -276,7 +275,7 @@ fn fmt_ast(krate: &ast::Crate, if config.verbose { println!("Formatting {}", path); } - let mut visitor = FmtVisitor::from_codemap(parse_session, config, Some(mode)); + let mut visitor = FmtVisitor::from_codemap(parse_session, config); visitor.format_separate_mod(module); file_map.insert(path.to_owned(), visitor.buffer); } @@ -366,7 +365,7 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { report } -pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap { +pub fn format_string(input: String, config: &Config) -> FileMap { let path = "stdin"; let mut parse_session = ParseSess::new(); let krate = parse::parse_crate_from_source_str(path.to_owned(), @@ -383,7 +382,7 @@ pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap let mut file_map = FileMap::new(); // do the actual formatting - let mut visitor = FmtVisitor::from_codemap(&parse_session, config, Some(mode)); + let mut visitor = FmtVisitor::from_codemap(&parse_session, config); visitor.format_separate_mod(&krate.module); // append final newline @@ -393,7 +392,7 @@ pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap file_map } -pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { +pub fn format(file: &Path, config: &Config) -> FileMap { let mut parse_session = ParseSess::new(); let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session); @@ -401,7 +400,7 @@ pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None)); parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter); - let mut file_map = fmt_ast(&krate, &parse_session, file, config, mode); + let mut file_map = fmt_ast(&krate, &parse_session, file, config); // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. @@ -410,27 +409,25 @@ pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { file_map } -// Make sure that we are using the correct WriteMode, -// preferring what is passed as an argument -fn check_write_mode(arg: WriteMode, config: WriteMode) -> WriteMode { - match (arg, config) { - (WriteMode::Default, WriteMode::Default) => WriteMode::Replace, - (WriteMode::Default, mode) => mode, - (mode, _) => mode, - } -} +// TODO: add test and REMOVE +// / Make sure that we are using the correct WriteMode, +// / preferring what is passed as an argument +// fn check_write_mode(arg: WriteMode, config: WriteMode) -> WriteMode { +// match (arg, config) { +// (WriteMode::Default, WriteMode::Default) => WriteMode::Replace, +// (WriteMode::Default, mode) => mode, +// (mode, _) => mode, +// } +// } // args are the arguments passed on the command line, generally passed through // to the compiler. -// write_mode determines what happens to the result of running rustfmt, see -// WriteMode. -pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { - let mode = check_write_mode(write_mode, config.write_mode); - let mut result = format(file, config, mode); +pub fn run(file: &Path, config: &Config) { + let mut result = format(file, config); print!("{}", fmt_lines(&mut result, config)); let out = stdout(); - let write_result = filemap::write_all_files(&result, out, mode, config); + let write_result = filemap::write_all_files(&result, out, config); if let Err(msg) = write_result { println!("Error writing files: {}", msg); @@ -438,13 +435,12 @@ pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { } // Similar to run, but takes an input String instead of a file to format -pub fn run_from_stdin(input: String, write_mode: WriteMode, config: &Config) { - let mode = check_write_mode(write_mode, config.write_mode); - let mut result = format_string(input, config, mode); +pub fn run_from_stdin(input: String, config: &Config) { + let mut result = format_string(input, config); fmt_lines(&mut result, config); let mut out = stdout(); - let write_result = filemap::write_file(&result["stdin"], "stdin", &mut out, mode, config); + let write_result = filemap::write_file(&result["stdin"], "stdin", &mut out, config); if let Err(msg) = write_result { panic!("Error writing to stdout: {}", msg); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index c86cd62a900..092cc0093f1 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -103,14 +103,9 @@ impl<'a> FmtVisitor<'a> { .collect() } - let replaced = match self.write_mode { - Some(mode) => { - match mode { - WriteMode::Coverage => replace_chars(old_snippet), - _ => old_snippet.to_owned(), - } - } - None => old_snippet.to_owned(), + let replaced = match self.config.write_mode { + WriteMode::Coverage => replace_chars(old_snippet), + _ => old_snippet.to_owned(), }; let snippet = &*replaced; diff --git a/src/visitor.rs b/src/visitor.rs index 073a05ef2bc..f53ed2246d5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -17,7 +17,7 @@ use strings::string_buffer::StringBuffer; use Indent; use utils; -use config::{Config, WriteMode}; +use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; @@ -31,7 +31,6 @@ pub struct FmtVisitor<'a> { // FIXME: use an RAII util or closure for indenting pub block_indent: Indent, pub config: &'a Config, - pub write_mode: Option, } impl<'a> FmtVisitor<'a> { @@ -380,10 +379,7 @@ impl<'a> FmtVisitor<'a> { self.last_pos = span.hi; } - pub fn from_codemap(parse_session: &'a ParseSess, - config: &'a Config, - mode: Option) - -> FmtVisitor<'a> { + pub fn from_codemap(parse_session: &'a ParseSess, config: &'a Config) -> FmtVisitor<'a> { FmtVisitor { parse_session: parse_session, codemap: parse_session.codemap(), @@ -394,7 +390,6 @@ impl<'a> FmtVisitor<'a> { alignment: 0, }, config: config, - write_mode: mode, } } diff --git a/tests/system.rs b/tests/system.rs index 29f34e88c01..c9b976ac7a4 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -12,6 +12,7 @@ extern crate rustfmt; extern crate diff; extern crate regex; extern crate term; +extern crate toml; use std::collections::HashMap; use std::fs; @@ -20,7 +21,7 @@ use std::path::Path; use rustfmt::*; use rustfmt::filemap::{write_system_newlines, FileMap}; -use rustfmt::config::{Config, ReportTactic, WriteMode}; +use rustfmt::config::{Config, PartialConfig, ReportTactic, WriteMode}; use rustfmt::rustfmt_diff::*; static DIFF_CONTEXT_SIZE: usize = 3; @@ -44,7 +45,7 @@ fn system_tests() { // Turn a DirEntry into a String that represents the relative path to the // file. let files = files.map(get_path_string); - let (_reports, count, fails) = check_files(files, WriteMode::Default); + let (_reports, count, fails) = check_files(files, None); // Display results. println!("Ran {} system tests.", count); @@ -57,7 +58,7 @@ fn system_tests() { fn coverage_tests() { let files = fs::read_dir("tests/coverage-source").expect("Couldn't read source dir"); let files = files.map(get_path_string); - let (_reports, count, fails) = check_files(files, WriteMode::Coverage); + let (_reports, count, fails) = check_files(files, Some(WriteMode::Coverage)); println!("Ran {} tests in coverage mode.", count); assert!(fails == 0, "{} tests failed", fails); @@ -67,19 +68,21 @@ fn coverage_tests() { fn checkstyle_test() { let filename = "tests/source/fn-single-line.rs"; let expected_filename = "tests/writemode/checkstyle.xml"; - assert_output(filename, expected_filename, WriteMode::Checkstyle); + assert_output(filename, expected_filename, Some(WriteMode::Checkstyle)); } // Helper function for comparing the results of rustfmt // to a known output file generated by one of the write modes. -fn assert_output(source: &str, expected_filename: &str, write_mode: WriteMode) { +fn assert_output(source: &str, expected_filename: &str, write_mode: Option) { let config = read_config(&source); let file_map = run_rustfmt(source.to_string(), write_mode); // Populate output by writing to a vec. let mut out = vec![]; - let _ = filemap::write_all_files(&file_map, &mut out, write_mode, &config); + let _ = filemap::write_all_files(&file_map, + &mut out, + &config.merge(&PartialConfig::from(write_mode))); let output = String::from_utf8(out).unwrap(); let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); @@ -104,7 +107,7 @@ fn idempotence_tests() { let files = fs::read_dir("tests/target") .expect("Couldn't read target dir") .map(get_path_string); - let (_reports, count, fails) = check_files(files, WriteMode::Default); + let (_reports, count, fails) = check_files(files, None); // Display results. println!("Ran {} idempotent tests.", count); @@ -122,7 +125,7 @@ fn self_tests() { // Hack because there's no `IntoIterator` impl for `[T; N]`. let files = files.chain(Some("src/lib.rs".to_owned()).into_iter()); - let (reports, count, fails) = check_files(files, WriteMode::Default); + let (reports, count, fails) = check_files(files, None); let mut warnings = 0; // Display results. @@ -141,7 +144,7 @@ fn self_tests() { // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. -fn check_files(files: I, write_mode: WriteMode) -> (Vec, u32, u32) +fn check_files(files: I, write_mode: Option) -> (Vec, u32, u32) where I: Iterator { let mut count = 0; @@ -192,13 +195,13 @@ fn read_config(filename: &str) -> Config { } // Simulate run() -fn run_rustfmt(filename: String, write_mode: WriteMode) -> FileMap { - let config = read_config(&filename); - format(Path::new(&filename), &config, write_mode) +fn run_rustfmt(filename: String, write_mode: Option) -> FileMap { + let config = read_config(&filename).merge(&PartialConfig::from(write_mode)); + format(Path::new(&filename), &config) } pub fn idempotent_check(filename: String, - write_mode: WriteMode) + write_mode: Option) -> Result>> { let sig_comments = read_significant_comments(&filename); let config = read_config(&filename); @@ -232,10 +235,11 @@ fn get_config(config_file: Option<&str>) -> Config { }; let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); - let mut def_config = String::new(); - def_config_file.read_to_string(&mut def_config).expect("Couldn't read config"); + let mut buf = String::new(); + def_config_file.read_to_string(&mut buf).expect("Couldn't read config"); - Config::from_toml(&def_config) + let def_config: PartialConfig = toml::decode_str(&buf).expect("Failed to parse config"); + Config::from(def_config) } // Reads significant comments of the form: // rustfmt-key: value @@ -266,7 +270,7 @@ fn read_significant_comments(file_name: &str) -> HashMap { // TODO: needs a better name, more explanation. fn handle_result(result: HashMap, target: Option<&str>, - write_mode: WriteMode) + write_mode: Option) -> Result<(), HashMap>> { let mut failures = HashMap::new(); @@ -292,10 +296,10 @@ fn handle_result(result: HashMap, } // Map source file paths to their target paths. -fn get_target(file_name: &str, target: Option<&str>, write_mode: WriteMode) -> String { +fn get_target(file_name: &str, target: Option<&str>, write_mode: Option) -> String { let file_path = Path::new(file_name); let (source_path_prefix, target_path_prefix) = match write_mode { - WriteMode::Coverage => { + Some(WriteMode::Coverage) => { (Path::new("tests/coverage-source/"), "tests/coverage-target/") }