mirror of
https://github.com/astral-sh/ruff
synced 2026-01-09 23:54:36 -05:00
Expand ruff.configuration to allow inline config (#16296)
## Summary [Internal design document](https://www.notion.so/astral-sh/In-editor-settings-19e48797e1ca807fa8c2c91b689d9070?pvs=4) This PR expands `ruff.configuration` to allow inline configuration directly in the editor. For example: ```json { "ruff.configuration": { "line-length": 100, "lint": { "unfixable": ["F401"], "flake8-tidy-imports": { "banned-api": { "typing.TypedDict": { "msg": "Use `typing_extensions.TypedDict` instead" } } } }, "format": { "quote-style": "single" } } } ``` This means that now `ruff.configuration` accepts either a path to configuration file or the raw config itself. It's _mostly_ similar to `--config` with one difference that's highlighted in the following section. So, it can be said that the format of `ruff.configuration` when provided the config map is same as the one on the [playground] [^1]. ## Limitations <details><summary><b>Casing (<code>kebab-case</code> v/s/ <code>camelCase</code>)</b></summary> <p> The config keys needs to be in `kebab-case` instead of `camelCase` which is being used for other settings in the editor. This could be a bit confusing. For example, the `line-length` option can be set directly via an editor setting or can be configured via `ruff.configuration`: ```json { "ruff.configuration": { "line-length": 100 }, "ruff.lineLength": 120 } ``` #### Possible solution We could use feature flag with [conditional compilation](https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute) to indicate that when used in `ruff_server`, we need the `Options` fields to be renamed as `camelCase` while for other crates it needs to be renamed as `kebab-case`. But, this might not work very easily because it will require wrapping the `Options` struct and create two structs in which we'll have to add `#[cfg_attr(...)]` because otherwise `serde` will complain: ``` error: duplicate serde attribute `rename_all` --> crates/ruff_workspace/src/options.rs:43:38 | 43 | #[cfg_attr(feature = "editor", serde(rename_all = "camelCase"))] | ^^^^^^^^^^ ``` </p> </details> <details><summary><b>Nesting (flat v/s nested keys)</b></summary> <p> This is the major difference between `--config` flag on the command-line v/s `ruff.configuration` and it makes it such that `ruff.configuration` has same value format as [playground] [^1]. The config keys needs to be split up into keys which can result in nested structure instead of flat structure: So, the following **won't work**: ```json { "ruff.configuration": { "format.quote-style": "single", "lint.flake8-tidy-imports.banned-api.\"typing.TypedDict\".msg": "Use `typing_extensions.TypedDict` instead" } } ``` But, instead it would need to be split up like the following: ```json { "ruff.configuration": { "format": { "quote-style": "single" }, "lint": { "flake8-tidy-imports": { "banned-api": { "typing.TypedDict": { "msg": "Use `typing_extensions.TypedDict` instead" } } } } } } ``` #### Possible solution (1) The way we could solve this and make it same as `--config` would be to add a manual logic of converting the JSON map into an equivalent TOML string which would be then parsed into `Options`. So, the following JSON map: ```json { "lint.flake8-tidy-imports": { "banned-api": {"\"typing.TypedDict\".msg": "Use typing_extensions.TypedDict instead"}}} ``` would need to be converted into the following TOML string: ```toml lint.flake8-tidy-imports = { banned-api = { "typing.TypedDict".msg = "Use typing_extensions.TypedDict instead" } } ``` by recursively convering `"key": value` into `key = value` which is to remove the quotes from key and replacing `:` with `=`. #### Possible solution (2) Another would be to just accept `Map<String, String>` strictly and convert it into `key = value` and then parse it as a TOML string. This would also match `--config` but quotes might become a nuisance because JSON only allows double quotes and so it'll require escaping any inner quotes or use single quotes. </p> </details> ## Test Plan ### VS Code **Requires https://github.com/astral-sh/ruff-vscode/pull/702** **`settings.json`**: ```json { "ruff.lint.extendSelect": ["TID"], "ruff.configuration": { "line-length": 50, "format": { "quote-style": "single" }, "lint": { "unfixable": ["F401"], "flake8-tidy-imports": { "banned-api": { "typing.TypedDict": { "msg": "Use `typing_extensions.TypedDict` instead" } } } } } } ``` Following video showcases me doing the following: 1. Check diagnostics that it includes `TID` 2. Run `Ruff: Fix all auto-fixable problems` to test `unfixable` 3. Run `Format: Document` to test `line-length` and `quote-style` https://github.com/user-attachments/assets/0a38176f-3fb0-4960-a213-73b2ea5b1180 ### Neovim **`init.lua`**: ```lua require('lspconfig').ruff.setup { init_options = { settings = { lint = { extendSelect = { 'TID' }, }, configuration = { ['line-length'] = 50, format = { ['quote-style'] = 'single', }, lint = { unfixable = { 'F401' }, ['flake8-tidy-imports'] = { ['banned-api'] = { ['typing.TypedDict'] = { msg = 'Use typing_extensions.TypedDict instead', }, }, }, }, }, }, }, } ``` Same steps as in the VS Code test: https://github.com/user-attachments/assets/cfe49a9b-9a89-43d7-94f2-7f565d6e3c9d ## Documentation Preview https://github.com/user-attachments/assets/e0062f58-6ec8-4e01-889d-fac76fd8b3c7 [playground]: https://play.ruff.rs [^1]: This has one advantage that the value can be copy-pasted directly into the playground
This commit is contained in:
@@ -11,10 +11,39 @@ as per the editor.
|
||||
|
||||
### `configuration`
|
||||
|
||||
Path to a `ruff.toml` or `pyproject.toml` file to use for configuration.
|
||||
The `configuration` setting allows you to configure editor-specific Ruff behavior. This can be done
|
||||
in one of the following ways:
|
||||
|
||||
By default, Ruff will discover configuration for each project from the filesystem, mirroring the
|
||||
behavior of the Ruff CLI.
|
||||
1. **Configuration file path:** Specify the path to a `ruff.toml` or `pyproject.toml` file that
|
||||
contains the configuration. User home directory and environment variables will be expanded.
|
||||
1. **Inline JSON configuration:** Directly provide the configuration as a JSON object.
|
||||
|
||||
!!! note "Added in Ruff `0.9.8`"
|
||||
|
||||
The **Inline JSON configuration** option was introduced in Ruff `0.9.8`.
|
||||
|
||||
The default behavior, if `configuration` is unset, is to load the settings from the project's
|
||||
configuration (a `ruff.toml` or `pyproject.toml` in the project's directory), consistent with when
|
||||
running Ruff on the command-line.
|
||||
|
||||
The [`configurationPreference`](#configurationpreference) setting controls the precedence if both an
|
||||
editor-provided configuration (`configuration`) and a project level configuration file are present.
|
||||
|
||||
#### Resolution order {: #configuration_resolution_order }
|
||||
|
||||
In an editor, Ruff supports three sources of configuration, prioritized as follows (from highest to
|
||||
lowest):
|
||||
|
||||
1. **Specific settings:** Individual settings like [`lineLength`](#linelength) or
|
||||
[`lint.select`](#select) defined in the editor
|
||||
1. [**`ruff.configuration`**](#configuration): Settings provided via the
|
||||
[`configuration`](#configuration) field (either a path to a configuration file or an inline
|
||||
configuration object)
|
||||
1. **Configuration file:** Settings defined in a `ruff.toml` or `pyproject.toml` file in the
|
||||
project's directory (if present)
|
||||
|
||||
For example, if the line length is specified in all three sources, Ruff will use the value from the
|
||||
[`lineLength`](#linelength) setting.
|
||||
|
||||
**Default value**: `null`
|
||||
|
||||
@@ -22,6 +51,8 @@ behavior of the Ruff CLI.
|
||||
|
||||
**Example usage**:
|
||||
|
||||
_Using configuration file path:_
|
||||
|
||||
=== "VS Code"
|
||||
|
||||
```json
|
||||
@@ -35,9 +66,7 @@ behavior of the Ruff CLI.
|
||||
```lua
|
||||
require('lspconfig').ruff.setup {
|
||||
init_options = {
|
||||
settings = {
|
||||
configuration = "~/path/to/ruff.toml"
|
||||
}
|
||||
configuration = "~/path/to/ruff.toml"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -58,6 +87,87 @@ behavior of the Ruff CLI.
|
||||
}
|
||||
```
|
||||
|
||||
_Using inline configuration:_
|
||||
|
||||
=== "VS Code"
|
||||
|
||||
```json
|
||||
{
|
||||
"ruff.configuration": {
|
||||
"lint": {
|
||||
"unfixable": ["F401"],
|
||||
"extend-select": ["TID251"],
|
||||
"flake8-tidy-imports": {
|
||||
"banned-api": {
|
||||
"typing.TypedDict": {
|
||||
"msg": "Use `typing_extensions.TypedDict` instead",
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
"quote-style": "single"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
=== "Neovim"
|
||||
|
||||
```lua
|
||||
require('lspconfig').ruff.setup {
|
||||
init_options = {
|
||||
configuration = {
|
||||
lint = {
|
||||
unfixable = {"F401"},
|
||||
["extend-select"] = {"TID251"},
|
||||
["flake8-tidy-imports"] = {
|
||||
["banned-api"] = {
|
||||
["typing.TypedDict"] = {
|
||||
msg = "Use `typing_extensions.TypedDict` instead"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
format = {
|
||||
["quote-style"] = "single"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
=== "Zed"
|
||||
|
||||
```json
|
||||
{
|
||||
"lsp": {
|
||||
"ruff": {
|
||||
"initialization_options": {
|
||||
"settings": {
|
||||
"configuration": {
|
||||
"lint": {
|
||||
"unfixable": ["F401"],
|
||||
"extend-select": ["TID251"],
|
||||
"flake8-tidy-imports": {
|
||||
"banned-api": {
|
||||
"typing.TypedDict": {
|
||||
"msg": "Use `typing_extensions.TypedDict` instead"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
"quote-style": "single"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `configurationPreference`
|
||||
|
||||
The strategy to use when resolving settings across VS Code and the filesystem. By default, editor
|
||||
@@ -594,9 +704,7 @@ Whether to enable linting. Set to `false` to use Ruff exclusively as a formatter
|
||||
"initialization_options": {
|
||||
"settings": {
|
||||
"lint": {
|
||||
"enable" = {
|
||||
"enable": false
|
||||
}
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user