Skip to content

Commit 9136696

Browse files
authored
feat(eslint): support eslint7 and @babel/eslint-parser (#6059)
closes #5734 closes #5981
1 parent 482ef10 commit 9136696

File tree

11 files changed

+359
-33
lines changed

11 files changed

+359
-33
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
},
4747
"devDependencies": {
4848
"@babel/core": "^7.11.6",
49+
"@babel/eslint-parser": "^7.12.1",
4950
"@typescript-eslint/eslint-plugin": "^2.33.0",
5051
"@typescript-eslint/parser": "^2.33.0",
5152
"@vue/eslint-config-airbnb": "^5.0.2",
@@ -55,11 +56,10 @@
5556
"@vuepress/plugin-pwa": "^1.5.4",
5657
"@vuepress/theme-vue": "^1.5.4",
5758
"babel-core": "7.0.0-bridge.0",
58-
"babel-eslint": "^10.1.0",
5959
"babel-jest": "^24.9.0",
6060
"chromedriver": "^87.0.0",
6161
"debug": "^4.1.0",
62-
"eslint": "^6.7.2",
62+
"eslint": "^7.13.0",
6363
"eslint-plugin-graphql": "^3.1.0",
6464
"eslint-plugin-import": "^2.20.2",
6565
"eslint-plugin-node": "^11.1.0",

packages/@vue/cli-plugin-eslint/__tests__/eslintGenerator.spec.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,26 @@ test('babel', async () => {
8383
])
8484

8585
expect(pkg.scripts.lint).toBeTruthy()
86-
expect(pkg.devDependencies).toHaveProperty('babel-eslint')
86+
expect(pkg.devDependencies).toHaveProperty('@babel/eslint-parser')
87+
expect(pkg.devDependencies).toHaveProperty('@babel/core')
8788
expect(pkg.eslintConfig.parserOptions).toEqual({
88-
parser: 'babel-eslint'
89+
parser: '@babel/eslint-parser'
90+
})
91+
})
92+
93+
test('no-@babel/eslint-parser', async () => {
94+
const { pkg } = await generateWithPlugin([
95+
{
96+
id: 'eslint',
97+
apply: require('../generator'),
98+
options: {}
99+
}
100+
])
101+
102+
expect(pkg.devDependencies).not.toHaveProperty('@babel/eslint-parser')
103+
expect(pkg.devDependencies).not.toHaveProperty('@babel/core')
104+
expect(pkg.eslintConfig.parserOptions).not.toMatchObject({
105+
parser: '@babel/eslint-parser'
89106
})
90107
})
91108

packages/@vue/cli-plugin-eslint/__tests__/eslintMigrator.spec.js

Lines changed: 143 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ test('upgrade: should add eslint to devDependencies', async () => {
1717
await project.upgrade('eslint')
1818

1919
const updatedPkg = JSON.parse(await project.read('package.json'))
20-
expect(updatedPkg.devDependencies.eslint).toMatch('^6')
20+
expect(updatedPkg.devDependencies.eslint).toMatch('^7')
2121
})
2222

23-
test('upgrade: should upgrade eslint from v5 to v6', async () => {
23+
test('upgrade: should upgrade eslint from v5 to v7', async () => {
2424
const project = await create('plugin-eslint-with-eslint-5', {
2525
plugins: {
2626
'@vue/cli-plugin-eslint': {
@@ -43,6 +43,146 @@ test('upgrade: should upgrade eslint from v5 to v6', async () => {
4343
}
4444

4545
const updatedPkg = JSON.parse(await project.read('package.json'))
46-
expect(updatedPkg.devDependencies.eslint).toMatch('^6')
46+
expect(updatedPkg.devDependencies.eslint).toMatch('^7')
4747
expect(updatedPkg.devDependencies).toHaveProperty('eslint-plugin-import')
4848
})
49+
50+
test.each([['3.12.1'], ['4.5.8']])('upgrade: replace babel-eslint with @babel/eslint-parser', async (version) => {
51+
const project = await create('plugin-eslint-replace-babel-eslint' + version[0], {
52+
plugins: {
53+
'@vue/cli-plugin-eslint': {
54+
version,
55+
config: 'airbnb'
56+
},
57+
'@vue/cli-plugin-babel': {
58+
version,
59+
config: 'airbnb'
60+
}
61+
}
62+
})
63+
64+
const pkg = JSON.parse(await project.read('package.json'))
65+
expect(pkg.devDependencies).toHaveProperty('babel-eslint')
66+
expect(pkg.devDependencies).not.toHaveProperty('@babel/core')
67+
expect(pkg.eslintConfig).toMatchObject({
68+
parserOptions: {
69+
parser: 'babel-eslint'
70+
}
71+
})
72+
pkg.eslintConfig.parserOptions.testMerge = 'testMerge'
73+
await project.write('package.json', JSON.stringify(pkg, null, 2))
74+
const eslintConfigBefore = pkg.eslintConfig
75+
76+
await project.upgrade('eslint')
77+
78+
const updatedPkg = JSON.parse(await project.read('package.json'))
79+
expect(updatedPkg.eslintConfig).toMatchObject({
80+
...eslintConfigBefore,
81+
parserOptions: {
82+
testMerge: 'testMerge',
83+
parser: '@babel/eslint-parser'
84+
}
85+
})
86+
expect(updatedPkg.devDependencies['@babel/eslint-parser']).toMatch('^7')
87+
expect(updatedPkg.devDependencies).not.toHaveProperty('babel-eslint')
88+
expect(updatedPkg.devDependencies).toHaveProperty('@babel/core')
89+
})
90+
91+
test('upgrade: not add @babel/eslint-parser without babel', async () => {
92+
const project = await create('plugin-eslint-not-replace-babel-eslint', {
93+
plugins: {
94+
'@vue/cli-plugin-eslint': {
95+
version: '3.12.1',
96+
config: 'airbnb'
97+
}
98+
}
99+
})
100+
101+
await project.upgrade('eslint')
102+
103+
const updatedPkg = await project.read('package.json')
104+
expect(updatedPkg).not.toMatch('@babel/eslint-parser')
105+
expect(updatedPkg).not.toMatch('@babel/core')
106+
expect(JSON.parse(updatedPkg).devDependencies.eslint).toMatch('^7')
107+
})
108+
109+
test('upgrade: not add @babel/eslint-parser with ts', async () => {
110+
const project = await create('plugin-eslint-not-add-babel-eslint-ts', {
111+
plugins: {
112+
'@vue/cli-plugin-eslint': {
113+
version: '3.12.1',
114+
config: 'airbnb'
115+
},
116+
'@vue/cli-plugin-typescript': {
117+
version: '3.12.1',
118+
config: 'airbnb'
119+
}
120+
}
121+
})
122+
123+
await project.upgrade('eslint')
124+
125+
const updatedPkg = await project.read('package.json')
126+
expect(updatedPkg).not.toMatch('@babel/eslint-parser')
127+
expect(updatedPkg).not.toMatch('@babel/core')
128+
expect(updatedPkg).toMatch('@typescript-eslint/parser')
129+
expect(JSON.parse(updatedPkg).devDependencies.eslint).toMatch('^7')
130+
})
131+
132+
test('upgrade: replace babel-eslint with @babel/eslint-parser in eslintrc.js', async () => {
133+
const project = await create('plugin-eslint-replace-babel-eslint-eslintrc', {
134+
useConfigFiles: true,
135+
plugins: {
136+
'@vue/cli-plugin-eslint': {
137+
version: '3.12.1',
138+
config: 'airbnb'
139+
},
140+
'@vue/cli-plugin-babel': {
141+
version: '3.12.1',
142+
config: 'airbnb'
143+
}
144+
}
145+
})
146+
147+
const eslintrc = await project.read('.eslintrc.js')
148+
expect(eslintrc).toMatch('babel-eslint')
149+
const eslintrcMerge = eslintrc.replace(`parser: 'babel-eslint'`, `testMerge: 'testMerge', parser: 'babel-eslint'`)
150+
await project.write('.eslintrc.js', eslintrcMerge)
151+
152+
await project.upgrade('eslint')
153+
154+
const updatedEslintrc = await project.read('.eslintrc.js')
155+
expect(updatedEslintrc).toMatch('@babel/eslint-parser')
156+
expect(updatedEslintrc).toMatch('testMerge')
157+
158+
const updatedPkg = JSON.parse(await project.read('package.json'))
159+
expect(updatedPkg.devDependencies).not.toHaveProperty('babel-eslint')
160+
expect(updatedPkg.devDependencies.eslint).toMatch('^7')
161+
})
162+
163+
test.each([
164+
['7.1.0', true],
165+
['7.2.0', false]
166+
])('upgrade: local @babel/core exists', async (localBabelCoreVersion, bumpVersion) => {
167+
const project = await create('plugin-eslint-core-' + String(bumpVersion), {
168+
plugins: {
169+
'@vue/cli-plugin-eslint': {
170+
version: '3.12.1',
171+
config: 'airbnb'
172+
},
173+
'@vue/cli-plugin-babel': {
174+
version: '3.12.1',
175+
config: 'airbnb'
176+
}
177+
}
178+
})
179+
180+
const pkg = JSON.parse(await project.read('package.json'))
181+
pkg.devDependencies['@babel/core'] = localBabelCoreVersion
182+
await project.write('package.json', JSON.stringify(pkg, null, 2))
183+
184+
await project.upgrade('eslint')
185+
186+
const updatedPkg = JSON.parse(await project.read('package.json'))
187+
expect(updatedPkg.devDependencies['@babel/core'] !== localBabelCoreVersion).toBe(bumpVersion)
188+
})

packages/@vue/cli-plugin-eslint/eslintDeps.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const DEPS_MAP = {
22
base: {
3-
eslint: '^6.7.2',
3+
eslint: '^7.13.0',
44
'eslint-plugin-vue': '^6.2.2'
55
},
66
airbnb: {
@@ -20,9 +20,9 @@ const DEPS_MAP = {
2020
'eslint-plugin-standard': '^4.0.0'
2121
},
2222
typescript: {
23-
'@vue/eslint-config-typescript': '^5.1.0',
24-
'@typescript-eslint/eslint-plugin': '^2.33.0',
25-
'@typescript-eslint/parser': '^2.33.0'
23+
'@vue/eslint-config-typescript': '^7.0.0',
24+
'@typescript-eslint/eslint-plugin': '^4.4.0',
25+
'@typescript-eslint/parser': '^4.4.0'
2626
}
2727
}
2828

@@ -41,7 +41,8 @@ exports.getDeps = function (api, preset, rootOptions = {}) {
4141

4242
if (api.hasPlugin('babel') && !api.hasPlugin('typescript')) {
4343
Object.assign(deps, {
44-
'babel-eslint': '^10.1.0'
44+
'@babel/eslint-parser': '^7.12.1',
45+
'@babel/core': '^7.12.3'
4546
})
4647
}
4748

packages/@vue/cli-plugin-eslint/eslintOptions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ exports.config = (api, preset, rootOptions = {}) => {
1414

1515
if (api.hasPlugin('babel') && !api.hasPlugin('typescript')) {
1616
config.parserOptions = {
17-
parser: 'babel-eslint'
17+
parser: '@babel/eslint-parser'
1818
}
1919
}
2020

packages/@vue/cli-plugin-eslint/migrator/index.js

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { semver } = require('@vue/cli-shared-utils')
22

3+
/** @param {import('@vue/cli/lib/MigratorAPI')} api MigratorAPI */
34
module.exports = async (api) => {
45
const pkg = require(api.resolve('package.json'))
56

@@ -13,7 +14,7 @@ module.exports = async (api) => {
1314
api.extendPackage({
1415
devDependencies: {
1516
eslint: localESLintRange,
16-
'babel-eslint': '^8.2.5',
17+
'@babel/eslint-parser': '^7.12.1',
1718
'eslint-plugin-vue': '^4.5.0'
1819
}
1920
})
@@ -24,10 +25,11 @@ module.exports = async (api) => {
2425
// in case the user does not specify a typical caret range;
2526
// it is used as **fallback** because the user may have not previously
2627
// installed eslint yet, such as in the case that they are from v3.0.x
28+
// eslint-disable-next-line node/no-extraneous-require
2729
require('eslint/package.json').version
2830
)
2931

30-
if (localESLintMajor >= 6) {
32+
if (localESLintMajor > 6) {
3133
return
3234
}
3335

@@ -44,7 +46,30 @@ module.exports = async (api) => {
4446
Object.assign(newDeps, getDeps(api, 'prettier'))
4547
}
4648

47-
api.extendPackage({ devDependencies: newDeps }, { warnIncompatibleVersions: false })
49+
const fields = { devDependencies: newDeps }
50+
51+
if (newDeps['@babel/core'] && newDeps['@babel/eslint-parser']) {
52+
Reflect.deleteProperty(api.generator.pkg.devDependencies, 'babel-eslint')
53+
54+
const minSupportedBabelCoreVersion = '>=7.2.0'
55+
const localBabelCoreVersion = pkg.devDependencies['@babel/core']
56+
57+
if (localBabelCoreVersion &&
58+
semver.satisfies(
59+
localBabelCoreVersion,
60+
minSupportedBabelCoreVersion
61+
)) {
62+
Reflect.deleteProperty(newDeps, '@babel/core')
63+
}
64+
65+
fields.eslintConfig = {
66+
parserOptions: {
67+
parser: '@babel/eslint-parser'
68+
}
69+
}
70+
}
71+
72+
api.extendPackage(fields, { warnIncompatibleVersions: false })
4873

4974
// in case anyone's upgrading from the legacy `typescript-eslint-parser`
5075
if (api.hasPlugin('typescript')) {
@@ -57,7 +82,7 @@ module.exports = async (api) => {
5782
})
5883
}
5984

60-
api.exitLog(`ESLint upgraded from v${localESLintMajor}. to v6\n`)
85+
api.exitLog(`ESLint upgraded from v${localESLintMajor}. to v7\n`)
6186

6287
// TODO:
6388
// transform `@vue/prettier` to `eslint:recommended` + `@vue/prettier`

packages/@vue/cli-plugin-eslint/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@
3232
},
3333
"peerDependencies": {
3434
"@vue/cli-service": "^3.0.0 || ^4.0.0-0",
35-
"eslint": ">= 6.0.0"
35+
"eslint": ">=7.5.0"
3636
}
3737
}

packages/@vue/cli-test-utils/createUpgradableProject.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ const Upgrader = require('@vue/cli/lib/Upgrader')
66

77
const outsideTestFolder = path.resolve(__dirname, '../../../../vue-upgrade-tests')
88

9-
module.exports = async function createUpgradableProject (...args) {
9+
/**
10+
* create upgradable project
11+
* @param {string} name
12+
* @param {import('@vue/cli').Preset} preset
13+
* @returns {ReturnType<createTestProject> & Promise<{upgrade: Upgrader['upgrade']}>}
14+
*/
15+
module.exports = async function createUpgradableProject (name, preset) {
1016
if (!fs.existsSync(outsideTestFolder)) {
1117
fs.mkdirSync(outsideTestFolder)
1218
}
1319
process.env.VUE_CLI_TEST_DO_INSTALL_PLUGIN = true
1420

15-
const project = await createTestProject(...args, outsideTestFolder)
21+
const project = await createTestProject(name, preset, outsideTestFolder)
1622
const upgrade = async function upgrade (pluginName, options) {
1723
return (new Upgrader(project.dir)).upgrade(pluginName, options || {})
1824
}

packages/@vue/cli-ui/.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module.exports = {
1919
'vue/html-self-closing': 'error',
2020
'vue/no-use-v-if-with-v-for': 'warn',
2121
'vue/no-unused-vars': 'warn',
22-
'vue/return-in-computed-property': 'warn',
22+
'vue/return-in-computed-property': 'warn'
2323
},
2424

2525
parserOptions: {

packages/@vue/cli/__tests__/invoke.spec.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,16 @@ test('invoke with prompts', async () => {
7272
])
7373
// need to be in the same process to have inquirer mocked
7474
// so calling directly
75+
const cwd = process.cwd()
76+
// By default, @babel/eslint-parser will load babel.config.js in `path.resolve('.')`(equals `process.cwd()`) through @babel/core.
77+
// chdir, and let @babel/eslint-parser find the babel.config.js in our test project
78+
process.chdir(project.dir)
79+
7580
await invoke(`eslint`, {}, project.dir)
7681
await assertUpdates(project)
82+
83+
// restore
84+
process.chdir(cwd)
7785
})
7886

7987
test('invoke with ts', async () => {

0 commit comments

Comments
 (0)