Skip to content

Commit 34067a1

Browse files
authored
Merge pull request #2775 from topecongiro/macro-def-with-complex-macro
Change format_snippet to return None when it has failed to format macro call
2 parents 8956b91 + 1905434 commit 34067a1

File tree

8 files changed

+117
-9
lines changed

8 files changed

+117
-9
lines changed

src/config/summary.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub struct Summary {
2323
// Code is valid, but it is impossible to format it properly.
2424
has_formatting_errors: bool,
2525

26+
// Code contains macro call that was unable to format.
27+
pub(crate) has_macro_format_failure: bool,
28+
2629
// Failed a check, such as the license check or other opt-in checking.
2730
has_check_errors: bool,
2831

@@ -80,6 +83,10 @@ impl Summary {
8083
self.has_check_errors
8184
}
8285

86+
pub(crate) fn has_macro_formatting_failure(&self) -> bool {
87+
self.has_macro_format_failure
88+
}
89+
8390
pub fn add_operational_error(&mut self) {
8491
self.has_operational_errors = true;
8592
}
@@ -100,6 +107,10 @@ impl Summary {
100107
self.has_diff = true;
101108
}
102109

110+
pub(crate) fn add_macro_foramt_failure(&mut self) {
111+
self.has_macro_format_failure = true;
112+
}
113+
103114
pub fn has_no_errors(&self) -> bool {
104115
!(self.has_operational_errors
105116
|| self.has_parsing_errors

src/lib.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,13 +422,14 @@ fn format_ast<F>(
422422
config: &Config,
423423
report: FormatReport,
424424
mut after_file: F,
425-
) -> Result<(FileMap, bool), io::Error>
425+
) -> Result<(FileMap, bool, bool), io::Error>
426426
where
427427
F: FnMut(&FileName, &mut String, &[(usize, usize)], &FormatReport) -> Result<bool, io::Error>,
428428
{
429429
let mut result = FileMap::new();
430430
// diff mode: check if any files are differing
431431
let mut has_diff = false;
432+
let mut has_macro_rewrite_failure = false;
432433

433434
let skip_children = config.skip_children();
434435
for (path, module) in modules::list_files(krate, parse_session.codemap())? {
@@ -472,10 +473,12 @@ where
472473
}
473474
};
474475

476+
has_macro_rewrite_failure |= visitor.macro_rewrite_failure;
477+
475478
result.push((path.clone(), visitor.buffer));
476479
}
477480

478-
Ok((result, has_diff))
481+
Ok((result, has_diff, has_macro_rewrite_failure))
479482
}
480483

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

904908
match format_result {
905-
Ok((file_map, has_diff)) => {
909+
Ok((file_map, has_diff, has_macro_rewrite_failure)) => {
906910
if report.has_warnings() {
907911
summary.add_formatting_error();
908912
}
@@ -911,6 +915,10 @@ fn format_input_inner<T: Write>(
911915
summary.add_diff();
912916
}
913917

918+
if has_macro_rewrite_failure {
919+
summary.add_macro_foramt_failure();
920+
}
921+
914922
Ok((summary, file_map, report))
915923
}
916924
Err(e) => Err((From::from(e), summary)),

src/macros.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ fn rewrite_macro_name(path: &ast::Path, extra_ident: Option<ast::Ident>) -> Stri
129129
}
130130
}
131131

132+
// Use this on failing to format the macro call.
133+
fn return_original_snippet_with_failure_marked(
134+
context: &RewriteContext,
135+
span: Span,
136+
) -> Option<String> {
137+
context.macro_rewrite_failure.replace(true);
138+
Some(context.snippet(span).to_owned())
139+
}
140+
132141
pub fn rewrite_macro(
133142
mac: &ast::Mac,
134143
extra_ident: Option<ast::Ident>,
@@ -138,6 +147,9 @@ pub fn rewrite_macro(
138147
) -> Option<String> {
139148
context.inside_macro.replace(true);
140149
let result = rewrite_macro_inner(mac, extra_ident, context, shape, position);
150+
if result.is_none() {
151+
context.macro_rewrite_failure.replace(true);
152+
}
141153
context.inside_macro.replace(false);
142154
result
143155
}
@@ -196,7 +208,7 @@ pub fn rewrite_macro_inner(
196208
loop {
197209
match parse_macro_arg(&mut parser) {
198210
Some(arg) => arg_vec.push(arg),
199-
None => return Some(context.snippet(mac.span).to_owned()),
211+
None => return return_original_snippet_with_failure_marked(context, mac.span),
200212
}
201213

202214
match parser.token {
@@ -216,13 +228,17 @@ pub fn rewrite_macro_inner(
216228
break;
217229
}
218230
}
219-
None => return Some(context.snippet(mac.span).to_owned()),
231+
None => {
232+
return return_original_snippet_with_failure_marked(
233+
context, mac.span,
234+
)
235+
}
220236
}
221237
}
222238
}
223-
return Some(context.snippet(mac.span).to_owned());
239+
return return_original_snippet_with_failure_marked(context, mac.span);
224240
}
225-
_ => return Some(context.snippet(mac.span).to_owned()),
241+
_ => return return_original_snippet_with_failure_marked(context, mac.span),
226242
}
227243

228244
parser.bump();

src/rewrite.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ pub struct RewriteContext<'a> {
3939
// When rewriting chain, veto going multi line except the last element
4040
pub force_one_line_chain: RefCell<bool>,
4141
pub snippet_provider: &'a SnippetProvider<'a>,
42+
// Used for `format_snippet`
43+
pub(crate) macro_rewrite_failure: RefCell<bool>,
4244
pub(crate) report: FormatReport,
4345
}
4446

src/visitor.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub struct FmtVisitor<'a> {
7070
pub snippet_provider: &'a SnippetProvider<'a>,
7171
pub line_number: usize,
7272
pub skipped_range: Vec<(usize, usize)>,
73+
pub macro_rewrite_failure: bool,
7374
pub(crate) report: FormatReport,
7475
}
7576

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

520521
// 1 = ;
521522
let shape = self.shape().sub_width(1).unwrap();
522-
let rewrite = rewrite_macro(mac, ident, &self.get_context(), shape, pos);
523+
let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos));
523524
self.push_rewrite(mac.span, rewrite);
524525
}
525526

@@ -578,6 +579,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
578579
snippet_provider,
579580
line_number: 0,
580581
skipped_range: vec![],
582+
macro_rewrite_failure: false,
581583
report,
582584
}
583585
}
@@ -736,6 +738,20 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
736738
}
737739
}
738740

741+
pub fn with_context<F>(&mut self, f: F) -> Option<String>
742+
where
743+
F: Fn(&RewriteContext) -> Option<String>,
744+
{
745+
let result;
746+
let macro_rewrite_failure = {
747+
let context = self.get_context();
748+
result = f(&context);
749+
unsafe { *context.macro_rewrite_failure.as_ptr() }
750+
};
751+
self.macro_rewrite_failure |= macro_rewrite_failure;
752+
result
753+
}
754+
739755
pub fn get_context(&self) -> RewriteContext {
740756
RewriteContext {
741757
parse_session: self.parse_session,
@@ -746,6 +762,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
746762
is_if_else_block: RefCell::new(false),
747763
force_one_line_chain: RefCell::new(false),
748764
snippet_provider: self.snippet_provider,
765+
macro_rewrite_failure: RefCell::new(false),
749766
report: self.report.clone(),
750767
}
751768
}

tests/source/macro_rules.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,30 @@ macro_rules! foo {
204204
macro_rules! __wundergraph_expand_sqlite_mutation {
205205
( $mutation_name:ident $((context = $($context:tt)*))*{ $( $entity_name:ident( $(insert = $insert:ident,)* $(update = $update:ident,)* $(delete = $($delete:tt)+)* ), )* } ) => {};
206206
}
207+
208+
// #2607
209+
macro_rules! bench {
210+
($ty:ident) => {
211+
criterion_group!(
212+
name = benches;
213+
config = ::common_bench::reduced_samples();
214+
targets = call, map;
215+
);
216+
};
217+
}
218+
219+
// #2770
220+
macro_rules! save_regs {
221+
() => {
222+
asm!("push rax
223+
push rcx
224+
push rdx
225+
push rsi
226+
push rdi
227+
push r8
228+
push r9
229+
push r10
230+
push r11"
231+
:::: "intel", "volatile");
232+
};
233+
}

tests/target/issue-2523.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
// Do not unindent macro calls in comment with unformattable syntax.
44
//! ```rust
5-
//! let x = 3;
5+
//! let x = 3 ;
66
//! some_macro!(pub fn fn foo() (
77
//! println!("Don't unindent me!");
88
//! ));

tests/target/macro_rules.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,30 @@ macro_rules! __wundergraph_expand_sqlite_mutation {
246246
}
247247
) => {};
248248
}
249+
250+
// #2607
251+
macro_rules! bench {
252+
($ty:ident) => {
253+
criterion_group!(
254+
name = benches;
255+
config = ::common_bench::reduced_samples();
256+
targets = call, map;
257+
);
258+
};
259+
}
260+
261+
// #2770
262+
macro_rules! save_regs {
263+
() => {
264+
asm!("push rax
265+
push rcx
266+
push rdx
267+
push rsi
268+
push rdi
269+
push r8
270+
push r9
271+
push r10
272+
push r11"
273+
:::: "intel", "volatile");
274+
};
275+
}

0 commit comments

Comments
 (0)