mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 13:13:34 +00:00
first unicode lint: zero_width_space
This commit is contained in:
parent
ad8841c20b
commit
23caf3cccc
4 changed files with 74 additions and 0 deletions
|
@ -29,6 +29,7 @@ Lints included in this crate:
|
|||
- `redundant_closure` warns on creating a closure where none is needed, e.g. `|x| foo(x)`, where `foo` can be used directly
|
||||
- `inline_always`: Warns on `#[inline(always)]`, because in most cases it is a bad idea
|
||||
- `collapsible_if`: Warns on cases where two nested `if`-expressions can be collapsed into one, e.g. `if x { if y { foo() } }` can be written as `if x && y { foo() }`
|
||||
- `zero_width_space`: Warns on encountering a unicode zero-width space
|
||||
|
||||
To use, add the following lines to your Cargo.toml:
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ pub mod mut_mut;
|
|||
pub mod len_zero;
|
||||
pub mod attrs;
|
||||
pub mod collapsible_if;
|
||||
pub mod unicode;
|
||||
pub mod utils;
|
||||
|
||||
#[plugin_registrar]
|
||||
|
@ -49,6 +50,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||
reg.register_lint_pass(box misc::CmpOwned as LintPassObject);
|
||||
reg.register_lint_pass(box attrs::AttrPass as LintPassObject);
|
||||
reg.register_lint_pass(box collapsible_if::CollapsibleIf as LintPassObject);
|
||||
reg.register_lint_pass(box unicode::Unicode as LintPassObject);
|
||||
|
||||
reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST,
|
||||
misc::SINGLE_MATCH, misc::STR_TO_STRING,
|
||||
|
@ -67,5 +69,6 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||
len_zero::LEN_WITHOUT_IS_EMPTY,
|
||||
attrs::INLINE_ALWAYS,
|
||||
collapsible_if::COLLAPSIBLE_IF,
|
||||
unicode::ZERO_WIDTH_SPACE,
|
||||
]);
|
||||
}
|
||||
|
|
45
src/unicode.rs
Normal file
45
src/unicode.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use rustc::lint::*;
|
||||
use syntax::ast::*;
|
||||
use syntax::codemap::{BytePos, Span};
|
||||
|
||||
declare_lint!{ pub ZERO_WIDTH_SPACE, Deny, "Zero-width space is confusing" }
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Unicode;
|
||||
|
||||
impl LintPass for Unicode {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(ZERO_WIDTH_SPACE)
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
|
||||
if let ExprLit(ref lit) = expr.node {
|
||||
if let LitStr(ref string, _) = lit.node {
|
||||
check_str(cx, string, lit.span)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_str(cx: &Context, string: &str, span: Span) {
|
||||
let mut start: Option<usize> = None;
|
||||
for (i, c) in string.char_indices() {
|
||||
if c == '\u{200B}' {
|
||||
if start.is_none() { start = Some(i); }
|
||||
} else {
|
||||
lint_zero_width(cx, span, start);
|
||||
start = None;
|
||||
}
|
||||
}
|
||||
lint_zero_width(cx, span, start);
|
||||
}
|
||||
|
||||
fn lint_zero_width(cx: &Context, span: Span, start: Option<usize>) {
|
||||
start.map(|index| {
|
||||
cx.span_lint(ZERO_WIDTH_SPACE, Span {
|
||||
lo: span.lo + BytePos(index as u32),
|
||||
hi: span.lo + BytePos(index as u32),
|
||||
expn_id: span.expn_id,
|
||||
}, "Zero-width space detected. Consider using \\u{200B}")
|
||||
});
|
||||
}
|
25
tests/compile-fail/unicode.rs
Normal file
25
tests/compile-fail/unicode.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
#![feature(plugin)]
|
||||
#![plugin(clippy)]
|
||||
|
||||
#[deny(zero_width_space)]
|
||||
fn zero() {
|
||||
print!("Here >< is a ZWS, and another");
|
||||
//~^ ERROR Zero-width space detected. Consider using \u{200B}
|
||||
//~^^ ERROR Zero-width space detected. Consider using \u{200B}
|
||||
}
|
||||
|
||||
//#[deny(unicode_canon)]
|
||||
fn canon() {
|
||||
print!("̀ah?"); //not yet ~ERROR Non-canonical unicode sequence detected. Consider using à
|
||||
}
|
||||
|
||||
//#[deny(ascii_only)]
|
||||
fn uni() {
|
||||
println!("Üben!"); //not yet ~ERROR Unicode literal detected. Consider using \u{FC}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
zero();
|
||||
uni();
|
||||
canon();
|
||||
}
|
Loading…
Reference in a new issue