@@ -9,12 +9,209 @@ const schema = [
9
9
} ,
10
10
] ;
11
11
12
+ function isNeverOption ( context ) {
13
+ return ( context . options [ 0 ] || 'never' ) === 'never' ;
14
+ }
15
+
16
+ function isWhitespaceCRLF ( whitespace ) {
17
+ return whitespace !== '\n' && whitespace !== '\r' ;
18
+ }
19
+
20
+ function spacesOutside ( node , context ) {
21
+ const { callee, typeArguments } = node ;
22
+ if ( typeArguments == null ) {
23
+ return ;
24
+ }
25
+
26
+ const sourceCode = context . getSourceCode ( ) ;
27
+ const { name } = callee ;
28
+ const never = isNeverOption ( context ) ;
29
+ const parentheses = sourceCode . getTokenAfter ( typeArguments ) ;
30
+
31
+ const spacesBefore = typeArguments . range [ 0 ] - callee . range [ 1 ] ;
32
+ const spacesAfter = parentheses . range [ 0 ] - typeArguments . range [ 1 ] ;
33
+
34
+ if ( never ) {
35
+ if ( spacesBefore ) {
36
+ const whiteSpaceBefore = sourceCode . text [ typeArguments . range [ 0 ] ] ;
37
+
38
+ if ( isWhitespaceCRLF ( whiteSpaceBefore ) ) {
39
+ context . report ( {
40
+ data : { name } ,
41
+ fix : spacingFixers . stripSpacesBefore ( typeArguments , spacesBefore ) ,
42
+ message : 'There must be no space before "{{name}}" type annotation' ,
43
+ node,
44
+ } ) ;
45
+ }
46
+ }
47
+
48
+ if ( spacesAfter ) {
49
+ const whiteSpaceAfter = sourceCode . text [ typeArguments . range [ 1 ] - 1 ] ;
50
+
51
+ if ( isWhitespaceCRLF ( whiteSpaceAfter ) ) {
52
+ context . report ( {
53
+ data : { name } ,
54
+ fix : spacingFixers . stripSpacesAfter ( typeArguments , spacesAfter ) ,
55
+ message : 'There must be no space after "{{name}}" type annotation' ,
56
+ node,
57
+ } ) ;
58
+ }
59
+ }
60
+
61
+ return ;
62
+ }
63
+
64
+ if ( ! never ) {
65
+ if ( spacesBefore > 1 ) {
66
+ context . report ( {
67
+ data : { name } ,
68
+ fix : spacingFixers . stripSpacesBefore ( typeArguments , spacesBefore - 1 ) ,
69
+ message : 'There must be one space before "{{name}}" generic type annotation bracket' ,
70
+ node,
71
+ } ) ;
72
+ }
73
+
74
+ if ( spacesBefore === 0 ) {
75
+ context . report ( {
76
+ data : { name } ,
77
+ fix : spacingFixers . addSpaceBefore ( typeArguments ) ,
78
+ message : 'There must be a space before "{{name}}" generic type annotation bracket' ,
79
+ node,
80
+ } ) ;
81
+ }
82
+
83
+ if ( spacesAfter > 1 ) {
84
+ context . report ( {
85
+ data : { name } ,
86
+ fix : spacingFixers . stripSpacesAfter ( typeArguments , spacesAfter ) ,
87
+ message : 'There must be one space before "{{name}}" generic type annotation bracket' ,
88
+ node,
89
+ } ) ;
90
+ }
91
+
92
+ if ( spacesAfter === 0 ) {
93
+ context . report ( {
94
+ data : { name } ,
95
+ fix : spacingFixers . addSpaceAfter ( typeArguments ) ,
96
+ message : 'There must be a space before "{{name}}" generic type annotation bracket' ,
97
+ node,
98
+ } ) ;
99
+ }
100
+ }
101
+ }
102
+
103
+ function spacesInside ( node , context ) {
104
+ const { callee, typeArguments } = node ;
105
+ if ( typeArguments == null ) {
106
+ return ;
107
+ }
108
+
109
+ const sourceCode = context . getSourceCode ( ) ;
110
+ const { name } = callee ;
111
+ const never = isNeverOption ( context ) ;
112
+ const isNullable = typeArguments . params [ 0 ] . type === 'NullableTypeAnnotation' ;
113
+ const [
114
+ opener ,
115
+ firstInnerToken ,
116
+ secondInnerToken ,
117
+ ] = sourceCode . getFirstTokens ( typeArguments , 3 ) ;
118
+ const [
119
+ lastInnerToken ,
120
+ closer ,
121
+ ] = sourceCode . getLastTokens ( typeArguments , 2 ) ;
122
+
123
+ const spacesBefore = firstInnerToken . range [ 0 ] - opener . range [ 1 ] ;
124
+ const spaceBetweenNullToken = secondInnerToken . range [ 0 ] - firstInnerToken . range [ 1 ] ;
125
+ const spacesAfter = closer . range [ 0 ] - lastInnerToken . range [ 1 ] ;
126
+
127
+ if ( never ) {
128
+ if ( spacesBefore ) {
129
+ const whiteSpaceBefore = sourceCode . text [ opener . range [ 1 ] ] ;
130
+
131
+ if ( whiteSpaceBefore !== '\n' && whiteSpaceBefore !== '\r' ) {
132
+ context . report ( {
133
+ data : { name } ,
134
+ fix : spacingFixers . stripSpacesAfter ( opener , spacesBefore ) ,
135
+ message : 'There must be no spaces inside at the start of "{{name}}" type annotation' ,
136
+ node,
137
+ } ) ;
138
+ }
139
+ }
140
+
141
+ if ( isNullable && spaceBetweenNullToken ) {
142
+ context . report ( {
143
+ data : { name } ,
144
+ fix : spacingFixers . stripSpacesAfter ( firstInnerToken , spaceBetweenNullToken ) ,
145
+ message : 'There must be no spaces inside "{{name}}" type annotation' ,
146
+ node,
147
+ } ) ;
148
+ }
149
+
150
+ if ( spacesAfter ) {
151
+ const whiteSpaceAfter = sourceCode . text [ closer . range [ 0 ] - 1 ] ;
152
+
153
+ if ( isWhitespaceCRLF ( whiteSpaceAfter ) ) {
154
+ context . report ( {
155
+ data : { name } ,
156
+ fix : spacingFixers . stripSpacesAfter ( lastInnerToken , spacesAfter ) ,
157
+ message : 'There must be no spaces inside at the end of "{{name}}" type annotation' ,
158
+ node,
159
+ } ) ;
160
+ }
161
+ }
162
+
163
+ return ;
164
+ }
165
+
166
+ if ( ! never ) {
167
+ if ( spacesBefore > 1 ) {
168
+ context . report ( {
169
+ data : { name } ,
170
+ fix : spacingFixers . stripSpacesBefore ( opener , spacesBefore - 1 ) ,
171
+ message : 'There must be one space before "{{name}}" generic type annotation bracket' ,
172
+ node,
173
+ } ) ;
174
+ }
175
+
176
+ if ( spacesBefore === 0 ) {
177
+ context . report ( {
178
+ data : { name } ,
179
+ fix : spacingFixers . addSpaceBefore ( opener ) ,
180
+ message : 'There must be a space before "{{name}}" generic type annotation bracket' ,
181
+ node,
182
+ } ) ;
183
+ }
184
+
185
+ if ( spacesAfter > 1 ) {
186
+ context . report ( {
187
+ data : { name } ,
188
+ fix : spacingFixers . stripSpacesAfter ( closer , spacesAfter ) ,
189
+ message : 'There must be one space before "{{name}}" generic type annotation bracket' ,
190
+ node,
191
+ } ) ;
192
+ }
193
+
194
+ if ( spacesAfter === 0 ) {
195
+ context . report ( {
196
+ data : { name } ,
197
+ fix : spacingFixers . addSpaceAfter ( closer ) ,
198
+ message : 'There must be a space before "{{name}}" generic type annotation bracket' ,
199
+ node,
200
+ } ) ;
201
+ }
202
+ }
203
+ }
204
+
12
205
const create = ( context ) => {
13
206
const sourceCode = context . getSourceCode ( ) ;
14
207
15
208
const never = ( context . options [ 0 ] || 'never' ) === 'never' ;
16
209
17
210
return {
211
+ CallExpression ( node ) {
212
+ spacesOutside ( node , context ) ;
213
+ spacesInside ( node , context ) ;
214
+ } ,
18
215
GenericTypeAnnotation ( node ) {
19
216
const types = node . typeParameters ;
20
217
0 commit comments