Skip to content

Commit 9faba45

Browse files
fix(parser): better unclosed delims handling
1 parent e131797 commit 9faba45

File tree

4 files changed

+86
-49
lines changed

4 files changed

+86
-49
lines changed

src/syntux/parser.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ pub(crate) struct Directory {
2323
/// A parser for Rust source code.
2424
pub(crate) struct Parser<'a> {
2525
parser: RawParser<'a>,
26-
sess: &'a ParseSess,
2726
}
2827

2928
/// A builder for the `Parser`.
@@ -71,7 +70,7 @@ impl<'a> ParserBuilder<'a> {
7170
}
7271
};
7372

74-
Ok(Parser { parser, sess })
73+
Ok(Parser { parser })
7574
}
7675

7776
fn parser(
@@ -150,33 +149,40 @@ impl<'a> Parser<'a> {
150149
input: Input,
151150
directory_ownership: Option<DirectoryOwnership>,
152151
sess: &'a ParseSess,
152+
) -> Result<ast::Crate, ParserError> {
153+
let krate = Parser::parse_crate_inner(config, input, directory_ownership, sess)?;
154+
if !sess.has_errors() {
155+
return Ok(krate);
156+
}
157+
158+
if sess.can_reset_errors() {
159+
sess.reset_errors();
160+
return Ok(krate);
161+
}
162+
163+
Err(ParserError::ParseError)
164+
}
165+
166+
fn parse_crate_inner(
167+
config: &'a Config,
168+
input: Input,
169+
directory_ownership: Option<DirectoryOwnership>,
170+
sess: &'a ParseSess,
153171
) -> Result<ast::Crate, ParserError> {
154172
let mut parser = ParserBuilder::default()
155173
.config(config)
156174
.input(input)
157175
.directory_ownership(directory_ownership)
158176
.sess(sess)
159177
.build()?;
160-
161-
parser.parse_crate_inner()
178+
parser.parse_crate_mod()
162179
}
163180

164-
fn parse_crate_inner(&mut self) -> Result<ast::Crate, ParserError> {
181+
fn parse_crate_mod(&mut self) -> Result<ast::Crate, ParserError> {
165182
let mut parser = AssertUnwindSafe(&mut self.parser);
166183

167184
match catch_unwind(move || parser.parse_crate_mod()) {
168-
Ok(Ok(krate)) => {
169-
if !self.sess.has_errors() {
170-
return Ok(krate);
171-
}
172-
173-
if self.sess.can_reset_errors() {
174-
self.sess.reset_errors();
175-
return Ok(krate);
176-
}
177-
178-
Err(ParserError::ParseError)
179-
}
185+
Ok(Ok(k)) => Ok(k),
180186
Ok(Err(mut db)) => {
181187
db.emit();
182188
Err(ParserError::ParseError)

src/test/mod.rs

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ use std::thread;
1111

1212
use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic};
1313
use crate::formatting::{ReportedErrors, SourceFile};
14-
use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind};
1514
use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter};
1615
use crate::source_file;
17-
use crate::{
18-
is_nightly_channel, ErrorKind, FormatReport, FormatReportFormatterBuilder, Input, Session,
19-
};
16+
use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session};
2017

2118
mod configuration_snippet;
19+
mod parser;
2220

2321
const DIFF_CONTEXT_SIZE: usize = 3;
2422

@@ -485,34 +483,6 @@ fn format_lines_errors_are_reported_with_tabs() {
485483
assert!(session.has_formatting_errors());
486484
}
487485

488-
#[test]
489-
fn parser_errors_in_submods_are_surfaced() {
490-
// See also https://github.com/rust-lang/rustfmt/issues/4126
491-
let filename = "tests/parser/issue-4126/lib.rs";
492-
let input_file = PathBuf::from(filename);
493-
let exp_mod_name = "invalid";
494-
let config = read_config(&input_file);
495-
let mut session = Session::<io::Stdout>::new(config, None);
496-
if let Err(ErrorKind::ModuleResolutionError(ModuleResolutionError { module, kind })) =
497-
session.format(Input::File(filename.into()))
498-
{
499-
assert_eq!(&module, exp_mod_name);
500-
if let ModuleResolutionErrorKind::ParseError {
501-
file: unparseable_file,
502-
} = kind
503-
{
504-
assert_eq!(
505-
unparseable_file,
506-
PathBuf::from("tests/parser/issue-4126/invalid.rs"),
507-
);
508-
} else {
509-
panic!("Expected parser error");
510-
}
511-
} else {
512-
panic!("Expected ModuleResolution operation error");
513-
}
514-
}
515-
516486
// For each file, run rustfmt and collect the output.
517487
// Returns the number of files checked and the number of failures.
518488
fn check_files(files: Vec<PathBuf>, opt_config: &Option<PathBuf>) -> (Vec<FormatReport>, u32, u32) {

src/test/parser.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use std::io;
2+
use std::path::PathBuf;
3+
4+
use super::read_config;
5+
6+
use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind};
7+
use crate::{ErrorKind, Input, Session};
8+
9+
#[test]
10+
fn parser_errors_in_submods_are_surfaced() {
11+
// See also https://github.com/rust-lang/rustfmt/issues/4126
12+
let filename = "tests/parser/issue-4126/lib.rs";
13+
let input_file = PathBuf::from(filename);
14+
let exp_mod_name = "invalid";
15+
let config = read_config(&input_file);
16+
let mut session = Session::<io::Stdout>::new(config, None);
17+
if let Err(ErrorKind::ModuleResolutionError(ModuleResolutionError { module, kind })) =
18+
session.format(Input::File(filename.into()))
19+
{
20+
assert_eq!(&module, exp_mod_name);
21+
if let ModuleResolutionErrorKind::ParseError {
22+
file: unparseable_file,
23+
} = kind
24+
{
25+
assert_eq!(
26+
unparseable_file,
27+
PathBuf::from("tests/parser/issue-4126/invalid.rs"),
28+
);
29+
} else {
30+
panic!("Expected parser error");
31+
}
32+
} else {
33+
panic!("Expected ModuleResolution operation error");
34+
}
35+
}
36+
37+
fn assert_parser_error(filename: &str) {
38+
let file = PathBuf::from(filename);
39+
let config = read_config(&file);
40+
let mut session = Session::<io::Stdout>::new(config, None);
41+
let _ = session.format(Input::File(filename.into())).unwrap();
42+
assert!(session.has_parsing_errors());
43+
}
44+
45+
#[test]
46+
fn crate_parsing_errors_on_unclosed_delims() {
47+
// See also https://github.com/rust-lang/rustfmt/issues/4466
48+
let filename = "tests/parser/unclosed-delims/issue_4466.rs";
49+
assert_parser_error(filename);
50+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fn main() {
2+
if true {
3+
println!("answer: {}", a_func();
4+
} else {
5+
println!("don't think so.");
6+
}
7+
}
8+
9+
fn a_func() -> i32 {
10+
42
11+
}

0 commit comments

Comments
 (0)