1+ use clippy_config:: Conf ;
2+ use clippy_config:: types:: InitializerSuggestionApplicability ;
13use clippy_utils:: diagnostics:: span_lint_and_sugg;
24use clippy_utils:: fulfill_or_allowed;
3- use clippy_utils:: source:: snippet;
5+ use clippy_utils:: source:: { snippet, snippet_opt } ;
46use rustc_data_structures:: fx:: FxHashMap ;
57use rustc_errors:: Applicability ;
68use rustc_hir:: { self as hir, ExprKind } ;
79use rustc_lint:: { LateContext , LateLintPass } ;
8- use rustc_session:: declare_lint_pass ;
10+ use rustc_session:: impl_lint_pass ;
911use rustc_span:: symbol:: Symbol ;
1012use std:: fmt:: { self , Write as _} ;
1113
1214declare_clippy_lint ! {
1315 /// ### What it does
14- /// Checks for struct constructors where all fields are shorthand and
15- /// the order of the field init shorthand in the constructor is inconsistent
16- /// with the order in the struct definition.
16+ /// Checks for struct constructors where the order of the field
17+ /// init in the constructor is inconsistent with the order in the
18+ /// struct definition.
1719 ///
1820 /// ### Why is this bad?
1921 /// Since the order of fields in a constructor doesn't affect the
@@ -59,16 +61,36 @@ declare_clippy_lint! {
5961 #[ clippy:: version = "1.52.0" ]
6062 pub INCONSISTENT_STRUCT_CONSTRUCTOR ,
6163 pedantic,
62- "the order of the field init shorthand is inconsistent with the order in the struct definition"
64+ "the order of the field init is inconsistent with the order in the struct definition"
6365}
6466
65- declare_lint_pass ! ( InconsistentStructConstructor => [ INCONSISTENT_STRUCT_CONSTRUCTOR ] ) ;
67+ pub struct InconsistentStructConstructor {
68+ initializer_suggestions : InitializerSuggestionApplicability ,
69+ }
70+
71+ impl InconsistentStructConstructor {
72+ pub fn new ( conf : & ' static Conf ) -> Self {
73+ Self {
74+ initializer_suggestions : conf. initializer_suggestions ,
75+ }
76+ }
77+ }
78+
79+ impl_lint_pass ! ( InconsistentStructConstructor => [ INCONSISTENT_STRUCT_CONSTRUCTOR ] ) ;
6680
6781impl < ' tcx > LateLintPass < ' tcx > for InconsistentStructConstructor {
6882 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx hir:: Expr < ' _ > ) {
69- if let ExprKind :: Struct ( qpath, fields, base) = expr. kind
70- && fields. iter ( ) . all ( |f| f. is_shorthand )
71- && !expr. span . from_expansion ( )
83+ let ExprKind :: Struct ( qpath, fields, base) = expr. kind else {
84+ return ;
85+ } ;
86+ let applicability = if fields. iter ( ) . all ( |f| f. is_shorthand ) {
87+ Applicability :: MachineApplicable
88+ } else if let Some ( applicability) = self . initializer_suggestions . to_applicability ( ) {
89+ applicability
90+ } else {
91+ return ;
92+ } ;
93+ if !expr. span . from_expansion ( )
7294 && let ty = cx. typeck_results ( ) . expr_ty ( expr)
7395 && let Some ( adt_def) = ty. ty_adt_def ( )
7496 && adt_def. is_struct ( )
@@ -85,15 +107,15 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
85107 return ;
86108 }
87109
88- let mut ordered_fields: Vec < _ > = fields. iter ( ) . map ( |f| f . ident . name ) . collect ( ) ;
89- ordered_fields. sort_unstable_by_key ( |id| def_order_map[ id ] ) ;
110+ let mut ordered_fields: Vec < _ > = fields. to_vec ( ) ;
111+ ordered_fields. sort_unstable_by_key ( |id| def_order_map[ & id . ident . name ] ) ;
90112
91113 let mut fields_snippet = String :: new ( ) ;
92- let ( last_ident , idents ) = ordered_fields. split_last ( ) . unwrap ( ) ;
93- for ident in idents {
94- let _: fmt:: Result = write ! ( fields_snippet, "{ident }, " ) ;
114+ let ( last_field , fields ) = ordered_fields. split_last ( ) . unwrap ( ) ;
115+ for field in fields {
116+ let _: fmt:: Result = write ! ( fields_snippet, "{}, " , snippet_opt ( cx , field . span ) . unwrap ( ) ) ;
95117 }
96- fields_snippet. push_str ( & last_ident . to_string ( ) ) ;
118+ fields_snippet. push_str ( & snippet_opt ( cx , last_field . span ) . unwrap ( ) ) ;
97119
98120 let base_snippet = if let Some ( base) = base {
99121 format ! ( ", ..{}" , snippet( cx, base. span, ".." ) )
@@ -114,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
114136 "struct constructor field order is inconsistent with struct definition field order" ,
115137 "try" ,
116138 sugg,
117- Applicability :: MachineApplicable ,
139+ applicability ,
118140 ) ;
119141 }
120142 }
0 commit comments