Skip to content

Commit 3eb864e

Browse files
fix: handle recoverable submod parse errors correctly (#4200)
1 parent 15e2854 commit 3eb864e

File tree

6 files changed

+57
-10
lines changed

6 files changed

+57
-10
lines changed

rustfmt-core/rustfmt-lib/src/formatting.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,6 @@ fn format_project(
106106
});
107107
}
108108
};
109-
timer = timer.done_parsing();
110-
111-
// Suppress error output if we have to do any further parsing.
112-
parse_session.set_silent_emitter();
113109

114110
let files = modules::ModResolver::new(
115111
&parse_session,
@@ -118,6 +114,11 @@ fn format_project(
118114
)
119115
.visit_crate(&krate)?;
120116

117+
timer = timer.done_parsing();
118+
119+
// Suppress error output if we have to do any further parsing.
120+
parse_session.set_silent_emitter();
121+
121122
for (path, module) in files {
122123
let should_ignore = !input_is_stdin && parse_session.ignore_file(&path);
123124
if (!operation_setting.recursive && path != main_file) || should_ignore {

rustfmt-core/rustfmt-lib/src/formatting/modules.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ pub(crate) struct ModResolver<'ast, 'sess> {
3636
#[error("failed to resolve mod `{module}`: {kind}")]
3737
#[derive(Debug, Error)]
3838
pub struct ModuleResolutionError {
39-
module: String,
40-
kind: ModuleResolutionErrorKind,
39+
pub(crate) module: String,
40+
pub(crate) kind: ModuleResolutionErrorKind,
4141
}
4242

4343
#[derive(Debug, Error)]

rustfmt-core/rustfmt-lib/src/formatting/syntux/parser.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,9 @@ impl<'a> Parser<'a> {
177177
Ok(_attrs) => (),
178178
Err(mut e) => {
179179
e.cancel();
180-
sess.reset_errors();
180+
if sess.can_reset_errors() {
181+
sess.reset_errors();
182+
}
181183
return None;
182184
}
183185
}
@@ -186,13 +188,25 @@ impl<'a> Parser<'a> {
186188
Ok(m) => Some(m),
187189
Err(mut db) => {
188190
db.cancel();
189-
sess.reset_errors();
191+
if sess.can_reset_errors() {
192+
sess.reset_errors();
193+
}
190194
None
191195
}
192196
}
193197
}));
194198
match result {
195-
Ok(Some(m)) => Ok(m),
199+
Ok(Some(m)) => {
200+
if !sess.has_errors() {
201+
return Ok(m);
202+
}
203+
204+
if sess.can_reset_errors() {
205+
sess.reset_errors();
206+
return Ok(m);
207+
}
208+
Err(ParserError::ParseError)
209+
}
196210
Ok(None) => Err(ParserError::ParseError),
197211
Err(..) if path.exists() => Err(ParserError::ParseError),
198212
Err(_) => Err(ParserError::ParsePanicError),

rustfmt-core/rustfmt-lib/src/test/mod.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ use crate::emitter::rustfmt_diff::{make_diff, print_diff, Mismatch, ModifiedChun
1111
use crate::config::{Config, FileName, NewlineStyle};
1212
use crate::{
1313
emitter::{emit_format_report, Color, EmitMode, EmitterConfig},
14-
format, is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, OperationError,
14+
format,
15+
formatting::modules::{ModuleResolutionError, ModuleResolutionErrorKind},
16+
is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, OperationError,
1517
OperationSetting,
1618
};
1719

@@ -519,6 +521,28 @@ fn format_lines_errors_are_reported_with_tabs() {
519521
assert!(report.has_errors());
520522
}
521523

524+
#[test]
525+
fn parser_errors_in_submods_are_surfaced() {
526+
// See also https://github.com/rust-lang/rustfmt/issues/4126
527+
let filename = "tests/parser/issue-4126/lib.rs";
528+
let file = PathBuf::from(filename);
529+
let exp_mod_name = "invalid";
530+
let (config, operation, _) = read_config(&file);
531+
if let Err(OperationError::ModuleResolutionError { 0: inner }) =
532+
format_file(&file, operation, config)
533+
{
534+
let ModuleResolutionError { module, kind } = inner;
535+
assert_eq!(&module, exp_mod_name);
536+
if let ModuleResolutionErrorKind::ParseError { file } = kind {
537+
assert_eq!(file, PathBuf::from("tests/parser/issue-4126/invalid.rs"));
538+
} else {
539+
panic!("Expected parser error");
540+
}
541+
} else {
542+
panic!("Expected ModuleResolution operation error");
543+
}
544+
}
545+
522546
// For each file, run rustfmt and collect the output.
523547
// Returns the number of files checked and the number of failures.
524548
fn check_files(files: Vec<PathBuf>, opt_config: &Option<PathBuf>) -> (Vec<FormatReport>, u32, u32) {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn foo() {
2+
if bar && if !baz {
3+
next_is_none = Some(true);
4+
}
5+
println!("foo");
6+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// rustfmt-recursive: true
2+
mod invalid;

0 commit comments

Comments
 (0)