Skip to content

Commit 8c01b7e

Browse files
committed
lint: upgrade perfectionist to 0.0.0-rc.18
Bump the dylint library tag from `0.0.0-rc.17` to `0.0.0-rc.18` and bring the tree into compliance with the rules it adds or extends: - `import_grouping` (new, active): configured for the `single_group` style. Blank lines that split an import run are removed so each module keeps one contiguous `use` block. - `bare_identifier_reference` (new, active): backticked identifiers in doc comments that resolve in scope are now written as intra-doc links. - `prefer_expect_over_allow` (new, active): the `clippy::float_cmp` suppressions in the fraction tests switch from `#[allow]` to `#[expect]`. - `prefer_raw_string` (bug fix #233): the rule now scans macro arguments, so the roff `write!`/`format!` strings in `man_page` become raw strings. The rendered man page is byte-for-byte unchanged. The `single_group` style cannot keep `#[cfg]`-gated imports in their own trailing group, so files that rely on that layout carry a module-level `#[expect(perfectionist::import_grouping)]`. This limitation is tracked in #436. https://claude.ai/code/session_016ZyYFnzSv876usUHLEX4qe
1 parent 2bcd85a commit 8c01b7e

37 files changed

Lines changed: 235 additions & 95 deletions

CONTRIBUTING.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,24 @@ Automated tools enforce formatting (`cargo fmt`), linting (`cargo clippy`), and
3636

3737
### Import Organization
3838

39-
Import granularity is enforced automatically by the `perfectionist::import_granularity` rule, configured for the `module` style. Items from the same module are merged into a single braced `use` statement, while each module keeps its own `use` statement rather than collapsing an entire crate into one nested-braces statement. Import ordering is enforced separately by `cargo fmt`.
39+
Two `perfectionist` rules govern imports automatically:
4040

41-
The remaining convention is not enforced and must be applied by hand. Imports gated by a platform attribute such as `#[cfg(unix)]` go in a separate block after the main imports.
41+
- `perfectionist::import_granularity`, configured for the `module` style, controls how items are merged within each `use` statement. Items from the same module are merged into a single braced `use` statement, while each module keeps its own `use` statement rather than collapsing an entire crate into one nested-braces statement.
42+
- `perfectionist::import_grouping`, configured for the `single_group` style, controls how `use` statements are partitioned into blocks. Every `use` statement, whether a `pub use` re-export or a private import, sits in one contiguous block with no blank lines between them.
43+
44+
Import ordering within the block is enforced separately by `cargo fmt`.
45+
46+
Imports gated by a platform or feature attribute such as `#[cfg(unix)]` are kept in their own block after the main imports, separated by a blank line. The `single_group` style cannot yet express this exception, so each file that uses it carries a module-level suppression. See [issue #436](https://github.com/KSXGitHub/parallel-disk-usage/issues/436).
4247

4348
```rust
49+
#![cfg_attr(
50+
dylint_lib = "perfectionist",
51+
expect(
52+
perfectionist::import_grouping,
53+
reason = "single_group cannot keep #[cfg]-gated imports in their own trailing group; see issue #436"
54+
)
55+
)]
56+
4457
use crate::args::{Args, Quantity, Threads};
4558
use crate::bytes_format::BytesFormat;
4659
use crate::size;
@@ -57,7 +70,7 @@ use crate::get_size::{GetBlockCount, GetBlockSize};
5770

5871
The flat file pattern (`module.rs` rather than `module/mod.rs`) is enforced by the `perfectionist::flat_module_pattern` dylint check. In addition to that requirement, follow these conventions:
5972

60-
- List `pub mod` declarations first, then `pub use` re-exports, then private imports and items.
73+
- List `pub mod` declarations first, followed by the `use` block, then the remaining items. The `use` block holds both `pub use` re-exports and private imports; `cargo fmt` and `perfectionist::import_grouping` keep them in one sorted group, so do not rely on a fixed order between the two kinds.
6174
- Use `pub use` to re-export key types at the module level for convenience.
6275

6376
```rust

dylint.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace.metadata.dylint]
22
libraries = [
3-
{ git = "https://github.com/KSXGitHub/perfectionist", tag = "0.0.0-rc.17" },
3+
{ git = "https://github.com/KSXGitHub/perfectionist", tag = "0.0.0-rc.18" },
44
]
55

66
["perfectionist::derive_ordering"]
@@ -22,6 +22,9 @@ prefix = [
2222
["perfectionist::import_granularity"]
2323
style = "module"
2424

25+
["perfectionist::import_grouping"]
26+
style = "single_group"
27+
2528
["perfectionist::macro_argument_binding"]
2629
deny_extra = ["debug_assert_op", "debug_assert_op_expr"]
2730
allow_extra = ["assert_op_expr"]

src/app.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
pub mod sub;
1+
#![cfg_attr(
2+
dylint_lib = "perfectionist",
3+
expect(
4+
perfectionist::import_grouping,
5+
reason = "single_group cannot keep #[cfg]-gated imports in their own trailing group; see issue #436"
6+
)
7+
)]
28

3-
pub use sub::Sub;
9+
pub mod sub;
410

511
use crate::args::{Args, Quantity, Threads};
612
use crate::bytes_format::BytesFormat;
@@ -17,6 +23,7 @@ use pipe_trait::Pipe;
1723
use std::io::stdin;
1824
use std::time::Duration;
1925
use sub::JsonOutputParam;
26+
pub use sub::Sub;
2027
use sysinfo::{Disk, Disks};
2128

2229
#[cfg(unix)]

src/app/hdd.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
#![cfg_attr(
2+
dylint_lib = "perfectionist",
3+
expect(
4+
perfectionist::import_grouping,
5+
reason = "single_group cannot keep #[cfg]-gated imports in their own trailing group; see issue #436"
6+
)
7+
)]
8+
19
use super::mount_point::find_mount_point;
210
use std::ffi::OsStr;
311
use std::fs::canonicalize;

src/app/hdd/test_linux.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ fn test_parse_block_device_name() {
3939
}
4040
}
4141

42-
/// Generate a test that builds a mock `FsApi` with identity `canonicalize`,
43-
/// then asserts that `reclassify_virtual_hdd` maps `DiskKind::HDD` to the
42+
/// Generate a test that builds a mock [`FsApi`] with identity `canonicalize`,
43+
/// then asserts that [`reclassify_virtual_hdd`] maps `DiskKind::HDD` to the
4444
/// expected `DiskKind`.
4545
///
4646
/// The sysfs paths (`/sys/block/{block}` and
@@ -171,7 +171,7 @@ identity_reclassify_test_case! {
171171
///
172172
/// **Note:** On real LVM setups, `/dev/mapper/vg0-lv0` canonicalizes to
173173
/// `/dev/dm-0`, not a partition device. See
174-
/// `test_mapper_dm_device_is_not_corrected` for that case.
174+
/// [`test_mapper_dm_device_is_not_corrected`] for that case.
175175
#[test]
176176
fn test_mapper_symlink_resolves_to_virtual_partition() {
177177
struct Fs;

src/args.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@ pub mod fraction;
33
pub mod quantity;
44
pub mod threads;
55

6-
pub use depth::Depth;
7-
pub use fraction::Fraction;
8-
pub use quantity::Quantity;
9-
pub use threads::Threads;
10-
116
use crate::bytes_format::BytesFormat;
127
use crate::visualizer::ColumnWidthDistribution;
138
use clap::{ColorChoice, Parser};
9+
pub use depth::Depth;
1410
use derive_setters::Setters;
11+
pub use fraction::Fraction;
12+
pub use quantity::Quantity;
1513
use smart_default::SmartDefault;
1614
use std::path::PathBuf;
1715
use terminal_size::{Width, terminal_size};
1816
use text_block_macros::text_block;
17+
pub use threads::Threads;
1918

2019
/// The CLI arguments.
2120
#[derive(Debug, SmartDefault, Clone, Parser, Setters)]

src/bytes_format.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
#![cfg_attr(
2+
dylint_lib = "perfectionist",
3+
expect(
4+
perfectionist::import_grouping,
5+
reason = "single_group cannot keep #[cfg]-gated imports in their own trailing group; see issue #436"
6+
)
7+
)]
8+
19
pub mod formatter;
210
pub mod output;
311
pub mod parsed_value;
@@ -6,7 +14,6 @@ pub mod scale_base;
614
pub use formatter::Formatter;
715
pub use output::Output;
816
pub use parsed_value::ParsedValue;
9-
1017
use pipe_trait::Pipe;
1118

1219
#[cfg(feature = "cli")]

src/data_tree.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
pub mod reflection;
22

3-
pub use reflection::Reflection;
4-
5-
pub use Reflection as DataTreeReflection;
6-
73
use super::size;
4+
pub use Reflection as DataTreeReflection;
5+
pub use reflection::Reflection;
86

97
/// Disk usage data of a filesystem tree.
108
///
11-
/// **Construction:** There are 3 main ways to create a `DataTree`:
9+
/// **Construction:** There are 3 main ways to create a [`DataTree`]:
1210
/// * Use [`FsTreeBuilder`](crate::fs_tree_builder::FsTreeBuilder) to create it from the real
1311
/// filesystem.
1412
/// * Use [`TreeBuilder`](crate::tree_builder::TreeBuilder) to create it from a representation
1513
/// of a filesystem.
1614
/// * Use [`Reflection`].
1715
///
1816
/// **Visualization:** Use the [`Visualizer`](crate::visualizer::Visualizer) struct to create an
19-
/// ASCII chart that visualizes `DataTree`.
17+
/// ASCII chart that visualizes [`DataTree`].
2018
///
21-
/// **Serialization and deserialization:** _(feature: `json`)_ `DataTree` does not implement
19+
/// **Serialization and deserialization:** _(feature: `json`)_ [`DataTree`] does not implement
2220
/// `Serialize` and `Deserialize` traits directly, instead, it can be converted into/from a
2321
/// [`Reflection`] which implements these traits.
2422
#[derive(Debug, PartialEq, Eq)]

src/data_tree/reflection.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
#![cfg_attr(
2+
dylint_lib = "perfectionist",
3+
expect(
4+
perfectionist::import_grouping,
5+
reason = "single_group cannot keep #[cfg]-gated imports in their own trailing group; see issue #436"
6+
)
7+
)]
8+
19
use crate::size;
210
use std::collections::VecDeque;
311
use std::ffi::OsStr;
@@ -10,21 +18,21 @@ use serde::{Deserialize, Serialize};
1018
/// Intermediate format used for construction and inspection of
1119
/// [`DataTree`](crate::data_tree::DataTree)'s internal content.
1220
///
13-
/// Unlike `DataTree` where the fields are all private, the fields of `Reflection`
21+
/// Unlike `DataTree` where the fields are all private, the fields of [`Reflection`]
1422
/// are all public to allow construction in tests.
1523
///
16-
/// **Conversion between `DataTree` and `Reflection`:**
17-
/// * Any `DataTree` can be safely [transmuted](std::mem::transmute) to a valid `Reflection`.
18-
/// * Any `Reflection` can be safely transmuted to a potentially invalid `DataTree`.
19-
/// * To safely convert a `DataTree` into a `Reflection` without the `unsafe` keyword, use
24+
/// **Conversion between `DataTree` and [`Reflection`]:**
25+
/// * Any `DataTree` can be safely [transmuted](std::mem::transmute) to a valid [`Reflection`].
26+
/// * Any [`Reflection`] can be safely transmuted to a potentially invalid `DataTree`.
27+
/// * To safely convert a `DataTree` into a [`Reflection`] without the `unsafe` keyword, use
2028
/// [`DataTree::into_reflection`](crate::data_tree::DataTree::into_reflection)
2129
/// (it would be slower than using `transmute`).
22-
/// * To safely convert a `Reflection` into a valid `DataTree`,
30+
/// * To safely convert a [`Reflection`] into a valid `DataTree`,
2331
/// use [`par_try_into_tree`](Self::par_try_into_tree).
2432
///
25-
/// **Serialization and deserialization:** _(feature: `json`)_ `Reflection` implements
33+
/// **Serialization and deserialization:** _(feature: `json`)_ [`Reflection`] implements
2634
/// `Serialize` and `Deserialize` traits, this allows functions in `serde_json` to convert
27-
/// a `Reflection` into/from JSON.
35+
/// a [`Reflection`] into/from JSON.
2836
#[derive(Debug, Clone, PartialEq, Eq)]
2937
#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
3038
#[cfg_attr(feature = "json", serde(rename_all = "kebab-case"))]

src/device.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
#![cfg_attr(
2+
dylint_lib = "perfectionist",
3+
expect(
4+
perfectionist::import_grouping,
5+
reason = "single_group cannot keep #[cfg]-gated imports in their own trailing group; see issue #436"
6+
)
7+
)]
8+
19
use derive_more::{Display, From, Into, LowerHex, Octal, UpperHex};
210

311
#[cfg(feature = "json")]

0 commit comments

Comments
 (0)