Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit cc26c5e

Browse files
authored
Merge pull request rust-lang#3454 from rchaser53/issue-3434
add new attribute rustfmt::skip::macros
2 parents b6dac24 + 8a905a8 commit cc26c5e

File tree

14 files changed

+372
-129
lines changed

14 files changed

+372
-129
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,18 @@ needs to be specified in `rustfmt.toml`, e.g., with `edition = "2018"`.
179179
## Tips
180180

181181
* For things you do not want rustfmt to mangle, use `#[rustfmt::skip]`
182+
* To prevent rustfmt from formatting a macro,
183+
use `#[rustfmt::skip::macros(target_macro_name)]`
184+
185+
Example:
186+
187+
```rust
188+
#[rustfmt::skip::macros(html)]
189+
fn main() {
190+
let macro_result1 = html! { <div>
191+
Hello</div>
192+
}.to_string();
193+
```
182194
* When you run rustfmt, place a file named `rustfmt.toml` or `.rustfmt.toml` in
183195
target file directory or its parents to override the default settings of
184196
rustfmt. You can generate a file containing the default configuration with

src/formatting.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP};
1515
use crate::comment::{CharClasses, FullCodeCharKind};
1616
use crate::config::{Config, FileName, Verbosity};
1717
use crate::issues::BadIssueSeeker;
18+
use crate::utils::{count_newlines, get_skip_macro_names};
1819
use crate::visitor::{FmtVisitor, SnippetProvider};
1920
use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
2021

@@ -153,6 +154,10 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
153154
&snippet_provider,
154155
self.report.clone(),
155156
);
157+
visitor
158+
.skip_macro_names
159+
.borrow_mut()
160+
.append(&mut get_skip_macro_names(&self.krate.attrs));
156161

157162
// Format inner attributes if available.
158163
if !self.krate.attrs.is_empty() && is_root {
@@ -168,10 +173,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
168173
visitor.format_separate_mod(module, &*source_file);
169174
};
170175

171-
debug_assert_eq!(
172-
visitor.line_number,
173-
crate::utils::count_newlines(&visitor.buffer)
174-
);
176+
debug_assert_eq!(visitor.line_number, count_newlines(&visitor.buffer));
175177

176178
// For some reason, the source_map does not include terminating
177179
// newlines so we must add one on for each file. This is sad.

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub enum ErrorKind {
9494
/// Used deprecated skip attribute.
9595
#[fail(display = "`rustfmt_skip` is deprecated; use `rustfmt::skip`")]
9696
DeprecatedAttr,
97-
/// Used a rustfmt:: attribute other than skip.
97+
/// Used a rustfmt:: attribute other than skip or skip::macros.
9898
#[fail(display = "invalid attribute")]
9999
BadAttr,
100100
/// An io error during reading or writing.

src/macros.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,21 @@ pub fn rewrite_macro(
208208
shape: Shape,
209209
position: MacroPosition,
210210
) -> Option<String> {
211-
let guard = InsideMacroGuard::inside_macro_context(context);
212-
let result = rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested);
213-
if result.is_none() {
214-
context.macro_rewrite_failure.replace(true);
211+
let should_skip = context
212+
.skip_macro_names
213+
.borrow()
214+
.contains(&context.snippet(mac.node.path.span).to_owned());
215+
if should_skip {
216+
None
217+
} else {
218+
let guard = InsideMacroGuard::inside_macro_context(context);
219+
let result =
220+
rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested);
221+
if result.is_none() {
222+
context.macro_rewrite_failure.replace(true);
223+
}
224+
result
215225
}
216-
result
217226
}
218227

219228
fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {

src/rewrite.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub struct RewriteContext<'a> {
3939
// Used for `format_snippet`
4040
pub(crate) macro_rewrite_failure: RefCell<bool>,
4141
pub(crate) report: FormatReport,
42+
pub skip_macro_names: RefCell<Vec<String>>,
4243
}
4344

4445
impl<'a> RewriteContext<'a> {

src/test/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[
2222
// We want to make sure that the `skip_children` is correctly working,
2323
// so we do not want to test this file directly.
2424
"configs/skip_children/foo/mod.rs",
25+
"issue-3434/no_entry.rs",
2526
];
2627

2728
fn is_file_skip(path: &Path) -> bool {

src/utils.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,26 @@ pub(crate) fn unicode_str_width(s: &str) -> usize {
603603
s.width()
604604
}
605605

606+
pub fn get_skip_macro_names(attrs: &[ast::Attribute]) -> Vec<String> {
607+
let mut skip_macro_names = vec![];
608+
for attr in attrs {
609+
// syntax::ast::Path is implemented partialEq
610+
// but it is designed for segments.len() == 1
611+
if format!("{}", attr.path) != "rustfmt::skip::macros" {
612+
continue;
613+
}
614+
615+
if let Some(list) = attr.meta_item_list() {
616+
for spanned in list {
617+
if let Some(name) = spanned.name() {
618+
skip_macro_names.push(name.to_string());
619+
}
620+
}
621+
}
622+
}
623+
skip_macro_names
624+
}
625+
606626
#[cfg(test)]
607627
mod test {
608628
use super::*;

0 commit comments

Comments
 (0)