-
Notifications
You must be signed in to change notification settings - Fork 903
/
non_ascii_name.rs
120 lines (111 loc) · 3.55 KB
/
non_ascii_name.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use std::fmt;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_semantic::{Binding, BindingKind};
use ruff_source_file::Locator;
use ruff_text_size::Ranged;
/// ## What it does
/// Checks for the use of non-ASCII characters in variable names.
///
/// ## Why is this bad?
/// The use of non-ASCII characters in variable names can cause confusion
/// and compatibility issues (see: [PEP 672]).
///
/// ## Example
/// ```python
/// ápple_count: int
/// ```
///
/// Use instead:
/// ```python
/// apple_count: int
/// ```
///
/// [PEP 672]: https://peps.python.org/pep-0672/
#[violation]
pub struct NonAsciiName {
name: String,
kind: Kind,
}
impl Violation for NonAsciiName {
#[derive_message_formats]
fn message(&self) -> String {
let Self { name, kind } = self;
format!("{kind} name `{name}` contains a non-ASCII character, consider renaming it")
}
}
/// PLC2401
pub(crate) fn non_ascii_name(binding: &Binding, locator: &Locator) -> Option<Diagnostic> {
let name = binding.name(locator);
if name.is_ascii() {
return None;
}
let kind = match binding.kind {
BindingKind::Annotation => Kind::Annotation,
BindingKind::Argument => Kind::Argument,
BindingKind::NamedExprAssignment => Kind::NamedExprAssignment,
BindingKind::Assignment => Kind::Assignment,
BindingKind::TypeParam => Kind::TypeParam,
BindingKind::LoopVar => Kind::LoopVar,
BindingKind::ComprehensionVar => Kind::ComprenhensionVar,
BindingKind::WithItemVar => Kind::WithItemVar,
BindingKind::Global => Kind::Global,
BindingKind::Nonlocal(_) => Kind::Nonlocal,
BindingKind::ClassDefinition(_) => Kind::ClassDefinition,
BindingKind::FunctionDefinition(_) => Kind::FunctionDefinition,
BindingKind::BoundException => Kind::BoundException,
BindingKind::Builtin
| BindingKind::Export(_)
| BindingKind::FutureImport
| BindingKind::Import(_)
| BindingKind::FromImport(_)
| BindingKind::SubmoduleImport(_)
| BindingKind::Deletion
| BindingKind::ConditionalDeletion(_)
| BindingKind::UnboundException(_) => {
return None;
}
};
Some(Diagnostic::new(
NonAsciiName {
name: name.to_string(),
kind,
},
binding.range(),
))
}
#[derive(Debug, PartialEq, Eq)]
enum Kind {
Annotation,
Argument,
NamedExprAssignment,
Assignment,
TypeParam,
LoopVar,
ComprenhensionVar,
WithItemVar,
Global,
Nonlocal,
ClassDefinition,
FunctionDefinition,
BoundException,
}
impl fmt::Display for Kind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Kind::Annotation => f.write_str("Annotation"),
Kind::Argument => f.write_str("Argument"),
Kind::NamedExprAssignment => f.write_str("Variable"),
Kind::Assignment => f.write_str("Variable"),
Kind::TypeParam => f.write_str("Type parameter"),
Kind::LoopVar => f.write_str("Variable"),
Kind::ComprenhensionVar => f.write_str("Variable"),
Kind::WithItemVar => f.write_str("Variable"),
Kind::Global => f.write_str("Global"),
Kind::Nonlocal => f.write_str("Nonlocal"),
Kind::ClassDefinition => f.write_str("Class"),
Kind::FunctionDefinition => f.write_str("Function"),
Kind::BoundException => f.write_str("Exception"),
}
}
}