Skip to content

Commit d8c154f

Browse files
committed
Extract branch rewrite function
1 parent 571af9d commit d8c154f

File tree

1 file changed

+95
-98
lines changed

1 file changed

+95
-98
lines changed

src/macros.rs

Lines changed: 95 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -310,118 +310,27 @@ pub fn rewrite_macro_def(
310310

311311
let multi_branch_style = def.legacy || parsed_def.branches.len() != 1;
312312

313-
let mac_indent = if multi_branch_style {
314-
indent.block_indent(context.config)
313+
let arm_shape = if multi_branch_style {
314+
shape
315+
.block_indent(context.config.tab_spaces())
316+
.with_max_width(context.config)
315317
} else {
316-
indent
318+
shape
317319
};
318320

319-
let mac_indent_str = mac_indent.to_string(context.config);
320-
321321
let branch_items = itemize_list(
322322
context.codemap,
323323
parsed_def.branches.iter(),
324324
"}",
325325
";",
326326
|branch| branch.span.lo(),
327327
|branch| branch.span.hi(),
328-
|branch| {
329-
// Only attempt to format function-like macros.
330-
if branch.args_paren_kind != DelimToken::Paren {
331-
// FIXME(#1539): implement for non-sugared macros.
332-
return None;
333-
}
334-
335-
let mut result = format_macro_args(branch.args.clone())?;
336-
337-
if multi_branch_style {
338-
result += " =>";
339-
}
340-
341-
// The macro body is the most interesting part. It might end up as various
342-
// AST nodes, but also has special variables (e.g, `$foo`) which can't be
343-
// parsed as regular Rust code (and note that these can be escaped using
344-
// `$$`). We'll try and format like an AST node, but we'll substitute
345-
// variables for new names with the same length first.
346-
347-
let old_body = context.snippet(branch.body).trim();
348-
let (body_str, substs) = match replace_names(old_body) {
349-
Some(result) => result,
350-
None => return snippet,
351-
};
352-
353-
let mut config = context.config.clone();
354-
config.set().hide_parse_errors(true);
355-
356-
result += " {";
357-
358-
let has_block_body = old_body.starts_with('{');
359-
360-
let body_indent = if has_block_body {
361-
mac_indent
362-
} else {
363-
// We'll hack the indent below, take this into account when formatting,
364-
let body_indent = mac_indent.block_indent(&config);
365-
let new_width = config.max_width() - body_indent.width();
366-
config.set().max_width(new_width);
367-
body_indent
368-
};
369-
370-
// First try to format as items, then as statements.
371-
let new_body = match ::format_snippet(&body_str, &config) {
372-
Some(new_body) => new_body,
373-
None => match ::format_code_block(&body_str, &config) {
374-
Some(new_body) => new_body,
375-
None => return None,
376-
},
377-
};
378-
379-
// Indent the body since it is in a block.
380-
let indent_str = body_indent.to_string(&config);
381-
let mut new_body = new_body
382-
.trim_right()
383-
.lines()
384-
.fold(String::new(), |mut s, l| {
385-
if !l.is_empty() {
386-
s += &indent_str;
387-
}
388-
s + l + "\n"
389-
});
390-
391-
// Undo our replacement of macro variables.
392-
// FIXME: this could be *much* more efficient.
393-
for (old, new) in &substs {
394-
if old_body.find(new).is_some() {
395-
debug!(
396-
"rewrite_macro_def: bailing matching variable: `{}` in `{}`",
397-
new, ident
398-
);
399-
return None;
400-
}
401-
new_body = new_body.replace(new, old);
402-
}
403-
404-
if has_block_body {
405-
result += new_body.trim();
406-
} else if !new_body.is_empty() {
407-
result += "\n";
408-
result += &new_body;
409-
result += &mac_indent_str;
410-
}
411-
412-
result += "}";
413-
414-
Some(result)
415-
},
328+
|branch| branch.rewrite(context, arm_shape, multi_branch_style),
416329
context.codemap.span_after(span, "{"),
417330
span.hi(),
418331
false,
419332
).collect::<Vec<_>>();
420333

421-
let arm_shape = shape
422-
.block_indent(context.config.tab_spaces())
423-
.with_max_width(context.config);
424-
425334
let fmt = ListFormatting {
426335
tactic: DefinitiveListTactic::Vertical,
427336
separator: if def.legacy { ";" } else { "" },
@@ -435,7 +344,7 @@ pub fn rewrite_macro_def(
435344

436345
if multi_branch_style {
437346
result += " {\n";
438-
result += &mac_indent_str;
347+
result += &arm_shape.indent.to_string(context.config);
439348
}
440349

441350
result += write_list(&branch_items, &fmt)?.as_str();
@@ -833,6 +742,94 @@ struct MacroBranch {
833742
body: Span,
834743
}
835744

745+
impl MacroBranch {
746+
fn rewrite(&self, context: &RewriteContext, shape: Shape, multi_branch_style: bool) -> Option<String> {
747+
// Only attempt to format function-like macros.
748+
if self.args_paren_kind != DelimToken::Paren {
749+
// FIXME(#1539): implement for non-sugared macros.
750+
return None;
751+
}
752+
753+
let mut result = format_macro_args(self.args.clone())?;
754+
755+
if multi_branch_style {
756+
result += " =>";
757+
}
758+
759+
// The macro body is the most interesting part. It might end up as various
760+
// AST nodes, but also has special variables (e.g, `$foo`) which can't be
761+
// parsed as regular Rust code (and note that these can be escaped using
762+
// `$$`). We'll try and format like an AST node, but we'll substitute
763+
// variables for new names with the same length first.
764+
765+
let old_body = context.snippet(self.body).trim();
766+
let (body_str, substs) = replace_names(old_body)?;
767+
768+
let mut config = context.config.clone();
769+
config.set().hide_parse_errors(true);
770+
771+
result += " {";
772+
773+
let has_block_body = old_body.starts_with('{');
774+
775+
let body_indent = if has_block_body {
776+
shape.indent
777+
} else {
778+
// We'll hack the indent below, take this into account when formatting,
779+
let body_indent = shape.indent.block_indent(&config);
780+
let new_width = config.max_width() - body_indent.width();
781+
config.set().max_width(new_width);
782+
body_indent
783+
};
784+
785+
// First try to format as items, then as statements.
786+
let new_body = match ::format_snippet(&body_str, &config) {
787+
Some(new_body) => new_body,
788+
None => match ::format_code_block(&body_str, &config) {
789+
Some(new_body) => new_body,
790+
None => return None,
791+
},
792+
};
793+
794+
// Indent the body since it is in a block.
795+
let indent_str = body_indent.to_string(&config);
796+
let mut new_body = new_body
797+
.trim_right()
798+
.lines()
799+
.fold(String::new(), |mut s, l| {
800+
if !l.is_empty() {
801+
s += &indent_str;
802+
}
803+
s + l + "\n"
804+
});
805+
806+
// Undo our replacement of macro variables.
807+
// FIXME: this could be *much* more efficient.
808+
for (old, new) in &substs {
809+
if old_body.find(new).is_some() {
810+
debug!(
811+
"rewrite_macro_def: bailing matching variable: `{}`",
812+
new
813+
);
814+
return None;
815+
}
816+
new_body = new_body.replace(new, old);
817+
}
818+
819+
if has_block_body {
820+
result += new_body.trim();
821+
} else if !new_body.is_empty() {
822+
result += "\n";
823+
result += &new_body;
824+
result += &shape.indent.to_string(&config);
825+
}
826+
827+
result += "}";
828+
829+
Some(result)
830+
}
831+
}
832+
836833
#[cfg(test)]
837834
mod test {
838835
use super::*;

0 commit comments

Comments
 (0)