expand: Cleanup attribute collection in invocation collector
This commit is contained in:
parent
dfb690eaa9
commit
ec547202b4
@ -1016,11 +1016,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||||||
|
|
||||||
fn collect_attr(
|
fn collect_attr(
|
||||||
&mut self,
|
&mut self,
|
||||||
attr: Option<ast::Attribute>,
|
(attr, derives, after_derive): (Option<ast::Attribute>, Vec<Path>, bool),
|
||||||
derives: Vec<Path>,
|
|
||||||
item: Annotatable,
|
item: Annotatable,
|
||||||
kind: AstFragmentKind,
|
kind: AstFragmentKind,
|
||||||
after_derive: bool,
|
|
||||||
) -> AstFragment {
|
) -> AstFragment {
|
||||||
self.collect(
|
self.collect(
|
||||||
kind,
|
kind,
|
||||||
@ -1048,10 +1046,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
|
/// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
|
||||||
fn classify_item(
|
fn take_first_attr(
|
||||||
&mut self,
|
&mut self,
|
||||||
item: &mut impl HasAttrs,
|
item: &mut impl HasAttrs,
|
||||||
) -> (Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool) {
|
) -> Option<(Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool)> {
|
||||||
let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false);
|
let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false);
|
||||||
|
|
||||||
item.visit_attrs(|mut attrs| {
|
item.visit_attrs(|mut attrs| {
|
||||||
@ -1059,23 +1057,23 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||||||
traits = collect_derives(&mut self.cx, &mut attrs);
|
traits = collect_derives(&mut self.cx, &mut attrs);
|
||||||
});
|
});
|
||||||
|
|
||||||
(attr, traits, after_derive)
|
if attr.is_some() || !traits.is_empty() { Some((attr, traits, after_derive)) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough
|
/// Alternative to `take_first_attr()` that ignores `#[derive]` so invocations fallthrough
|
||||||
/// to the unused-attributes lint (making it an error on statements and expressions
|
/// to the unused-attributes lint (making it an error on statements and expressions
|
||||||
/// is a breaking change)
|
/// is a breaking change)
|
||||||
fn classify_nonitem(
|
fn take_first_attr_no_derive(
|
||||||
&mut self,
|
&mut self,
|
||||||
nonitem: &mut impl HasAttrs,
|
nonitem: &mut impl HasAttrs,
|
||||||
) -> (Option<ast::Attribute>, /* after_derive */ bool) {
|
) -> Option<(Option<ast::Attribute>, Vec<Path>, /* after_derive */ bool)> {
|
||||||
let (mut attr, mut after_derive) = (None, false);
|
let (mut attr, mut after_derive) = (None, false);
|
||||||
|
|
||||||
nonitem.visit_attrs(|mut attrs| {
|
nonitem.visit_attrs(|mut attrs| {
|
||||||
attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
|
attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
|
||||||
});
|
});
|
||||||
|
|
||||||
(attr, after_derive)
|
attr.map(|attr| (Some(attr), Vec::new(), after_derive))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
|
fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
|
||||||
@ -1119,23 +1117,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
visit_clobber(expr.deref_mut(), |mut expr| {
|
visit_clobber(expr.deref_mut(), |mut expr| {
|
||||||
self.cfg.configure_expr_kind(&mut expr.kind);
|
self.cfg.configure_expr_kind(&mut expr.kind);
|
||||||
|
|
||||||
// ignore derives so they remain unused
|
if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
|
||||||
let (attr, after_derive) = self.classify_nonitem(&mut expr);
|
|
||||||
|
|
||||||
if let Some(ref attr_value) = attr {
|
|
||||||
// Collect the invoc regardless of whether or not attributes are permitted here
|
// Collect the invoc regardless of whether or not attributes are permitted here
|
||||||
// expansion will eat the attribute so it won't error later.
|
// expansion will eat the attribute so it won't error later.
|
||||||
self.cfg.maybe_emit_expr_attr_err(attr_value);
|
attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr));
|
||||||
|
|
||||||
// AstFragmentKind::Expr requires the macro to emit an expression.
|
// AstFragmentKind::Expr requires the macro to emit an expression.
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::Expr)
|
||||||
attr,
|
|
||||||
vec![],
|
|
||||||
Annotatable::Expr(P(expr)),
|
|
||||||
AstFragmentKind::Expr,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_expr()
|
.make_expr()
|
||||||
.into_inner();
|
.into_inner();
|
||||||
}
|
}
|
||||||
@ -1153,16 +1142,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
|
fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
|
||||||
let mut arm = configure!(self, arm);
|
let mut arm = configure!(self, arm);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut arm);
|
if let Some(attr) = self.take_first_attr(&mut arm) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::Arm(arm), AstFragmentKind::Arms)
|
||||||
attr,
|
|
||||||
traits,
|
|
||||||
Annotatable::Arm(arm),
|
|
||||||
AstFragmentKind::Arms,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_arms();
|
.make_arms();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1172,16 +1154,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
|
fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
|
||||||
let mut field = configure!(self, field);
|
let mut field = configure!(self, field);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut field);
|
if let Some(attr) = self.take_first_attr(&mut field) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::Field(field), AstFragmentKind::Fields)
|
||||||
attr,
|
|
||||||
traits,
|
|
||||||
Annotatable::Field(field),
|
|
||||||
AstFragmentKind::Fields,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_fields();
|
.make_fields();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1191,16 +1166,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
|
fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
|
||||||
let mut fp = configure!(self, fp);
|
let mut fp = configure!(self, fp);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut fp);
|
if let Some(attr) = self.take_first_attr(&mut fp) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::FieldPat(fp), AstFragmentKind::FieldPats)
|
||||||
attr,
|
|
||||||
traits,
|
|
||||||
Annotatable::FieldPat(fp),
|
|
||||||
AstFragmentKind::FieldPats,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_field_patterns();
|
.make_field_patterns();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1210,16 +1178,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
|
fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
|
||||||
let mut p = configure!(self, p);
|
let mut p = configure!(self, p);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut p);
|
if let Some(attr) = self.take_first_attr(&mut p) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::Param(p), AstFragmentKind::Params)
|
||||||
attr,
|
|
||||||
traits,
|
|
||||||
Annotatable::Param(p),
|
|
||||||
AstFragmentKind::Params,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_params();
|
.make_params();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1229,16 +1190,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
|
fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
|
||||||
let mut sf = configure!(self, sf);
|
let mut sf = configure!(self, sf);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut sf);
|
if let Some(attr) = self.take_first_attr(&mut sf) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::StructField(sf), AstFragmentKind::StructFields)
|
||||||
attr,
|
|
||||||
traits,
|
|
||||||
Annotatable::StructField(sf),
|
|
||||||
AstFragmentKind::StructFields,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_struct_fields();
|
.make_struct_fields();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1248,16 +1202,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
|
fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
|
||||||
let mut variant = configure!(self, variant);
|
let mut variant = configure!(self, variant);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut variant);
|
if let Some(attr) = self.take_first_attr(&mut variant) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::Variant(variant), AstFragmentKind::Variants)
|
||||||
attr,
|
|
||||||
traits,
|
|
||||||
Annotatable::Variant(variant),
|
|
||||||
AstFragmentKind::Variants,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_variants();
|
.make_variants();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1269,20 +1216,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
expr.filter_map(|mut expr| {
|
expr.filter_map(|mut expr| {
|
||||||
self.cfg.configure_expr_kind(&mut expr.kind);
|
self.cfg.configure_expr_kind(&mut expr.kind);
|
||||||
|
|
||||||
// Ignore derives so they remain unused.
|
if let Some(attr) = self.take_first_attr_no_derive(&mut expr) {
|
||||||
let (attr, after_derive) = self.classify_nonitem(&mut expr);
|
attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr));
|
||||||
|
|
||||||
if let Some(ref attr_value) = attr {
|
|
||||||
self.cfg.maybe_emit_expr_attr_err(attr_value);
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr)
|
||||||
attr,
|
|
||||||
vec![],
|
|
||||||
Annotatable::Expr(P(expr)),
|
|
||||||
AstFragmentKind::OptExpr,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_opt_expr()
|
.make_opt_expr()
|
||||||
.map(|expr| expr.into_inner());
|
.map(|expr| expr.into_inner());
|
||||||
}
|
}
|
||||||
@ -1321,25 +1259,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
|
|
||||||
// we'll expand attributes on expressions separately
|
// we'll expand attributes on expressions separately
|
||||||
if !stmt.is_expr() {
|
if !stmt.is_expr() {
|
||||||
let (attr, derives, after_derive) = if stmt.is_item() {
|
// FIXME: Handle custom attributes on statements (#15701).
|
||||||
// FIXME: Handle custom attributes on statements (#15701)
|
let attr =
|
||||||
(None, vec![], false)
|
if stmt.is_item() { None } else { self.take_first_attr_no_derive(&mut stmt) };
|
||||||
} else {
|
|
||||||
// ignore derives on non-item statements so it falls through
|
|
||||||
// to the unused-attributes lint
|
|
||||||
let (attr, after_derive) = self.classify_nonitem(&mut stmt);
|
|
||||||
(attr, vec![], after_derive)
|
|
||||||
};
|
|
||||||
|
|
||||||
if attr.is_some() || !derives.is_empty() {
|
if let Some(attr) = attr {
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts)
|
||||||
attr,
|
|
||||||
derives,
|
|
||||||
Annotatable::Stmt(P(stmt)),
|
|
||||||
AstFragmentKind::Stmts,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_stmts();
|
.make_stmts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1379,16 +1305,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
||||||
let mut item = configure!(self, item);
|
let mut item = configure!(self, item);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut item);
|
if let Some(attr) = self.take_first_attr(&mut item) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::Item(item), AstFragmentKind::Items)
|
||||||
attr,
|
|
||||||
traits,
|
|
||||||
Annotatable::Item(item),
|
|
||||||
AstFragmentKind::Items,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_items();
|
.make_items();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1482,16 +1401,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||||
let mut item = configure!(self, item);
|
let mut item = configure!(self, item);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut item);
|
if let Some(attr) = self.take_first_attr(&mut item) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::TraitItem(item), AstFragmentKind::TraitItems)
|
||||||
attr,
|
|
||||||
traits,
|
|
||||||
Annotatable::TraitItem(item),
|
|
||||||
AstFragmentKind::TraitItems,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_trait_items();
|
.make_trait_items();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1512,16 +1424,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||||
let mut item = configure!(self, item);
|
let mut item = configure!(self, item);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut item);
|
if let Some(attr) = self.take_first_attr(&mut item) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(attr, Annotatable::ImplItem(item), AstFragmentKind::ImplItems)
|
||||||
attr,
|
|
||||||
traits,
|
|
||||||
Annotatable::ImplItem(item),
|
|
||||||
AstFragmentKind::ImplItems,
|
|
||||||
after_derive,
|
|
||||||
)
|
|
||||||
.make_impl_items();
|
.make_impl_items();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1562,16 +1467,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
mut foreign_item: P<ast::ForeignItem>,
|
mut foreign_item: P<ast::ForeignItem>,
|
||||||
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
|
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut foreign_item);
|
if let Some(attr) = self.take_first_attr(&mut foreign_item) {
|
||||||
|
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(
|
||||||
attr,
|
attr,
|
||||||
traits,
|
|
||||||
Annotatable::ForeignItem(foreign_item),
|
Annotatable::ForeignItem(foreign_item),
|
||||||
AstFragmentKind::ForeignItems,
|
AstFragmentKind::ForeignItems,
|
||||||
after_derive,
|
|
||||||
)
|
)
|
||||||
.make_foreign_items();
|
.make_foreign_items();
|
||||||
}
|
}
|
||||||
@ -1606,15 +1507,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||||||
) -> SmallVec<[ast::GenericParam; 1]> {
|
) -> SmallVec<[ast::GenericParam; 1]> {
|
||||||
let mut param = configure!(self, param);
|
let mut param = configure!(self, param);
|
||||||
|
|
||||||
let (attr, traits, after_derive) = self.classify_item(&mut param);
|
if let Some(attr) = self.take_first_attr(&mut param) {
|
||||||
if attr.is_some() || !traits.is_empty() {
|
|
||||||
return self
|
return self
|
||||||
.collect_attr(
|
.collect_attr(
|
||||||
attr,
|
attr,
|
||||||
traits,
|
|
||||||
Annotatable::GenericParam(param),
|
Annotatable::GenericParam(param),
|
||||||
AstFragmentKind::GenericParams,
|
AstFragmentKind::GenericParams,
|
||||||
after_derive,
|
|
||||||
)
|
)
|
||||||
.make_generic_params();
|
.make_generic_params();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user