1
1
// @ts -check
2
2
const eslint = require ( 'eslint' )
3
+ const semver = require ( 'semver' )
4
+
5
+ let ESLint = eslint . ESLint
6
+ let Linter = eslint . Linter
7
+ let RuleTester = eslint . RuleTester
8
+ if ( semver . lt ( eslint . Linter . version , '9.0.0-0' ) ) {
9
+ ESLint = eslint . ESLint ? getESLintClassForV8 ( ) : getESLintClassForV6 ( )
10
+ Linter = getLinterClassForV8 ( )
11
+ RuleTester = getRuleTesterClassForV8 ( )
12
+ }
3
13
4
14
module . exports = {
5
- ESLint : eslint . ESLint || getESLintClassForV6 ( ) ,
6
- RuleTester : eslint . RuleTester
15
+ ESLint,
16
+ RuleTester,
17
+ Linter
7
18
}
8
19
20
+ /** @returns {typeof eslint.ESLint } */
21
+ function getESLintClassForV8 ( BaseESLintClass = eslint . ESLint ) {
22
+ return class ESLintForV8 extends BaseESLintClass {
23
+ static get version ( ) {
24
+ return BaseESLintClass . version
25
+ }
26
+ constructor ( options ) {
27
+ super ( adjustOptions ( options ) )
28
+ }
29
+ }
30
+
31
+ // eslint-disable-next-line unicorn/consistent-function-scoping
32
+ function adjustOptions ( options ) {
33
+ const newOptions = {
34
+ ...options ,
35
+ useEslintrc : false
36
+ }
37
+ if ( newOptions . overrideConfig ) {
38
+ newOptions . overrideConfig = { ...newOptions . overrideConfig }
39
+ let plugins
40
+ if ( newOptions . overrideConfig . plugins ) {
41
+ plugins = newOptions . overrideConfig . plugins
42
+ delete newOptions . overrideConfig . plugins
43
+ }
44
+ newOptions . overrideConfig = processCompatibleConfig (
45
+ newOptions . overrideConfig
46
+ )
47
+ if ( plugins ) {
48
+ newOptions . overrideConfig . plugins = Object . keys ( plugins )
49
+ newOptions . plugins = plugins
50
+ }
51
+
52
+ // adjust
53
+ delete newOptions . overrideConfig . files
54
+ delete newOptions . overrideConfig . processor
55
+ }
56
+ return newOptions
57
+ }
58
+ }
9
59
/** @returns {typeof eslint.ESLint } */
10
60
function getESLintClassForV6 ( ) {
11
61
class ESLintForV6 {
12
62
static get version ( ) {
63
+ // @ts -expect-error
13
64
return eslint . CLIEngine . version
14
65
}
15
66
@@ -26,7 +77,7 @@ function getESLintClassForV6() {
26
77
plugins : pluginsMap ,
27
78
...otherOptions
28
79
} = options || { }
29
- /** @type { eslint.CLIEngine.Options } */
80
+
30
81
const newOptions = {
31
82
fix : Boolean ( fix ) ,
32
83
reportUnusedDisableDirectives : reportUnusedDisableDirectives
@@ -47,6 +98,8 @@ function getESLintClassForV6() {
47
98
: undefined ,
48
99
...overrideConfig
49
100
}
101
+
102
+ // @ts -expect-error
50
103
this . engine = new eslint . CLIEngine ( newOptions )
51
104
52
105
for ( const [ name , plugin ] of Object . entries ( pluginsMap || { } ) ) {
@@ -59,12 +112,105 @@ function getESLintClassForV6() {
59
112
* @returns {ReturnType<eslint.ESLint['lintText']> }
60
113
*/
61
114
async lintText ( ...params ) {
62
- const result = this . engine . executeOnText ( params [ 0 ] , params [ 1 ] . filePath )
115
+ const result = this . engine . executeOnText ( params [ 0 ] , params [ 1 ] ? .filePath )
63
116
return result . results
64
117
}
65
118
}
66
119
67
120
/** @type {typeof eslint.ESLint } */
68
121
const eslintClass = /** @type {any } */ ( ESLintForV6 )
69
- return eslintClass
122
+ return getESLintClassForV8 ( eslintClass )
123
+ }
124
+
125
+ /** @returns {typeof eslint.Linter } */
126
+ function getLinterClassForV8 ( ) {
127
+ return class LinterForV8 extends eslint . Linter {
128
+ static get version ( ) {
129
+ return eslint . Linter . version
130
+ }
131
+ verify ( code , config , option ) {
132
+ return super . verify ( code , processCompatibleConfig ( config , this ) , option )
133
+ }
134
+ }
135
+ }
136
+
137
+ function getRuleTesterClassForV8 ( ) {
138
+ return class RuleTesterForV8 extends eslint . RuleTester {
139
+ constructor ( options ) {
140
+ const defineRules = [ ]
141
+ super (
142
+ processCompatibleConfig ( options , {
143
+ defineRule ( ...args ) {
144
+ defineRules . push ( args )
145
+ }
146
+ } )
147
+ )
148
+ for ( const args of defineRules ) {
149
+ // @ts -expect-error
150
+ this . linter . defineRule ( ...args )
151
+ }
152
+ }
153
+ run ( name , rule , tests ) {
154
+ super . run ( name , rule , {
155
+ valid : ( tests . valid || [ ] ) . map ( ( test ) =>
156
+ typeof test === 'string' ? test : adjustOptions ( test )
157
+ ) ,
158
+ invalid : ( tests . invalid || [ ] ) . map ( ( test ) => adjustOptions ( test ) )
159
+ } )
160
+ }
161
+ }
162
+ // eslint-disable-next-line unicorn/consistent-function-scoping
163
+ function adjustOptions ( test ) {
164
+ return processCompatibleConfig ( test )
165
+ }
166
+ }
167
+
168
+ function processCompatibleConfig ( config , linter ) {
169
+ const newConfig = { ...config }
170
+ if ( newConfig . languageOptions ) {
171
+ const languageOptions = newConfig . languageOptions
172
+ delete newConfig . languageOptions
173
+ newConfig . parserOptions = {
174
+ ...newConfig . parserOptions ,
175
+ ...languageOptions ,
176
+ ...languageOptions . parserOptions
177
+ }
178
+ if ( languageOptions . globals ) {
179
+ newConfig . globals = {
180
+ ...newConfig . globals ,
181
+ ...languageOptions . globals
182
+ }
183
+ }
184
+ if ( languageOptions . parser ) {
185
+ newConfig . parser = getParserName ( languageOptions . parser )
186
+ if ( ! languageOptions . parserOptions ?. parser ) {
187
+ delete newConfig . parserOptions . parser
188
+ }
189
+ linter ?. defineParser ?. ( newConfig . parser , require ( newConfig . parser ) )
190
+ }
191
+ }
192
+ if ( newConfig . plugins ) {
193
+ const plugins = newConfig . plugins
194
+ delete newConfig . plugins
195
+ for ( const [ pluginName , plugin ] of Object . entries ( plugins ) ) {
196
+ for ( const [ ruleName , rule ] of Object . entries ( plugin . rules || { } ) ) {
197
+ linter . defineRule ( `${ pluginName } /${ ruleName } ` , rule )
198
+ }
199
+ }
200
+ }
201
+ newConfig . env = { ...newConfig . env , es6 : true }
202
+ return newConfig
203
+ }
204
+
205
+ function getParserName ( parser ) {
206
+ const name = parser . meta ?. name || parser . name
207
+ if ( name === 'typescript-eslint/parser' ) {
208
+ return require . resolve ( '@typescript-eslint/parser' )
209
+ } else if (
210
+ name == null &&
211
+ // @ts -expect-error
212
+ parser === require ( '@typescript-eslint/parser' )
213
+ )
214
+ return require . resolve ( '@typescript-eslint/parser' )
215
+ return require . resolve ( name )
70
216
}
0 commit comments