@@ -416,7 +416,7 @@ const compareString = (a, b) => {
416
416
} ;
417
417
418
418
/** Some parsers (languages without types) don't provide ImportKind */
419
- const DEAFULT_IMPORT_KIND = 'value' ;
419
+ const DEFAULT_IMPORT_KIND = 'value' ;
420
420
const getNormalizedValue = ( node , toLowerCase ) => {
421
421
const value = node . value ;
422
422
return toLowerCase ? String ( value ) . toLowerCase ( ) : value ;
@@ -462,8 +462,8 @@ function getSorter(alphabetizeOptions) {
462
462
// In case the paths are equal (result === 0), sort them by importKind
463
463
if ( ! result && multiplierImportKind ) {
464
464
result = multiplierImportKind * compareString (
465
- nodeA . node . importKind || DEAFULT_IMPORT_KIND ,
466
- nodeB . node . importKind || DEAFULT_IMPORT_KIND ,
465
+ nodeA . node . importKind || DEFAULT_IMPORT_KIND ,
466
+ nodeB . node . importKind || DEFAULT_IMPORT_KIND ,
467
467
) ;
468
468
}
469
469
@@ -677,7 +677,7 @@ function removeNewLineAfterImport(context, currentImport, previousImport) {
677
677
return undefined ;
678
678
}
679
679
680
- function makeNewlinesBetweenReport ( context , imported , newlinesBetweenImports , distinctGroup ) {
680
+ function makeNewlinesBetweenReport ( context , imported , newlinesBetweenImports , newlinesBetweenTypeOnlyImports , distinctGroup , isSortingTypesGroup ) {
681
681
const getNumberOfEmptyLinesBetween = ( currentImport , previousImport ) => {
682
682
const linesBetweenImports = getSourceCode ( context ) . lines . slice (
683
683
previousImport . node . loc . end . line ,
@@ -690,35 +690,72 @@ function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports, di
690
690
let previousImport = imported [ 0 ] ;
691
691
692
692
imported . slice ( 1 ) . forEach ( function ( currentImport ) {
693
- const emptyLinesBetween = getNumberOfEmptyLinesBetween ( currentImport , previousImport ) ;
694
- const isStartOfDistinctGroup = getIsStartOfDistinctGroup ( currentImport , previousImport ) ;
695
-
696
- if ( newlinesBetweenImports === 'always'
697
- || newlinesBetweenImports === 'always-and-inside-groups' ) {
698
- if ( currentImport . rank !== previousImport . rank && emptyLinesBetween === 0 ) {
699
- if ( distinctGroup || ! distinctGroup && isStartOfDistinctGroup ) {
700
- context . report ( {
701
- node : previousImport . node ,
702
- message : 'There should be at least one empty line between import groups' ,
703
- fix : fixNewLineAfterImport ( context , previousImport ) ,
704
- } ) ;
705
- }
706
- } else if ( emptyLinesBetween > 0
707
- && newlinesBetweenImports !== 'always-and-inside-groups' ) {
708
- if ( distinctGroup && currentImport . rank === previousImport . rank || ! distinctGroup && ! isStartOfDistinctGroup ) {
709
- context . report ( {
710
- node : previousImport . node ,
711
- message : 'There should be no empty line within import group' ,
712
- fix : removeNewLineAfterImport ( context , currentImport , previousImport ) ,
713
- } ) ;
693
+ const emptyLinesBetween = getNumberOfEmptyLinesBetween (
694
+ currentImport ,
695
+ previousImport ,
696
+ ) ;
697
+
698
+ const isStartOfDistinctGroup = getIsStartOfDistinctGroup (
699
+ currentImport ,
700
+ previousImport ,
701
+ ) ;
702
+
703
+ const isTypeOnlyImport = currentImport . node . importKind === 'type' ;
704
+ const isPreviousImportTypeOnlyImport = previousImport . node . importKind === 'type' ;
705
+
706
+ const isNormalImportFollowingTypeOnlyImportAndRelevant = ! isTypeOnlyImport && isPreviousImportTypeOnlyImport && isSortingTypesGroup ;
707
+
708
+ const isTypeOnlyImportAndRelevant = isTypeOnlyImport && isSortingTypesGroup ;
709
+
710
+ const isNotIgnored = isTypeOnlyImportAndRelevant
711
+ && newlinesBetweenTypeOnlyImports !== 'ignore'
712
+ || ! isTypeOnlyImportAndRelevant && newlinesBetweenImports !== 'ignore' ;
713
+
714
+ if ( isNotIgnored ) {
715
+ const shouldAssertNewlineBetweenGroups = ( isTypeOnlyImportAndRelevant || isNormalImportFollowingTypeOnlyImportAndRelevant )
716
+ && ( newlinesBetweenTypeOnlyImports === 'always'
717
+ || newlinesBetweenTypeOnlyImports === 'always-and-inside-groups' )
718
+ || ! isTypeOnlyImportAndRelevant && ! isNormalImportFollowingTypeOnlyImportAndRelevant
719
+ && ( newlinesBetweenImports === 'always'
720
+ || newlinesBetweenImports === 'always-and-inside-groups' ) ;
721
+
722
+ const shouldAssertNoNewlineWithinGroup = ( isTypeOnlyImportAndRelevant || isNormalImportFollowingTypeOnlyImportAndRelevant )
723
+ && newlinesBetweenTypeOnlyImports !== 'always-and-inside-groups'
724
+ || ! isTypeOnlyImportAndRelevant && ! isNormalImportFollowingTypeOnlyImportAndRelevant
725
+ && newlinesBetweenImports !== 'always-and-inside-groups' ;
726
+
727
+ const shouldAssertNoNewlineBetweenGroup = ! isSortingTypesGroup
728
+ || ! isNormalImportFollowingTypeOnlyImportAndRelevant
729
+ || newlinesBetweenTypeOnlyImports === 'never' ;
730
+
731
+ if ( shouldAssertNewlineBetweenGroups ) {
732
+ if ( currentImport . rank !== previousImport . rank && emptyLinesBetween === 0 ) {
733
+ if ( distinctGroup || ! distinctGroup && isStartOfDistinctGroup ) {
734
+ context . report ( {
735
+ node : previousImport . node ,
736
+ message : 'There should be at least one empty line between import groups' ,
737
+ fix : fixNewLineAfterImport ( context , previousImport ) ,
738
+ } ) ;
739
+ }
740
+ } else if ( emptyLinesBetween > 0 && shouldAssertNoNewlineWithinGroup ) {
741
+ if (
742
+ distinctGroup && currentImport . rank === previousImport . rank
743
+ || ! distinctGroup && ! isStartOfDistinctGroup
744
+ ) {
745
+ context . report ( {
746
+ node : previousImport . node ,
747
+ message : 'There should be no empty line within import group' ,
748
+ fix : removeNewLineAfterImport ( context , currentImport , previousImport ) ,
749
+ } ) ;
750
+ }
714
751
}
752
+ } else if ( emptyLinesBetween > 0 && shouldAssertNoNewlineBetweenGroup ) {
753
+ context . report ( {
754
+ node : previousImport . node ,
755
+ message : 'There should be no empty line between import groups' ,
756
+ fix : removeNewLineAfterImport ( context , currentImport , previousImport ) ,
757
+ } ) ;
715
758
}
716
- } else if ( emptyLinesBetween > 0 ) {
717
- context . report ( {
718
- node : previousImport . node ,
719
- message : 'There should be no empty line between import groups' ,
720
- fix : removeNewLineAfterImport ( context , currentImport , previousImport ) ,
721
- } ) ;
722
759
}
723
760
724
761
previousImport = currentImport ;
@@ -793,6 +830,14 @@ module.exports = {
793
830
'never' ,
794
831
] ,
795
832
} ,
833
+ 'newlines-between-types' : {
834
+ enum : [
835
+ 'ignore' ,
836
+ 'always' ,
837
+ 'always-and-inside-groups' ,
838
+ 'never' ,
839
+ ] ,
840
+ } ,
796
841
sortTypesGroup : {
797
842
type : 'boolean' ,
798
843
default : false ,
@@ -845,13 +890,22 @@ module.exports = {
845
890
} ,
846
891
} ,
847
892
additionalProperties : false ,
893
+ dependencies : {
894
+ 'newlines-between-types' : {
895
+ properties : {
896
+ sortTypesGroup : { enum : [ true ] } ,
897
+ } ,
898
+ required : [ 'sortTypesGroup' ] ,
899
+ } ,
900
+ } ,
848
901
} ,
849
902
] ,
850
903
} ,
851
904
852
905
create ( context ) {
853
906
const options = context . options [ 0 ] || { } ;
854
907
const newlinesBetweenImports = options [ 'newlines-between' ] || 'ignore' ;
908
+ const newlinesBetweenTypeOnlyImports = options [ 'newlines-between-types' ] || newlinesBetweenImports ;
855
909
const pathGroupsExcludedImportTypes = new Set ( options . pathGroupsExcludedImportTypes || [ 'builtin' , 'external' , 'object' ] ) ;
856
910
const sortTypesGroup = options . sortTypesGroup ;
857
911
@@ -1115,8 +1169,8 @@ module.exports = {
1115
1169
} ,
1116
1170
'Program:exit' ( ) {
1117
1171
importMap . forEach ( ( imported ) => {
1118
- if ( newlinesBetweenImports !== 'ignore' ) {
1119
- makeNewlinesBetweenReport ( context , imported , newlinesBetweenImports , distinctGroup ) ;
1172
+ if ( newlinesBetweenImports !== 'ignore' || newlinesBetweenTypeOnlyImports !== 'ignore' ) {
1173
+ makeNewlinesBetweenReport ( context , imported , newlinesBetweenImports , newlinesBetweenTypeOnlyImports , distinctGroup , isSortingTypesGroup ) ;
1120
1174
}
1121
1175
1122
1176
if ( alphabetize . order !== 'ignore' ) {
0 commit comments