1
+ //! Utility functions for attributes, including Clippy's built-in ones
2
+
1
3
use crate :: source:: SpanRangeExt ;
2
4
use crate :: { sym, tokenize_with_text} ;
3
5
use rustc_ast:: attr;
@@ -16,10 +18,12 @@ use std::str::FromStr;
16
18
pub enum DeprecationStatus {
17
19
/// Attribute is deprecated and was possibly replaced by the named attribute
18
20
Deprecated ( Option < & ' static str > ) ,
21
+ /// Attribute is currently used
19
22
None ,
20
23
}
21
24
22
25
#[ rustfmt:: skip]
26
+ /// Attributes known by Clippy
23
27
pub const BUILTIN_ATTRIBUTES : & [ ( Symbol , DeprecationStatus ) ] = & [
24
28
( sym:: author, DeprecationStatus :: None ) ,
25
29
( sym:: version, DeprecationStatus :: None ) ,
@@ -43,6 +47,7 @@ impl Drop for LimitStack {
43
47
}
44
48
}
45
49
50
+ #[ expect( missing_docs, reason = "they're all trivial..." ) ]
46
51
impl LimitStack {
47
52
#[ must_use]
48
53
pub fn new ( limit : u64 ) -> Self {
@@ -61,7 +66,8 @@ impl LimitStack {
61
66
}
62
67
}
63
68
64
- pub fn get_attr < ' a , A : AttributeExt + ' a > (
69
+ /// Given `attrs`, extract all the instances of a built-in Clippy attribute called `name`
70
+ pub fn get_builtin_attr < ' a , A : AttributeExt + ' a > (
65
71
sess : & ' a Session ,
66
72
attrs : & ' a [ A ] ,
67
73
name : Symbol ,
@@ -104,7 +110,7 @@ pub fn get_attr<'a, A: AttributeExt + 'a>(
104
110
}
105
111
106
112
fn parse_attrs < F : FnMut ( u64 ) > ( sess : & Session , attrs : & [ impl AttributeExt ] , name : Symbol , mut f : F ) {
107
- for attr in get_attr ( sess, attrs, name) {
113
+ for attr in get_builtin_attr ( sess, attrs, name) {
108
114
let Some ( value) = attr. value_str ( ) else {
109
115
sess. dcx ( ) . span_err ( attr. span ( ) , "bad clippy attribute" ) ;
110
116
continue ;
@@ -117,9 +123,11 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[impl AttributeExt], name:
117
123
}
118
124
}
119
125
120
- pub fn get_unique_attr < ' a , A : AttributeExt > ( sess : & ' a Session , attrs : & ' a [ A ] , name : Symbol ) -> Option < & ' a A > {
126
+ /// If `attrs` contain exactly one instance of a built-in Clippy attribute called `name`,
127
+ /// returns that attribute, and `None` otherwise
128
+ pub fn get_unique_builtin_attr < ' a , A : AttributeExt > ( sess : & ' a Session , attrs : & ' a [ A ] , name : Symbol ) -> Option < & ' a A > {
121
129
let mut unique_attr: Option < & A > = None ;
122
- for attr in get_attr ( sess, attrs, name) {
130
+ for attr in get_builtin_attr ( sess, attrs, name) {
123
131
if let Some ( duplicate) = unique_attr {
124
132
sess. dcx ( )
125
133
. struct_span_err ( attr. span ( ) , format ! ( "`{name}` is defined multiple times" ) )
@@ -132,13 +140,13 @@ pub fn get_unique_attr<'a, A: AttributeExt>(sess: &'a Session, attrs: &'a [A], n
132
140
unique_attr
133
141
}
134
142
135
- /// Returns true if the attributes contain any of `proc_macro`,
136
- /// `proc_macro_derive` or ` proc_macro_attribute`, false otherwise
143
+ /// Checks whether `attrs` contain any of `proc_macro`, `proc_macro_derive` or
144
+ /// `proc_macro_attribute`
137
145
pub fn is_proc_macro ( attrs : & [ impl AttributeExt ] ) -> bool {
138
146
attrs. iter ( ) . any ( AttributeExt :: is_proc_macro_attr)
139
147
}
140
148
141
- /// Returns true if the attributes contain `#[doc(hidden)]`
149
+ /// Checks whether `attrs` contain `#[doc(hidden)]`
142
150
pub fn is_doc_hidden ( attrs : & [ impl AttributeExt ] ) -> bool {
143
151
attrs
144
152
. iter ( )
@@ -147,6 +155,7 @@ pub fn is_doc_hidden(attrs: &[impl AttributeExt]) -> bool {
147
155
. any ( |l| attr:: list_contains_name ( & l, sym:: hidden) )
148
156
}
149
157
158
+ /// Checks whether the given ADT, or any of its fields/variants, are marked as `#[non_exhaustive]`
150
159
pub fn has_non_exhaustive_attr ( tcx : TyCtxt < ' _ > , adt : AdtDef < ' _ > ) -> bool {
151
160
adt. is_variant_list_non_exhaustive ( )
152
161
|| find_attr ! ( tcx. get_all_attrs( adt. did( ) ) , AttributeKind :: NonExhaustive ( ..) )
@@ -159,7 +168,7 @@ pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool {
159
168
. any ( |field_def| find_attr ! ( tcx. get_all_attrs( field_def. did) , AttributeKind :: NonExhaustive ( ..) ) )
160
169
}
161
170
162
- /// Checks if the given span contains a `#[cfg(..)]` attribute
171
+ /// Checks whether the given span contains a `#[cfg(..)]` attribute
163
172
pub fn span_contains_cfg ( cx : & LateContext < ' _ > , s : Span ) -> bool {
164
173
s. check_source_text ( cx, |src| {
165
174
let mut iter = tokenize_with_text ( src) ;
0 commit comments