17
17
//! ```
18
18
//!
19
19
20
- use clippy_utils:: { diagnostics:: span_lint_and_then, source:: snippet_opt} ;
21
- use rustc_ast:: ast:: { Expr , ExprKind } ;
20
+ use clippy_utils:: {
21
+ diagnostics:: span_lint_and_then,
22
+ higher,
23
+ source:: { snippet, snippet_opt} ,
24
+ } ;
25
+
26
+ use rustc_ast:: ast;
22
27
use rustc_errors:: Applicability ;
23
- use rustc_lint:: { EarlyContext , EarlyLintPass } ;
28
+ use rustc_hir:: { Expr , ExprKind } ;
29
+
30
+ use rustc_lint:: { LateContext , LateLintPass } ;
24
31
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
25
32
26
33
declare_clippy_lint ! {
@@ -40,27 +47,47 @@ declare_clippy_lint! {
40
47
41
48
declare_lint_pass ! ( NeedlessParensOnRangeLiteral => [ NEEDLESS_PARENS_ON_RANGE_LITERAL ] ) ;
42
49
43
- fn check_for_parens ( cx : & EarlyContext < ' _ > , e : & Expr ) {
44
- if_chain ! {
45
- if let ExprKind :: Paren ( ref start_statement) = & e. kind;
46
- if let ExprKind :: Lit ( ref literal) = start_statement. kind;
47
- then {
48
- span_lint_and_then( cx, NEEDLESS_PARENS_ON_RANGE_LITERAL , e. span,
49
- "needless parenthesis on range literal can be removed" ,
50
- |diag| {
51
- if let Some ( suggestion) = snippet_opt( cx, literal. span) {
52
- diag. span_suggestion( e. span, "try" , suggestion, Applicability :: MachineApplicable ) ;
53
- }
54
- } ) ;
50
+ fn snippet_enclosed_in_parenthesis ( snippet : & str ) -> bool {
51
+ snippet. starts_with ( '(' ) && snippet. ends_with ( ')' )
52
+ }
53
+
54
+ fn check_for_parens ( cx : & LateContext < ' _ > , e : & Expr < ' _ > , is_start : bool ) {
55
+ if is_start &&
56
+ let ExprKind :: Lit ( ref literal) = e. kind &&
57
+ let ast:: LitKind :: Float ( _sym, ast:: LitFloatType :: Unsuffixed ) = literal. node
58
+ {
59
+ // don't check floating point literals on the start expression of a range
60
+ return ;
55
61
}
62
+ if_chain ! {
63
+ if let ExprKind :: Lit ( ref literal) = e. kind;
64
+ // the indicator that paranthese surround the literal is that span of the expression and the literal differ
65
+ if ( literal. span. data( ) . hi - literal. span. data( ) . lo) != ( e. span. data( ) . hi - e. span. data( ) . lo) ;
66
+ // inspect the source code of the expression for parenthesis
67
+ if snippet_enclosed_in_parenthesis( & snippet( cx, e. span, "" ) ) ;
68
+ then {
69
+ span_lint_and_then( cx, NEEDLESS_PARENS_ON_RANGE_LITERAL , e. span,
70
+ "needless parenthesis on range literal can be removed" ,
71
+ |diag| {
72
+ if let Some ( suggestion) = snippet_opt( cx, literal. span) {
73
+ diag. span_suggestion( e. span, "try" , suggestion, Applicability :: MachineApplicable ) ;
74
+ }
75
+ } ) ;
76
+ }
56
77
}
57
78
}
58
79
59
- impl EarlyLintPass for NeedlessParensOnRangeLiteral {
60
- fn check_expr ( & mut self , cx : & EarlyContext < ' _ > , e : & Expr ) {
61
- if let ExprKind :: Range ( Some ( start) , Some ( end) , _) = & e. kind {
62
- check_for_parens ( cx, start) ;
63
- check_for_parens ( cx, end) ;
80
+ impl < ' tcx > LateLintPass < ' tcx > for NeedlessParensOnRangeLiteral {
81
+ fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
82
+ // if let higher::Range { start, end, limits } = &e.kind {
83
+ if let Some ( higher:: Range {
84
+ start : Some ( start) ,
85
+ end : Some ( end) ,
86
+ ..
87
+ } ) = higher:: Range :: hir ( expr)
88
+ {
89
+ check_for_parens ( cx, start, true ) ;
90
+ check_for_parens ( cx, end, false ) ;
64
91
}
65
92
}
66
93
}
0 commit comments