about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Cartwright <caleb.cartwright@outlook.com>2020-10-29 22:50:25 -0500
committerCaleb Cartwright <calebcartwright@users.noreply.github.com>2020-11-02 18:31:51 -0600
commit9faba4539b24ac2db69edd385774d085bb0fd120 (patch)
tree926899a142152ef8b30022fb5c4312f5180ad759
parente131797b62fd52f48fb59296c4c700a97250dee4 (diff)
fix(parser): better unclosed delims handling
-rw-r--r--src/syntux/parser.rs40
-rw-r--r--src/test/mod.rs34
-rw-r--r--src/test/parser.rs50
-rw-r--r--tests/parser/unclosed-delims/issue_4466.rs11
4 files changed, 86 insertions, 49 deletions
diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs
index 711dfc80c2c..78de08b993e 100644
--- a/src/syntux/parser.rs
+++ b/src/syntux/parser.rs
@@ -23,7 +23,6 @@ pub(crate) struct Directory {
 /// A parser for Rust source code.
 pub(crate) struct Parser<'a> {
     parser: RawParser<'a>,
-    sess: &'a ParseSess,
 }
 
 /// A builder for the `Parser`.
@@ -71,7 +70,7 @@ impl<'a> ParserBuilder<'a> {
             }
         };
 
-        Ok(Parser { parser, sess })
+        Ok(Parser { parser })
     }
 
     fn parser(
@@ -151,32 +150,39 @@ impl<'a> Parser<'a> {
         directory_ownership: Option<DirectoryOwnership>,
         sess: &'a ParseSess,
     ) -> Result<ast::Crate, ParserError> {
+        let krate = Parser::parse_crate_inner(config, input, directory_ownership, sess)?;
+        if !sess.has_errors() {
+            return Ok(krate);
+        }
+
+        if sess.can_reset_errors() {
+            sess.reset_errors();
+            return Ok(krate);
+        }
+
+        Err(ParserError::ParseError)
+    }
+
+    fn parse_crate_inner(
+        config: &'a Config,
+        input: Input,
+        directory_ownership: Option<DirectoryOwnership>,
+        sess: &'a ParseSess,
+    ) -> Result<ast::Crate, ParserError> {
         let mut parser = ParserBuilder::default()
             .config(config)
             .input(input)
             .directory_ownership(directory_ownership)
             .sess(sess)
             .build()?;
-
-        parser.parse_crate_inner()
+        parser.parse_crate_mod()
     }
 
-    fn parse_crate_inner(&mut self) -> Result<ast::Crate, ParserError> {
+    fn parse_crate_mod(&mut self) -> Result<ast::Crate, ParserError> {
         let mut parser = AssertUnwindSafe(&mut self.parser);
 
         match catch_unwind(move || parser.parse_crate_mod()) {
-            Ok(Ok(krate)) => {
-                if !self.sess.has_errors() {
-                    return Ok(krate);
-                }
-
-                if self.sess.can_reset_errors() {
-                    self.sess.reset_errors();
-                    return Ok(krate);
-                }
-
-                Err(ParserError::ParseError)
-            }
+            Ok(Ok(k)) => Ok(k),
             Ok(Err(mut db)) => {
                 db.emit();
                 Err(ParserError::ParseError)
diff --git a/src/test/mod.rs b/src/test/mod.rs
index 57b5f2a78cd..9b3ca717152 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -11,14 +11,12 @@ use std::thread;
 
 use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic};
 use crate::formatting::{ReportedErrors, SourceFile};
-use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind};
 use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter};
 use crate::source_file;
-use crate::{
-    is_nightly_channel, ErrorKind, FormatReport, FormatReportFormatterBuilder, Input, Session,
-};
+use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session};
 
 mod configuration_snippet;
+mod parser;
 
 const DIFF_CONTEXT_SIZE: usize = 3;
 
@@ -485,34 +483,6 @@ 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) {
diff --git a/src/test/parser.rs b/src/test/parser.rs
new file mode 100644
index 00000000000..75aed32e68b
--- /dev/null
+++ b/src/test/parser.rs
@@ -0,0 +1,50 @@
+use std::io;
+use std::path::PathBuf;
+
+use super::read_config;
+
+use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind};
+use crate::{ErrorKind, Input, Session};
+
+#[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");
+    }
+}
+
+fn assert_parser_error(filename: &str) {
+    let file = PathBuf::from(filename);
+    let config = read_config(&file);
+    let mut session = Session::<io::Stdout>::new(config, None);
+    let _ = session.format(Input::File(filename.into())).unwrap();
+    assert!(session.has_parsing_errors());
+}
+
+#[test]
+fn crate_parsing_errors_on_unclosed_delims() {
+    // See also https://github.com/rust-lang/rustfmt/issues/4466
+    let filename = "tests/parser/unclosed-delims/issue_4466.rs";
+    assert_parser_error(filename);
+}
diff --git a/tests/parser/unclosed-delims/issue_4466.rs b/tests/parser/unclosed-delims/issue_4466.rs
new file mode 100644
index 00000000000..2c2c81c91d1
--- /dev/null
+++ b/tests/parser/unclosed-delims/issue_4466.rs
@@ -0,0 +1,11 @@
+fn main() {
+    if true {
+        println!("answer: {}", a_func();
+    } else {
+        println!("don't think so.");
+    }
+}
+
+fn a_func() -> i32 {
+    42
+} 
\ No newline at end of file