1717//! ```
1818//!
1919
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;
2227use rustc_errors:: Applicability ;
23- use rustc_lint:: { EarlyContext , EarlyLintPass } ;
28+ use rustc_hir:: { Expr , ExprKind } ;
29+
30+ use rustc_lint:: { LateContext , LateLintPass } ;
2431use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
2532
2633declare_clippy_lint ! {
@@ -40,27 +47,47 @@ declare_clippy_lint! {
4047
4148declare_lint_pass ! ( NeedlessParensOnRangeLiteral => [ NEEDLESS_PARENS_ON_RANGE_LITERAL ] ) ;
4249
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 ;
5561 }
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+ }
5677 }
5778}
5879
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 ) ;
6491 }
6592 }
6693}
0 commit comments