@@ -113,6 +113,8 @@ enum Modifiers {
113
113
global = 1 << 8 ,
114
114
// things that are exported
115
115
exported = 1 << 9 ,
116
+ // things that are unused
117
+ unused = 1 << 10 ,
116
118
}
117
119
type ModifiersString = keyof typeof Modifiers ;
118
120
@@ -334,15 +336,16 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
334
336
selectorsSchema ( ) ,
335
337
...selectorSchema ( 'default' , false , util . getEnumNames ( Modifiers ) ) ,
336
338
337
- ...selectorSchema ( 'variableLike' , false ) ,
339
+ ...selectorSchema ( 'variableLike' , false , [ 'unused' ] ) ,
338
340
...selectorSchema ( 'variable' , true , [
339
341
'const' ,
340
342
'destructured' ,
341
343
'global' ,
342
344
'exported' ,
345
+ 'unused' ,
343
346
] ) ,
344
- ...selectorSchema ( 'function' , false , [ 'global' , 'exported' ] ) ,
345
- ...selectorSchema ( 'parameter' , true ) ,
347
+ ...selectorSchema ( 'function' , false , [ 'global' , 'exported' , 'unused' ] ) ,
348
+ ...selectorSchema ( 'parameter' , true , [ 'unused' ] ) ,
346
349
347
350
...selectorSchema ( 'memberLike' , false , [
348
351
'private' ,
@@ -428,12 +431,12 @@ const SCHEMA: JSONSchema.JSONSchema4 = {
428
431
] ) ,
429
432
...selectorSchema ( 'enumMember' , false ) ,
430
433
431
- ...selectorSchema ( 'typeLike' , false , [ 'abstract' , 'exported' ] ) ,
432
- ...selectorSchema ( 'class' , false , [ 'abstract' , 'exported' ] ) ,
433
- ...selectorSchema ( 'interface' , false , [ 'exported' ] ) ,
434
- ...selectorSchema ( 'typeAlias' , false , [ 'exported' ] ) ,
435
- ...selectorSchema ( 'enum' , false , [ 'exported' ] ) ,
436
- ...selectorSchema ( 'typeParameter' , false ) ,
434
+ ...selectorSchema ( 'typeLike' , false , [ 'abstract' , 'exported' , 'unused' ] ) ,
435
+ ...selectorSchema ( 'class' , false , [ 'abstract' , 'exported' , 'unused' ] ) ,
436
+ ...selectorSchema ( 'interface' , false , [ 'exported' , 'unused' ] ) ,
437
+ ...selectorSchema ( 'typeAlias' , false , [ 'exported' , 'unused' ] ) ,
438
+ ...selectorSchema ( 'enum' , false , [ 'exported' , 'unused' ] ) ,
439
+ ...selectorSchema ( 'typeParameter' , false , [ 'unused' ] ) ,
437
440
] ,
438
441
} ,
439
442
additionalItems : false ,
@@ -558,6 +561,27 @@ export default util.createRule<Options, MessageIds>({
558
561
return modifiers ;
559
562
}
560
563
564
+ const unusedVariables = util . collectUnusedVariables ( context ) ;
565
+ function isUnused (
566
+ name : string ,
567
+ initialScope : TSESLint . Scope . Scope | null = context . getScope ( ) ,
568
+ ) : boolean {
569
+ let variable : TSESLint . Scope . Variable | null = null ;
570
+ let scope : TSESLint . Scope . Scope | null = initialScope ;
571
+ while ( scope ) {
572
+ variable = scope . set . get ( name ) ?? null ;
573
+ if ( variable ) {
574
+ break ;
575
+ }
576
+ scope = scope . upper ;
577
+ }
578
+ if ( ! variable ) {
579
+ return false ;
580
+ }
581
+
582
+ return unusedVariables . has ( variable ) ;
583
+ }
584
+
561
585
return {
562
586
// #region variable
563
587
@@ -574,13 +598,15 @@ export default util.createRule<Options, MessageIds>({
574
598
if ( parent . kind === 'const' ) {
575
599
baseModifiers . add ( Modifiers . const ) ;
576
600
}
601
+
577
602
if ( isGlobal ( context . getScope ( ) ) ) {
578
603
baseModifiers . add ( Modifiers . global ) ;
579
604
}
580
605
}
581
606
582
607
identifiers . forEach ( id => {
583
608
const modifiers = new Set ( baseModifiers ) ;
609
+
584
610
if (
585
611
// `const { x }`
586
612
// does not match `const { x: y }`
@@ -599,6 +625,10 @@ export default util.createRule<Options, MessageIds>({
599
625
modifiers . add ( Modifiers . exported ) ;
600
626
}
601
627
628
+ if ( isUnused ( id . name ) ) {
629
+ modifiers . add ( Modifiers . unused ) ;
630
+ }
631
+
602
632
validator ( id , modifiers ) ;
603
633
} ) ;
604
634
} ,
@@ -621,13 +651,19 @@ export default util.createRule<Options, MessageIds>({
621
651
const modifiers = new Set < Modifiers > ( ) ;
622
652
// functions create their own nested scope
623
653
const scope = context . getScope ( ) . upper ;
654
+
624
655
if ( isGlobal ( scope ) ) {
625
656
modifiers . add ( Modifiers . global ) ;
626
657
}
658
+
627
659
if ( isExported ( node , node . id . name , scope ) ) {
628
660
modifiers . add ( Modifiers . exported ) ;
629
661
}
630
662
663
+ if ( isUnused ( node . id . name , scope ) ) {
664
+ modifiers . add ( Modifiers . unused ) ;
665
+ }
666
+
631
667
validator ( node . id , modifiers ) ;
632
668
} ,
633
669
@@ -655,7 +691,13 @@ export default util.createRule<Options, MessageIds>({
655
691
const identifiers = getIdentifiersFromPattern ( param ) ;
656
692
657
693
identifiers . forEach ( i => {
658
- validator ( i ) ;
694
+ const modifiers = new Set < Modifiers > ( ) ;
695
+
696
+ if ( isUnused ( i . name ) ) {
697
+ modifiers . add ( Modifiers . unused ) ;
698
+ }
699
+
700
+ validator ( i , modifiers ) ;
659
701
} ) ;
660
702
} ) ;
661
703
} ,
@@ -803,15 +845,21 @@ export default util.createRule<Options, MessageIds>({
803
845
}
804
846
805
847
const modifiers = new Set < Modifiers > ( ) ;
848
+ // classes create their own nested scope
849
+ const scope = context . getScope ( ) . upper ;
850
+
806
851
if ( node . abstract ) {
807
852
modifiers . add ( Modifiers . abstract ) ;
808
853
}
809
854
810
- // classes create their own nested scope
811
- if ( isExported ( node , id . name , context . getScope ( ) . upper ) ) {
855
+ if ( isExported ( node , id . name , scope ) ) {
812
856
modifiers . add ( Modifiers . exported ) ;
813
857
}
814
858
859
+ if ( isUnused ( id . name , scope ) ) {
860
+ modifiers . add ( Modifiers . unused ) ;
861
+ }
862
+
815
863
validator ( id , modifiers ) ;
816
864
} ,
817
865
@@ -826,10 +874,16 @@ export default util.createRule<Options, MessageIds>({
826
874
}
827
875
828
876
const modifiers = new Set < Modifiers > ( ) ;
829
- if ( isExported ( node , node . id . name , context . getScope ( ) ) ) {
877
+ const scope = context . getScope ( ) ;
878
+
879
+ if ( isExported ( node , node . id . name , scope ) ) {
830
880
modifiers . add ( Modifiers . exported ) ;
831
881
}
832
882
883
+ if ( isUnused ( node . id . name , scope ) ) {
884
+ modifiers . add ( Modifiers . unused ) ;
885
+ }
886
+
833
887
validator ( node . id , modifiers ) ;
834
888
} ,
835
889
@@ -844,10 +898,16 @@ export default util.createRule<Options, MessageIds>({
844
898
}
845
899
846
900
const modifiers = new Set < Modifiers > ( ) ;
847
- if ( isExported ( node , node . id . name , context . getScope ( ) ) ) {
901
+ const scope = context . getScope ( ) ;
902
+
903
+ if ( isExported ( node , node . id . name , scope ) ) {
848
904
modifiers . add ( Modifiers . exported ) ;
849
905
}
850
906
907
+ if ( isUnused ( node . id . name , scope ) ) {
908
+ modifiers . add ( Modifiers . unused ) ;
909
+ }
910
+
851
911
validator ( node . id , modifiers ) ;
852
912
} ,
853
913
@@ -863,10 +923,16 @@ export default util.createRule<Options, MessageIds>({
863
923
864
924
const modifiers = new Set < Modifiers > ( ) ;
865
925
// enums create their own nested scope
866
- if ( isExported ( node , node . id . name , context . getScope ( ) . upper ) ) {
926
+ const scope = context . getScope ( ) . upper ;
927
+
928
+ if ( isExported ( node , node . id . name , scope ) ) {
867
929
modifiers . add ( Modifiers . exported ) ;
868
930
}
869
931
932
+ if ( isUnused ( node . id . name , scope ) ) {
933
+ modifiers . add ( Modifiers . unused ) ;
934
+ }
935
+
870
936
validator ( node . id , modifiers ) ;
871
937
} ,
872
938
@@ -882,7 +948,14 @@ export default util.createRule<Options, MessageIds>({
882
948
return ;
883
949
}
884
950
885
- validator ( node . name ) ;
951
+ const modifiers = new Set < Modifiers > ( ) ;
952
+ const scope = context . getScope ( ) ;
953
+
954
+ if ( isUnused ( node . name . name , scope ) ) {
955
+ modifiers . add ( Modifiers . unused ) ;
956
+ }
957
+
958
+ validator ( node . name , modifiers ) ;
886
959
} ,
887
960
888
961
// #endregion typeParameter
0 commit comments