mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
fix(parser): better unclosed delims handling
This commit is contained in:
parent
e131797b62
commit
9faba4539b
@ -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(
|
||||
@ -150,6 +149,25 @@ impl<'a> Parser<'a> {
|
||||
input: Input,
|
||||
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)
|
||||
@ -157,26 +175,14 @@ impl<'a> Parser<'a> {
|
||||
.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)
|
||||
|
@ -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) {
|
||||
|
50
src/test/parser.rs
Normal file
50
src/test/parser.rs
Normal file
@ -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);
|
||||
}
|
11
tests/parser/unclosed-delims/issue_4466.rs
Normal file
11
tests/parser/unclosed-delims/issue_4466.rs
Normal file
@ -0,0 +1,11 @@
|
||||
fn main() {
|
||||
if true {
|
||||
println!("answer: {}", a_func();
|
||||
} else {
|
||||
println!("don't think so.");
|
||||
}
|
||||
}
|
||||
|
||||
fn a_func() -> i32 {
|
||||
42
|
||||
}
|
Loading…
Reference in New Issue
Block a user