11// @ts -check
22const 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+ }
313
414module . exports = {
5- ESLint : eslint . ESLint || getESLintClassForV6 ( ) ,
6- RuleTester : eslint . RuleTester
15+ ESLint,
16+ RuleTester,
17+ Linter
718}
819
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+ }
959/** @returns {typeof eslint.ESLint } */
1060function getESLintClassForV6 ( ) {
1161 class ESLintForV6 {
1262 static get version ( ) {
63+ // @ts -expect-error
1364 return eslint . CLIEngine . version
1465 }
1566
@@ -26,7 +77,7 @@ function getESLintClassForV6() {
2677 plugins : pluginsMap ,
2778 ...otherOptions
2879 } = options || { }
29- /** @type { eslint.CLIEngine.Options } */
80+
3081 const newOptions = {
3182 fix : Boolean ( fix ) ,
3283 reportUnusedDisableDirectives : reportUnusedDisableDirectives
@@ -47,6 +98,8 @@ function getESLintClassForV6() {
4798 : undefined ,
4899 ...overrideConfig
49100 }
101+
102+ // @ts -expect-error
50103 this . engine = new eslint . CLIEngine ( newOptions )
51104
52105 for ( const [ name , plugin ] of Object . entries ( pluginsMap || { } ) ) {
@@ -59,12 +112,105 @@ function getESLintClassForV6() {
59112 * @returns {ReturnType<eslint.ESLint['lintText']> }
60113 */
61114 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 )
63116 return result . results
64117 }
65118 }
66119
67120 /** @type {typeof eslint.ESLint } */
68121 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 )
70216}
0 commit comments