Skip to content

Commit eec253d

Browse files
committed
lint!: enable perfectionist::derive_ordering
Configure the rule for `prefix_then_alphabetical` with an explicit `prefix` that encodes the project's preferred derive families in order: standard, comparison, `Hash`, formatting / error, conversions, reference wrappers, iteration, arithmetic operator pairs and folds, and integer-format derives. Anything not in the prefix (`Setters`, `SmartDefault`, `Parser`, …) falls in ASCII- case-insensitive alphabetical order after, matching the existing convention. Reorder 18 derive lists across the codebase to satisfy the rule. Every case had derive-more-style traits mixed into the standard- trait block, contradicting the convention CONTRIBUTING.md already documents; the rule's suggestions match that documented intent. Document the rule in `CONTRIBUTING.md`'s derive-ordering section, and drop the now-redundant within-line ordering bullet from the shared AI-instructions template (the rule enforces it). The line-splitting convention (separate `#[cfg_attr(...)]` line for feature-gated derives) is not enforced by the rule and stays in the contributing guide as a manual style preference. https://claude.ai/code/session_01CoRidYHvni9nKNgxMPXmfQ
1 parent 2c9f3c6 commit eec253d

26 files changed

Lines changed: 62 additions & 35 deletions

.github/copilot-instructions.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
1212
- Use descriptive names for variables and closure parameters. Single letters are permitted only in these cases: (1) conventional names like `n` for count or `f` for formatter; (2) comparison closures like `|a, b|`; (3) trivial single-expression closures; (4) fold accumulators; (5) index variables `i`/`j`/`k` in short closures or index-based loops; and (6) test fixtures with identical roles. Single letters are never permitted in multi-line functions or closures.
1313
- Use `pipe-trait` to chain through unary functions such as constructors, `Some`, `Ok`, and free functions. Use it to flatten nested calls and to continue method chains. Do not use it for simple standalone calls; prefer `foo(value)` over `value.pipe(foo)`.
1414
- Prefer `where` clauses when a type has multiple trait bounds.
15-
- Derive order: standard traits, then comparison traits, then `Hash`, then `derive_more`, then feature-gated derives.
1615
- For error types, only derive `Display` and `Error` from `derive_more` when each is actually needed. Not all displayable types are errors.
1716
- Minimize `unwrap()` in non-test code. Use proper error handling instead.
1817
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.

AGENTS.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
1212
- Use descriptive names for variables and closure parameters. Single letters are permitted only in these cases: (1) conventional names like `n` for count or `f` for formatter; (2) comparison closures like `|a, b|`; (3) trivial single-expression closures; (4) fold accumulators; (5) index variables `i`/`j`/`k` in short closures or index-based loops; and (6) test fixtures with identical roles. Single letters are never permitted in multi-line functions or closures.
1313
- Use `pipe-trait` to chain through unary functions such as constructors, `Some`, `Ok`, and free functions. Use it to flatten nested calls and to continue method chains. Do not use it for simple standalone calls; prefer `foo(value)` over `value.pipe(foo)`.
1414
- Prefer `where` clauses when a type has multiple trait bounds.
15-
- Derive order: standard traits, then comparison traits, then `Hash`, then `derive_more`, then feature-gated derives.
1615
- For error types, only derive `Display` and `Error` from `derive_more` when each is actually needed. Not all displayable types are errors.
1716
- Minimize `unwrap()` in non-test code. Use proper error handling instead.
1817
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.

CLAUDE.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Read and follow the CONTRIBUTING.md file in this repository for all code style c
1212
- Use descriptive names for variables and closure parameters. Single letters are permitted only in these cases: (1) conventional names like `n` for count or `f` for formatter; (2) comparison closures like `|a, b|`; (3) trivial single-expression closures; (4) fold accumulators; (5) index variables `i`/`j`/`k` in short closures or index-based loops; and (6) test fixtures with identical roles. Single letters are never permitted in multi-line functions or closures.
1313
- Use `pipe-trait` to chain through unary functions such as constructors, `Some`, `Ok`, and free functions. Use it to flatten nested calls and to continue method chains. Do not use it for simple standalone calls; prefer `foo(value)` over `value.pipe(foo)`.
1414
- Prefer `where` clauses when a type has multiple trait bounds.
15-
- Derive order: standard traits, then comparison traits, then `Hash`, then `derive_more`, then feature-gated derives.
1615
- For error types, only derive `Display` and `Error` from `derive_more` when each is actually needed. Not all displayable types are errors.
1716
- Minimize `unwrap()` in non-test code. Use proper error handling instead.
1817
- Prefer `#[cfg_attr(..., ignore = "reason")]` over `#[cfg(...)]` when skipping tests. Use `#[cfg]` on tests only when the code cannot compile under the condition, such as when it references types or functions that do not exist on other platforms.

CONTRIBUTING.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,9 @@ pub use event::Event;
7171

7272
### Derive Macro Ordering
7373

74-
When deriving multiple traits, use this order and split across multiple `#[derive(...)]` lines for readability:
74+
The order of trait names within each `#[derive(...)]` attribute is enforced automatically by the `perfectionist::derive_ordering` rule, configured for the `prefix_then_alphabetical` style. The configured `prefix` in `dylint.toml` lists the trait families in their project-preferred order: standard traits, then comparison traits, then `Hash`, then formatting / error derives, then conversions, then reference wrappers, then iteration, then arithmetic operator pairs and folds, then integer-format derives. Any trait that is not in the `prefix` (project-specific derives such as `Setters`, `SmartDefault`, and `Parser`) falls in ASCII-case-insensitive alphabetical order after the prefix entries.
7575

76-
1. **Standard traits:** `Debug`, `Default`, `Clone`, `Copy`
77-
2. **Comparison traits:** `PartialEq`, `Eq`, `PartialOrd`, `Ord`
78-
3. **Hash**
79-
4. **`derive_more` traits:** `Display`, `From`, `Into`, `Add`, `AddAssign`, etc.
80-
5. **Feature-gated derives** on a separate `#[cfg_attr(...)]` line
76+
The remaining conventions are not enforced by the rule and must be applied by hand. When a type derives many traits, split them across multiple `#[derive(...)]` lines for readability, and place feature-gated derives on a separate `#[cfg_attr(...)]` line.
8177

8278
```rust
8379
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]

dylint.toml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,41 @@ libraries = [
33
{ git = "https://github.com/KSXGitHub/perfectionist", tag = "0.0.0-rc.9" },
44
]
55

6+
["perfectionist::derive_ordering"]
7+
# Match the convention documented in `CONTRIBUTING.md`. The `prefix`
8+
# extends the rule's default with the derive-more-style families this
9+
# project uses, in the project-preferred logical order: formatting
10+
# (`Display`, `Error`), conversions (`From`, `Into`, …), reference
11+
# wrappers (`AsRef`, `AsMut`, `Deref`, `DerefMut`), iteration
12+
# (`IntoIterator`), arithmetic operator pairs (`Add` / `AddAssign`,
13+
# `Sub` / `SubAssign`, …), and integer-format derives (`LowerHex`,
14+
# `UpperHex`, `Octal`). Anything not listed here (project-specific
15+
# `Setters`, `SmartDefault`, `Parser`, etc.) falls alphabetically
16+
# after the prefix, which matches the existing convention.
17+
style = "prefix_then_alphabetical"
18+
prefix = [
19+
# Standard traits.
20+
"Debug", "Default", "Clone", "Copy",
21+
# Comparison traits.
22+
"PartialEq", "Eq", "PartialOrd", "Ord",
23+
# Hash.
24+
"Hash",
25+
# Formatting / error.
26+
"Display", "Error",
27+
# Conversions.
28+
"From", "Into", "TryFrom", "TryInto", "FromStr",
29+
# Reference wrappers.
30+
"AsRef", "AsMut", "Deref", "DerefMut",
31+
# Iteration.
32+
"IntoIterator",
33+
# Arithmetic operator pairs.
34+
"Add", "AddAssign", "Sub", "SubAssign", "Mul", "MulAssign", "Div", "DivAssign",
35+
# Folds.
36+
"Sum", "Product",
37+
# Integer-format derives.
38+
"LowerHex", "UpperHex", "Octal",
39+
]
40+
641
["perfectionist::single_letter_names"]
742
# Treat project-specific and third-party comparison-style helpers as if
843
# they were standard `sort_by`-shaped methods, so the idiomatic

src/args.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use terminal_size::{Width, terminal_size};
2525
use text_block_macros::text_block;
2626

2727
/// The CLI arguments.
28-
#[derive(Debug, SmartDefault, Setters, Clone, Parser)]
28+
#[derive(Debug, Clone, Parser, Setters, SmartDefault)]
2929
#[clap(
3030
name = "pdu",
3131

src/args/depth.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl Depth {
2525
}
2626

2727
/// Error that occurs when parsing a string as [`Depth`].
28-
#[derive(Debug, Display, Clone, PartialEq, Eq, Error)]
28+
#[derive(Debug, Clone, PartialEq, Eq, Display, Error)]
2929
#[non_exhaustive]
3030
pub enum FromStrError {
3131
#[display("Value is neither {INFINITE:?} nor a positive integer: {_0}")]

src/args/fraction.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ use std::{
66
};
77

88
/// Floating-point value that is greater than or equal to 0 and less than 1.
9-
#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd, AsRef, Deref, Display, Into)]
9+
#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd, Display, Into, AsRef, Deref)]
1010
pub struct Fraction(f32);
1111

1212
/// Error that occurs when calling [`Fraction::new`].
13-
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Error)]
13+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, Error)]
1414
#[non_exhaustive]
1515
pub enum ConversionError {
1616
/// Provided value is greater than or equal to 1.
@@ -43,7 +43,7 @@ impl TryFrom<f32> for Fraction {
4343
}
4444

4545
/// Error that occurs when parsing a string as [`Fraction`].
46-
#[derive(Debug, Display, Clone, PartialEq, Eq, Error)]
46+
#[derive(Debug, Clone, PartialEq, Eq, Display, Error)]
4747
#[non_exhaustive]
4848
pub enum FromStrError {
4949
ParseFloatError(ParseFloatError),

src/args/threads.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub enum Threads {
1919
}
2020

2121
/// Error that occurs when parsing a string as [`Threads`].
22-
#[derive(Debug, Display, Clone, PartialEq, Eq, Error)]
22+
#[derive(Debug, Clone, PartialEq, Eq, Display, Error)]
2323
#[non_exhaustive]
2424
pub enum FromStrError {
2525
#[display("Value is neither {AUTO:?}, {MAX:?}, nor a number: {_0}")]

src/bytes_format/output.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::ParsedValue;
22
use derive_more::Display;
33

44
/// The [`DisplayOutput`](crate::size::Size::DisplayOutput) type of [`Bytes`](crate::size::Bytes).
5-
#[derive(Debug, Display, Clone, Copy)]
5+
#[derive(Debug, Clone, Copy, Display)]
66
pub enum Output {
77
/// Display the value as-is.
88
PlainNumber(u64),

0 commit comments

Comments
 (0)