1
- use clippy_utils:: diagnostics:: span_lint_and_note;
1
+ use clippy_utils:: diagnostics:: span_lint_and_sugg;
2
+ use clippy_utils:: source:: snippet_with_applicability;
3
+ use clippy_utils:: ty:: is_type_diagnostic_item;
2
4
use if_chain:: if_chain;
5
+ use rustc_errors:: Applicability ;
3
6
use rustc_hir as hir;
4
7
use rustc_lint:: { LateContext , LateLintPass } ;
8
+ use rustc_middle:: ty;
5
9
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
10
+ use rustc_span:: sym;
6
11
7
12
declare_clippy_lint ! {
8
13
/// ### What it does
@@ -16,37 +21,45 @@ declare_clippy_lint! {
16
21
/// ### Example
17
22
/// ```rust
18
23
/// "hello".bytes().count();
24
+ /// String::from("hello").bytes().count();
19
25
/// ```
20
26
/// Use instead:
21
27
/// ```rust
22
- /// "hello".len();
28
+ /// "hello".len()
29
+ /// String::from("hello").len();
23
30
/// ```
24
- #[ clippy:: version = "1.60 .0" ]
31
+ #[ clippy:: version = "1.62 .0" ]
25
32
pub BYTES_COUNT_TO_LEN ,
26
33
complexity,
27
- "Using bytest ().count() when len() performs the same functionality"
34
+ "Using bytes ().count() when len() performs the same functionality"
28
35
}
29
36
30
37
declare_lint_pass ! ( BytesCountToLen => [ BYTES_COUNT_TO_LEN ] ) ;
31
38
32
39
impl < ' tcx > LateLintPass < ' tcx > for BytesCountToLen {
33
40
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx hir:: Expr < ' _ > ) {
34
41
if_chain ! {
35
- //check for method call called "count"
36
- if let hir:: ExprKind :: MethodCall ( count_path, count_args, _) = & expr. kind;
37
- if count_path. ident. name == rustc_span:: sym:: count;
38
- if let [ bytes_expr] = & * * count_args;
39
- //check for method call called "bytes" that was linked to "count"
40
- if let hir:: ExprKind :: MethodCall ( bytes_path, _, _) = & bytes_expr. kind;
41
- if bytes_path. ident. name. as_str( ) == "bytes" ;
42
+ if let hir:: ExprKind :: MethodCall ( expr_method, expr_args, _) = & expr. kind;
43
+ if expr_method. ident. name == rustc_span:: sym:: count;
44
+
45
+ if let [ bytes_expr] = & * * expr_args;
46
+ if let hir:: ExprKind :: MethodCall ( bytes_method, bytes_args, _) = & bytes_expr. kind;
47
+ if bytes_method. ident. name. as_str( ) == "bytes" ;
48
+
49
+ if let [ str_expr] = & * * bytes_args;
50
+ let ty = cx. typeck_results( ) . expr_ty( str_expr) . peel_refs( ) ;
51
+
52
+ if is_type_diagnostic_item( cx, ty, sym:: String ) || ty. kind( ) == & ty:: Str ;
42
53
then {
43
- span_lint_and_note(
54
+ let mut applicability = Applicability :: MachineApplicable ;
55
+ span_lint_and_sugg(
44
56
cx,
45
57
BYTES_COUNT_TO_LEN ,
46
58
expr. span,
47
59
"using long and hard to read `.bytes().count()`" ,
48
- None ,
49
- "`.len()` achieves same functionality"
60
+ "consider calling `.len` instead:" ,
61
+ format!( "{}.len()" , snippet_with_applicability( cx, str_expr. span, ".." , & mut applicability) ) ,
62
+ applicability
50
63
) ;
51
64
}
52
65
} ;
0 commit comments