Skip to content

Commit a99b99b

Browse files
feat: continue on recovered parse errors in ignore files
1 parent 9ad9df0 commit a99b99b

File tree

7 files changed

+68
-15
lines changed

7 files changed

+68
-15
lines changed

src/formatting.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// High level formatting functions.
22

3+
use std::cell::RefCell;
34
use std::collections::HashMap;
45
use std::io::{self, Write};
56
use std::panic::{catch_unwind, AssertUnwindSafe};
@@ -70,17 +71,19 @@ fn format_project<T: FormatHandler>(
7071
Ok(set) => set,
7172
Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)),
7273
};
73-
let is_ignore_match = ignore_path_set.is_match(&main_file);
74-
if config.skip_children() && is_ignore_match {
74+
if config.skip_children() && ignore_path_set.is_match(&main_file) {
7575
return Ok(FormatReport::new());
7676
}
7777

7878
// Parse the crate.
79+
let can_reset = Rc::new(RefCell::new(false));
7980
let source_map = Rc::new(SourceMap::new(FilePathMapping::empty()));
80-
let mut parse_session = make_parse_sess(source_map.clone(), config, &ignore_path_set);
81-
if is_ignore_match {
82-
parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter());
83-
}
81+
let mut parse_session = make_parse_sess(
82+
source_map.clone(),
83+
config,
84+
&ignore_path_set,
85+
can_reset.clone(),
86+
);
8487
let mut report = FormatReport::new();
8588
let directory_ownership = input.to_directory_ownership();
8689
let krate = match parse_crate(
@@ -89,16 +92,11 @@ fn format_project<T: FormatHandler>(
8992
config,
9093
&mut report,
9194
directory_ownership,
95+
can_reset.clone(),
9296
) {
9397
Ok(krate) => krate,
9498
// Surface parse error via Session (errors are merged there from report)
95-
Err(ErrorKind::ParseError) => {
96-
// https://github.com/rust-lang/rustfmt/issues/3779
97-
if is_ignore_match {
98-
return Ok(FormatReport::new());
99-
}
100-
return Ok(report);
101-
}
99+
Err(ErrorKind::ParseError) => return Ok(report),
102100
Err(e) => return Err(e),
103101
};
104102
timer = timer.done_parsing();
@@ -630,6 +628,7 @@ fn parse_crate(
630628
config: &Config,
631629
report: &mut FormatReport,
632630
directory_ownership: Option<parse::DirectoryOwnership>,
631+
parser_error_resetter: Rc<RefCell<bool>>,
633632
) -> Result<ast::Crate, ErrorKind> {
634633
let input_is_stdin = input.is_text();
635634

@@ -677,6 +676,15 @@ fn parse_crate(
677676
if !parse_session.span_diagnostic.has_errors() {
678677
return Ok(c);
679678
}
679+
// This scenario occurs when the parser encountered errors
680+
// but was still able to recover. If all of the parser errors
681+
// occurred in files that are ignored, then reset
682+
// the error count and continue.
683+
// https://github.com/rust-lang/rustfmt/issues/3779
684+
if *parser_error_resetter.borrow() {
685+
parse_session.span_diagnostic.reset_err_count();
686+
return Ok(c);
687+
}
680688
}
681689
Ok(Err(mut diagnostics)) => diagnostics.iter_mut().for_each(DiagnosticBuilder::emit),
682690
Err(_) => {
@@ -697,6 +705,9 @@ struct SilentOnIgnoredFilesEmitter {
697705
ignore_path_set: IgnorePathSet,
698706
source_map: Rc<SourceMap>,
699707
emitter: EmitterWriter,
708+
can_reset: bool,
709+
has_non_ignorable_parser_errors: bool,
710+
parser_error_resetter: Rc<RefCell<bool>>,
700711
}
701712

702713
impl Emitter for SilentOnIgnoredFilesEmitter {
@@ -709,13 +720,22 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
709720
.ignore_path_set
710721
.is_match(&FileName::Real(path.to_path_buf()))
711722
{
712-
db.handler.reset_err_count();
723+
if !self.has_non_ignorable_parser_errors && !self.can_reset {
724+
self.can_reset = true;
725+
*self.parser_error_resetter.borrow_mut() = true;
726+
}
713727
return;
714728
}
715729
}
716730
_ => (),
717731
};
718732
}
733+
734+
self.has_non_ignorable_parser_errors = true;
735+
if self.can_reset {
736+
*self.parser_error_resetter.borrow_mut() = false;
737+
}
738+
self.can_reset = false;
719739
self.emitter.emit_diagnostic(db);
720740
}
721741
}
@@ -735,6 +755,7 @@ fn make_parse_sess(
735755
source_map: Rc<SourceMap>,
736756
config: &Config,
737757
ignore_path_set: &IgnorePathSet,
758+
parser_error_resetter: Rc<RefCell<bool>>,
738759
) -> ParseSess {
739760
let tty_handler = if config.hide_parse_errors() {
740761
let silent_emitter = silent_emitter();
@@ -746,12 +767,16 @@ fn make_parse_sess(
746767
} else {
747768
ColorConfig::Never
748769
};
770+
749771
let emitter_writer =
750-
EmitterWriter::stderr(color_cfg, Some(source_map.clone()), false, false);
772+
EmitterWriter::stderr(color_cfg, Some(source_map.clone()), false, false, None);
751773
let emitter = Box::new(SilentOnIgnoredFilesEmitter {
774+
has_non_ignorable_parser_errors: false,
775+
can_reset: false,
752776
ignore_path_set: ignore_path_set.clone(),
753777
source_map: source_map.clone(),
754778
emitter: emitter_writer,
779+
parser_error_resetter,
755780
});
756781
Handler::with_emitter_and_flags(
757782
emitter,

src/test/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[
2727
"configs/skip_children/foo/mod.rs",
2828
"issue-3434/no_entry.rs",
2929
"issue-3665/sub_mod.rs",
30+
// Testing for issue-3779
31+
"issue-3779/ice.rs",
3032
// These files and directory are a part of modules defined inside `cfg_if!`.
3133
"cfg_if/mod.rs",
3234
"cfg_if/detect",

tests/config/issue-3779.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
unstable_features = true
2+
ignore = [
3+
"tests/**/issue-3779/ice.rs"
4+
]

tests/source/issue-3779/ice.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn bar() {
2+
1x;
3+
}

tests/source/issue-3779/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// rustfmt-config: issue-3779.toml
2+
3+
#[path = "ice.rs"]
4+
mod ice;
5+
6+
fn foo() {
7+
println!("abc") ;
8+
}

tests/target/issue-3779/ice.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn bar() {
2+
1x;
3+
}

tests/target/issue-3779/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// rustfmt-config: issue-3779.toml
2+
3+
#[path = "ice.rs"]
4+
mod ice;
5+
6+
fn foo() {
7+
println!("abc");
8+
}

0 commit comments

Comments
 (0)