Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Better error message for flat config plugins #17399

Merged
merged 5 commits into from Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -255,14 +255,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 @@ -287,7 +287,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 @@ -341,6 +341,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` the flat config array.
nzakas marked this conversation as resolved.
Show resolved Hide resolved

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