Skip to content

Commit 4dabaf1

Browse files
committed
Do not format inner attributes twice in the main file
1 parent 7594d9d commit 4dabaf1

File tree

3 files changed

+44
-59
lines changed

3 files changed

+44
-59
lines changed

rustfmt-core/rustfmt-lib/src/formatting.rs

+3-17
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,12 @@ fn format_project(
128128
should_emit_verbose(input_is_stdin, operation_setting.verbosity, || {
129129
println!("Formatting {}", path)
130130
});
131-
let is_root = path == main_file;
132131
format_file(
133132
&parse_session,
134133
config,
135134
&krate,
136135
path,
137136
&module,
138-
is_root,
139137
&format_report,
140138
original_snippet.clone(),
141139
);
@@ -159,28 +157,16 @@ fn format_file(
159157
krate: &ast::Crate,
160158
path: FileName,
161159
module: &Module<'_>,
162-
is_root: bool,
163160
report: &FormatReport,
164161
original_snippet: Option<String>,
165162
) {
166163
let snippet_provider = parse_session.snippet_provider(module.as_ref().inner);
167164
let mut visitor =
168165
FmtVisitor::from_parse_sess(&parse_session, config, &snippet_provider, report.clone());
169166
visitor.skip_context.update_with_attrs(&krate.attrs);
170-
171-
// Format inner attributes if available.
172-
if !krate.attrs.is_empty() && is_root {
173-
visitor.skip_empty_lines(snippet_provider.end_pos());
174-
if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) {
175-
visitor.push_rewrite(module.as_ref().inner, None);
176-
} else {
177-
visitor.format_separate_mod(module.as_ref(), snippet_provider.end_pos());
178-
}
179-
} else {
180-
visitor.last_pos = snippet_provider.start_pos();
181-
visitor.skip_empty_lines(snippet_provider.end_pos());
182-
visitor.format_separate_mod(module.as_ref(), snippet_provider.end_pos());
183-
};
167+
visitor.last_pos = snippet_provider.start_pos();
168+
visitor.skip_empty_lines(snippet_provider.end_pos());
169+
visitor.format_separate_mod(module, snippet_provider.end_pos());
184170

185171
debug_assert_eq!(
186172
visitor.line_number,

rustfmt-core/rustfmt-lib/src/formatting/modules.rs

+32-38
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::collections::BTreeMap;
33
use std::path::{Path, PathBuf};
44

55
use rustc_ast::ast;
6+
use rustc_ast::attr::HasAttrs;
67
use rustc_ast::visit::Visitor;
78
use rustc_span::symbol::{self, sym, Symbol};
89
use thiserror::Error;
@@ -31,6 +32,29 @@ pub(crate) struct Module<'a> {
3132
inner_attr: Vec<ast::Attribute>,
3233
}
3334

35+
impl<'a> Module<'a> {
36+
pub(crate) fn new(ast_mod: Cow<'a, ast::Mod>, attrs: &[ast::Attribute]) -> Self {
37+
let inner_attr = attrs
38+
.iter()
39+
.filter(|attr| attr.style == ast::AttrStyle::Inner)
40+
.cloned()
41+
.collect();
42+
Module {
43+
ast_mod,
44+
inner_attr,
45+
}
46+
}
47+
}
48+
49+
impl<'a> HasAttrs for Module<'a> {
50+
fn attrs(&self) -> &[ast::Attribute] {
51+
&self.inner_attr
52+
}
53+
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<ast::Attribute>)) {
54+
f(&mut self.inner_attr)
55+
}
56+
}
57+
3458
impl<'a> AsRef<ast::Mod> for Module<'a> {
3559
fn as_ref(&self) -> &ast::Mod {
3660
&self.ast_mod
@@ -109,10 +133,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
109133

110134
self.file_map.insert(
111135
root_filename,
112-
Module {
113-
ast_mod: Cow::Borrowed(&krate.module),
114-
inner_attr: krate.attrs.clone(),
115-
},
136+
Module::new(Cow::Borrowed(&krate.module), &krate.attrs),
116137
);
117138
Ok(self.file_map)
118139
}
@@ -125,10 +146,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
125146
if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind {
126147
self.visit_sub_mod(
127148
&module_item.item,
128-
Module {
129-
ast_mod: Cow::Owned(sub_mod.clone()),
130-
inner_attr: module_item.item.attrs.clone(),
131-
},
149+
Module::new(Cow::Owned(sub_mod.clone()), &module_item.item.attrs),
132150
)?;
133151
}
134152
}
@@ -144,13 +162,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
144162
}
145163

146164
if let ast::ItemKind::Mod(ref sub_mod) = item.kind {
147-
self.visit_sub_mod(
148-
&item,
149-
Module {
150-
ast_mod: Cow::Owned(sub_mod.clone()),
151-
inner_attr: item.attrs.clone(),
152-
},
153-
)?;
165+
self.visit_sub_mod(&item, Module::new(Cow::Owned(sub_mod.clone()), &item.attrs))?;
154166
}
155167
}
156168
Ok(())
@@ -164,13 +176,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
164176
}
165177

166178
if let ast::ItemKind::Mod(ref sub_mod) = item.kind {
167-
self.visit_sub_mod(
168-
item,
169-
Module {
170-
ast_mod: Cow::Borrowed(sub_mod),
171-
inner_attr: item.attrs.clone(),
172-
},
173-
)?;
179+
self.visit_sub_mod(item, Module::new(Cow::Borrowed(sub_mod), &item.attrs))?;
174180
}
175181
}
176182
Ok(())
@@ -297,10 +303,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
297303
Ok(m) => Ok(Some(SubModKind::External(
298304
path,
299305
DirectoryOwnership::Owned { relative: None },
300-
Module {
301-
ast_mod: Cow::Owned(m.0),
302-
inner_attr: m.1,
303-
},
306+
Module::new(Cow::Owned(m.0), &m.1),
304307
))),
305308
Err(ParserError::ParseError) => Err(ModuleResolutionError {
306309
module: mod_name.to_string(),
@@ -342,19 +345,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
342345
Ok(m) if outside_mods_empty => Ok(Some(SubModKind::External(
343346
path,
344347
ownership,
345-
Module {
346-
ast_mod: Cow::Owned(m.0),
347-
inner_attr: m.1,
348-
},
348+
Module::new(Cow::Owned(m.0), &m.1),
349349
))),
350350
Ok(m) => {
351351
mods_outside_ast.push((
352352
path.clone(),
353353
ownership,
354-
Module {
355-
ast_mod: Cow::Owned(m.0),
356-
inner_attr: m.1,
357-
},
354+
Module::new(Cow::Owned(m.0), &m.1),
358355
));
359356
if should_insert {
360357
mods_outside_ast.push((path, ownership, sub_mod.clone()));
@@ -457,10 +454,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
457454
result.push((
458455
actual_path,
459456
DirectoryOwnership::Owned { relative: None },
460-
Module {
461-
ast_mod: Cow::Owned(m.0),
462-
inner_attr: m.1,
463-
},
457+
Module::new(Cow::Owned(m.0), &m.1),
464458
))
465459
}
466460
result

rustfmt-core/rustfmt-lib/src/formatting/visitor.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use std::cell::{Cell, RefCell};
22
use std::rc::Rc;
33

4-
use rustc_ast::{ast, token::DelimToken, visit};
4+
use rustc_ast::{ast, attr::HasAttrs, token::DelimToken, visit};
55
use rustc_span::{symbol, BytePos, Pos, Span};
66

77
use crate::config::{BraceStyle, Config};
8+
use crate::formatting::modules::Module;
89
use crate::formatting::{
910
attr::*,
1011
comment::{rewrite_comment, CodeCharKind, CommentCodeSlices},
@@ -947,10 +948,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
947948
}
948949
}
949950

950-
pub(crate) fn format_separate_mod(&mut self, m: &ast::Mod, end_pos: BytePos) {
951+
pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) {
951952
self.block_indent = Indent::empty();
952-
self.walk_mod_items(m);
953-
self.format_missing_with_indent(end_pos);
953+
if self.visit_attrs(m.attrs(), ast::AttrStyle::Inner) {
954+
self.push_skipped_with_span(m.attrs(), m.as_ref().inner, m.as_ref().inner);
955+
} else {
956+
self.walk_mod_items(m.as_ref());
957+
self.format_missing_with_indent(end_pos);
958+
}
954959
}
955960

956961
pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) {

0 commit comments

Comments
 (0)