@@ -2,6 +2,7 @@ use clippy_config::Conf;
22use clippy_config:: types:: {
33 SourceItemOrderingCategory , SourceItemOrderingModuleItemGroupings , SourceItemOrderingModuleItemKind ,
44 SourceItemOrderingTraitAssocItemKind , SourceItemOrderingTraitAssocItemKinds ,
5+ SourceItemOrderingWithinModuleItemGroupings ,
56} ;
67use clippy_utils:: diagnostics:: span_lint_and_note;
78use rustc_hir:: {
@@ -37,7 +38,7 @@ declare_clippy_lint! {
3738 /// 2. Individual ordering rules per item kind.
3839 ///
3940 /// The item kinds that can be linted are:
40- /// - Module (with customized groupings, alphabetical within)
41+ /// - Module (with customized groupings, alphabetical within - configurable )
4142 /// - Trait (with customized order of associated items, alphabetical within)
4243 /// - Enum, Impl, Struct (purely alphabetical)
4344 ///
@@ -58,8 +59,31 @@ declare_clippy_lint! {
5859 /// | `PascalCase` | "ty_alias", "opaque_ty", "enum", "struct", "union", "trait", "trait_alias", "impl" |
5960 /// | `lower_snake_case` | "fn" |
6061 ///
62+ /// The groups' names are arbitrary and can be changed to suit the
63+ /// conventions that should be enforced for a specific project.
64+ ///
6165 /// All item kinds must be accounted for to create an enforceable linting
62- /// rule set.
66+ /// rule set. Following are some example configurations that may be useful.
67+ ///
68+ /// Example: *module inclusions and use statements to be at the top*
69+ ///
70+ /// ```toml
71+ /// module-item-order-groupings = [
72+ /// [ "modules", [ "extern_crate", "mod", "foreign_mod" ], ],
73+ /// [ "use", [ "use", ], ],
74+ /// [ "everything_else", [ "macro", "global_asm", "static", "const", "ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl", "fn", ], ],
75+ /// ]
76+ /// ```
77+ ///
78+ /// Example: *only consts and statics should be alphabetically ordered*
79+ ///
80+ /// It is also possible to configure a selection of module item groups that
81+ /// should be ordered alphabetically. This may be useful if for example
82+ /// statics and consts should be ordered, but the rest should be left open.
83+ ///
84+ /// ```toml
85+ /// module-items-ordered-within-groupings = ["UPPER_SNAKE_CASE"]
86+ /// ```
6387 ///
6488 /// ### Known Problems
6589 ///
@@ -144,6 +168,7 @@ pub struct ArbitrarySourceItemOrdering {
144168 enable_ordering_for_struct : bool ,
145169 enable_ordering_for_trait : bool ,
146170 module_item_order_groupings : SourceItemOrderingModuleItemGroupings ,
171+ module_items_ordered_within_groupings : SourceItemOrderingWithinModuleItemGroupings ,
147172}
148173
149174impl ArbitrarySourceItemOrdering {
@@ -158,6 +183,7 @@ impl ArbitrarySourceItemOrdering {
158183 enable_ordering_for_struct : conf. source_item_ordering . contains ( & Struct ) ,
159184 enable_ordering_for_trait : conf. source_item_ordering . contains ( & Trait ) ,
160185 module_item_order_groupings : conf. module_item_order_groupings . clone ( ) ,
186+ module_items_ordered_within_groupings : conf. module_items_ordered_within_groupings . clone ( ) ,
161187 }
162188 }
163189
@@ -192,7 +218,7 @@ impl ArbitrarySourceItemOrdering {
192218 ) ;
193219 }
194220
195- fn lint_member_item < T : LintContext > ( cx : & T , item : & Item < ' _ > , before_item : & Item < ' _ > ) {
221+ fn lint_member_item < T : LintContext > ( cx : & T , item : & Item < ' _ > , before_item : & Item < ' _ > , msg : & ' static str ) {
196222 let span = if item. ident . as_str ( ) . is_empty ( ) {
197223 & item. span
198224 } else {
@@ -216,14 +242,7 @@ impl ArbitrarySourceItemOrdering {
216242 return ;
217243 }
218244
219- span_lint_and_note (
220- cx,
221- ARBITRARY_SOURCE_ITEM_ORDERING ,
222- * span,
223- "incorrect ordering of items (must be alphabetically ordered)" ,
224- Some ( * before_span) ,
225- note,
226- ) ;
245+ span_lint_and_note ( cx, ARBITRARY_SOURCE_ITEM_ORDERING , * span, msg, Some ( * before_span) , note) ;
227246 }
228247
229248 /// Produces a linting warning for incorrectly ordered trait items.
@@ -403,6 +422,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
403422 }
404423
405424 let item_kind = convert_module_item_kind ( & item. kind ) ;
425+ let grouping_name = self . module_item_order_groupings . grouping_name_of ( & item_kind) ;
406426 let module_level_order = self
407427 . module_item_order_groupings
408428 . module_level_order_of ( & item_kind)
@@ -412,13 +432,28 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
412432 use std:: cmp:: Ordering ; // Better legibility.
413433 match module_level_order. cmp ( & cur_t. order ) {
414434 Ordering :: Less => {
415- Self :: lint_member_item ( cx, item, cur_t. item ) ;
435+ Self :: lint_member_item (
436+ cx,
437+ item,
438+ cur_t. item ,
439+ "incorrect ordering of items (module item groupings specify another order)" ,
440+ ) ;
416441 } ,
417442 Ordering :: Equal if item_kind == SourceItemOrderingModuleItemKind :: Use => {
418443 // Skip ordering use statements, as these should be ordered by rustfmt.
419444 } ,
420- Ordering :: Equal if cur_t. name > get_item_name ( item) => {
421- Self :: lint_member_item ( cx, item, cur_t. item ) ;
445+ Ordering :: Equal
446+ if ( grouping_name. is_some_and ( |grouping_name| {
447+ self . module_items_ordered_within_groupings
448+ . ordered_within ( & grouping_name)
449+ } ) && cur_t. name > get_item_name ( item) ) =>
450+ {
451+ Self :: lint_member_item (
452+ cx,
453+ item,
454+ cur_t. item ,
455+ "incorrect ordering of items (must be alphabetically ordered)" ,
456+ ) ;
422457 } ,
423458 Ordering :: Equal | Ordering :: Greater => {
424459 // Nothing to do in this case, they're already in the right order.
0 commit comments