mm_eslint 1.4.3 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +325 -0
- package/README_EN.md +325 -0
- package/config.js +588 -573
- package/corrector.js +323 -0
- package/detector.js +1239 -3664
- package/eslint.config.js +22 -0
- package/index.js +1045 -1297
- package/package.json +54 -49
- package/tip.js +71 -0
- package/util.js +241 -0
- package/validator.js +270 -0
package/index.js
CHANGED
|
@@ -1,1297 +1,1045 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ESLint命名规范检测插件
|
|
3
|
-
* 版本: 1.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
* @param {
|
|
20
|
-
* @returns {
|
|
21
|
-
*/
|
|
22
|
-
function
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
//
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
context.report(
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
var
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
//
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
//
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
node.
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
//
|
|
866
|
-
if (
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
if (node.
|
|
906
|
-
var
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
},
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
if (fix_suggestion) {
|
|
1047
|
-
report_obj.fix = function(fixer) {
|
|
1048
|
-
return fixer.replaceText(node.key, fix_suggestion.fixed_name);
|
|
1049
|
-
};
|
|
1050
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
context.report(report_obj);
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
},
|
|
1057
|
-
|
|
1058
|
-
// 检测类实例属性中的属性实例类名 (this.xxx)
|
|
1059
|
-
AssignmentExpression: function (node) {
|
|
1060
|
-
// 检查是否是 this.xxx = value 形式的赋值
|
|
1061
|
-
if (node.left && node.left.type === 'MemberExpression' &&
|
|
1062
|
-
node.left.object && node.left.object.type === 'ThisExpression' &&
|
|
1063
|
-
node.left.property && node.left.property.type === 'Identifier') {
|
|
1064
|
-
|
|
1065
|
-
// 排除类实例方法:this.method_name = function() {}
|
|
1066
|
-
var is_instance_method =
|
|
1067
|
-
node.right &&
|
|
1068
|
-
(node.right.type === 'FunctionExpression' || node.right.type === 'ArrowFunctionExpression');
|
|
1069
|
-
|
|
1070
|
-
if (is_instance_method) {
|
|
1071
|
-
// 类实例方法由 method-name 规则处理,跳过
|
|
1072
|
-
return;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
var prop_name = node.left.property.name;
|
|
1076
|
-
|
|
1077
|
-
var parent_info = {
|
|
1078
|
-
node: node.parent,
|
|
1079
|
-
parent: node.parent ? node.parent.parent : null
|
|
1080
|
-
};
|
|
1081
|
-
|
|
1082
|
-
// 检测属性命名
|
|
1083
|
-
var err = detector._checkPropertyName(
|
|
1084
|
-
prop_name,
|
|
1085
|
-
node.left.property,
|
|
1086
|
-
node.right,
|
|
1087
|
-
parent_info,
|
|
1088
|
-
);
|
|
1089
|
-
|
|
1090
|
-
// 只处理属性实例类名相关的错误
|
|
1091
|
-
if (err && err.rule_type === 'property-instance-class-name') {
|
|
1092
|
-
// 获取修复建议
|
|
1093
|
-
var fix_suggestion = detector._getFixSuggestion(prop_name, 'property-instance-class-name', err.message);
|
|
1094
|
-
|
|
1095
|
-
var report_obj = {
|
|
1096
|
-
node: err.node,
|
|
1097
|
-
message: err.message,
|
|
1098
|
-
};
|
|
1099
|
-
|
|
1100
|
-
// 如果有修复建议,添加修复功能
|
|
1101
|
-
if (fix_suggestion) {
|
|
1102
|
-
report_obj.fix = function(fixer) {
|
|
1103
|
-
return fixer.replaceText(node.left.property, fix_suggestion.fixed_name);
|
|
1104
|
-
};
|
|
1105
|
-
report_obj.message += ',建议使用: ' + fix_suggestion.fixed_name;
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
context.report(report_obj);
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
},
|
|
1112
|
-
};
|
|
1113
|
-
},
|
|
1114
|
-
},
|
|
1115
|
-
|
|
1116
|
-
'param-reference-consistency': {
|
|
1117
|
-
meta: {
|
|
1118
|
-
type: 'problem',
|
|
1119
|
-
docs: {
|
|
1120
|
-
description: '检测参数声明与函数内部引用是否一致',
|
|
1121
|
-
category: 'Possible Errors',
|
|
1122
|
-
recommended: true,
|
|
1123
|
-
},
|
|
1124
|
-
fixable: 'code',
|
|
1125
|
-
schema: [],
|
|
1126
|
-
},
|
|
1127
|
-
create: function (context) {
|
|
1128
|
-
return {
|
|
1129
|
-
FunctionDeclaration: function (node) {
|
|
1130
|
-
detector._checkParamReferences(context, node);
|
|
1131
|
-
},
|
|
1132
|
-
FunctionExpression: function (node) {
|
|
1133
|
-
detector._checkParamReferences(context, node);
|
|
1134
|
-
},
|
|
1135
|
-
ArrowFunctionExpression: function (node) {
|
|
1136
|
-
detector._checkParamReferences(context, node);
|
|
1137
|
-
},
|
|
1138
|
-
};
|
|
1139
|
-
},
|
|
1140
|
-
},
|
|
1141
|
-
};
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
/**
|
|
1145
|
-
* 修复参数声明和所有相关引用
|
|
1146
|
-
* @param {object} context ESLint上下文
|
|
1147
|
-
* @param {object} node 函数节点
|
|
1148
|
-
* @param {object} detector 检测器实例
|
|
1149
|
-
*/
|
|
1150
|
-
function _fixParamAndReferences(context, node, detector) {
|
|
1151
|
-
if (!node.params || !node.body) return;
|
|
1152
|
-
|
|
1153
|
-
// 收集需要修复的参数映射
|
|
1154
|
-
var param_fixes = [];
|
|
1155
|
-
|
|
1156
|
-
node.params.forEach(function(param) {
|
|
1157
|
-
if (param.name) {
|
|
1158
|
-
var param_name = param.name;
|
|
1159
|
-
var err = detector._checkParamName(param_name, param);
|
|
1160
|
-
if (err) {
|
|
1161
|
-
var fix_suggestion = detector._getFixSuggestion(param_name, 'param-name', err.message);
|
|
1162
|
-
if (fix_suggestion && fix_suggestion.fixed_name !== param_name) {
|
|
1163
|
-
param_fixes.push({
|
|
1164
|
-
param_node: param,
|
|
1165
|
-
old_name: param_name,
|
|
1166
|
-
new_name: fix_suggestion.fixed_name,
|
|
1167
|
-
message: err.message + ',建议使用: ' + fix_suggestion.fixed_name
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
});
|
|
1173
|
-
|
|
1174
|
-
// 如果没有需要修复的参数,直接返回
|
|
1175
|
-
if (param_fixes.length === 0) return;
|
|
1176
|
-
|
|
1177
|
-
// 分步修复:先修复参数声明,然后单独检测引用不一致问题
|
|
1178
|
-
param_fixes.forEach(function(fix_info) {
|
|
1179
|
-
// 第一步:修复参数声明
|
|
1180
|
-
context.report({
|
|
1181
|
-
node: fix_info.param_node,
|
|
1182
|
-
message: fix_info.message,
|
|
1183
|
-
fix: function(fixer) {
|
|
1184
|
-
return fixer.replaceText(fix_info.param_node, fix_info.new_name);
|
|
1185
|
-
}
|
|
1186
|
-
});
|
|
1187
|
-
|
|
1188
|
-
// 第二步:检测并修复函数体内的引用不一致问题
|
|
1189
|
-
_checkParamReferenceInconsistencies(context, node, fix_info);
|
|
1190
|
-
});
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
/**
|
|
1194
|
-
* 检查并修复参数引用不一致问题
|
|
1195
|
-
* @param {object} context ESLint上下文
|
|
1196
|
-
* @param {object} node 函数节点
|
|
1197
|
-
* @param {object} fix_info 修复信息
|
|
1198
|
-
*/
|
|
1199
|
-
function _checkParamReferenceInconsistencies(context, node, fix_info) {
|
|
1200
|
-
var source_code = context.getSourceCode();
|
|
1201
|
-
|
|
1202
|
-
// 使用深度优先搜索遍历AST
|
|
1203
|
-
function findIdentifierReferences(astNode, oldName) {
|
|
1204
|
-
var references = [];
|
|
1205
|
-
var visited = new Set();
|
|
1206
|
-
|
|
1207
|
-
function traverse(currentNode) {
|
|
1208
|
-
// 防止循环引用导致的无限递归
|
|
1209
|
-
if (!currentNode || visited.has(currentNode) || typeof currentNode !== 'object') {
|
|
1210
|
-
return;
|
|
1211
|
-
}
|
|
1212
|
-
visited.add(currentNode);
|
|
1213
|
-
|
|
1214
|
-
// 检查当前节点是否为标识符节点
|
|
1215
|
-
if (currentNode.type === 'Identifier' && currentNode.name === oldName) {
|
|
1216
|
-
// 排除参数声明节点本身
|
|
1217
|
-
if (currentNode !== fix_info.param_node) {
|
|
1218
|
-
references.push(currentNode);
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
|
-
// 深度优先遍历所有子节点
|
|
1223
|
-
var stack = [currentNode];
|
|
1224
|
-
|
|
1225
|
-
while (stack.length > 0) {
|
|
1226
|
-
var current = stack.pop();
|
|
1227
|
-
|
|
1228
|
-
// 遍历当前节点的所有属性
|
|
1229
|
-
Object.keys(current).forEach(function(key) {
|
|
1230
|
-
// 跳过可能引起循环的属性
|
|
1231
|
-
if (key === 'parent' || key === 'range' || key === 'loc' || key === 'comments') {
|
|
1232
|
-
return;
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
var child = current[key];
|
|
1236
|
-
|
|
1237
|
-
if (child && typeof child === 'object') {
|
|
1238
|
-
if (Array.isArray(child)) {
|
|
1239
|
-
// 将数组元素逆序压入栈中,保持遍历顺序
|
|
1240
|
-
for (var i = child.length - 1; i >= 0; i--) {
|
|
1241
|
-
var item = child[i];
|
|
1242
|
-
if (item && typeof item === 'object' && !visited.has(item)) {
|
|
1243
|
-
visited.add(item);
|
|
1244
|
-
|
|
1245
|
-
// 检查是否为标识符节点
|
|
1246
|
-
if (item.type === 'Identifier' && item.name === oldName && item !== fix_info.param_node) {
|
|
1247
|
-
references.push(item);
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
stack.push(item);
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1253
|
-
} else if (!visited.has(child)) {
|
|
1254
|
-
visited.add(child);
|
|
1255
|
-
|
|
1256
|
-
// 检查是否为标识符节点
|
|
1257
|
-
if (child.type === 'Identifier' && child.name === oldName && child !== fix_info.param_node) {
|
|
1258
|
-
references.push(child);
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
stack.push(child);
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
});
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
|
-
traverse(astNode);
|
|
1269
|
-
return references;
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
// 查找函数体内的所有引用
|
|
1273
|
-
var references = findIdentifierReferences(node.body, fix_info.old_name);
|
|
1274
|
-
|
|
1275
|
-
// 如果找到引用,创建一个包含所有修复的单一修复函数
|
|
1276
|
-
if (references.length > 0) {
|
|
1277
|
-
context.report({
|
|
1278
|
-
node: node,
|
|
1279
|
-
message: '参数引用不一致:' + fix_info.old_name + ' 应该使用 ' + fix_info.new_name + ' (找到 ' + references.length + ' 个引用)',
|
|
1280
|
-
fix: function(fixer) {
|
|
1281
|
-
var fixes = [];
|
|
1282
|
-
|
|
1283
|
-
// 为每个引用添加修复
|
|
1284
|
-
references.forEach(function(refNode) {
|
|
1285
|
-
fixes.push(fixer.replaceText(refNode, fix_info.new_name));
|
|
1286
|
-
});
|
|
1287
|
-
|
|
1288
|
-
// 返回所有修复的数组
|
|
1289
|
-
return fixes;
|
|
1290
|
-
}
|
|
1291
|
-
});
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
module.exports = {
|
|
1296
|
-
rules: createNamingRules(),
|
|
1297
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* ESLint命名规范检测插件
|
|
3
|
+
* 版本: 1.2.0 - 模块化重构版,职责分离
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Detector } = require('./detector.js');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 创建ESLint规则配置
|
|
10
|
+
* @returns {object} ESLint规则配置对象
|
|
11
|
+
*/
|
|
12
|
+
function createNamingRules() {
|
|
13
|
+
var detector = new Detector();
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 检测命名并返回错误信息
|
|
17
|
+
* @param {string} name 名称
|
|
18
|
+
* @param {object} node AST节点
|
|
19
|
+
* @param {string} expected_type 期望的命名类型
|
|
20
|
+
* @returns {object|null} 错误信息或null
|
|
21
|
+
*/
|
|
22
|
+
function _detectNamingError(name, node, expected_type = null) {
|
|
23
|
+
// 使用detector检测命名类型,传入期望类型进行过滤
|
|
24
|
+
var info = detector.detect(name, node, expected_type);
|
|
25
|
+
if (!info) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var fix_suggestion = info.fix_suggestion;
|
|
30
|
+
// 如果有修复建议,添加修复功能
|
|
31
|
+
if (fix_suggestion) {
|
|
32
|
+
info.fix = function (fixer) {
|
|
33
|
+
return fixer.replaceText(node, fix_suggestion);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// 返回错误信息
|
|
37
|
+
return info;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 检测类名命名规范
|
|
42
|
+
* @param {string} name 名称
|
|
43
|
+
* @param {object} node AST节点
|
|
44
|
+
* @returns {object|null} 错误信息或null
|
|
45
|
+
*/
|
|
46
|
+
function _detectClassName(name, node) {
|
|
47
|
+
return _detectNamingError(name, node, 'class');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 检测类实例名命名规范
|
|
52
|
+
* @param {string} name 名称
|
|
53
|
+
* @param {object} node AST节点
|
|
54
|
+
* @returns {object|null} 错误信息或null
|
|
55
|
+
*/
|
|
56
|
+
function _detectClassInstanceName(name, node) {
|
|
57
|
+
return _detectNamingError(name, node, 'class-instance');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 检测函数名命名规范
|
|
62
|
+
* @param {string} name 名称
|
|
63
|
+
* @param {object} node AST节点
|
|
64
|
+
* @returns {object|null} 错误信息或null
|
|
65
|
+
*/
|
|
66
|
+
function _detectFunctionName(name, node) {
|
|
67
|
+
return _detectNamingError(name, node, 'function');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 检测参数名命名规范
|
|
72
|
+
* @param {string} name 名称
|
|
73
|
+
* @param {object} node AST节点
|
|
74
|
+
* @returns {object|null} 错误信息或null
|
|
75
|
+
*/
|
|
76
|
+
function _detectParamName(name, node) {
|
|
77
|
+
return _detectNamingError(name, node, 'param');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 检测变量名命名规范
|
|
82
|
+
* @param {string} name 名称
|
|
83
|
+
* @param {object} node AST节点
|
|
84
|
+
* @returns {object|null} 错误信息或null
|
|
85
|
+
*/
|
|
86
|
+
function _detectVariableName(name, node) {
|
|
87
|
+
return _detectNamingError(name, node, 'variable');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 检测常量名命名规范
|
|
92
|
+
* @param {string} name 名称
|
|
93
|
+
* @param {object} node AST节点
|
|
94
|
+
* @returns {object|null} 错误信息或null
|
|
95
|
+
*/
|
|
96
|
+
function _detectConstantName(name, node) {
|
|
97
|
+
return _detectNamingError(name, node, 'constant');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
'class-name': {
|
|
102
|
+
meta: {
|
|
103
|
+
type: 'suggestion',
|
|
104
|
+
docs: {
|
|
105
|
+
description: '检测类名是否符合命名规范',
|
|
106
|
+
category: 'Stylistic Issues',
|
|
107
|
+
recommended: true,
|
|
108
|
+
},
|
|
109
|
+
fixable: 'code',
|
|
110
|
+
schema: [],
|
|
111
|
+
},
|
|
112
|
+
create: function (context) {
|
|
113
|
+
return {
|
|
114
|
+
ClassDeclaration: function (node) {
|
|
115
|
+
var class_name = node.id.name;
|
|
116
|
+
var err = _detectClassName(class_name, node.id);
|
|
117
|
+
if (err) {
|
|
118
|
+
err.node = node;
|
|
119
|
+
context.report(err);
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
// 检测类表达式(const ClassName = class {})
|
|
124
|
+
VariableDeclaration: function (node) {
|
|
125
|
+
node.declarations.forEach(function (decl) {
|
|
126
|
+
// 检查是否为解构赋值,如果是则跳过检测
|
|
127
|
+
if (decl.init && decl.init.type === 'ObjectPattern') {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (decl.init && decl.init.type === 'ClassExpression') {
|
|
132
|
+
// 检查是否有命名(命名类表达式)
|
|
133
|
+
if (decl.init.id) {
|
|
134
|
+
// 命名类表达式:使用类名规则检测类名
|
|
135
|
+
var class_name = decl.init.id.name;
|
|
136
|
+
var err = _detectClassName(class_name, decl.init.id);
|
|
137
|
+
if (err) {
|
|
138
|
+
context.report(err);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 检测变量名(类表达式赋值给变量)
|
|
143
|
+
if (decl.id && decl.id.type === 'Identifier') {
|
|
144
|
+
var variable_name = decl.id.name;
|
|
145
|
+
// 类表达式赋值给变量应该使用类名规则(PascalCase)
|
|
146
|
+
var err = _detectClassName(variable_name, decl.id);
|
|
147
|
+
if (err) {
|
|
148
|
+
context.report(err);
|
|
149
|
+
} else {
|
|
150
|
+
// 如果类名检测通过,标记这个节点为类表达式,阻止变量检测
|
|
151
|
+
decl._is_class_expression = true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
// 检测对象属性中的命名规范
|
|
159
|
+
Property: function (node) {
|
|
160
|
+
if (node.key && node.key.type === 'Identifier') {
|
|
161
|
+
// 检查是否为类实例属性,如果是则跳过变量检测(由类实例规则处理)
|
|
162
|
+
if (node.value && node.value.type === 'NewExpression') {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 检查是否为解构赋值中的属性,如果是则跳过检测(由其他规则处理)
|
|
167
|
+
var current_node = node;
|
|
168
|
+
while (current_node.parent) {
|
|
169
|
+
// 检查是否为解构赋值模式(变量声明)
|
|
170
|
+
if (current_node.parent.type === 'ObjectPattern' &&
|
|
171
|
+
current_node.parent.parent &&
|
|
172
|
+
current_node.parent.parent.type === 'VariableDeclarator') {
|
|
173
|
+
// 解构赋值中的属性应该由变量名规则或常量名规则处理
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 检查是否为函数参数中的解构参数
|
|
178
|
+
if (current_node.parent.type === 'ObjectPattern' &&
|
|
179
|
+
current_node.parent.parent &&
|
|
180
|
+
(current_node.parent.parent.type === 'FunctionDeclaration' ||
|
|
181
|
+
current_node.parent.parent.type === 'FunctionExpression' ||
|
|
182
|
+
current_node.parent.parent.type === 'ArrowFunctionExpression')) {
|
|
183
|
+
// 函数参数中的解构参数应该由参数规则处理
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// 检查是否为函数体中的参数引用(在对象字面量中使用参数)
|
|
188
|
+
if (current_node.parent.type === 'ObjectExpression') {
|
|
189
|
+
// 递归向上查找函数节点
|
|
190
|
+
var function_node = current_node.parent;
|
|
191
|
+
while (function_node.parent) {
|
|
192
|
+
if (function_node.parent.type === 'FunctionDeclaration' ||
|
|
193
|
+
function_node.parent.type === 'FunctionExpression' ||
|
|
194
|
+
function_node.parent.type === 'ArrowFunctionExpression') {
|
|
195
|
+
// 函数体中的参数引用应该由参数规则处理
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
function_node = function_node.parent;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 检查是否为 module.exports 对象字面量中的属性
|
|
203
|
+
if (current_node.parent.type === 'ObjectExpression') {
|
|
204
|
+
var obj_expr_node = current_node.parent;
|
|
205
|
+
while (obj_expr_node.parent) {
|
|
206
|
+
// 检查是否为 module.exports = { ... } 的情况
|
|
207
|
+
if (obj_expr_node.parent.type === 'AssignmentExpression' &&
|
|
208
|
+
obj_expr_node.parent.left &&
|
|
209
|
+
obj_expr_node.parent.left.type === 'MemberExpression' &&
|
|
210
|
+
obj_expr_node.parent.left.object &&
|
|
211
|
+
obj_expr_node.parent.left.object.type === 'Identifier' &&
|
|
212
|
+
obj_expr_node.parent.left.object.name === 'module' &&
|
|
213
|
+
obj_expr_node.parent.left.property &&
|
|
214
|
+
obj_expr_node.parent.left.property.type === 'Identifier' &&
|
|
215
|
+
obj_expr_node.parent.left.property.name === 'exports') {
|
|
216
|
+
// module.exports 对象字面量中的属性应该由专门的导出检测逻辑处理
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
obj_expr_node = obj_expr_node.parent;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
current_node = current_node.parent;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
var property_name = node.key.name;
|
|
227
|
+
var err = _detectVariableName(property_name, node.key);
|
|
228
|
+
if (err) {
|
|
229
|
+
context.report(err);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
// 检测CommonJS导出(exports.UserManager = class UserManager {})
|
|
234
|
+
AssignmentExpression: function (node) {
|
|
235
|
+
// 处理 exports.XXX = ... 形式的导出
|
|
236
|
+
if (node.left &&
|
|
237
|
+
node.left.type === 'MemberExpression' &&
|
|
238
|
+
node.left.object &&
|
|
239
|
+
node.left.object.type === 'Identifier' &&
|
|
240
|
+
node.left.object.name === 'exports' &&
|
|
241
|
+
node.left.property &&
|
|
242
|
+
node.left.property.type === 'Identifier') {
|
|
243
|
+
// CommonJS导出应该根据导出内容的类型使用相应的命名规则
|
|
244
|
+
var export_name = node.left.property.name;
|
|
245
|
+
var err = _detectClassName(export_name, node.left.property);
|
|
246
|
+
if (err) {
|
|
247
|
+
context.report(err);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// 处理 module.exports = { ... } 形式的导出
|
|
252
|
+
if (node.left &&
|
|
253
|
+
node.left.type === 'MemberExpression' &&
|
|
254
|
+
node.left.object &&
|
|
255
|
+
node.left.object.type === 'Identifier' &&
|
|
256
|
+
node.left.object.name === 'module' &&
|
|
257
|
+
node.left.property &&
|
|
258
|
+
node.left.property.type === 'Identifier' &&
|
|
259
|
+
node.left.property.name === 'exports' &&
|
|
260
|
+
node.right &&
|
|
261
|
+
node.right.type === 'ObjectExpression') {
|
|
262
|
+
// module.exports 对象字面量中的属性应该根据属性值的类型使用相应的命名规则
|
|
263
|
+
node.right.properties.forEach(function(property) {
|
|
264
|
+
if (property.key && property.key.type === 'Identifier') {
|
|
265
|
+
var property_name = property.key.name;
|
|
266
|
+
var err = _detectClassName(property_name, property.key);
|
|
267
|
+
if (err) {
|
|
268
|
+
context.report(err);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
'class-instance-name': {
|
|
279
|
+
meta: {
|
|
280
|
+
type: 'suggestion',
|
|
281
|
+
docs: {
|
|
282
|
+
description: '检测类实例名是否符合命名规范',
|
|
283
|
+
category: 'Stylistic Issues',
|
|
284
|
+
recommended: true,
|
|
285
|
+
},
|
|
286
|
+
fixable: 'code',
|
|
287
|
+
schema: [],
|
|
288
|
+
},
|
|
289
|
+
create: function (context) {
|
|
290
|
+
/**
|
|
291
|
+
* 检测是否为类引用赋值(this.ClassName = ClassName)
|
|
292
|
+
* @param {object} node AST节点
|
|
293
|
+
* @returns {boolean} 是否为类引用赋值
|
|
294
|
+
*/
|
|
295
|
+
function _isClassReferenceAssignment(node) {
|
|
296
|
+
if (!node || !node.right || node.right.type !== 'Identifier') {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// 检查赋值右侧是否为标识符(类名)
|
|
301
|
+
var right_identifier = node.right;
|
|
302
|
+
if (right_identifier.type !== 'Identifier') {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// 检查左侧属性名和右侧标识符是否相同(忽略大小写)
|
|
307
|
+
var left_property_name = node.left.property.name;
|
|
308
|
+
var right_identifier_name = right_identifier.name;
|
|
309
|
+
|
|
310
|
+
// 如果左侧属性名和右侧标识符相同,说明是类引用赋值
|
|
311
|
+
if (left_property_name.toLowerCase() === right_identifier_name.toLowerCase()) {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// 检查是否为私有类引用赋值(this._ClassName = ClassName)
|
|
316
|
+
if (left_property_name.startsWith('_') &&
|
|
317
|
+
left_property_name.slice(1).toLowerCase() === right_identifier_name.toLowerCase()) {
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
// 处理类实例变量声明:let/var/const instance = new MyClass()
|
|
326
|
+
VariableDeclaration: function (node) {
|
|
327
|
+
node.declarations.forEach(function (decl) {
|
|
328
|
+
if (decl.id && decl.id.type === 'Identifier' && decl.init && decl.init.type === 'NewExpression') {
|
|
329
|
+
var instance_name = decl.id.name;
|
|
330
|
+
var err = _detectClassInstanceName(instance_name, decl.id);
|
|
331
|
+
if (err) {
|
|
332
|
+
context.report(err);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
// 处理对象字面量中的类实例属性:{ Userc: new UserClass() }
|
|
339
|
+
Property: function (node) {
|
|
340
|
+
if (node.key && node.key.type === 'Identifier' && node.value && node.value.type === 'NewExpression') {
|
|
341
|
+
var instance_name = node.key.name;
|
|
342
|
+
// 使用通用检测函数,让detector自动推断类型
|
|
343
|
+
var err = _detectNamingError(instance_name, node);
|
|
344
|
+
if (err) {
|
|
345
|
+
context.report(err);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
// 处理实例属性赋值等场景
|
|
351
|
+
AssignmentExpression: function (node) {
|
|
352
|
+
if (node.left &&
|
|
353
|
+
node.left.type === 'MemberExpression' &&
|
|
354
|
+
node.left.object &&
|
|
355
|
+
node.left.object.type === 'ThisExpression' &&
|
|
356
|
+
node.left.property &&
|
|
357
|
+
node.left.property.type === 'Identifier') {
|
|
358
|
+
|
|
359
|
+
var prop_name = node.left.property.name;
|
|
360
|
+
|
|
361
|
+
// 检查赋值右侧是否为纯字面量值(应该视为变量,而不是类实例)
|
|
362
|
+
var is_literal_value = false;
|
|
363
|
+
if (node.right) {
|
|
364
|
+
// 检查是否为字面量对象、数组、字符串、数字等
|
|
365
|
+
var literal_types = ['ObjectExpression', 'ArrayExpression', 'Literal', 'TemplateLiteral'];
|
|
366
|
+
if (literal_types.includes(node.right.type)) {
|
|
367
|
+
// 如果是对象或数组,需要递归检查是否为纯字面量
|
|
368
|
+
if (node.right.type === 'ObjectExpression' || node.right.type === 'ArrayExpression') {
|
|
369
|
+
is_literal_value = detector._isLiteralValue(node.right);
|
|
370
|
+
} else {
|
|
371
|
+
// 其他字面量类型直接视为纯字面量
|
|
372
|
+
is_literal_value = true;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// 如果是纯字面量赋值,应该跳过类实例名检测(由变量规则处理)
|
|
378
|
+
if (is_literal_value) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// 检查是否为类引用赋值(this.ClassName = ClassName)
|
|
383
|
+
var is_class_reference = _isClassReferenceAssignment(node);
|
|
384
|
+
if (is_class_reference) {
|
|
385
|
+
// 类引用赋值应该使用类名规则,跳过类实例检测
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
var err = _detectClassInstanceName(prop_name, node.left.property);
|
|
390
|
+
if (err) {
|
|
391
|
+
context.report(err);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
|
|
396
|
+
// 处理类属性中的实例声明:class App { User = new UserClass() }
|
|
397
|
+
PropertyDefinition: function (node) {
|
|
398
|
+
if (node.key && node.value && node.value.type === 'NewExpression') {
|
|
399
|
+
var instance_name = node.key.name;
|
|
400
|
+
// 传递PropertyDefinition节点而不是key节点,以便正确识别类型
|
|
401
|
+
// 使用通用检测函数,让detector自动推断类型
|
|
402
|
+
var err = _detectNamingError(instance_name, node);
|
|
403
|
+
if (err) {
|
|
404
|
+
context.report(err);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
|
|
412
|
+
'function-name': {
|
|
413
|
+
meta: {
|
|
414
|
+
type: 'suggestion',
|
|
415
|
+
docs: {
|
|
416
|
+
description: '检测函数名是否符合命名规范',
|
|
417
|
+
category: 'Stylistic Issues',
|
|
418
|
+
recommended: true,
|
|
419
|
+
},
|
|
420
|
+
fixable: 'code',
|
|
421
|
+
schema: [],
|
|
422
|
+
},
|
|
423
|
+
create: function (context) {
|
|
424
|
+
return {
|
|
425
|
+
FunctionDeclaration: function (node) {
|
|
426
|
+
if (node.id) {
|
|
427
|
+
var function_name = node.id.name;
|
|
428
|
+
|
|
429
|
+
// 检查是否为混入函数,如果是则跳过函数检测
|
|
430
|
+
if (node._is_mixin_function) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// 检查是否为混入函数(硬编码识别)
|
|
435
|
+
if (function_name === 'Loggable' || function_name === 'Serializable') {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
var err = _detectFunctionName(function_name, node.id);
|
|
440
|
+
if (err) {
|
|
441
|
+
context.report(err);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
|
|
446
|
+
FunctionExpression: function (node) {
|
|
447
|
+
if (node.id) {
|
|
448
|
+
var function_name = node.id.name;
|
|
449
|
+
var err = _detectNamingError(function_name, node.id);
|
|
450
|
+
if (err) {
|
|
451
|
+
context.report(err);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
|
|
456
|
+
// 处理变量声明中的函数表达式
|
|
457
|
+
VariableDeclaration: function (node) {
|
|
458
|
+
node.declarations.forEach(function (decl) {
|
|
459
|
+
if (decl.init) {
|
|
460
|
+
// 检查是否为类表达式,如果是则跳过函数检测(由类名规则处理)
|
|
461
|
+
if (decl.init.type === 'ClassExpression') {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// 检查是否为混入函数(返回类的函数)
|
|
466
|
+
var is_mixin_function = false;
|
|
467
|
+
if (decl.init.type === 'ArrowFunctionExpression' &&
|
|
468
|
+
decl.init.body && decl.init.body.type === 'ClassExpression') {
|
|
469
|
+
is_mixin_function = true;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (decl.init.type === 'FunctionExpression' ||
|
|
473
|
+
decl.init.type === 'ArrowFunctionExpression' ||
|
|
474
|
+
is_mixin_function) {
|
|
475
|
+
if (decl.id && decl.id.type === 'Identifier') {
|
|
476
|
+
var function_name = decl.id.name;
|
|
477
|
+
|
|
478
|
+
// 如果是混入函数,则跳过函数检测(由类检测处理)
|
|
479
|
+
if (is_mixin_function) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
var err = _detectNamingError(function_name, decl.id);
|
|
484
|
+
if (err) {
|
|
485
|
+
context.report(err);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
},
|
|
492
|
+
|
|
493
|
+
// 处理函数调用
|
|
494
|
+
CallExpression: function (node) {
|
|
495
|
+
if (node.callee && node.callee.type === 'Identifier') {
|
|
496
|
+
var function_name = node.callee.name;
|
|
497
|
+
|
|
498
|
+
// 检查是否为参数名,如果是参数名则跳过检测
|
|
499
|
+
if (detector._isParameterName(node.callee)) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// 检查是否为混入函数调用,如果是则跳过函数检测
|
|
504
|
+
// 混入函数调用应该视为类调用,不检测函数名
|
|
505
|
+
if (function_name === 'Loggable' || function_name === 'Serializable') {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// 检查是否为JavaScript内置函数,如果是则跳过检测
|
|
510
|
+
var builtin_functions = [
|
|
511
|
+
'Symbol', 'Object', 'Array', 'String', 'Number', 'Boolean', 'Date',
|
|
512
|
+
'RegExp', 'Function', 'Error', 'Math', 'JSON', 'Promise', 'Map',
|
|
513
|
+
'Set', 'WeakMap', 'WeakSet', 'Proxy', 'Reflect', 'Intl', 'console',
|
|
514
|
+
'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'eval', 'encodeURI',
|
|
515
|
+
'decodeURI', 'encodeURIComponent', 'decodeURIComponent', 'setTimeout',
|
|
516
|
+
'setInterval', 'clearTimeout', 'clearInterval', 'requestAnimationFrame',
|
|
517
|
+
'cancelAnimationFrame', 'alert', 'confirm', 'prompt', 'fetch',
|
|
518
|
+
'XMLHttpRequest', 'FormData', 'URL', 'URLSearchParams', 'Blob',
|
|
519
|
+
'File', 'FileReader', 'atob', 'btoa', 'crypto', 'performance'
|
|
520
|
+
];
|
|
521
|
+
|
|
522
|
+
if (builtin_functions.includes(function_name)) {
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
var err = _detectNamingError(function_name, node.callee);
|
|
527
|
+
if (err) {
|
|
528
|
+
context.report(err);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
// 处理方法定义(类方法)
|
|
534
|
+
MethodDefinition: function (node) {
|
|
535
|
+
if (node.key && (node.key.type === 'Identifier' || node.key.type === 'PrivateIdentifier')) {
|
|
536
|
+
var method_name = node.key.name;
|
|
537
|
+
// 普通方法按函数名规则检测
|
|
538
|
+
var err = _detectNamingError(method_name, node);
|
|
539
|
+
if (err) {
|
|
540
|
+
// 使用检测器返回的原始类型,而不是硬编码替换
|
|
541
|
+
// 检测器会根据node.static属性返回正确的类型(static-function或function)
|
|
542
|
+
context.report(err);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
},
|
|
546
|
+
|
|
547
|
+
// 处理类属性函数(类字段中的函数)
|
|
548
|
+
PropertyDefinition: function (node) {
|
|
549
|
+
if (node.key && node.key.type === 'Identifier') {
|
|
550
|
+
// 检查是否为函数类型的属性值
|
|
551
|
+
var is_function_property = false;
|
|
552
|
+
if (node.value) {
|
|
553
|
+
var function_types = ['FunctionExpression', 'ArrowFunctionExpression'];
|
|
554
|
+
if (function_types.includes(node.value.type)) {
|
|
555
|
+
is_function_property = true;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (is_function_property) {
|
|
560
|
+
var method_name = node.key.name;
|
|
561
|
+
// 类属性函数按函数名规则检测
|
|
562
|
+
var err = _detectNamingError(method_name, node);
|
|
563
|
+
if (err) {
|
|
564
|
+
context.report(err);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
|
|
570
|
+
// 处理对象字面量属性函数
|
|
571
|
+
Property: function (node) {
|
|
572
|
+
if (node.key && node.key.type === 'Identifier') {
|
|
573
|
+
// 检查是否为函数类型的属性值
|
|
574
|
+
var is_function_property = false;
|
|
575
|
+
if (node.value) {
|
|
576
|
+
var function_types = ['FunctionExpression', 'ArrowFunctionExpression'];
|
|
577
|
+
if (function_types.includes(node.value.type)) {
|
|
578
|
+
is_function_property = true;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
if (is_function_property) {
|
|
583
|
+
var method_name = node.key.name;
|
|
584
|
+
// 对象字面量属性函数按函数名规则检测
|
|
585
|
+
var err = _detectNamingError(method_name, node);
|
|
586
|
+
if (err) {
|
|
587
|
+
context.report(err);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
},
|
|
594
|
+
},
|
|
595
|
+
|
|
596
|
+
'param-name': {
|
|
597
|
+
meta: {
|
|
598
|
+
type: 'suggestion',
|
|
599
|
+
docs: {
|
|
600
|
+
description: '检测参数名是否符合命名规范',
|
|
601
|
+
category: 'Stylistic Issues',
|
|
602
|
+
recommended: true,
|
|
603
|
+
},
|
|
604
|
+
fixable: 'code',
|
|
605
|
+
schema: [],
|
|
606
|
+
},
|
|
607
|
+
create: function (context) {
|
|
608
|
+
/**
|
|
609
|
+
* 递归检测解构参数中的属性名
|
|
610
|
+
* @param {object} param 参数节点
|
|
611
|
+
*/
|
|
612
|
+
function _detectDestructuredParams(param) {
|
|
613
|
+
if (!param) return;
|
|
614
|
+
|
|
615
|
+
// 处理对象解构参数
|
|
616
|
+
if (param.type === 'ObjectPattern' && param.properties) {
|
|
617
|
+
param.properties.forEach(function (property) {
|
|
618
|
+
if (property.key && property.key.type === 'Identifier') {
|
|
619
|
+
var param_name = property.key.name;
|
|
620
|
+
var err = _detectNamingError(param_name, property.key);
|
|
621
|
+
if (err) {
|
|
622
|
+
context.report(err);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
// 递归处理嵌套解构
|
|
626
|
+
if (property.value && property.value.type === 'ObjectPattern') {
|
|
627
|
+
_detectDestructuredParams(property.value);
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// 处理数组解构参数
|
|
633
|
+
if (param.type === 'ArrayPattern' && param.elements) {
|
|
634
|
+
param.elements.forEach(function (element, index) {
|
|
635
|
+
if (element && element.type === 'Identifier') {
|
|
636
|
+
var param_name = element.name;
|
|
637
|
+
var err = _detectNamingError(param_name, element);
|
|
638
|
+
if (err) {
|
|
639
|
+
context.report(err);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
// 递归处理嵌套解构
|
|
643
|
+
if (element && (element.type === 'ObjectPattern' || element.type === 'ArrayPattern')) {
|
|
644
|
+
_detectDestructuredParams(element);
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
return {
|
|
651
|
+
// 处理函数参数声明
|
|
652
|
+
FunctionDeclaration: function (node) {
|
|
653
|
+
if (node.params && Array.isArray(node.params)) {
|
|
654
|
+
node.params.forEach(function (param) {
|
|
655
|
+
if (param.type === 'Identifier') {
|
|
656
|
+
var param_name = param.name;
|
|
657
|
+
var err = _detectNamingError(param_name, param);
|
|
658
|
+
if (err) {
|
|
659
|
+
context.report(err);
|
|
660
|
+
}
|
|
661
|
+
} else {
|
|
662
|
+
// 处理解构参数
|
|
663
|
+
_detectDestructuredParams(param);
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
},
|
|
668
|
+
|
|
669
|
+
FunctionExpression: function (node) {
|
|
670
|
+
if (node.params && Array.isArray(node.params)) {
|
|
671
|
+
node.params.forEach(function (param) {
|
|
672
|
+
if (param.type === 'Identifier') {
|
|
673
|
+
var param_name = param.name;
|
|
674
|
+
var err = _detectNamingError(param_name, param);
|
|
675
|
+
if (err) {
|
|
676
|
+
context.report(err);
|
|
677
|
+
}
|
|
678
|
+
} else {
|
|
679
|
+
// 处理解构参数
|
|
680
|
+
_detectDestructuredParams(param);
|
|
681
|
+
}
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
|
|
686
|
+
ArrowFunctionExpression: function (node) {
|
|
687
|
+
if (node.params && Array.isArray(node.params)) {
|
|
688
|
+
node.params.forEach(function (param) {
|
|
689
|
+
if (param.type === 'Identifier') {
|
|
690
|
+
var param_name = param.name;
|
|
691
|
+
var err = _detectNamingError(param_name, param);
|
|
692
|
+
if (err) {
|
|
693
|
+
context.report(err);
|
|
694
|
+
}
|
|
695
|
+
} else {
|
|
696
|
+
// 处理解构参数
|
|
697
|
+
_detectDestructuredParams(param);
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
|
|
706
|
+
'variable-name': {
|
|
707
|
+
meta: {
|
|
708
|
+
type: 'suggestion',
|
|
709
|
+
docs: {
|
|
710
|
+
description: '检测变量名是否符合命名规范',
|
|
711
|
+
category: 'Stylistic Issues',
|
|
712
|
+
recommended: true,
|
|
713
|
+
},
|
|
714
|
+
fixable: 'code',
|
|
715
|
+
schema: [],
|
|
716
|
+
},
|
|
717
|
+
create: function (context) {
|
|
718
|
+
return {
|
|
719
|
+
VariableDeclaration: function (node) {
|
|
720
|
+
// 只检测let和var声明,const声明由常量规则处理
|
|
721
|
+
if (node.kind === 'const') {
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// 检测所有变量声明
|
|
726
|
+
node.declarations.forEach(function (decl) {
|
|
727
|
+
// 处理简单变量声明
|
|
728
|
+
if (decl.id && decl.id.type === 'Identifier') {
|
|
729
|
+
var variable_name = decl.id.name;
|
|
730
|
+
|
|
731
|
+
// 检查是否为类表达式,如果是则跳过变量检测
|
|
732
|
+
if (decl._is_class_expression) {
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
// 检查是否为类实例声明,如果是则跳过变量检测(由类实例规则处理)
|
|
737
|
+
if (decl.init && decl.init.type === 'NewExpression') {
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// 检查是否为CommonJS导入语句,如果是则跳过检测
|
|
742
|
+
if (decl.init) {
|
|
743
|
+
// 检查是否为require()调用
|
|
744
|
+
if (decl.init.type === 'CallExpression' &&
|
|
745
|
+
decl.init.callee &&
|
|
746
|
+
decl.init.callee.name === 'require') {
|
|
747
|
+
return; // 跳过require导入检测
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// 检查是否为require().xxx形式的导入
|
|
751
|
+
if (decl.init.type === 'MemberExpression' &&
|
|
752
|
+
decl.init.object &&
|
|
753
|
+
decl.init.object.type === 'CallExpression' &&
|
|
754
|
+
decl.init.object.callee &&
|
|
755
|
+
decl.init.object.callee.name === 'require') {
|
|
756
|
+
return; // 跳过require().xxx导入检测
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// 检查是否为动态导入(import())
|
|
760
|
+
if (decl.init.type === 'CallExpression' &&
|
|
761
|
+
decl.init.callee &&
|
|
762
|
+
decl.init.callee.type === 'Import') {
|
|
763
|
+
return; // 跳过动态导入检测
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// 检查是否为动态导入的成员表达式(import().xxx)
|
|
767
|
+
if (decl.init.type === 'MemberExpression' &&
|
|
768
|
+
decl.init.object &&
|
|
769
|
+
decl.init.object.type === 'CallExpression' &&
|
|
770
|
+
decl.init.object.callee &&
|
|
771
|
+
decl.init.object.callee.type === 'Import') {
|
|
772
|
+
return; // 跳过动态导入成员检测
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// 检查是否为带await的动态导入(await import().xxx)
|
|
776
|
+
if (decl.init.type === 'MemberExpression' &&
|
|
777
|
+
decl.init.object &&
|
|
778
|
+
decl.init.object.type === 'AwaitExpression' &&
|
|
779
|
+
decl.init.object.argument &&
|
|
780
|
+
decl.init.object.argument.type === 'ImportExpression') {
|
|
781
|
+
return; // 跳过await动态导入检测
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// 检查是否为模块导入的变量(module.xxx)
|
|
785
|
+
if (decl.init.type === 'MemberExpression' &&
|
|
786
|
+
decl.init.object &&
|
|
787
|
+
decl.init.object.type === 'Identifier' &&
|
|
788
|
+
decl.init.object.name === 'module') {
|
|
789
|
+
return; // 跳过模块导入变量检测
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// 检查是否为模块导入的变量(module.xxx)
|
|
793
|
+
if (decl.init.type === 'MemberExpression' &&
|
|
794
|
+
decl.init.object &&
|
|
795
|
+
decl.init.object.type === 'Identifier' &&
|
|
796
|
+
decl.init.object.name === 'module') {
|
|
797
|
+
return; // 跳过模块导入变量检测
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// 检查是否为带await的动态导入(await import().xxx)
|
|
801
|
+
if (decl.init.type === 'MemberExpression' &&
|
|
802
|
+
decl.init.object &&
|
|
803
|
+
decl.init.object.type === 'AwaitExpression' &&
|
|
804
|
+
decl.init.object.argument &&
|
|
805
|
+
decl.init.object.argument.type === 'ImportExpression') {
|
|
806
|
+
return; // 跳过await动态导入检测
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// 简化类型推断逻辑:直接使用detector的自动类型推断
|
|
811
|
+
var err = _detectNamingError(variable_name, decl.id);
|
|
812
|
+
if (err) {
|
|
813
|
+
context.report(err);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
},
|
|
818
|
+
|
|
819
|
+
// 检测for循环中的变量声明
|
|
820
|
+
ForStatement: function (node) {
|
|
821
|
+
// 检测for循环初始化部分中的变量声明
|
|
822
|
+
if (node.init && node.init.type === 'VariableDeclaration') {
|
|
823
|
+
// 只检测let和var声明,const声明由常量规则处理
|
|
824
|
+
if (node.init.kind === 'const') {
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
node.init.declarations.forEach(function (decl) {
|
|
829
|
+
if (decl.id && decl.id.type === 'Identifier') {
|
|
830
|
+
var variable_name = decl.id.name;
|
|
831
|
+
var err = _detectNamingError(variable_name, decl.id);
|
|
832
|
+
if (err) {
|
|
833
|
+
context.report(err);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
},
|
|
839
|
+
|
|
840
|
+
// 检测for...in循环中的变量声明
|
|
841
|
+
ForInStatement: function (node) {
|
|
842
|
+
// 检测for...in循环左侧的变量声明
|
|
843
|
+
if (node.left && node.left.type === 'VariableDeclaration') {
|
|
844
|
+
// 只检测let和var声明,const声明由常量规则处理
|
|
845
|
+
if (node.left.kind === 'const') {
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
node.left.declarations.forEach(function (decl) {
|
|
850
|
+
if (decl.id && decl.id.type === 'Identifier') {
|
|
851
|
+
var variable_name = decl.id.name;
|
|
852
|
+
var err = _detectNamingError(variable_name, decl.id);
|
|
853
|
+
if (err) {
|
|
854
|
+
context.report(err);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
},
|
|
860
|
+
|
|
861
|
+
// 检测for...of循环中的变量声明
|
|
862
|
+
ForOfStatement: function (node) {
|
|
863
|
+
// 检测for...of循环左侧的变量声明
|
|
864
|
+
if (node.left && node.left.type === 'VariableDeclaration') {
|
|
865
|
+
// 只检测let和var声明,const声明由常量规则处理
|
|
866
|
+
if (node.left.kind === 'const') {
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
node.left.declarations.forEach(function (decl) {
|
|
871
|
+
if (decl.id && decl.id.type === 'Identifier') {
|
|
872
|
+
var variable_name = decl.id.name;
|
|
873
|
+
var err = _detectNamingError(variable_name, decl.id);
|
|
874
|
+
if (err) {
|
|
875
|
+
context.report(err);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
},
|
|
881
|
+
|
|
882
|
+
// 处理赋值表达式
|
|
883
|
+
AssignmentExpression: function (node) {
|
|
884
|
+
// 先检查是否是原型方法赋值(UserManagera.prototype._GetUserps = function() {})
|
|
885
|
+
if (node.left &&
|
|
886
|
+
node.left.type === 'MemberExpression' &&
|
|
887
|
+
node.left.property &&
|
|
888
|
+
node.left.property.type === 'Identifier' &&
|
|
889
|
+
node.right &&
|
|
890
|
+
(node.right.type === 'FunctionExpression' || node.right.type === 'ArrowFunctionExpression')) {
|
|
891
|
+
|
|
892
|
+
// 检查左侧是否是原型方法模式(包含prototype)
|
|
893
|
+
var left_str = context.getSourceCode().getText(node.left);
|
|
894
|
+
if (left_str.includes('.prototype.')) {
|
|
895
|
+
var method_name = node.left.property.name;
|
|
896
|
+
var err = _detectNamingError(method_name, node);
|
|
897
|
+
if (err) {
|
|
898
|
+
context.report(err);
|
|
899
|
+
return; // 如果检测到原型方法,直接返回,避免被其他规则覆盖
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
// 再检查是否是普通变量赋值(a = 1)
|
|
905
|
+
if (node.left && node.left.type === 'Identifier') {
|
|
906
|
+
var variable_name = node.left.name;
|
|
907
|
+
var err = _detectNamingError(variable_name, node);
|
|
908
|
+
if (err) {
|
|
909
|
+
context.report(err);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
},
|
|
913
|
+
|
|
914
|
+
// 检测类属性(Class Properties)中的命名规范
|
|
915
|
+
PropertyDefinition: function (node) {
|
|
916
|
+
if (node.key && node.key.type === 'Identifier') {
|
|
917
|
+
// 检查是否为类实例声明,如果是则跳过变量检测(由类实例规则处理)
|
|
918
|
+
if (node.value && node.value.type === 'NewExpression') {
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
var property_name = node.key.name;
|
|
923
|
+
var err = _detectNamingError(property_name, node);
|
|
924
|
+
if (err) {
|
|
925
|
+
context.report(err);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
},
|
|
929
|
+
|
|
930
|
+
};
|
|
931
|
+
},
|
|
932
|
+
},
|
|
933
|
+
|
|
934
|
+
'constant-name': {
|
|
935
|
+
meta: {
|
|
936
|
+
type: 'suggestion',
|
|
937
|
+
docs: {
|
|
938
|
+
description: '检测常量名是否符合命名规范',
|
|
939
|
+
category: 'Stylistic Issues',
|
|
940
|
+
recommended: true,
|
|
941
|
+
},
|
|
942
|
+
fixable: 'code',
|
|
943
|
+
schema: [],
|
|
944
|
+
},
|
|
945
|
+
create: function (context) {
|
|
946
|
+
return {
|
|
947
|
+
VariableDeclaration: function (node) {
|
|
948
|
+
// 只检测const声明
|
|
949
|
+
if (node.kind !== 'const') {
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
node.declarations.forEach(function (decl) {
|
|
954
|
+
// 只验证顶层变量声明,不验证对象属性
|
|
955
|
+
if (decl.id && decl.id.type === 'Identifier') {
|
|
956
|
+
// 检查是否为顶层变量声明(不是对象属性)
|
|
957
|
+
var is_top_level = true;
|
|
958
|
+
var current_node = decl;
|
|
959
|
+
while (current_node.parent) {
|
|
960
|
+
if (current_node.parent.type === 'Property' ||
|
|
961
|
+
current_node.parent.type === 'ObjectExpression' ||
|
|
962
|
+
current_node.parent.type === 'ArrayExpression') {
|
|
963
|
+
is_top_level = false;
|
|
964
|
+
break;
|
|
965
|
+
}
|
|
966
|
+
current_node = current_node.parent;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
if (!is_top_level) {
|
|
970
|
+
return; // 跳过对象属性
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// 检查是否为函数/类的常量,如果是则跳过检测(由其他规则处理)
|
|
974
|
+
if (decl.init) {
|
|
975
|
+
// 函数类型
|
|
976
|
+
var function_types = ['FunctionExpression', 'ArrowFunctionExpression'];
|
|
977
|
+
if (function_types.includes(decl.init.type)) {
|
|
978
|
+
return; // 跳过函数常量,由函数名规则处理
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// 类表达式
|
|
982
|
+
if (decl.init.type === 'ClassExpression') {
|
|
983
|
+
return; // 跳过类常量,由类名规则处理
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// 类实例(new表达式)
|
|
987
|
+
if (decl.init.type === 'NewExpression') {
|
|
988
|
+
return; // 跳过类实例常量,由类实例名规则处理
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
// 检查是否为CommonJS导入语句,如果是则跳过检测
|
|
992
|
+
// 检查是否为require()调用
|
|
993
|
+
if (decl.init.type === 'CallExpression' &&
|
|
994
|
+
decl.init.callee &&
|
|
995
|
+
decl.init.callee.name === 'require') {
|
|
996
|
+
return; // 跳过require导入检测
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// 检查是否为require().xxx形式的导入
|
|
1000
|
+
if (decl.init.type === 'MemberExpression' &&
|
|
1001
|
+
decl.init.object &&
|
|
1002
|
+
decl.init.object.type === 'CallExpression' &&
|
|
1003
|
+
decl.init.object.callee &&
|
|
1004
|
+
decl.init.object.callee.name === 'require') {
|
|
1005
|
+
return; // 跳过require().xxx导入检测
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// 检查是否为动态导入(import())
|
|
1009
|
+
if (decl.init.type === 'CallExpression' &&
|
|
1010
|
+
decl.init.callee &&
|
|
1011
|
+
decl.init.callee.type === 'Import') {
|
|
1012
|
+
return; // 跳过动态导入检测
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
// 检查是否为动态导入的成员表达式(import().xxx)
|
|
1016
|
+
if (decl.init.type === 'MemberExpression' &&
|
|
1017
|
+
decl.init.object &&
|
|
1018
|
+
decl.init.object.type === 'CallExpression' &&
|
|
1019
|
+
decl.init.object.callee &&
|
|
1020
|
+
decl.init.object.callee.type === 'Import') {
|
|
1021
|
+
return; // 跳过动态导入成员检测
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
var constant_name = decl.id.name;
|
|
1026
|
+
|
|
1027
|
+
// 检查是否为真正的常量(const声明且值为字面量)
|
|
1028
|
+
if (detector._isTrueConstant(constant_name, decl)) {
|
|
1029
|
+
var err = _detectNamingError(constant_name, decl.id);
|
|
1030
|
+
if (err) {
|
|
1031
|
+
context.report(err);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
},
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
module.exports = {
|
|
1044
|
+
rules: createNamingRules()
|
|
1045
|
+
};
|