]> git.proxmox.com Git - pve-eslint.git/blob - eslint/docs/user-guide/migrating-to-8.0.0.md
444ac124c4cd0925de336827af60b6f047eb7f54
[pve-eslint.git] / eslint / docs / user-guide / migrating-to-8.0.0.md
1 # Migrating to v8.0.0
2
3 ESLint v8.0.0 is a major release of ESLint. We have made a few breaking changes in this release. This guide is intended to walk you through the breaking changes.
4
5 The lists below are ordered roughly by the number of users each change is expected to affect, where the first items are expected to affect the most users.
6
7 ## Table of Contents
8
9 ### Breaking changes for users
10
11 - [Node.js 10, 13, and 15 are no longer supported](#drop-old-node)
12 - [Removed `codeframe` and `table` formatters](#removed-formatters)
13 - [`comma-dangle` rule schema is stricter](#comma-dangle)
14 - [Unused disable directives are now fixable](#directives)
15 - [`eslint:recommended` has been updated](#eslint-recommended)
16
17 ### Breaking changes for plugin developers
18
19 - [Node.js 10, 13, and 15 are no longer supported](#drop-old-node)
20 - [Rules require `meta.hasSuggestions` to provide suggestions](#suggestions)
21 - [Rules require `meta.fixable` to provide fixes](#fixes)
22 - [`SourceCode#getComments()` fails in `RuleTester`](#get-comments)
23 - [Changes to shorthand property AST format](#ast-format)
24
25 ### Breaking changes for integration developers
26
27 - [Node.js 10, 13, and 15 are no longer supported](#drop-old-node)
28 - [The `CLIEngine` class has been removed](#remove-cliengine)
29 - [The `linter` object has been removed](#remove-linter)
30 - [The `/lib` entrypoint has been removed](#remove-lib)
31
32 ---
33
34 ## <a name="drop-old-node"></a> Node.js 10, 13, and 15 are no longer supported
35
36 Node.js 10, 13, 15 all reached end of life either in 2020 or early 2021. ESLint is officially dropping support for these versions of Node.js starting with ESLint v8.0.0. ESLint now supports the following versions of Node.js:
37
38 - Node.js 12.22 and above
39 - Node.js 14 and above
40 - Node.js 16 and above
41
42 **To address:** Make sure you upgrade to at least Node.js `12.22.0` when using ESLint v8.0.0. One important thing to double check is the Node.js version supported by your editor when using ESLint via editor integrations. If you are unable to upgrade, we recommend continuing to use ESLint 7 until you are able to upgrade Node.js.
43
44 **Related issue(s):** [#14023](https://github.com/eslint/eslint/issues/14023)
45
46 ## <a name="removed-formatters"></a> Removed `codeframe` and `table` formatters
47
48 ESLint v8.0.0 has removed the `codeframe` and `table` formatters from the core. These formatters required dependencies that weren't used anywhere else in ESLint, and removing them allows us to reduce the size of ESLint, allowing for faster installation.
49
50 **To address:** If you are using the `codeframe` or `table` formatters, you'll need to install the standalone [`eslint-formatter-codeframe`](https://github.com/fregante/eslint-formatter-codeframe) or [`eslint-formatter-table`](https://github.com/fregante/eslint-formatter-table) packages, respectively, to be able to use them in ESLint v8.0.0.
51
52 **Related issue(s):** [#14277](https://github.com/eslint/eslint/issues/14277), [#14316](https://github.com/eslint/eslint/pull/14316)
53
54 ## <a name="comma-dangle"></a> `comma-dangle` rule schema is stricter
55
56 In ESLint v7.0.0, the `comma-dangle` rule could be configured like this without error:
57
58 ```json
59 {
60 "rules": {
61 "comma-dangle": ["error", "never", { "arrays": "always" }]
62 }
63 }
64 ```
65
66 With this configuration, the rule would ignore the third element in the array because only the second element is read. In ESLint v8.0.0, this configuration will cause ESLint to throw an error.
67
68 **To address:** Change your rule configuration so that there are only two elements in the array, and the second element is either a string or an object, such as:
69
70 ```jsonc
71 {
72 "comma-dangle": ["error", "never"],
73 // or
74 "comma-dangle": ["error", {
75 "arrays": "never",
76 "objects": "never",
77 "imports": "never",
78 "exports": "never",
79 "functions": "never"
80 }]
81 }
82 ```
83
84 **Related issue(s):** [#13739](https://github.com/eslint/eslint/issues/13739)
85
86 ## <a name="directives"></a> Unused disable directives are now fixable
87
88 In ESLint v7.0.0, using both `--report-unused-disable-directives` and `--fix` on the command line would fix only rules but leave unused disable directives in place. In ESLint v8.0.0, this combination of command-line options will result in the unused disable directives being removed.
89
90 **To address:** If you are using `--report-unused-disable-directives` and `--fix` together on the command line, and you don't want unused disable directives to be removed, add `--fix-type problem,suggestion,layout` as a command line option.
91
92 **Related issue(s):** [#11815](https://github.com/eslint/eslint/issues/11815)
93
94 ## <a name="eslint-recommended"></a> `eslint:recommended` has been updated
95
96 Four new rules have been enabled in the `eslint:recommended` preset.
97
98 - [`no-loss-of-precision`](https://eslint.org/docs/rules/no-loss-of-precision)
99 - [`no-nonoctal-decimal-escape`](https://eslint.org/docs/rules/no-nonoctal-decimal-escape)
100 - [`no-unsafe-optional-chaining`](https://eslint.org/docs/rules/no-unsafe-optional-chaining)
101 - [`no-useless-backreference`](https://eslint.org/docs/rules/no-useless-backreference)
102
103 **To address:** Fix errors or disable these rules.
104
105 **Related issue(s):** [#14673](https://github.com/eslint/eslint/issues/14673)
106
107 ## <a name="suggestions"></a> Rules require `meta.hasSuggestions` to provide suggestions
108
109 In ESLint v7.0.0, rules that [provided suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) did not need to let ESLint know. In v8.0.0, rules providing suggestions need to set their `meta.hasSuggestions` to `true`. This informs ESLint that the rule intends to provide suggestions. Without this property, any attempt to provide a suggestion will result in an error.
110
111 **To address:** If your rule provides suggestions, add `meta.hasSuggestions` to the object, such as:
112
113 ```js
114 module.exports = {
115 meta: {
116 hasSuggestions: true
117 },
118 create(context) {
119 // your rule
120 }
121 };
122 ```
123
124 The [eslint-plugin/require-meta-has-suggestions](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/require-meta-has-suggestions.md) rule can automatically fix and enforce that your rules are properly specifying `meta.hasSuggestions`.
125
126 **Related issue(s):** [#14312](https://github.com/eslint/eslint/issues/14312)
127
128 ## <a name="fixes"></a> Rules require `meta.fixable` to provide fixes
129
130 In ESLint v7.0.0, rules that were written as a function (rather than object) were able to provide fixes. In ESLint v8.0.0, only rules written as an object are allowed to provide fixes and must have a `meta.fixable` property set to either `"code"` or `"whitespace"`.
131
132 **To address:** If your rule makes fixes and is written as a function, such as:
133
134 ```js
135 module.exports = function(context) {
136 // your rule
137 };
138 ```
139
140 Then rewrite your rule in this format:
141
142 ```js
143 module.exports = {
144 meta: {
145 fixable: "code" // or "whitespace"
146 },
147 create(context) {
148 // your rule
149 }
150 };
151 ```
152
153 The [eslint-plugin/require-meta-fixable](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/require-meta-fixable.md) rule can automatically fix and enforce that your rules are properly specifying `meta.fixable`.
154
155 The [eslint-plugin/prefer-object-rule](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/prefer-object-rule.md) rule can automatically fix and enforce that your rules are written with the object format instead of the deprecated function format.
156
157 See the [rule documentation](https://eslint.org/docs/developer-guide/working-with-rules) for more information on writing rules.
158
159 **Related issue(s):** [#13349](https://github.com/eslint/eslint/issues/13349)
160
161 ## <a name="get-comments"></a> `SourceCode#getComments()` fails in `RuleTester`
162
163 Back in ESLint v4.0.0, we deprecated `SourceCode#getComments()`, but we neglected to remove it. Rather than removing it completely in v8.0.0, we are taking the intermediate step of updating `RuleTester` to fail when `SourceCode#getComments()` is used inside of a rule. As such, all existing rules will continue to work, but when the developer runs tests for the rule there will be a failure.
164
165 The `SourceCode#getComments()` method will be removed in v9.0.0.
166
167 **To address:** If your rule uses `SourceCode#getComments()`, please use [`SourceCode#getCommentsBefore()`, `SourceCode#getCommentsAfter()`, or `SourceCode#getCommentsInside()`](https://eslint.org/docs/developer-guide/working-with-rules#sourcecodegetcommentsbefore-sourcecodegetcommentsafter-and-sourcecodegetcommentsinside).
168
169 **Related issue(s):** [#14744](https://github.com/eslint/eslint/issues/14744)
170
171 ## <a name="ast-format"></a> Changes to shorthand property AST format
172
173 ESLint v8.0.0 includes an upgrade to Espree v8.0.0 to support new syntax. This Espree upgrade, in turn, contains an upgrade to Acorn v8.0.0, which changed how shorthand properties were represented in the AST. Here's an example:
174
175 ```js
176 const version = 8;
177 const x = {
178 version
179 };
180 ```
181
182 This code creates a property node that looks like this:
183
184 ```json
185 {
186 "type": "Property",
187 "method": false,
188 "shorthand": true,
189 "computed": false,
190 "key": {
191 "type": "Identifier",
192 "name": "version"
193 },
194 "kind": "init",
195 "value": {
196 "type": "Identifier",
197 "name": "version"
198 }
199 }
200 ```
201
202 Note that both the `key` and the `value` properties contain the same information. Prior to Acorn v8.0.0 (and therefore prior to ESLint v8.0.0), these two nodes were represented by the same object, so you could use `===` to determine if they represented the same node, such as:
203
204 ```js
205 // true in ESLint v7.x, false in ESLint v8.0.0
206 if (propertyNode.key === propertyNode.value) {
207 // do something
208 }
209 ```
210
211 In ESLint v8.0.0 (via Acorn v8.0.0), the key and value are now separate objects and therefore no longer equivalent.
212
213 **To address:** If your rule makes a comparison between the key and value of a shorthand object literal property to determine if they are the same node, you'll need to change your code in one of two ways:
214
215 1. Use `propertyNode.shorthand` to determine if the property is a shorthand property node.
216 1. Use the `range` property of each node to determine if the key and value occupy the same location.
217
218 **Related issue(s):** [#14591](https://github.com/eslint/eslint/pull/14591#issuecomment-887733070)
219
220 ## <a name="remove-cliengine"></a> The `CLIEngine` class has been removed
221
222 The `CLIEngine` class has been removed and replaced by the [`ESLint` class](https://eslint.org/docs/developer-guide/nodejs-api#eslint-class).
223
224 **To address:** Update your code to use the new `ESLint` class if you are currently using `CLIEngine`. The following table maps the existing `CLIEngine` methods to their `ESLint` counterparts:
225
226 | `CLIEngine` | `ESLint` |
227 | :------------------------------------------- | :--------------------------------- |
228 | `executeOnFiles(patterns)` | `lintFiles(patterns)` |
229 | `executeOnText(text, filePath, warnIgnored)` | `lintText(text, options)` |
230 | `getFormatter(name)` | `loadFormatter(name)` |
231 | `getConfigForFile(filePath)` | `calculateConfigForFile(filePath)` |
232 | `isPathIgnored(filePath)` | `isPathIgnored(filePath)` |
233 | `static outputFixes(results)` | `static outputFixes(results)` |
234 | `static getErrorResults(results)` | `static getErrorResults(results)` |
235 | `static getFormatter(name)` | (removed ※1) |
236 | `addPlugin(pluginId, definition)` | the `plugins` constructor option |
237 | `getRules()` | (removed ※2) |
238 | `resolveFileGlobPatterns()` | (removed ※3) |
239
240 - ※1 The `engine.getFormatter()` method currently returns the object of loaded packages as-is, which made it difficult to add new features to formatters for backward compatibility reasons. The new `eslint.loadFormatter()` method returns an adapter object that wraps the object of loaded packages, to ease the process of adding new features. Additionally, the adapter object has access to the `ESLint` instance to calculate default data (using loaded plugin rules to make `rulesMeta`, for example). As a result, the `ESLint` class only implements an instance version of the `loadFormatter()` method.
241 - ※2 The `CLIEngine#getRules()` method had side effects and so was removed. If you were using `CLIEngine#getRules()` to retrieve meta information about rules based on linting results, use `ESLint#getRulesMetaForResults()` instead. If you were using `CLIEngine#getRules()` to retrieve all built-in rules, import `builtinRules` from `eslint/use-at-your-own-risk` for an unsupported API that allows access to internal rules.
242 - ※3 Since ESLint v6.0.0, ESLint uses different logic from the `resolveFileGlobPatterns()` method to iterate files, making this method obsolete.
243
244 **Related issue(s):** [RFC80](https://github.com/eslint/rfcs/tree/main/designs/2021-package-exports), [#14716](https://github.com/eslint/eslint/pull/14716), [#13654](https://github.com/eslint/eslint/issues/13654)
245
246 ## <a name="remove-linter"></a> The `linter` object has been removed
247
248 The deprecated `linter` object has been removed from the ESLint package in v8.0.0.
249
250 **To address:** If you are using the `linter` object, such as:
251
252 ```js
253 const { linter } = require("eslint");
254 ```
255
256 Change your code to this:
257
258 ```js
259 const { Linter } = require("eslint");
260 const linter = new Linter();
261 ```
262
263 **Related issue(s):** [RFC80](https://github.com/eslint/rfcs/tree/main/designs/2021-package-exports), [#14716](https://github.com/eslint/eslint/pull/14716), [#13654](https://github.com/eslint/eslint/issues/13654)
264
265 ## <a name="remove-lib"></a> The `/lib` entrypoint has been removed
266
267 Beginning in v8.0.0, ESLint is strictly defining its public API. Previously, you could reach into individual files such as `require("eslint/lib/rules/semi")` and this is no longer allowed. There are a limited number of existing APIs that are now available through the `/use-at-your-own-risk` entrypoint for backwards compatibility, but these APIs are not formally supported and may break or disappear at any point in time.
268
269 **To address:** If you are accessing rules directly through the `/lib` entrypoint, such as:
270
271 ```js
272 const rule = require("eslint/lib/rules/semi");
273 ```
274
275 Change your code to this:
276
277 ```js
278 const { builtinRules } = require("eslint/use-at-your-own-risk");
279 const rule = builtinRules.get("semi");
280 ```
281
282 If you are accessing `FileEnumerator` directly through the `/lib` entrypoint, such as:
283
284 ```js
285 const { FileEnumerator } = require("eslint/lib/cli-engine/file-enumerator");
286 ```
287
288 Change your code to this:
289
290 ```js
291 const { FileEnumerator } = require("eslint/use-at-your-own-risk");
292 ```
293
294 **Related issue(s):** [RFC80](https://github.com/eslint/rfcs/tree/main/designs/2021-package-exports), [#14716](https://github.com/eslint/eslint/pull/14716), [#13654](https://github.com/eslint/eslint/issues/13654)