about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorCaleb Cartwright <caleb.cartwright@outlook.com>2020-06-11 21:49:40 -0500
committerCaleb Cartwright <caleb.cartwright@outlook.com>2020-06-11 21:49:40 -0500
commitce1a3efff03a17af6f0f8f93c07e3abe9058762e (patch)
tree224caf342f9b2ba799d83b93a10a381e9fca1165 /src
parentdead3a807d6031972559c67ac5d30c61c50b0067 (diff)
fix: backport fix for submod parser errors
Diffstat (limited to 'src')
-rw-r--r--src/formatting.rs14
-rw-r--r--src/modules.rs4
-rw-r--r--src/syntux/parser.rs12
-rw-r--r--src/test/mod.rs34
4 files changed, 52 insertions, 12 deletions
diff --git a/src/formatting.rs b/src/formatting.rs
index 8178342f28c..28d111ba623 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -62,7 +62,7 @@ fn format_project<T: FormatHandler>(
     let main_file = input.file_name();
     let input_is_stdin = main_file == FileName::Stdin;
 
-    let mut parse_session = ParseSess::new(config)?;
+    let parse_session = ParseSess::new(config)?;
     if config.skip_children() && parse_session.ignore_file(&main_file) {
         return Ok(FormatReport::new());
     }
@@ -82,10 +82,6 @@ fn format_project<T: FormatHandler>(
             return Ok(report);
         }
     };
-    timer = timer.done_parsing();
-
-    // Suppress error output if we have to do any further parsing.
-    parse_session.set_silent_emitter();
 
     let mut context = FormatContext::new(&krate, report, parse_session, config, handler);
     let files = modules::ModResolver::new(
@@ -93,8 +89,12 @@ fn format_project<T: FormatHandler>(
         directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod),
         !input_is_stdin && !config.skip_children(),
     )
-    .visit_crate(&krate)
-    .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
+    .visit_crate(&krate)?;
+
+    timer = timer.done_parsing();
+
+    // Suppress error output if we have to do any further parsing.
+    context.parse_session.set_silent_emitter();
 
     for (path, module) in files {
         let should_ignore = !input_is_stdin && context.ignore_file(&path);
diff --git a/src/modules.rs b/src/modules.rs
index 8ecb121f9e7..cbe663cb412 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -36,8 +36,8 @@ pub(crate) struct ModResolver<'ast, 'sess> {
 #[error("failed to resolve mod `{module}`: {kind}")]
 #[derive(Debug, Error)]
 pub struct ModuleResolutionError {
-    module: String,
-    kind: ModuleResolutionErrorKind,
+    pub(crate) module: String,
+    pub(crate) kind: ModuleResolutionErrorKind,
 }
 
 #[derive(Debug, Error)]
diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs
index 89db0f5553c..decad02d049 100644
--- a/src/syntux/parser.rs
+++ b/src/syntux/parser.rs
@@ -119,7 +119,17 @@ impl<'a> Parser<'a> {
             }
         }));
         match result {
-            Ok(Some(m)) => Ok(m),
+            Ok(Some(m)) => {
+                if !sess.has_errors() {
+                    return Ok(m);
+                }
+
+                if sess.can_reset_errors() {
+                    sess.reset_errors();
+                    return Ok(m);
+                }
+                Err(ParserError::ParseError)
+            }
             Ok(None) => Err(ParserError::ParseError),
             Err(..) if path.exists() => Err(ParserError::ParseError),
             Err(_) => Err(ParserError::ParsePanicError),
diff --git a/src/test/mod.rs b/src/test/mod.rs
index e6497f48e0f..57b5f2a78cd 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -11,10 +11,12 @@ use std::thread;
 
 use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic};
 use crate::formatting::{ReportedErrors, SourceFile};
-use crate::is_nightly_channel;
+use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind};
 use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter};
 use crate::source_file;
-use crate::{FormatReport, FormatReportFormatterBuilder, Input, Session};
+use crate::{
+    is_nightly_channel, ErrorKind, FormatReport, FormatReportFormatterBuilder, Input, Session,
+};
 
 mod configuration_snippet;
 
@@ -483,6 +485,34 @@ fn format_lines_errors_are_reported_with_tabs() {
     assert!(session.has_formatting_errors());
 }
 
+#[test]
+fn parser_errors_in_submods_are_surfaced() {
+    // See also https://github.com/rust-lang/rustfmt/issues/4126
+    let filename = "tests/parser/issue-4126/lib.rs";
+    let input_file = PathBuf::from(filename);
+    let exp_mod_name = "invalid";
+    let config = read_config(&input_file);
+    let mut session = Session::<io::Stdout>::new(config, None);
+    if let Err(ErrorKind::ModuleResolutionError(ModuleResolutionError { module, kind })) =
+        session.format(Input::File(filename.into()))
+    {
+        assert_eq!(&module, exp_mod_name);
+        if let ModuleResolutionErrorKind::ParseError {
+            file: unparseable_file,
+        } = kind
+        {
+            assert_eq!(
+                unparseable_file,
+                PathBuf::from("tests/parser/issue-4126/invalid.rs"),
+            );
+        } else {
+            panic!("Expected parser error");
+        }
+    } else {
+        panic!("Expected ModuleResolution operation error");
+    }
+}
+
 // For each file, run rustfmt and collect the output.
 // Returns the number of files checked and the number of failures.
 fn check_files(files: Vec<PathBuf>, opt_config: &Option<PathBuf>) -> (Vec<FormatReport>, u32, u32) {