Skip to content

Change format_snippet to return None when it has failed to format macro call #2775

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/config/summary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ pub struct Summary {
// Code is valid, but it is impossible to format it properly.
has_formatting_errors: bool,

// Code contains macro call that was unable to format.
pub(crate) has_macro_format_failure: bool,

// Failed a check, such as the license check or other opt-in checking.
has_check_errors: bool,

Expand Down Expand Up @@ -80,6 +83,10 @@ impl Summary {
self.has_check_errors
}

pub(crate) fn has_macro_formatting_failure(&self) -> bool {
self.has_macro_format_failure
}

pub fn add_operational_error(&mut self) {
self.has_operational_errors = true;
}
Expand All @@ -100,6 +107,10 @@ impl Summary {
self.has_diff = true;
}

pub(crate) fn add_macro_foramt_failure(&mut self) {
self.has_macro_format_failure = true;
}

pub fn has_no_errors(&self) -> bool {
!(self.has_operational_errors
|| self.has_parsing_errors
Expand Down
14 changes: 11 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,13 +422,14 @@ fn format_ast<F>(
config: &Config,
report: FormatReport,
mut after_file: F,
) -> Result<(FileMap, bool), io::Error>
) -> Result<(FileMap, bool, bool), io::Error>
where
F: FnMut(&FileName, &mut String, &[(usize, usize)], &FormatReport) -> Result<bool, io::Error>,
{
let mut result = FileMap::new();
// diff mode: check if any files are differing
let mut has_diff = false;
let mut has_macro_rewrite_failure = false;
Copy link
Contributor

@t-botz t-botz Jun 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@topecongiro @nrc
Shouldn't has_macro_rewrite_failure be part of the FormatReport instead?
IMO That should be a new ErrorKind

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figure the two will get merged in some way, so it doesn't really matter what we do right now


let skip_children = config.skip_children();
for (path, module) in modules::list_files(krate, parse_session.codemap())? {
Expand Down Expand Up @@ -472,10 +473,12 @@ where
}
};

has_macro_rewrite_failure |= visitor.macro_rewrite_failure;

result.push((path.clone(), visitor.buffer));
}

Ok((result, has_diff))
Ok((result, has_diff, has_macro_rewrite_failure))
}

/// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`.
Expand Down Expand Up @@ -686,6 +689,7 @@ fn format_snippet(snippet: &str, config: &Config) -> Option<String> {
config.set().hide_parse_errors(true);
match format_input(input, &config, Some(&mut out)) {
// `format_input()` returns an empty string on parsing error.
Ok((summary, _)) if summary.has_macro_formatting_failure() => None,
Ok(..) if out.is_empty() && !snippet.is_empty() => None,
Ok(..) => String::from_utf8(out).ok(),
Err(..) => None,
Expand Down Expand Up @@ -902,7 +906,7 @@ fn format_input_inner<T: Write>(
}

match format_result {
Ok((file_map, has_diff)) => {
Ok((file_map, has_diff, has_macro_rewrite_failure)) => {
if report.has_warnings() {
summary.add_formatting_error();
}
Expand All @@ -911,6 +915,10 @@ fn format_input_inner<T: Write>(
summary.add_diff();
}

if has_macro_rewrite_failure {
summary.add_macro_foramt_failure();
}

Ok((summary, file_map, report))
}
Err(e) => Err((From::from(e), summary)),
Expand Down
24 changes: 20 additions & 4 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ fn rewrite_macro_name(path: &ast::Path, extra_ident: Option<ast::Ident>) -> Stri
}
}

// Use this on failing to format the macro call.
fn return_original_snippet_with_failure_marked(
context: &RewriteContext,
span: Span,
) -> Option<String> {
context.macro_rewrite_failure.replace(true);
Some(context.snippet(span).to_owned())
}

pub fn rewrite_macro(
mac: &ast::Mac,
extra_ident: Option<ast::Ident>,
Expand All @@ -138,6 +147,9 @@ pub fn rewrite_macro(
) -> Option<String> {
context.inside_macro.replace(true);
let result = rewrite_macro_inner(mac, extra_ident, context, shape, position);
if result.is_none() {
context.macro_rewrite_failure.replace(true);
}
context.inside_macro.replace(false);
result
}
Expand Down Expand Up @@ -196,7 +208,7 @@ pub fn rewrite_macro_inner(
loop {
match parse_macro_arg(&mut parser) {
Some(arg) => arg_vec.push(arg),
None => return Some(context.snippet(mac.span).to_owned()),
None => return return_original_snippet_with_failure_marked(context, mac.span),
}

match parser.token {
Expand All @@ -216,13 +228,17 @@ pub fn rewrite_macro_inner(
break;
}
}
None => return Some(context.snippet(mac.span).to_owned()),
None => {
return return_original_snippet_with_failure_marked(
context, mac.span,
)
}
}
}
}
return Some(context.snippet(mac.span).to_owned());
return return_original_snippet_with_failure_marked(context, mac.span);
}
_ => return Some(context.snippet(mac.span).to_owned()),
_ => return return_original_snippet_with_failure_marked(context, mac.span),
}

parser.bump();
Expand Down
2 changes: 2 additions & 0 deletions src/rewrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub struct RewriteContext<'a> {
// When rewriting chain, veto going multi line except the last element
pub force_one_line_chain: RefCell<bool>,
pub snippet_provider: &'a SnippetProvider<'a>,
// Used for `format_snippet`
pub(crate) macro_rewrite_failure: RefCell<bool>,
pub(crate) report: FormatReport,
}

Expand Down
19 changes: 18 additions & 1 deletion src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub struct FmtVisitor<'a> {
pub snippet_provider: &'a SnippetProvider<'a>,
pub line_number: usize,
pub skipped_range: Vec<(usize, usize)>,
pub macro_rewrite_failure: bool,
pub(crate) report: FormatReport,
}

Expand Down Expand Up @@ -519,7 +520,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {

// 1 = ;
let shape = self.shape().sub_width(1).unwrap();
let rewrite = rewrite_macro(mac, ident, &self.get_context(), shape, pos);
let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos));
self.push_rewrite(mac.span, rewrite);
}

Expand Down Expand Up @@ -578,6 +579,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
snippet_provider,
line_number: 0,
skipped_range: vec![],
macro_rewrite_failure: false,
report,
}
}
Expand Down Expand Up @@ -736,6 +738,20 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
}
}

pub fn with_context<F>(&mut self, f: F) -> Option<String>
where
F: Fn(&RewriteContext) -> Option<String>,
{
let result;
let macro_rewrite_failure = {
let context = self.get_context();
result = f(&context);
unsafe { *context.macro_rewrite_failure.as_ptr() }
};
self.macro_rewrite_failure |= macro_rewrite_failure;
result
}

pub fn get_context(&self) -> RewriteContext {
RewriteContext {
parse_session: self.parse_session,
Expand All @@ -746,6 +762,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
is_if_else_block: RefCell::new(false),
force_one_line_chain: RefCell::new(false),
snippet_provider: self.snippet_provider,
macro_rewrite_failure: RefCell::new(false),
report: self.report.clone(),
}
}
Expand Down
27 changes: 27 additions & 0 deletions tests/source/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,30 @@ macro_rules! foo {
macro_rules! __wundergraph_expand_sqlite_mutation {
( $mutation_name:ident $((context = $($context:tt)*))*{ $( $entity_name:ident( $(insert = $insert:ident,)* $(update = $update:ident,)* $(delete = $($delete:tt)+)* ), )* } ) => {};
}

// #2607
macro_rules! bench {
($ty:ident) => {
criterion_group!(
name = benches;
config = ::common_bench::reduced_samples();
targets = call, map;
);
};
}

// #2770
macro_rules! save_regs {
() => {
asm!("push rax
push rcx
push rdx
push rsi
push rdi
push r8
push r9
push r10
push r11"
:::: "intel", "volatile");
};
}
2 changes: 1 addition & 1 deletion tests/target/issue-2523.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// Do not unindent macro calls in comment with unformattable syntax.
//! ```rust
//! let x = 3;
//! let x = 3 ;
//! some_macro!(pub fn fn foo() (
//! println!("Don't unindent me!");
//! ));
Expand Down
27 changes: 27 additions & 0 deletions tests/target/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,30 @@ macro_rules! __wundergraph_expand_sqlite_mutation {
}
) => {};
}

// #2607
macro_rules! bench {
($ty:ident) => {
criterion_group!(
name = benches;
config = ::common_bench::reduced_samples();
targets = call, map;
);
};
}

// #2770
macro_rules! save_regs {
() => {
asm!("push rax
push rcx
push rdx
push rsi
push rdi
push r8
push r9
push r10
push r11"
:::: "intel", "volatile");
};
}