]>
git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_utils/src/attrs.rs
1 use rustc_ast
::{ast, attr}
;
2 use rustc_errors
::Applicability
;
3 use rustc_session
::Session
;
7 /// Deprecation status of attributes known by Clippy.
9 pub enum DeprecationStatus
{
10 /// Attribute is deprecated
12 /// Attribute is deprecated and was replaced by the named attribute
13 Replaced(&'
static str),
17 pub const BUILTIN_ATTRIBUTES
: &[(&str, DeprecationStatus
)] = &[
18 ("author", DeprecationStatus
::None
),
19 ("cognitive_complexity", DeprecationStatus
::None
),
21 "cyclomatic_complexity",
22 DeprecationStatus
::Replaced("cognitive_complexity"),
24 ("dump", DeprecationStatus
::None
),
25 ("msrv", DeprecationStatus
::None
),
28 pub struct LimitStack
{
32 impl Drop
for LimitStack
{
34 assert_eq
!(self.stack
.len(), 1);
40 pub fn new(limit
: u64) -> Self {
41 Self { stack: vec![limit] }
43 pub fn limit(&self) -> u64 {
44 *self.stack
.last().expect("there should always be a value in the stack")
46 pub fn push_attrs(&mut self, sess
: &Session
, attrs
: &[ast
::Attribute
], name
: &'
static str) {
47 let stack
= &mut self.stack
;
48 parse_attrs(sess
, attrs
, name
, |val
| stack
.push(val
));
50 pub fn pop_attrs(&mut self, sess
: &Session
, attrs
: &[ast
::Attribute
], name
: &'
static str) {
51 let stack
= &mut self.stack
;
52 parse_attrs(sess
, attrs
, name
, |val
| assert_eq
!(stack
.pop(), Some(val
)));
58 attrs
: &'a
[ast
::Attribute
],
60 ) -> impl Iterator
<Item
= &'a ast
::Attribute
> {
61 attrs
.iter().filter(move |attr
| {
62 let attr
= if let ast
::AttrKind
::Normal(ref attr
, _
) = attr
.kind
{
67 let attr_segments
= &attr
.path
.segments
;
68 if attr_segments
.len() == 2 && attr_segments
[0].ident
.name
== sym
::clippy
{
71 .find_map(|&(builtin_name
, ref deprecation_status
)| {
72 if attr_segments
[1].ident
.name
.as_str() == builtin_name
{
73 Some(deprecation_status
)
80 sess
.span_err(attr_segments
[1].ident
.span
, "usage of unknown attribute");
83 |deprecation_status
| {
85 sess
.struct_span_err(attr_segments
[1].ident
.span
, "usage of deprecated attribute");
86 match *deprecation_status
{
87 DeprecationStatus
::Deprecated
=> {
91 DeprecationStatus
::Replaced(new_name
) => {
93 attr_segments
[1].ident
.span
,
96 Applicability
::MachineApplicable
,
101 DeprecationStatus
::None
=> {
103 attr_segments
[1].ident
.name
.as_str() == name
114 fn parse_attrs
<F
: FnMut(u64)>(sess
: &Session
, attrs
: &[ast
::Attribute
], name
: &'
static str, mut f
: F
) {
115 for attr
in get_attr(sess
, attrs
, name
) {
116 if let Some(ref value
) = attr
.value_str() {
117 if let Ok(value
) = FromStr
::from_str(&value
.as_str()) {
120 sess
.span_err(attr
.span
, "not a number");
123 sess
.span_err(attr
.span
, "bad clippy attribute");
128 pub fn get_unique_inner_attr(sess
: &Session
, attrs
: &[ast
::Attribute
], name
: &'
static str) -> Option
<ast
::Attribute
> {
129 let mut unique_attr
= None
;
130 for attr
in get_attr(sess
, attrs
, name
) {
132 ast
::AttrStyle
::Inner
if unique_attr
.is_none() => unique_attr
= Some(attr
.clone()),
133 ast
::AttrStyle
::Inner
=> {
134 sess
.struct_span_err(attr
.span
, &format
!("`{}` is defined multiple times", name
))
135 .span_note(unique_attr
.as_ref().unwrap().span
, "first definition found here")
138 ast
::AttrStyle
::Outer
=> {
139 sess
.span_err(attr
.span
, &format
!("`{}` cannot be an outer attribute", name
));
146 /// Return true if the attributes contain any of `proc_macro`,
147 /// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
148 pub fn is_proc_macro(sess
: &Session
, attrs
: &[ast
::Attribute
]) -> bool
{
149 attrs
.iter().any(|attr
| sess
.is_proc_macro_attr(attr
))
152 /// Return true if the attributes contain `#[doc(hidden)]`
153 pub fn is_doc_hidden(attrs
: &[ast
::Attribute
]) -> bool
{
156 .filter(|attr
| attr
.has_name(sym
::doc
))
157 .filter_map(ast
::Attribute
::meta_item_list
)
158 .any(|l
| attr
::list_contains_name(&l
, sym
::hidden
))