From a99b99bfe3ab593d4d212fcede5faf6229db2592 Mon Sep 17 00:00:00 2001 From: calebcartwright Date: Sun, 8 Sep 2019 15:44:12 -0500 Subject: [PATCH] feat: continue on recovered parse errors in ignore files --- src/formatting.rs | 55 ++++++++++++++++++++++++---------- src/test/mod.rs | 2 ++ tests/config/issue-3779.toml | 4 +++ tests/source/issue-3779/ice.rs | 3 ++ tests/source/issue-3779/lib.rs | 8 +++++ tests/target/issue-3779/ice.rs | 3 ++ tests/target/issue-3779/lib.rs | 8 +++++ 7 files changed, 68 insertions(+), 15 deletions(-) create mode 100644 tests/config/issue-3779.toml create mode 100644 tests/source/issue-3779/ice.rs create mode 100644 tests/source/issue-3779/lib.rs create mode 100644 tests/target/issue-3779/ice.rs create mode 100644 tests/target/issue-3779/lib.rs diff --git a/src/formatting.rs b/src/formatting.rs index d45ef762e87..7d9dd6f8c8a 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -1,5 +1,6 @@ // High level formatting functions. +use std::cell::RefCell; use std::collections::HashMap; use std::io::{self, Write}; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -70,17 +71,19 @@ fn format_project( Ok(set) => set, Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), }; - let is_ignore_match = ignore_path_set.is_match(&main_file); - if config.skip_children() && is_ignore_match { + if config.skip_children() && ignore_path_set.is_match(&main_file) { return Ok(FormatReport::new()); } // Parse the crate. + let can_reset = Rc::new(RefCell::new(false)); let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let mut parse_session = make_parse_sess(source_map.clone(), config, &ignore_path_set); - if is_ignore_match { - parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter()); - } + let mut parse_session = make_parse_sess( + source_map.clone(), + config, + &ignore_path_set, + can_reset.clone(), + ); let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); let krate = match parse_crate( @@ -89,16 +92,11 @@ fn format_project( config, &mut report, directory_ownership, + can_reset.clone(), ) { Ok(krate) => krate, // Surface parse error via Session (errors are merged there from report) - Err(ErrorKind::ParseError) => { - // https://github.com/rust-lang/rustfmt/issues/3779 - if is_ignore_match { - return Ok(FormatReport::new()); - } - return Ok(report); - } + Err(ErrorKind::ParseError) => return Ok(report), Err(e) => return Err(e), }; timer = timer.done_parsing(); @@ -630,6 +628,7 @@ fn parse_crate( config: &Config, report: &mut FormatReport, directory_ownership: Option, + parser_error_resetter: Rc>, ) -> Result { let input_is_stdin = input.is_text(); @@ -677,6 +676,15 @@ fn parse_crate( if !parse_session.span_diagnostic.has_errors() { return Ok(c); } + // This scenario occurs when the parser encountered errors + // but was still able to recover. If all of the parser errors + // occurred in files that are ignored, then reset + // the error count and continue. + // https://github.com/rust-lang/rustfmt/issues/3779 + if *parser_error_resetter.borrow() { + parse_session.span_diagnostic.reset_err_count(); + return Ok(c); + } } Ok(Err(mut diagnostics)) => diagnostics.iter_mut().for_each(DiagnosticBuilder::emit), Err(_) => { @@ -697,6 +705,9 @@ struct SilentOnIgnoredFilesEmitter { ignore_path_set: IgnorePathSet, source_map: Rc, emitter: EmitterWriter, + can_reset: bool, + has_non_ignorable_parser_errors: bool, + parser_error_resetter: Rc>, } impl Emitter for SilentOnIgnoredFilesEmitter { @@ -709,13 +720,22 @@ impl Emitter for SilentOnIgnoredFilesEmitter { .ignore_path_set .is_match(&FileName::Real(path.to_path_buf())) { - db.handler.reset_err_count(); + if !self.has_non_ignorable_parser_errors && !self.can_reset { + self.can_reset = true; + *self.parser_error_resetter.borrow_mut() = true; + } return; } } _ => (), }; } + + self.has_non_ignorable_parser_errors = true; + if self.can_reset { + *self.parser_error_resetter.borrow_mut() = false; + } + self.can_reset = false; self.emitter.emit_diagnostic(db); } } @@ -735,6 +755,7 @@ fn make_parse_sess( source_map: Rc, config: &Config, ignore_path_set: &IgnorePathSet, + parser_error_resetter: Rc>, ) -> ParseSess { let tty_handler = if config.hide_parse_errors() { let silent_emitter = silent_emitter(); @@ -746,12 +767,16 @@ fn make_parse_sess( } else { ColorConfig::Never }; + let emitter_writer = - EmitterWriter::stderr(color_cfg, Some(source_map.clone()), false, false); + EmitterWriter::stderr(color_cfg, Some(source_map.clone()), false, false, None); let emitter = Box::new(SilentOnIgnoredFilesEmitter { + has_non_ignorable_parser_errors: false, + can_reset: false, ignore_path_set: ignore_path_set.clone(), source_map: source_map.clone(), emitter: emitter_writer, + parser_error_resetter, }); Handler::with_emitter_and_flags( emitter, diff --git a/src/test/mod.rs b/src/test/mod.rs index 3793a98ab00..47430760bee 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -27,6 +27,8 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ "configs/skip_children/foo/mod.rs", "issue-3434/no_entry.rs", "issue-3665/sub_mod.rs", + // Testing for issue-3779 + "issue-3779/ice.rs", // These files and directory are a part of modules defined inside `cfg_if!`. "cfg_if/mod.rs", "cfg_if/detect", diff --git a/tests/config/issue-3779.toml b/tests/config/issue-3779.toml new file mode 100644 index 00000000000..83505f409af --- /dev/null +++ b/tests/config/issue-3779.toml @@ -0,0 +1,4 @@ +unstable_features = true +ignore = [ + "tests/**/issue-3779/ice.rs" +] diff --git a/tests/source/issue-3779/ice.rs b/tests/source/issue-3779/ice.rs new file mode 100644 index 00000000000..cde21412d94 --- /dev/null +++ b/tests/source/issue-3779/ice.rs @@ -0,0 +1,3 @@ +pub fn bar() { + 1x; +} diff --git a/tests/source/issue-3779/lib.rs b/tests/source/issue-3779/lib.rs new file mode 100644 index 00000000000..d7c2ae28975 --- /dev/null +++ b/tests/source/issue-3779/lib.rs @@ -0,0 +1,8 @@ +// rustfmt-config: issue-3779.toml + +#[path = "ice.rs"] +mod ice; + +fn foo() { +println!("abc") ; + } diff --git a/tests/target/issue-3779/ice.rs b/tests/target/issue-3779/ice.rs new file mode 100644 index 00000000000..cde21412d94 --- /dev/null +++ b/tests/target/issue-3779/ice.rs @@ -0,0 +1,3 @@ +pub fn bar() { + 1x; +} diff --git a/tests/target/issue-3779/lib.rs b/tests/target/issue-3779/lib.rs new file mode 100644 index 00000000000..ebebce417d1 --- /dev/null +++ b/tests/target/issue-3779/lib.rs @@ -0,0 +1,8 @@ +// rustfmt-config: issue-3779.toml + +#[path = "ice.rs"] +mod ice; + +fn foo() { + println!("abc"); +}