1
1
import type * as TSSLint from '@tsslint/types' ;
2
2
import type * as ESLint from 'eslint' ;
3
3
import type * as ts from 'typescript' ;
4
- import type { ESLintRulesConfig } from './lib/types.js' ;
4
+ import type { ESLintRulesConfig , O } from './lib/types.js' ;
5
5
6
6
export { create as createDisableNextLinePlugin } from './lib/plugins/disableNextLine.js' ;
7
7
export { create as createShowDocsActionPlugin } from './lib/plugins/showDocsAction.js' ;
@@ -12,14 +12,21 @@ const estrees = new WeakMap<ts.SourceFile, {
12
12
eventQueue : any [ ] ;
13
13
} > ( ) ;
14
14
const noop = ( ) => { } ;
15
+ const plugins : Record < string , Promise < {
16
+ rules : Record < string , ESLint . Rule . RuleModule > ;
17
+ } > > = { } ;
18
+ const loader = async ( mod : string ) => {
19
+ try {
20
+ return require ( mod ) ;
21
+ } catch {
22
+ return await import ( mod ) ;
23
+ }
24
+ } ;
15
25
16
26
/**
17
27
* @deprecated Use `convertRules` instead.
18
28
*/
19
- export function convertConfig (
20
- rulesConfig : ESLintRulesConfig ,
21
- loader : ( mod : string ) => any = require
22
- ) {
29
+ export function convertConfig ( rulesConfig : ESLintRulesConfig ) {
23
30
const rules : TSSLint . Rules = { } ;
24
31
const plugins : Record < string , {
25
32
rules : Record < string , ESLint . Rule . RuleModule > ;
@@ -65,7 +72,7 @@ export function convertConfig(
65
72
const ruleName = rule . slice ( slashIndex + 1 ) ;
66
73
67
74
try {
68
- plugins [ pluginName ] ??= loader ( pluginName ) ;
75
+ plugins [ pluginName ] ??= require ( pluginName ) ;
69
76
} catch ( e ) {
70
77
_rule = noop ;
71
78
console . log ( '\n\n' , new Error ( `Plugin "${ pluginName } " does not exist.` ) ) ;
@@ -99,20 +106,8 @@ export function convertConfig(
99
106
return rules ;
100
107
}
101
108
102
- export async function convertRules (
103
- rulesConfig : ESLintRulesConfig ,
104
- loader = async ( mod : string ) => {
105
- try {
106
- return require ( mod ) ;
107
- } catch {
108
- return await import ( mod ) ;
109
- }
110
- }
111
- ) {
109
+ export async function convertRules ( rulesConfig : ESLintRulesConfig ) {
112
110
const rules : TSSLint . Rules = { } ;
113
- const plugins : Record < string , Promise < {
114
- rules : Record < string , ESLint . Rule . RuleModule > ;
115
- } > > = { } ;
116
111
for ( const [ rule , severityOrOptions ] of Object . entries ( rulesConfig ) ) {
117
112
let rawSeverity : 'error' | 'warn' | 'suggestion' | 'off' | 0 | 1 | 2 ;
118
113
let options : any [ ] ;
@@ -142,45 +137,91 @@ export async function convertRules(
142
137
rules [ rule ] = noop ;
143
138
continue ;
144
139
}
145
- rules [ rule ] = await loadRuleByKey ( rule , options , tsSeverity ) ;
140
+ const ruleModule = await getRuleByKey ( rule ) ;
141
+ if ( ! ruleModule ) {
142
+ rules [ rule ] = noop ;
143
+ continue ;
144
+ }
145
+ rules [ rule ] = convertRule ( ruleModule , options , tsSeverity ) ;
146
146
}
147
147
return rules ;
148
+ }
149
+
150
+ export async function convertFormattingRules ( config : {
151
+ [ K in keyof ESLintRulesConfig ] ?: ESLintRulesConfig [ K ] extends O < infer T > | undefined ? T : never ;
152
+ } ) {
153
+ const processes : TSSLint . FormattingProcess [ ] = [ ] ;
154
+ for ( const [ rule , options ] of Object . entries ( config ) ) {
155
+ const ruleModule = await getRuleByKey ( rule ) ;
156
+ if ( ! ruleModule ) {
157
+ continue ;
158
+ }
159
+ const tsslingRule = convertRule ( ruleModule , options , 2 satisfies ts . DiagnosticCategory . Suggestion ) ;
160
+ processes . push ( ctx => {
161
+ const reporter : TSSLint . Reporter = {
162
+ withDeprecated : ( ) => reporter ,
163
+ withUnnecessary : ( ) => reporter ,
164
+ withRefactor : ( ) => reporter ,
165
+ withFix ( _title , getChanges ) {
166
+ const changes = getChanges ( ) ;
167
+ for ( const change of changes ) {
168
+ if ( change . fileName !== ctx . sourceFile . fileName ) {
169
+ continue ;
170
+ }
171
+ for ( const textChange of change . textChanges ) {
172
+ ctx . replace ( textChange . span . start , textChange . span . start + textChange . span . length , textChange . newText ) ;
173
+ }
174
+ }
175
+ return reporter ;
176
+ } ,
177
+ } ;
178
+ tsslingRule ( {
179
+ ...ctx ,
180
+ languageService : { } as any ,
181
+ languageServiceHost : {
182
+ getCompilationSettings : ( ) => ( { } ) ,
183
+ } as any ,
184
+ reportError : ( ) => reporter ,
185
+ reportWarning : ( ) => reporter ,
186
+ reportSuggestion : ( ) => reporter ,
187
+ } ) ;
188
+ } ) ;
189
+ }
190
+ return processes ;
191
+ }
148
192
149
- async function loadRuleByKey ( rule : string , options : any [ ] , tsSeverity ?: ts . DiagnosticCategory ) {
150
- let ruleModule : ESLint . Rule . RuleModule ;
151
- const slashIndex = rule . indexOf ( '/' ) ;
152
- if ( slashIndex !== - 1 ) {
153
- const pluginName = rule . startsWith ( '@' )
154
- ? `${ rule . slice ( 0 , slashIndex ) } /eslint-plugin`
155
- : `eslint-plugin-${ rule . slice ( 0 , slashIndex ) } ` ;
156
- const ruleName = rule . slice ( slashIndex + 1 ) ;
193
+ async function getRuleByKey ( rule : string ) {
194
+ const slashIndex = rule . indexOf ( '/' ) ;
195
+ if ( slashIndex !== - 1 ) {
196
+ const pluginName = rule . startsWith ( '@' )
197
+ ? `${ rule . slice ( 0 , slashIndex ) } /eslint-plugin`
198
+ : `eslint-plugin-${ rule . slice ( 0 , slashIndex ) } ` ;
199
+ const ruleName = rule . slice ( slashIndex + 1 ) ;
157
200
158
- try {
159
- plugins [ pluginName ] ??= loader ( pluginName ) ;
160
- } catch ( e ) {
161
- console . log ( '\n\n' , new Error ( `Plugin "${ pluginName } " does not exist.` ) ) ;
162
- return noop ;
163
- }
201
+ try {
202
+ plugins [ pluginName ] ??= loader ( pluginName ) ;
203
+ } catch ( e ) {
204
+ console . log ( '\n\n' , new Error ( `Plugin "${ pluginName } " does not exist.` ) ) ;
205
+ return ;
206
+ }
164
207
165
- let plugin = await plugins [ pluginName ] ;
166
- if ( 'default' in plugin ) {
167
- // @ts -expect-error
168
- plugin = plugin . default ;
169
- }
170
- ruleModule = plugin . rules [ ruleName ] ;
171
- if ( ! ruleModule ) {
172
- console . log ( '\n\n' , new Error ( `Rule "${ ruleName } " does not exist in plugin "${ pluginName } ".` ) ) ;
173
- return noop ;
174
- }
208
+ let plugin = await plugins [ pluginName ] ;
209
+ if ( 'default' in plugin ) {
210
+ // @ts -expect-error
211
+ plugin = plugin . default ;
175
212
}
176
- else {
177
- try {
178
- ruleModule = require ( `../../eslint/lib/rules/${ rule } .js` ) ;
179
- } catch {
180
- ruleModule = require ( `./node_modules/eslint/lib/rules/${ rule } .js` ) ;
181
- }
213
+ if ( ! plugin . rules [ ruleName ] ) {
214
+ console . log ( '\n\n' , new Error ( `Rule "${ ruleName } " does not exist in plugin "${ pluginName } ".` ) ) ;
215
+ return ;
216
+ }
217
+ return plugin . rules [ ruleName ] ;
218
+ }
219
+ else {
220
+ try {
221
+ return require ( `../../eslint/lib/rules/${ rule } .js` ) ;
222
+ } catch {
223
+ return require ( `./node_modules/eslint/lib/rules/${ rule } .js` ) ;
182
224
}
183
- return convertRule ( ruleModule , options , tsSeverity ) ;
184
225
}
185
226
}
186
227
@@ -216,7 +257,7 @@ export function convertRule(
216
257
const { sourceCode, eventQueue } = getEstree (
217
258
sourceFile ,
218
259
languageService ,
219
- ( ) => languageServiceHost . getCompilationSettings ( )
260
+ languageServiceHost . getCompilationSettings ( )
220
261
) ;
221
262
const emitter = createEmitter ( ) ;
222
263
@@ -504,7 +545,7 @@ export function convertRule(
504
545
function getEstree (
505
546
sourceFile : ts . SourceFile ,
506
547
languageService : ts . LanguageService ,
507
- getCompilationSettings : ( ) => ts . CompilerOptions
548
+ compilationSettings : ts . CompilerOptions
508
549
) {
509
550
if ( ! estrees . has ( sourceFile ) ) {
510
551
let program : ts . Program | undefined ;
@@ -530,8 +571,8 @@ function getEstree(
530
571
range : true ,
531
572
preserveNodeMaps : true ,
532
573
filePath : sourceFile . fileName ,
533
- emitDecoratorMetadata : getCompilationSettings ( ) . emitDecoratorMetadata ?? false ,
534
- experimentalDecorators : getCompilationSettings ( ) . experimentalDecorators ?? false ,
574
+ emitDecoratorMetadata : compilationSettings . emitDecoratorMetadata ?? false ,
575
+ experimentalDecorators : compilationSettings . experimentalDecorators ?? false ,
535
576
} ) ;
536
577
const sourceCode = new SourceCode ( {
537
578
text : sourceFile . text ,
0 commit comments