about summary refs log tree commit diff
path: root/clippy_lints/src/strings.rs
diff options
context:
space:
mode:
authorJane Lusby <jlusby42@gmail.com>2018-10-05 09:06:05 -0700
committerJane Lusby <jlusby42@gmail.com>2018-10-26 09:12:01 -0700
commitc209fc9349ff750dc983ecfe23d8e0bb74f002df (patch)
treeb43d0e01088ba930cd7252068dd20d43c5b9ee56 /clippy_lints/src/strings.rs
parent457e7f12e9fc028eae182f23b279194e5344b676 (diff)
downloadrust-c209fc9349ff750dc983ecfe23d8e0bb74f002df.tar.gz
rust-c209fc9349ff750dc983ecfe23d8e0bb74f002df.zip
Fix string_lit_as_bytes lint for macros
Prior to this change, string_lit_as_bytes would trigger for constructs
like `include_str!("filename").as_bytes()` and would recommend fixing it
by rewriting as `binclude_str!("filename")`.

This change updates the lint to act as an EarlyLintPass lint. It then
differentiates between string literals and macros that have bytes
yielding alternatives.

Closes #3205
Diffstat (limited to 'clippy_lints/src/strings.rs')
-rw-r--r--clippy_lints/src/strings.rs39
1 files changed, 31 insertions, 8 deletions
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index f4798842205..9b6478fb9cd 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -92,7 +92,14 @@ impl LintPass for StringAdd {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
-        if let ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref left, _) = e.node {
+        if let ExprKind::Binary(
+            Spanned {
+                node: BinOpKind::Add, ..
+            },
+            ref left,
+            _,
+        ) = e.node
+        {
             if is_string(cx, left) {
                 if !is_allowed(cx, STRING_ADD_ASSIGN, e.id) {
                     let parent = get_parent_expr(cx, e);
@@ -132,13 +139,15 @@ fn is_string(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
 
 fn is_add(cx: &LateContext<'_, '_>, src: &Expr, target: &Expr) -> bool {
     match src.node {
-        ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left),
+        ExprKind::Binary(
+            Spanned {
+                node: BinOpKind::Add, ..
+            },
+            ref left,
+            _,
+        ) => SpanlessEq::new(cx).eq_expr(target, left),
         ExprKind::Block(ref block, _) => {
-            block.stmts.is_empty()
-                && block
-                    .expr
-                    .as_ref()
-                    .map_or(false, |expr| is_add(cx, expr, target))
+            block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target))
         },
         _ => false,
     }
@@ -162,7 +171,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
             if path.ident.name == "as_bytes" {
                 if let ExprKind::Lit(ref lit) = args[0].node {
                     if let LitKind::Str(ref lit_content, _) = lit.node {
-                        if lit_content.as_str().chars().all(|c| c.is_ascii()) && !in_macro(args[0].span) {
+                        let callsite = snippet(cx, args[0].span.source_callsite(), "");
+                        let expanded = format!("\"{}\"", lit_content.as_str());
+                        if callsite.starts_with("include_str!") {
+                            span_lint_and_sugg(
+                                cx,
+                                STRING_LIT_AS_BYTES,
+                                e.span,
+                                "calling `as_bytes()` on `include_str!(..)`",
+                                "consider using `include_bytes!(..)` instead",
+                                snippet(cx, args[0].span, r#""foo""#).replacen("include_str", "include_bytes", 1),
+                            );
+                        } else if callsite == expanded
+                            && lit_content.as_str().chars().all(|c| c.is_ascii())
+                            && !in_macro(args[0].span)
+                        {
                             span_lint_and_sugg(
                                 cx,
                                 STRING_LIT_AS_BYTES,