Skip to content

Commit 92c8d70

Browse files
committed
overhaul LimitStack
- Add some documentation - Move it and its helper function `parse_attrs` together to the end of the file, because it's surprising to see front-and-center a struct that's only really used in one place (`cognitive_complexity`). - Avoid panic path in `LimitStack::limit`
1 parent badd57c commit 92c8d70

File tree

1 file changed

+49
-43
lines changed

1 file changed

+49
-43
lines changed

clippy_utils/src/attrs.rs

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -37,35 +37,6 @@ pub const BUILTIN_ATTRIBUTES: &[(Symbol, DeprecationStatus)] = &[
3737
(sym::format_args, DeprecationStatus::None),
3838
];
3939

40-
pub struct LimitStack {
41-
stack: Vec<u64>,
42-
}
43-
44-
impl Drop for LimitStack {
45-
fn drop(&mut self) {
46-
assert_eq!(self.stack.len(), 1);
47-
}
48-
}
49-
50-
#[expect(missing_docs, reason = "they're all trivial...")]
51-
impl LimitStack {
52-
#[must_use]
53-
pub fn new(limit: u64) -> Self {
54-
Self { stack: vec![limit] }
55-
}
56-
pub fn limit(&self) -> u64 {
57-
*self.stack.last().expect("there should always be a value in the stack")
58-
}
59-
pub fn push_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) {
60-
let stack = &mut self.stack;
61-
parse_attrs(sess, attrs, name, |val| stack.push(val));
62-
}
63-
pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) {
64-
let stack = &mut self.stack;
65-
parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val)));
66-
}
67-
}
68-
6940
/// Given `attrs`, extract all the instances of a built-in Clippy attribute called `name`
7041
pub fn get_builtin_attr<'a, A: AttributeExt + 'a>(
7142
sess: &'a Session,
@@ -109,20 +80,6 @@ pub fn get_builtin_attr<'a, A: AttributeExt + 'a>(
10980
})
11081
}
11182

112-
fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[impl AttributeExt], name: Symbol, mut f: F) {
113-
for attr in get_builtin_attr(sess, attrs, name) {
114-
let Some(value) = attr.value_str() else {
115-
sess.dcx().span_err(attr.span(), "bad clippy attribute");
116-
continue;
117-
};
118-
let Ok(value) = u64::from_str(value.as_str()) else {
119-
sess.dcx().span_err(attr.span(), "not a number");
120-
continue;
121-
};
122-
f(value);
123-
}
124-
}
125-
12683
/// If `attrs` contain exactly one instance of a built-in Clippy attribute called `name`,
12784
/// returns that attribute, and `None` otherwise
12885
pub fn get_unique_builtin_attr<'a, A: AttributeExt>(sess: &'a Session, attrs: &'a [A], name: Symbol) -> Option<&'a A> {
@@ -190,3 +147,52 @@ pub fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
190147
false
191148
})
192149
}
150+
151+
/// Currently used to keep track of the current value of `#[clippy::cognitive_complexity(N)]`
152+
pub struct LimitStack {
153+
default: u64,
154+
stack: Vec<u64>,
155+
}
156+
157+
impl Drop for LimitStack {
158+
fn drop(&mut self) {
159+
assert_eq!(self.stack, Vec::<u64>::new()); // avoid `.is_empty()`, for a nicer error message
160+
}
161+
}
162+
163+
#[expect(missing_docs, reason = "they're all trivial...")]
164+
impl LimitStack {
165+
#[must_use]
166+
/// Initialize the stack starting with a default value, which usually comes from configuration
167+
pub fn new(limit: u64) -> Self {
168+
Self {
169+
default: limit,
170+
stack: vec![],
171+
}
172+
}
173+
pub fn limit(&self) -> u64 {
174+
self.stack.last().copied().unwrap_or(self.default)
175+
}
176+
pub fn push_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) {
177+
let stack = &mut self.stack;
178+
parse_attrs(sess, attrs, name, |val| stack.push(val));
179+
}
180+
pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) {
181+
let stack = &mut self.stack;
182+
parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val)));
183+
}
184+
}
185+
186+
fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[impl AttributeExt], name: Symbol, mut f: F) {
187+
for attr in get_builtin_attr(sess, attrs, name) {
188+
let Some(value) = attr.value_str() else {
189+
sess.dcx().span_err(attr.span(), "bad clippy attribute");
190+
continue;
191+
};
192+
let Ok(value) = u64::from_str(value.as_str()) else {
193+
sess.dcx().span_err(attr.span(), "not a number");
194+
continue;
195+
};
196+
f(value);
197+
}
198+
}

0 commit comments

Comments
 (0)