Skip to content

Commit

Permalink
feat: Better error message for flat config plugins (#17399)
Browse files Browse the repository at this point in the history
* feat: Better error message for flat config plugins

Refs #17370

* Update docs/src/use/configure/migration-guide.md

Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>

* Update extended error message

* Update docs/src/use/configure/migration-guide.md

Co-authored-by: Francesco Trotta <github@fasttime.org>

---------

Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
Co-authored-by: Francesco Trotta <github@fasttime.org>
  • Loading branch information
3 people committed Jul 25, 2023
1 parent 6d6dc51 commit 8ca8b50
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 5 deletions.
44 changes: 39 additions & 5 deletions docs/src/use/configure/migration-guide.md
Expand Up @@ -211,7 +211,7 @@ In eslintrc files, you configure various language options across the `env`, `glo

In flat config files, the `globals`, and `parserOptions` are consolidated under the `languageOptions` key; the `env` property doesn't exist. Groups of global variables for specific runtimes are imported from the [globals](https://www.npmjs.com/package/globals) npm package and included in the `globals` property. You can use the spread operator (`...`) to import multiple globals at once.

For example, here's a eslintrc file with language options:
For example, here's an eslintrc file with language options:

```javascript
// .eslintrc.js
Expand Down Expand Up @@ -314,14 +314,14 @@ export default [
];
```

### Predefined Configs
### Predefined and Shareable Configs

In eslintrc files, use the `extends` property to use predefined configs. ESLint comes with two predefined configs that you can access as strings:
In eslintrc files, use the `extends` property to use predefined and shareable configs. ESLint comes with two predefined configs that you can access as strings:

* `"eslint:recommended"`: the rules recommended by ESLint
* `"eslint:all"`: all rules shipped with ESLint

You can also use the `extends` property to extend a custom config. Custom configs can either be paths to local config files or npm package names.
You can also use the `extends` property to extend a shareable config. Shareable configs can either be paths to local config files or npm package names.

In flat config files, predefined configs are imported from separate modules into flat config files. The `recommended` and `all` rules configs are located in the [`@eslint/js`](https://www.npmjs.com/package/@eslint/js) package. You must import this package to use these configs:

Expand All @@ -346,7 +346,7 @@ module.exports = {
}
```

This eslintrc file uses built-in config, local custom config, and custom config from an npm package:
This eslintrc file uses built-in config, local custom config, and shareable config from an npm package:

```javascript
// .eslintrc.js
Expand Down Expand Up @@ -400,6 +400,40 @@ export default [
];
```

#### Using eslintrc Configs in Flat Config

You may find that there's a shareable config you rely on that hasn't yet been updated to flat config format. In that case, you can use the `FlatCompat` utility to translate the eslintrc format into flat config format. First, install the `@eslint/eslintrc` package:

```shell
npm install @eslint/eslintrc --save-dev
```

Then, import `FlatCompat` and create a new instance to convert an existing eslintrc config. For example, if the npm package `eslint-config-my-config` is in eslintrc format, you can write this:

```js
import { FlatCompat } from "@eslint/eslintrc";
import path from "path";
import { fileURLToPath } from "url";

// mimic CommonJS variables -- not needed if using CommonJS
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const compat = new FlatCompat({
baseDirectory: __dirname
});

export default [

// mimic ESLintRC-style extends
...compat.extends("eslint-config-my-config"),
];
```
This example uses the `FlatCompat#extends()` method to insert the `eslint-config-my-config` into the flat config array.
For more information about the `FlatCompat` class, please see the [package README](https://github.com/eslint/eslintrc#usage).
### Ignoring Files
With eslintrc, you can make ESLint ignore files by creating a separate `.eslintignore` file in the root of your project. The `.eslintignore` file uses the same glob pattern syntax as `.gitignore` files. Alternatively, you can use an `ignorePatterns` property in your eslintrc file.
Expand Down
21 changes: 21 additions & 0 deletions lib/config/flat-config-schema.js
Expand Up @@ -227,6 +227,22 @@ class IncompatibleKeyError extends Error {
}
}

/**
* The error type when there's an eslintrc-style plugins array found.
*/
class IncompatiblePluginsError extends Error {

/**
* Creates a new instance.
* @param {Array<string>} plugins The plugins array.
*/
constructor(plugins) {
super("This appears to be in eslintrc format (array of strings) rather than flat config format (object).");
this.messageTemplate = "eslintrc-plugins";
this.messageData = { plugins };
}
}


//-----------------------------------------------------------------------------
// Low-Level Schemas
Expand Down Expand Up @@ -319,6 +335,11 @@ const pluginsSchema = {
throw new TypeError("Expected an object.");
}

// make sure it's not an array, which would mean eslintrc-style is used
if (Array.isArray(value)) {
throw new IncompatiblePluginsError(value);
}

// second check the keys to make sure they are objects
for (const key of Object.keys(value)) {

Expand Down
24 changes: 24 additions & 0 deletions messages/eslintrc-plugins.js
@@ -0,0 +1,24 @@
"use strict";

module.exports = function({ plugins }) {

const isArrayOfStrings = typeof plugins[0] === "string";

return `
A config object has a "plugins" key defined as an array${isArrayOfStrings ? " of strings" : ""}.
Flat config requires "plugins" to be an object in this form:
{
plugins: {
${isArrayOfStrings && plugins[0] ? plugins[0] : "namespace"}: pluginObject
}
}
Please see the following page for information on how to convert your config object into the correct format:
https://eslint.org/docs/latest/use/configure/migration-guide#importing-plugins-and-custom-parsers
If you're using a shareable config that you cannot rewrite in flat config format, then use the compatibility utility:
https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config
`;
};
9 changes: 9 additions & 0 deletions tests/lib/config/flat-config-array.js
Expand Up @@ -1963,6 +1963,15 @@ describe("FlatConfigArray", () => {
});
});

it("should error when plugins is an array", async () => {
await assertInvalidConfig([
{
plugins: ["foo"]
}
], "Key \"plugins\": This appears to be in eslintrc format (array of strings) rather than flat config format (object).");

});


});

Expand Down

0 comments on commit 8ca8b50

Please sign in to comment.