@@ -18,7 +18,7 @@ export function getDefaultRules(): Rules {
1818 * }
1919 * ```
2020 */
21- 'interface-property-semicolon' ( { typescript : ts , sourceFile, reportWarning } ) {
21+ 'format/ interface-property-semicolon' ( { typescript : ts , sourceFile, reportWarning } ) {
2222 const { text } = sourceFile ;
2323 ts . forEachChild ( sourceFile , function visit ( node ) {
2424 if ( ts . isInterfaceDeclaration ( node ) ) {
@@ -56,7 +56,7 @@ export function getDefaultRules(): Rules {
5656 * + }
5757 * ```
5858 */
59- 'braces-around-statements' ( { typescript : ts , sourceFile, reportWarning } ) {
59+ 'format/ braces-around-statements' ( { typescript : ts , sourceFile, reportWarning } ) {
6060 ts . forEachChild ( sourceFile , function visit ( node ) {
6161 if ( ts . isIfStatement ( node ) ) {
6262 if ( ! ts . isBlock ( node . thenStatement ) ) {
@@ -115,60 +115,14 @@ export function getDefaultRules(): Rules {
115115 === ts . getLineAndCharacterOfPosition ( sourceFile , node . parent . getEnd ( ) ) . line ;
116116 }
117117 } ,
118- 'missing-dependency' ( { typescript : ts , sourceFile, reportError, languageServiceHost } ) {
119- const { noEmit } = languageServiceHost . getCompilationSettings ( ) ;
120- if ( noEmit ) {
121- return ;
122- }
123- const packageJsonPath = ts . findConfigFile ( sourceFile . fileName , ts . sys . fileExists , 'package.json' ) ;
124- if ( ! packageJsonPath ) {
125- return ;
126- }
127- const packageJson = JSON . parse ( ts . sys . readFile ( packageJsonPath ) ?? '' ) ;
128- const parentPackageJsonPath = ts . findConfigFile ( path . dirname ( path . dirname ( packageJsonPath ) ) , ts . sys . fileExists , 'package.json' ) ;
129- const parentPackageJson = ! ! parentPackageJsonPath && parentPackageJsonPath !== packageJsonPath
130- ? JSON . parse ( ts . sys . readFile ( parentPackageJsonPath ) ?? '' )
131- : { } ;
132- ts . forEachChild ( sourceFile , function visit ( node ) {
133- if (
134- ts . isImportDeclaration ( node )
135- && ! node . importClause ?. isTypeOnly
136- && ts . isStringLiteral ( node . moduleSpecifier )
137- && ! node . moduleSpecifier . text . startsWith ( './' )
138- && ! node . moduleSpecifier . text . startsWith ( '../' )
139- ) {
140- let moduleName = node . moduleSpecifier . text . split ( '/' ) [ 0 ] ;
141- if ( moduleName . startsWith ( '@' ) ) {
142- moduleName += '/' + node . moduleSpecifier . text . split ( '/' ) [ 1 ] ;
143- }
144- if (
145- (
146- packageJson . devDependencies ?. [ moduleName ]
147- || parentPackageJson . dependencies ?. [ moduleName ]
148- || parentPackageJson . devDependencies ?. [ moduleName ]
149- || parentPackageJson . peerDependencies ?. [ moduleName ]
150- )
151- && ! packageJson . dependencies ?. [ moduleName ]
152- && ! packageJson . peerDependencies ?. [ moduleName ]
153- ) {
154- reportError (
155- `Module '${ moduleName } ' should be in the dependencies.` ,
156- node . getStart ( sourceFile ) ,
157- node . getEnd ( )
158- ) ;
159- }
160- }
161- ts . forEachChild ( node , visit ) ;
162- } ) ;
163- } ,
164118 /**
165119 * @example
166120 * ```diff
167121 * - const foo = (bar) => {};
168122 * + const foo = bar => {};
169123 * ```
170124 */
171- 'arrow-parens' ( { typescript : ts , sourceFile, reportWarning } ) {
125+ 'format/ arrow-parens' ( { typescript : ts , sourceFile, reportWarning } ) {
172126 ts . forEachChild ( sourceFile , function visit ( node ) {
173127 if (
174128 ts . isArrowFunction ( node )
@@ -215,7 +169,7 @@ export function getDefaultRules(): Rules {
215169 ts . forEachChild ( node , visit ) ;
216170 } ) ;
217171 } ,
218- 'need-format' ( { typescript : ts , sourceFile, languageService, reportWarning } ) {
172+ 'format/ need-format' ( { typescript : ts , sourceFile, languageService, reportWarning } ) {
219173 const textChanges = languageService . getFormattingEditsForDocument ( sourceFile . fileName , {
220174 ...ts . getDefaultFormatCodeSettings ( ) ,
221175 convertTabsToSpaces : false ,
@@ -258,6 +212,109 @@ export function getDefaultRules(): Rules {
258212 }
259213 }
260214 } ,
215+ 'format/no-trailing-comma-in-function' ( { typescript : ts , sourceFile, reportWarning } ) {
216+ const { text } = sourceFile ;
217+ ts . forEachChild ( sourceFile , function visit ( node ) {
218+ if ( ts . isFunctionDeclaration ( node ) || ts . isArrowFunction ( node ) || ts . isMethodDeclaration ( node ) ) {
219+ const parameters = node . parameters ;
220+ if ( parameters . length > 0 ) {
221+ const lastParameter = parameters [ parameters . length - 1 ] ;
222+ const nextCharIndex = lastParameter . end ;
223+ if ( text [ nextCharIndex ] === ',' ) {
224+ reportWarning (
225+ `The last parameter of a function should not have a trailing comma.` ,
226+ lastParameter . getStart ( sourceFile ) ,
227+ lastParameter . getEnd ( )
228+ ) . withFix (
229+ 'Remove trailing comma' ,
230+ ( ) => [ {
231+ fileName : sourceFile . fileName ,
232+ textChanges : [ {
233+ span : { start : nextCharIndex , length : 1 } ,
234+ newText : ''
235+ } ]
236+ } ]
237+ ) ;
238+ }
239+ }
240+ }
241+ ts . forEachChild ( node , visit ) ;
242+ } ) ;
243+ } ,
244+ 'format/no-trailing-comma-in-function-call' ( { typescript : ts , sourceFile, reportWarning } ) {
245+ const { text } = sourceFile ;
246+ ts . forEachChild ( sourceFile , function visit ( node ) {
247+ if ( ts . isCallExpression ( node ) ) {
248+ if ( node . arguments . length > 0 ) {
249+ const lastArgument = node . arguments [ node . arguments . length - 1 ] ;
250+ const nextCharIndex = lastArgument . end ;
251+ if ( text [ nextCharIndex ] === ',' ) {
252+ reportWarning (
253+ `The last argument of a function call should not have a trailing comma.` ,
254+ lastArgument . getStart ( sourceFile ) ,
255+ lastArgument . getEnd ( )
256+ ) . withFix (
257+ 'Remove trailing comma' ,
258+ ( ) => [ {
259+ fileName : sourceFile . fileName ,
260+ textChanges : [ {
261+ span : { start : nextCharIndex , length : 1 } ,
262+ newText : ''
263+ } ]
264+ } ]
265+ ) ;
266+ }
267+ }
268+ }
269+ ts . forEachChild ( node , visit ) ;
270+ } ) ;
271+ } ,
272+ 'missing-dependency' ( { typescript : ts , sourceFile, reportError, languageServiceHost } ) {
273+ const { noEmit } = languageServiceHost . getCompilationSettings ( ) ;
274+ if ( noEmit ) {
275+ return ;
276+ }
277+ const packageJsonPath = ts . findConfigFile ( sourceFile . fileName , ts . sys . fileExists , 'package.json' ) ;
278+ if ( ! packageJsonPath ) {
279+ return ;
280+ }
281+ const packageJson = JSON . parse ( ts . sys . readFile ( packageJsonPath ) ?? '' ) ;
282+ const parentPackageJsonPath = ts . findConfigFile ( path . dirname ( path . dirname ( packageJsonPath ) ) , ts . sys . fileExists , 'package.json' ) ;
283+ const parentPackageJson = ! ! parentPackageJsonPath && parentPackageJsonPath !== packageJsonPath
284+ ? JSON . parse ( ts . sys . readFile ( parentPackageJsonPath ) ?? '' )
285+ : { } ;
286+ ts . forEachChild ( sourceFile , function visit ( node ) {
287+ if (
288+ ts . isImportDeclaration ( node )
289+ && ! node . importClause ?. isTypeOnly
290+ && ts . isStringLiteral ( node . moduleSpecifier )
291+ && ! node . moduleSpecifier . text . startsWith ( './' )
292+ && ! node . moduleSpecifier . text . startsWith ( '../' )
293+ ) {
294+ let moduleName = node . moduleSpecifier . text . split ( '/' ) [ 0 ] ;
295+ if ( moduleName . startsWith ( '@' ) ) {
296+ moduleName += '/' + node . moduleSpecifier . text . split ( '/' ) [ 1 ] ;
297+ }
298+ if (
299+ (
300+ packageJson . devDependencies ?. [ moduleName ]
301+ || parentPackageJson . dependencies ?. [ moduleName ]
302+ || parentPackageJson . devDependencies ?. [ moduleName ]
303+ || parentPackageJson . peerDependencies ?. [ moduleName ]
304+ )
305+ && ! packageJson . dependencies ?. [ moduleName ]
306+ && ! packageJson . peerDependencies ?. [ moduleName ]
307+ ) {
308+ reportError (
309+ `Module '${ moduleName } ' should be in the dependencies.` ,
310+ node . getStart ( sourceFile ) ,
311+ node . getEnd ( )
312+ ) ;
313+ }
314+ }
315+ ts . forEachChild ( node , visit ) ;
316+ } ) ;
317+ } ,
261318 /**
262319 * TODO: fix the case
263320 * let foo: Foo;
@@ -362,63 +419,6 @@ export function getDefaultRules(): Rules {
362419 ts . forEachChild ( node , visit ) ;
363420 } ) ;
364421 } ,
365- 'no-trailing-comma-in-function' ( { typescript : ts , sourceFile, reportWarning } ) {
366- const { text } = sourceFile ;
367- ts . forEachChild ( sourceFile , function visit ( node ) {
368- if ( ts . isFunctionDeclaration ( node ) || ts . isArrowFunction ( node ) || ts . isMethodDeclaration ( node ) ) {
369- const parameters = node . parameters ;
370- if ( parameters . length > 0 ) {
371- const lastParameter = parameters [ parameters . length - 1 ] ;
372- const nextCharIndex = lastParameter . end ;
373- if ( text [ nextCharIndex ] === ',' ) {
374- reportWarning (
375- `The last parameter of a function should not have a trailing comma.` ,
376- lastParameter . getStart ( sourceFile ) ,
377- lastParameter . getEnd ( )
378- ) . withFix (
379- 'Remove trailing comma' ,
380- ( ) => [ {
381- fileName : sourceFile . fileName ,
382- textChanges : [ {
383- span : { start : nextCharIndex , length : 1 } ,
384- newText : ''
385- } ]
386- } ]
387- ) ;
388- }
389- }
390- }
391- ts . forEachChild ( node , visit ) ;
392- } ) ;
393- } ,
394- 'no-trailing-comma-in-function-call' ( { typescript : ts , sourceFile, reportWarning } ) {
395- const { text } = sourceFile ;
396- ts . forEachChild ( sourceFile , function visit ( node ) {
397- if ( ts . isCallExpression ( node ) ) {
398- if ( node . arguments . length > 0 ) {
399- const lastArgument = node . arguments [ node . arguments . length - 1 ] ;
400- const nextCharIndex = lastArgument . end ;
401- if ( text [ nextCharIndex ] === ',' ) {
402- reportWarning (
403- `The last argument of a function call should not have a trailing comma.` ,
404- lastArgument . getStart ( sourceFile ) ,
405- lastArgument . getEnd ( )
406- ) . withFix (
407- 'Remove trailing comma' ,
408- ( ) => [ {
409- fileName : sourceFile . fileName ,
410- textChanges : [ {
411- span : { start : nextCharIndex , length : 1 } ,
412- newText : ''
413- } ]
414- } ]
415- ) ;
416- }
417- }
418- }
419- ts . forEachChild ( node , visit ) ;
420- } ) ;
421- } ,
422422 'no-async-without-await' ( { typescript : ts , sourceFile, reportWarning } ) {
423423 ts . forEachChild ( sourceFile , function visit ( node ) {
424424 if ( ts . isFunctionDeclaration ( node ) || ts . isArrowFunction ( node ) || ts . isMethodDeclaration ( node ) ) {
0 commit comments