Skip to content
This repository was archived by the owner on Aug 7, 2023. It is now read-only.

Commit 1297ab6

Browse files
committed
fix: detect ESLint >= 8 and tell the user about linter-eslint-node (#1464)
Co-Authored-By: Tony Brix <[email protected]>
1 parent 3c27e5d commit 1297ab6

File tree

13 files changed

+149
-16
lines changed

13 files changed

+149
-16
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
[![Dependency Status](https://david-dm.org/AtomLinter/linter-eslint.svg)](https://david-dm.org/AtomLinter/linter-eslint)
55

66
This linter plugin for [Linter](https://github.com/AtomLinter/Linter) provides
7-
an interface to [eslint](http://eslint.org). It will be used with files that
7+
an interface to [eslint](http://eslint.org) versions 7 and below. It will be used with files that
88
have the "JavaScript" syntax.
99

10+
**For linting in projects that use ESLint v8 and above, install [linter-eslint-node](https://atom.io/packages/linter-eslint-node).**
11+
1012
## Installation
1113

1214
```ShellSession
@@ -24,7 +26,7 @@ This package requires an `eslint` of at least v1.0.0.
2426

2527
If you do not have the `linter` package installed, it will be
2628
installed
27-
for you. If you are using an alternative `linter-*` consumer,
29+
for you. If you are using an alternative `linter-*` consumer,
2830
the `linter` package can be disabled.
2931

3032
If you wish to lint files in JavaScript-derivative languages (like Typescript,

dist/worker-helpers.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "linter-eslint",
33
"main": "./dist/main.js",
44
"version": "9.0.0",
5-
"description": "Lint JavaScript on the fly, using ESLint",
5+
"description": "Lint JavaScript on the fly, using ESLint (v7 or older)",
66
"repository": "https://github.com/AtomLinter/linter-eslint.git",
77
"license": "MIT",
88
"engines": {
@@ -155,6 +155,13 @@
155155
"type": "string",
156156
"default": "",
157157
"order": 5
158+
},
159+
"showIncompatibleVersionNotification": {
160+
"title": "Notify when incompatible ESLint is detected",
161+
"description": "When enabled, will show a notification if this package loads inside a project using ESLint version 8 or greater _and_ the user has not already installed the newer `linter-eslint-node` package. Uncheck if you don't want these notifications.",
162+
"type": "boolean",
163+
"default": true,
164+
"order": 6
158165
}
159166
}
160167
}

spec/fixtures/global-eslint/lib/node_modules/eslint/lib/api.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/fixtures/incompatible-eslint/node_modules/eslint/lib/api.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/fixtures/incompatible-eslint/node_modules/eslint/package.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/fixtures/indirect-local-eslint/testing/eslint/node_modules/eslint/lib/api.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/fixtures/local-eslint/node_modules/eslint/lib/api.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/worker-helpers-spec.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ describe('Worker Helpers', () => {
8181
advanced: { localNodeModules: path }
8282
})
8383
const eslint = Helpers.getESLintInstance('', config)
84-
expect(eslint).toBe('located')
84+
expect(eslint.type).toBe('located')
8585
})
8686

8787
it('tries to find an indirect local eslint using a relative path', () => {
@@ -93,13 +93,13 @@ describe('Worker Helpers', () => {
9393
})
9494
const eslint = Helpers.getESLintInstance('', config, projectPath)
9595

96-
expect(eslint).toBe('located')
96+
expect(eslint.type).toBe('located')
9797
})
9898

9999
it('tries to find a local eslint', () => {
100100
const config = createConfig()
101101
const eslint = Helpers.getESLintInstance(getFixturesPath('local-eslint'), config)
102-
expect(eslint).toBe('located')
102+
expect(eslint.type).toBe('located')
103103
})
104104

105105
it('cries if local eslint is not found', () => {
@@ -109,13 +109,20 @@ describe('Worker Helpers', () => {
109109
}).toThrow()
110110
})
111111

112+
it('cries if incompatible eslint is found', () => {
113+
expect(() => {
114+
const config = createConfig()
115+
Helpers.getESLintInstance(getFixturesPath('incompatible-eslint'), config)
116+
}).toThrow()
117+
})
118+
112119
it('tries to find a global eslint if config is specified', () => {
113120
const config = createConfig({
114121
global: { useGlobalEslint: true, globalNodePath }
115122
})
116123
console.log({ config })
117124
const eslint = Helpers.getESLintInstance(getFixturesPath('local-eslint'), config)
118-
expect(eslint).toBe('located')
125+
expect(eslint.type).toBe('located')
119126
})
120127

121128
it('cries if global eslint is not found', () => {
@@ -133,7 +140,7 @@ describe('Worker Helpers', () => {
133140
const fileDir = Path.join(getFixturesPath('local-eslint'), 'lib', 'foo.js')
134141
const config = createConfig()
135142
const eslint = Helpers.getESLintInstance(fileDir, config)
136-
expect(eslint).toBe('located')
143+
expect(eslint.type).toBe('located')
137144
})
138145
})
139146

src/helpers.js

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import { randomBytes } from 'crypto'
44
import { promisify } from 'util'
55
// eslint-disable-next-line import/no-extraneous-dependencies, import/extensions
66
import { Range, Task } from 'atom'
7+
// eslint-disable-next-line import/no-unresolved
8+
import { shell } from 'electron'
79
import Rules from './rules'
810
import { throwIfInvalidPoint } from './validate/editor'
911

1012
const asyncRandomBytes = promisify(randomBytes)
1113
export const rules = new Rules()
1214
let worker = null
15+
let isIncompatibleEslintVersion = false
16+
let seenIncompatibleVersionNotification = false
1317

1418
/**
1519
* Start the worker process if it hasn't already been started
@@ -48,6 +52,10 @@ export function killWorker() {
4852
}
4953
}
5054

55+
export function isIncompatibleEslint() {
56+
return isIncompatibleEslintVersion
57+
}
58+
5159
/**
5260
* Send a job to the worker and return the results
5361
* @param {Object} config Configuration for the job to send to the worker
@@ -74,11 +82,12 @@ export async function sendJob(config) {
7482
// All worker errors are caught and re-emitted along with their associated
7583
// emitKey, so that we do not create multiple listeners for the same
7684
// 'task:error' event
77-
const errSub = worker.on(`workerError:${config.emitKey}`, ({ msg, stack }) => {
85+
const errSub = worker.on(`workerError:${config.emitKey}`, ({ msg, stack, name }) => {
7886
// Re-throw errors from the task
7987
const error = new Error(msg)
8088
// Set the stack to the one given to us by the worker
8189
error.stack = stack
90+
error.name = name
8291
errSub.dispose()
8392
// eslint-disable-next-line no-use-before-define
8493
responseSub.dispose()
@@ -189,6 +198,44 @@ export function generateUserMessage(textEditor, options) {
189198
}]
190199
}
191200

201+
function isNewPackageInstalled() {
202+
return atom.packages.isPackageLoaded('linter-eslint-node')
203+
|| atom.packages.isPackageDisabled('linter-eslint-node')
204+
}
205+
206+
function showIncompatibleVersionNotification(message) {
207+
const notificationEnabled = atom.config.get('linter-eslint.advanced.showIncompatibleVersionNotification')
208+
if (!notificationEnabled || seenIncompatibleVersionNotification || isNewPackageInstalled()) {
209+
return
210+
}
211+
212+
// Show this message only once per session.
213+
seenIncompatibleVersionNotification = true
214+
const notification = atom.notifications.addWarning(
215+
'linter-eslint: Incompatible version',
216+
{
217+
description: message,
218+
dismissable: true,
219+
buttons: [
220+
{
221+
text: 'Install linter-eslint-node',
222+
onDidClick() {
223+
shell.openExternal('https://atom.io/packages/linter-eslint-node')
224+
notification.dismiss()
225+
}
226+
},
227+
{
228+
text: 'Don\'t show this notification again',
229+
onDidClick() {
230+
atom.config.set('linter-eslint.advanced.showIncompatibleVersionNotification', false)
231+
notification.dismiss()
232+
}
233+
}
234+
]
235+
}
236+
)
237+
}
238+
192239
/**
193240
* Generates a message to the user in order to nicely display the Error being
194241
* thrown instead of depending on generic error handling.
@@ -197,10 +244,19 @@ export function generateUserMessage(textEditor, options) {
197244
* @return {import("atom/linter").Message[]} Message to user generated from the Error
198245
*/
199246
export function handleError(textEditor, error) {
200-
const { stack, message } = error
247+
const { stack, message, name } = error
248+
// We want this specific worker error to show up as a notification so that we
249+
// can include a button for installing the new package.
250+
if (name === 'IncompatibleESLintError') {
251+
isIncompatibleEslintVersion = true
252+
killWorker()
253+
showIncompatibleVersionNotification(message)
254+
return
255+
}
201256
// Only show the first line of the message as the excerpt
202257
const excerpt = `Error while running ESLint: ${message.split('\n')[0]}.`
203258
const description = `<div style="white-space: pre-wrap">${message}\n<hr />${stack}</div>`
259+
// eslint-disable-next-line consistent-return
204260
return generateUserMessage(textEditor, { severity: 'error', excerpt, description })
205261
}
206262

0 commit comments

Comments
 (0)