-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
7 changed files
with
97 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; | ||
use crate::rustc::{declare_tool_lint, lint_array}; | ||
use crate::utils::span_lint_and_sugg; | ||
|
||
/// **What it does:** Checks for the `as_bytes` method called on string literals | ||
/// that contain only ASCII characters. | ||
/// | ||
/// **Why is this bad?** Byte string literals (e.g. `b"foo"`) can be used | ||
/// instead. They are shorter but less discoverable than `as_bytes()`. | ||
/// | ||
/// **Known Problems:** None. | ||
/// | ||
/// **Example:** | ||
/// ```rust | ||
/// let bs = "a byte string".as_bytes(); | ||
/// ``` | ||
declare_clippy_lint! { | ||
pub STRING_LIT_AS_BYTES, | ||
style, | ||
"calling `as_bytes` on a string literal instead of using a byte string literal" | ||
} | ||
|
||
#[derive(Copy, Clone)] | ||
pub struct StringLitAsBytes; | ||
|
||
impl LintPass for StringLitAsBytes { | ||
fn get_lints(&self) -> LintArray { | ||
lint_array!(STRING_LIT_AS_BYTES) | ||
} | ||
} | ||
|
||
impl EarlyLintPass for StringLitAsBytes { | ||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &crate::syntax::ast::Expr) { | ||
use crate::syntax::ast::ExprKind; | ||
use crate::syntax::ast::LitKind; | ||
use crate::utils::{in_macro, snippet}; | ||
|
||
if let ExprKind::MethodCall(ref path, ref args) = e.node { | ||
if path.ident.name == "as_bytes" { | ||
cx.sess.err(&format!("{:?}", e.node)); | ||
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) { | ||
span_lint_and_sugg( | ||
cx, | ||
STRING_LIT_AS_BYTES, | ||
e.span, | ||
"calling `as_bytes()` on a string literal", | ||
"consider using a byte string literal instead", | ||
format!("b{}", snippet(cx, args[0].span, r#""foo""#)), | ||
); | ||
} | ||
} | ||
} else if let ExprKind::Mac(ref mac) = args[0].node { | ||
cx.sess.err(&format!("{:?}", mac)) | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#![feature(tool_lints)] | ||
|
||
#[allow(dead_code, unused_variables)] | ||
#[warn(clippy::string_lit_as_bytes)] | ||
fn str_lit_as_bytes() { | ||
let bs = "hello there".as_bytes(); | ||
|
||
// no warning, because this cannot be written as a byte string literal: | ||
let ubs = "☃".as_bytes(); | ||
|
||
let strify = stringify!(foobar).as_bytes(); | ||
|
||
let includestr = include_str!("entry.rs").as_bytes(); | ||
} | ||
|
||
fn main() { | ||
assert_eq!(2, 2); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
error: calling `as_bytes()` on a string literal | ||
--> $DIR/strings_early.rs:6:14 | ||
| | ||
6 | let bs = "hello there".as_bytes(); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"hello there"` | ||
| | ||
= note: `-D clippy::string-lit-as-bytes` implied by `-D warnings` | ||
|
||
error: calling `as_bytes()` on a string literal | ||
--> $DIR/strings_early.rs:11:18 | ||
| | ||
11 | let strify = stringify!(foobar).as_bytes(); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `bstringify!(foobar)` | ||
|
||
error: aborting due to 2 previous errors | ||
|