Catch parser panic in format_snippet (#3103)
This commit is contained in:
parent
c09d7ef088
commit
8c4e92a14e
3 changed files with 59 additions and 13 deletions
34
src/lib.rs
34
src/lib.rs
|
|
@ -42,6 +42,7 @@ use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::panic;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
@ -355,21 +356,28 @@ impl fmt::Display for FormatReport {
|
||||||
/// Format the given snippet. The snippet is expected to be *complete* code.
|
/// Format the given snippet. The snippet is expected to be *complete* code.
|
||||||
/// When we cannot parse the given snippet, this function returns `None`.
|
/// When we cannot parse the given snippet, this function returns `None`.
|
||||||
fn format_snippet(snippet: &str, config: &Config) -> Option<String> {
|
fn format_snippet(snippet: &str, config: &Config) -> Option<String> {
|
||||||
let mut out: Vec<u8> = Vec::with_capacity(snippet.len() * 2);
|
|
||||||
let input = Input::Text(snippet.into());
|
|
||||||
let mut config = config.clone();
|
let mut config = config.clone();
|
||||||
config.set().emit_mode(config::EmitMode::Stdout);
|
let out = panic::catch_unwind(|| {
|
||||||
config.set().verbose(Verbosity::Quiet);
|
let mut out: Vec<u8> = Vec::with_capacity(snippet.len() * 2);
|
||||||
config.set().hide_parse_errors(true);
|
config.set().emit_mode(config::EmitMode::Stdout);
|
||||||
{
|
config.set().verbose(Verbosity::Quiet);
|
||||||
let mut session = Session::new(config, Some(&mut out));
|
config.set().hide_parse_errors(true);
|
||||||
let result = session.format(input);
|
let formatting_error = {
|
||||||
let formatting_error = session.errors.has_macro_format_failure
|
let input = Input::Text(snippet.into());
|
||||||
|| session.out.as_ref().unwrap().is_empty() && !snippet.is_empty();
|
let mut session = Session::new(config, Some(&mut out));
|
||||||
if formatting_error || result.is_err() {
|
let result = session.format(input);
|
||||||
return None;
|
session.errors.has_macro_format_failure
|
||||||
|
|| session.out.as_ref().unwrap().is_empty() && !snippet.is_empty()
|
||||||
|
|| result.is_err()
|
||||||
|
};
|
||||||
|
if formatting_error {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(out)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.ok()??; // The first try operator handles the error from catch_unwind,
|
||||||
|
// whereas the second one handles None from the closure.
|
||||||
String::from_utf8(out).ok()
|
String::from_utf8(out).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
20
tests/source/invalid-rust-code-in-doc-comment.rs
Normal file
20
tests/source/invalid-rust-code-in-doc-comment.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// rustfmt-format_doc_comments: true
|
||||||
|
|
||||||
|
/// ```rust
|
||||||
|
/// if (true) { … }
|
||||||
|
/// ```
|
||||||
|
fn a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```rust
|
||||||
|
/// if foo() {
|
||||||
|
/// …
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
fn a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ```rust
|
||||||
|
/// k1 == k2 ⇒ hash(k1) == hash(k2)
|
||||||
|
/// ```
|
||||||
|
pub struct a ;
|
||||||
18
tests/target/invalid-rust-code-in-doc-comment.rs
Normal file
18
tests/target/invalid-rust-code-in-doc-comment.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// rustfmt-format_doc_comments: true
|
||||||
|
|
||||||
|
/// ```rust
|
||||||
|
/// if (true) { … }
|
||||||
|
/// ```
|
||||||
|
fn a() {}
|
||||||
|
|
||||||
|
/// ```rust
|
||||||
|
/// if foo() {
|
||||||
|
/// …
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
fn a() {}
|
||||||
|
|
||||||
|
/// ```rust
|
||||||
|
/// k1 == k2 ⇒ hash(k1) == hash(k2)
|
||||||
|
/// ```
|
||||||
|
pub struct a;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue