Skip to content

Commit 344f3f9

Browse files
committed
refactor(linter): minor refactors to eslint/id-length (#11976)
removes some TODOs, restructure the code to follow the pattern of the docs being at the top of the file (but below the config)
1 parent 8e1573d commit 344f3f9

File tree

1 file changed

+148
-151
lines changed

1 file changed

+148
-151
lines changed

crates/oxc_linter/src/rules/eslint/id_length.rs

Lines changed: 148 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,152 @@ pub struct IdLengthConfig {
5858
properties: PropertyKind,
5959
}
6060

61+
impl Default for IdLength {
62+
fn default() -> Self {
63+
Self(Box::new(IdLengthConfig {
64+
exception_patterns: vec![],
65+
exceptions: vec![],
66+
max: DEFAULT_MAX_LENGTH,
67+
min: DEFAULT_MIN_LENGTH,
68+
properties: PropertyKind::default(),
69+
}))
70+
}
71+
}
72+
73+
declare_oxc_lint!(
74+
/// ### What it does
75+
///
76+
/// This rule enforces a minimum and/or maximum identifier length convention by counting the
77+
/// graphemes for a given identifier.
78+
///
79+
/// ### Why is this bad?
80+
///
81+
/// Very short identifier names like e, x, _t or very long ones like
82+
/// hashGeneratorResultOutputContainerObject can make code harder to read and potentially less
83+
/// maintainable. To prevent this, one may enforce a minimum and/or maximum identifier length.
84+
///
85+
/// ### Examples
86+
///
87+
/// Examples of **incorrect** code for this rule:
88+
/// ```js
89+
/// /*eslint id-length: "error"*/ // default is minimum 2-chars ({ "min": 2 })
90+
///
91+
/// const x = 5;
92+
/// obj.e = document.body;
93+
/// const foo = function (e) { };
94+
/// try {
95+
/// dangerousStuff();
96+
/// } catch (e) {
97+
/// // ignore as many do
98+
/// }
99+
/// const myObj = { a: 1 };
100+
/// (a) => { a * a };
101+
/// class y { }
102+
/// class Foo { x() {} }
103+
/// class Bar { #x() {} }
104+
/// class Baz { x = 1 }
105+
/// class Qux { #x = 1 }
106+
/// function bar(...x) { }
107+
/// function baz([x]) { }
108+
/// const [z] = arr;
109+
/// const { prop: [i]} = {};
110+
/// function qux({x}) { }
111+
/// const { j } = {};
112+
/// const { prop: a} = {};
113+
/// ({ prop: obj.x } = {});
114+
/// ```
115+
///
116+
/// Examples of **correct** code for this rule:
117+
/// ```js
118+
/// /*eslint id-length: "error"*/ // default is minimum 2-chars ({ "min": 2 })
119+
///
120+
/// const num = 5;
121+
/// function _f() { return 42; }
122+
/// function _func() { return 42; }
123+
/// obj.el = document.body;
124+
/// const foo = function (evt) { /* do stuff */ };
125+
/// try {
126+
/// dangerousStuff();
127+
/// } catch (error) {
128+
/// // ignore as many do
129+
/// }
130+
/// const myObj = { apple: 1 };
131+
/// (num) => { num * num };
132+
/// function bar(num = 0) { }
133+
/// class MyClass { }
134+
/// class Foo { method() {} }
135+
/// class Bar { #method() {} }
136+
/// class Baz { field = 1 }
137+
/// class Qux { #field = 1 }
138+
/// function baz(...args) { }
139+
/// function qux([longName]) { }
140+
/// const { prop } = {};
141+
/// const { prop: [name] } = {};
142+
/// const [longName] = arr;
143+
/// function foobar({ prop }) { }
144+
/// function foobaz({ a: prop }) { }
145+
/// const { a: property } = {};
146+
/// ({ prop: obj.longName } = {});
147+
/// const data = { "x": 1 }; // excused because of quotes
148+
/// data["y"] = 3; // excused because of calculated property access
149+
/// ```
150+
IdLength,
151+
eslint,
152+
style,
153+
);
154+
155+
impl Rule for IdLength {
156+
fn from_configuration(value: Value) -> Self {
157+
let object = value.get(0).and_then(Value::as_object);
158+
159+
Self(Box::new(IdLengthConfig {
160+
exception_patterns: object
161+
.and_then(|map| map.get("exceptionPatterns"))
162+
.and_then(Value::as_array)
163+
.unwrap_or(&vec![])
164+
.iter()
165+
.filter_map(|val| val.as_str().and_then(|val| Regex::new(val).ok()))
166+
.collect(),
167+
exceptions: object
168+
.and_then(|map| map.get("exceptions"))
169+
.and_then(Value::as_array)
170+
.unwrap_or(&vec![])
171+
.iter()
172+
.filter_map(|val| val.as_str())
173+
.map(ToString::to_string)
174+
.collect(),
175+
max: object
176+
.and_then(|map| map.get("max"))
177+
.and_then(Value::as_u64)
178+
.unwrap_or(DEFAULT_MAX_LENGTH),
179+
min: object
180+
.and_then(|map| map.get("min"))
181+
.and_then(Value::as_u64)
182+
.unwrap_or(DEFAULT_MIN_LENGTH),
183+
properties: object
184+
.and_then(|map| map.get("properties"))
185+
.and_then(Value::as_str)
186+
.map(PropertyKind::from)
187+
.unwrap_or_default(),
188+
}))
189+
}
190+
191+
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
192+
match node.kind() {
193+
AstKind::BindingIdentifier(ident) => {
194+
self.handle_binding_identifier(ident, node, ctx);
195+
}
196+
AstKind::IdentifierName(ident) => {
197+
self.handle_identifier_name(ident, node, ctx);
198+
}
199+
AstKind::PrivateIdentifier(ident) => {
200+
self.handle_private_identifier(ident, node, ctx);
201+
}
202+
_ => {}
203+
}
204+
}
205+
}
206+
61207
impl IdLength {
62208
fn handle_binding_identifier(
63209
&self,
@@ -83,8 +229,7 @@ impl IdLength {
83229
};
84230
match parent_node.kind() {
85231
AstKind::ImportSpecifier(import_specifier) => {
86-
// TODO: Is there a better way to do this check?
87-
if import_specifier.imported.name().eq(&import_specifier.local.name) {
232+
if import_specifier.imported.name() == import_specifier.local.name {
88233
return;
89234
}
90235
// TODO: Is there a better way to do this check?
@@ -93,9 +238,8 @@ impl IdLength {
93238
}
94239
}
95240
AstKind::ObjectPattern(object_pattern) => {
96-
// TODO: Is there a better way to do this check?
97241
let binding_property_option =
98-
object_pattern.properties.iter().find(|x| x.span.eq(&ident.span));
242+
object_pattern.properties.iter().find(|x| x.span == ident.span);
99243

100244
if IdLength::is_binding_identifier_or_object_pattern(binding_property_option)
101245
&& self.properties == PropertyKind::Never
@@ -248,153 +392,6 @@ impl IdLength {
248392
}
249393
}
250394

251-
impl Default for IdLength {
252-
fn default() -> Self {
253-
Self(Box::new(IdLengthConfig {
254-
exception_patterns: vec![],
255-
exceptions: vec![],
256-
max: DEFAULT_MAX_LENGTH,
257-
min: DEFAULT_MIN_LENGTH,
258-
properties: PropertyKind::default(),
259-
}))
260-
}
261-
}
262-
263-
// See <https://github.com/oxc-project/oxc/issues/6050> for documentation details.
264-
declare_oxc_lint!(
265-
/// ### What it does
266-
///
267-
/// This rule enforces a minimum and/or maximum identifier length convention by counting the
268-
/// graphemes for a given identifier.
269-
///
270-
/// ### Why is this bad?
271-
///
272-
/// Very short identifier names like e, x, _t or very long ones like
273-
/// hashGeneratorResultOutputContainerObject can make code harder to read and potentially less
274-
/// maintainable. To prevent this, one may enforce a minimum and/or maximum identifier length.
275-
///
276-
/// ### Examples
277-
///
278-
/// Examples of **incorrect** code for this rule:
279-
/// ```js
280-
/// /*eslint id-length: "error"*/ // default is minimum 2-chars ({ "min": 2 })
281-
///
282-
/// const x = 5;
283-
/// obj.e = document.body;
284-
/// const foo = function (e) { };
285-
/// try {
286-
/// dangerousStuff();
287-
/// } catch (e) {
288-
/// // ignore as many do
289-
/// }
290-
/// const myObj = { a: 1 };
291-
/// (a) => { a * a };
292-
/// class y { }
293-
/// class Foo { x() {} }
294-
/// class Bar { #x() {} }
295-
/// class Baz { x = 1 }
296-
/// class Qux { #x = 1 }
297-
/// function bar(...x) { }
298-
/// function baz([x]) { }
299-
/// const [z] = arr;
300-
/// const { prop: [i]} = {};
301-
/// function qux({x}) { }
302-
/// const { j } = {};
303-
/// const { prop: a} = {};
304-
/// ({ prop: obj.x } = {});
305-
/// ```
306-
///
307-
/// Examples of **correct** code for this rule:
308-
/// ```js
309-
/// /*eslint id-length: "error"*/ // default is minimum 2-chars ({ "min": 2 })
310-
///
311-
/// const num = 5;
312-
/// function _f() { return 42; }
313-
/// function _func() { return 42; }
314-
/// obj.el = document.body;
315-
/// const foo = function (evt) { /* do stuff */ };
316-
/// try {
317-
/// dangerousStuff();
318-
/// } catch (error) {
319-
/// // ignore as many do
320-
/// }
321-
/// const myObj = { apple: 1 };
322-
/// (num) => { num * num };
323-
/// function bar(num = 0) { }
324-
/// class MyClass { }
325-
/// class Foo { method() {} }
326-
/// class Bar { #method() {} }
327-
/// class Baz { field = 1 }
328-
/// class Qux { #field = 1 }
329-
/// function baz(...args) { }
330-
/// function qux([longName]) { }
331-
/// const { prop } = {};
332-
/// const { prop: [name] } = {};
333-
/// const [longName] = arr;
334-
/// function foobar({ prop }) { }
335-
/// function foobaz({ a: prop }) { }
336-
/// const { a: property } = {};
337-
/// ({ prop: obj.longName } = {});
338-
/// const data = { "x": 1 }; // excused because of quotes
339-
/// data["y"] = 3; // excused because of calculated property access
340-
/// ```
341-
IdLength,
342-
eslint,
343-
style,
344-
);
345-
346-
impl Rule for IdLength {
347-
fn from_configuration(value: Value) -> Self {
348-
let object = value.get(0).and_then(Value::as_object);
349-
350-
Self(Box::new(IdLengthConfig {
351-
exception_patterns: object
352-
.and_then(|map| map.get("exceptionPatterns"))
353-
.and_then(Value::as_array)
354-
.unwrap_or(&vec![])
355-
.iter()
356-
.filter_map(|val| val.as_str().and_then(|val| Regex::new(val).ok()))
357-
.collect(),
358-
exceptions: object
359-
.and_then(|map| map.get("exceptions"))
360-
.and_then(Value::as_array)
361-
.unwrap_or(&vec![])
362-
.iter()
363-
.filter_map(|val| val.as_str())
364-
.map(ToString::to_string)
365-
.collect(),
366-
max: object
367-
.and_then(|map| map.get("max"))
368-
.and_then(Value::as_u64)
369-
.unwrap_or(DEFAULT_MAX_LENGTH),
370-
min: object
371-
.and_then(|map| map.get("min"))
372-
.and_then(Value::as_u64)
373-
.unwrap_or(DEFAULT_MIN_LENGTH),
374-
properties: object
375-
.and_then(|map| map.get("properties"))
376-
.and_then(Value::as_str)
377-
.map(PropertyKind::from)
378-
.unwrap_or_default(),
379-
}))
380-
}
381-
382-
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
383-
match node.kind() {
384-
AstKind::BindingIdentifier(ident) => {
385-
self.handle_binding_identifier(ident, node, ctx);
386-
}
387-
AstKind::IdentifierName(ident) => {
388-
self.handle_identifier_name(ident, node, ctx);
389-
}
390-
AstKind::PrivateIdentifier(ident) => {
391-
self.handle_private_identifier(ident, node, ctx);
392-
}
393-
_ => {}
394-
}
395-
}
396-
}
397-
398395
#[test]
399396
fn test() {
400397
use crate::tester::Tester;

0 commit comments

Comments
 (0)