@@ -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+
61207impl 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]
399396fn test ( ) {
400397 use crate :: tester:: Tester ;
0 commit comments