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

New: Add overrides and files configuration options (refs #3611) #8081

Merged
merged 15 commits into from Jun 22, 2017
68 changes: 68 additions & 0 deletions conf/config-schema.js
@@ -0,0 +1,68 @@
/**
* @fileoverview Defines a schema for configs.
* @author Sylvan Mably
*/

"use strict";

const baseConfigProperties = {
env: { type: "object" },
globals: { type: "object" },
parser: { type: ["string", "null"] },
parserOptions: { type: "object" },
plugins: { type: "array" },
rules: { type: "object" },
settings: { type: "object" }
};

const overrideProperties = Object.assign(
{},
baseConfigProperties,
{
files: {
oneOf: [
{ type: "string" },
{
type: "array",
items: { type: "string" },
minItems: 1
}
]
},
excludedFiles: {
oneOf: [
{ type: "string" },
{
type: "array",
items: { type: "string" }
}
]
}
}
);

const topLevelConfigProperties = Object.assign(
{},
baseConfigProperties,
{
extends: { type: ["string", "array"] },
root: { type: "boolean" },
overrides: {
type: "array",
items: {
type: "object",
properties: overrideProperties,
required: ["files"],
additionalProperties: false
}
}
}
);

const configSchema = {
type: "object",
properties: topLevelConfigProperties,
additionalProperties: false
};

module.exports = configSchema;
15 changes: 0 additions & 15 deletions conf/config-schema.json

This file was deleted.

55 changes: 55 additions & 0 deletions docs/user-guide/configuring.md
Expand Up @@ -713,6 +713,61 @@ module.exports = {
}
```

## Configuration Based on Glob Patterns

Sometimes a more fine-controlled configuration is necessary, for example if the configuration for files within the same directory has to be different. Therefore you can provide configurations under the `overrides` key that will only apply to files that match specific glob patterns, using the same format you would pass on the command line (e.g., `app/**/*.test.js`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you'll need to update the config schema because ESLint now throws f it encounters an unknown top-level property.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


### How it works

* Glob pattern overrides can only be configured within config files (`.eslintrc.*` or `package.json`).
* The patterns are applied against the file path relative to the directory of the config file. For example, if your config file has the path `/Users/john/workspace/any-project/.eslintrc.js` and the file you want to lint has the path `/Users/john/workspace/any-project/lib/util.js`, then the pattern provided in `.eslintrc.js` will be executed against the relative path `lib/util.js`.
* Glob pattern overrides have higher precedence than the regular configuration in the same config file. Multiple overrides within the same config are applied in order. That is, the last override block in a config file always has the highest precedence.
* A glob specific configuration works almost the same as any other ESLint config. Override blocks can contain any configuration options that are valid in a regular config, with the exception of `extends`, `overrides`, and `root`.
* Multiple glob patterns can be provided within a single override block. A file must match at least one of the supplied patterns for the configuration to apply.
* Override blocks can also specify patterns to exclude from matches. If a file matches any of the excluded patterns, the configuration won't apply.

### Relative glob patterns

```
project-root
├── app
│ ├── lib
│ │ ├── foo.js
│ │ ├── fooSpec.js
│ ├── components
│ │ ├── bar.js
│ │ ├── barSpec.js
│ ├── .eslintrc.json
├── server
│ ├── server.js
│ ├── serverSpec.js
├── .eslintrc.json
```

The config in `app/.eslintrc.json` defines the glob pattern `**/*Spec.js`. This pattern is relative to the base directory of `app/.eslintrc.json`. So, this pattern would match `app/lib/fooSpec.js` and `app/components/barSpec.js` but **NOT** `server/serverSpec.js`. If you defined the same pattern in the `.eslintrc.json` file within in the `project-root` folder, it would match all three of the `*Spec` files.

### Example configuration

In your `.eslintrc.json`:

```json
{
"rules": {
"quotes": [ 2, "double" ]
},

"overrides": [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if a config has nested overrides?

{
  "overrides": [
    {
      "files": ["*.js"],
      "config": {
        "rules": {
          "semi": ["error", "never"]
        },
        "overrides": [
          {
            "files": ["bar.js"],
            "config": {
              "rules": {
                "semi": ["error", "always"]
              }
            }
          }
        ]
      }
    }
  ]
}

Would this break the "vector" caching strategy? If it's not supported, we should probably clarify that in the docs and make it a fatal error to avoid confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nested overrides are not allowed. I clarified the docs to make this more explicit and added schema validation so this will throw an error right away.

{
"files": [ "bin/*.js", "lib/*.js" ],
"excludedFiles": "*.test.js",
"rules": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was it intentional that this commit removed the config property and put the rest of the config in the the overrides object? I could go either way on this, but it seems like there would be a benefit to making it clear that files and excludedFiles aren't regular config keys.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure this was just a mistake in the docs, because this proposal has put the globs at the same level as the other config properties since the beginning (see #3611). I don't feel strongly either way -- on the one hand, it might be nice to separate the config from the override globs, but on the other hand, it would be yet one more level of nesting. Unless anyone has a strong preference, I guess I'll leave it as is?

"quotes": [ 2, "single" ]
}
}
]
}
```

## Comments in Configuration Files

Both the JSON and YAML configuration file formats support comments (`package.json` files should not include them). You can use JavaScript-style comments or YAML-style comments in either type of file and ESLint will safely ignore them. This allows your configuration files to be more human-friendly. For example:
Expand Down