@@ -2,8 +2,10 @@ import type { ESLintExtendedProgram, ESLintProgram } from "../ast"
2
2
import type { ParserOptions } from "../common/parser-options"
3
3
import { getLinterRequire } from "./linter-require"
4
4
// @ts -expect-error -- ignore
5
- import * as espree from "espree"
5
+ import * as dependencyEspree from "espree"
6
6
import { lte , lt } from "semver"
7
+ import { createRequire } from "./create-require"
8
+ import path from "path"
7
9
8
10
/**
9
11
* The interface of a result of ESLint custom parser.
@@ -17,66 +19,59 @@ export interface ESLintCustomParser {
17
19
parse ( code : string , options : any ) : ESLintCustomParserResult
18
20
parseForESLint ?( code : string , options : any ) : ESLintCustomParserResult
19
21
}
20
- type OldEspree = ESLintCustomParser & {
21
- latestEcmaVersion ?: number
22
- version : string
23
- }
24
22
type Espree = ESLintCustomParser & {
25
- latestEcmaVersion : number
23
+ latestEcmaVersion ? : number
26
24
version : string
27
25
}
28
- let espreeCache : OldEspree | Espree | null = null
26
+ let espreeCache : Espree | null = null
29
27
30
28
/**
31
29
* Gets the espree that the given ecmaVersion can parse.
32
30
*/
33
31
export function getEspreeFromEcmaVersion (
34
32
ecmaVersion : ParserOptions [ "ecmaVersion" ] ,
35
- ) : OldEspree | Espree {
33
+ ) : Espree {
36
34
const linterEspree = getEspreeFromLinter ( )
37
- if (
38
- linterEspree . version != null &&
39
- lte ( espree . version , linterEspree . version )
40
- ) {
41
- // linterEspree is newest
42
- return linterEspree
43
- }
44
35
if ( ecmaVersion == null ) {
45
36
return linterEspree
46
37
}
47
38
if ( ecmaVersion === "latest" ) {
48
- return espree
39
+ return getNewestEspree ( )
49
40
}
50
- if ( normalizeEcmaVersion ( ecmaVersion ) <= getLinterLatestEcmaVersion ( ) ) {
41
+ if (
42
+ normalizeEcmaVersion ( ecmaVersion ) <= getLatestEcmaVersion ( linterEspree )
43
+ ) {
51
44
return linterEspree
52
45
}
53
- return espree
46
+ const userEspree = getEspreeFromUser ( )
47
+ if ( normalizeEcmaVersion ( ecmaVersion ) <= getLatestEcmaVersion ( userEspree ) ) {
48
+ return userEspree
49
+ }
50
+ return linterEspree
51
+ }
54
52
55
- function getLinterLatestEcmaVersion ( ) {
56
- if ( linterEspree . latestEcmaVersion == null ) {
57
- for ( const { v, latest } of [
58
- { v : "6.1.0" , latest : 2020 } ,
59
- { v : "4.0.0" , latest : 2019 } ,
60
- ] ) {
61
- if ( lte ( v , linterEspree . version ) ) {
62
- return latest
63
- }
64
- }
65
- return 2018
66
- }
67
- return normalizeEcmaVersion ( linterEspree . latestEcmaVersion )
53
+ /**
54
+ * Load `espree` from the user dir.
55
+ */
56
+ export function getEspreeFromUser ( ) : Espree {
57
+ try {
58
+ const cwd = process . cwd ( )
59
+ const relativeTo = path . join ( cwd , "__placeholder__.js" )
60
+ return createRequire ( relativeTo ) ( "espree" )
61
+ } catch {
62
+ return getEspreeFromLinter ( )
68
63
}
69
64
}
70
65
71
66
/**
72
67
* Load `espree` from the loaded ESLint.
73
68
* If the loaded ESLint was not found, just returns `require("espree")`.
74
69
*/
75
- export function getEspreeFromLinter ( ) : Espree | OldEspree {
70
+ export function getEspreeFromLinter ( ) : Espree {
76
71
if ( ! espreeCache ) {
77
72
espreeCache = getLinterRequire ( ) ?.( "espree" )
78
73
if ( ! espreeCache ) {
79
- espreeCache = espree
74
+ espreeCache = dependencyEspree
80
75
}
81
76
}
82
77
@@ -87,14 +82,19 @@ export function getEspreeFromLinter(): Espree | OldEspree {
87
82
* Load the newest `espree` from the loaded ESLint or dependency.
88
83
*/
89
84
function getNewestEspree ( ) : Espree {
85
+ let newest = dependencyEspree
90
86
const linterEspree = getEspreeFromLinter ( )
91
87
if (
92
- linterEspree . version == null ||
93
- lte ( linterEspree . version , espree . version )
88
+ linterEspree . version != null &&
89
+ lte ( newest . version , linterEspree . version )
94
90
) {
95
- return espree
91
+ newest = linterEspree
96
92
}
97
- return linterEspree as Espree
93
+ const userEspree = getEspreeFromUser ( )
94
+ if ( userEspree . version != null && lte ( newest . version , userEspree . version ) ) {
95
+ newest = userEspree
96
+ }
97
+ return newest
98
98
}
99
99
100
100
export function getEcmaVersionIfUseEspree (
@@ -106,7 +106,7 @@ export function getEcmaVersionIfUseEspree(
106
106
}
107
107
108
108
if ( parserOptions . ecmaVersion === "latest" ) {
109
- return normalizeEcmaVersion ( getNewestEspree ( ) . latestEcmaVersion )
109
+ return normalizeEcmaVersion ( getLatestEcmaVersion ( getNewestEspree ( ) ) )
110
110
}
111
111
if ( parserOptions . ecmaVersion == null ) {
112
112
const defVer = getDefaultEcmaVersion ( )
@@ -120,7 +120,7 @@ function getDefaultEcmaVersion(): number {
120
120
return 5
121
121
}
122
122
// Perhaps the version 9 will change the default to "latest".
123
- return normalizeEcmaVersion ( getNewestEspree ( ) . latestEcmaVersion )
123
+ return normalizeEcmaVersion ( getLatestEcmaVersion ( getNewestEspree ( ) ) )
124
124
}
125
125
126
126
/**
@@ -132,3 +132,18 @@ function normalizeEcmaVersion(version: number) {
132
132
}
133
133
return version
134
134
}
135
+
136
+ function getLatestEcmaVersion ( espree : Espree ) {
137
+ if ( espree . latestEcmaVersion == null ) {
138
+ for ( const { v, latest } of [
139
+ { v : "6.1.0" , latest : 2020 } ,
140
+ { v : "4.0.0" , latest : 2019 } ,
141
+ ] ) {
142
+ if ( lte ( v , espree . version ) ) {
143
+ return latest
144
+ }
145
+ }
146
+ return 2018
147
+ }
148
+ return normalizeEcmaVersion ( espree . latestEcmaVersion )
149
+ }
0 commit comments