ruff server: Ruff configuration from client settings overrides project configuration (#11062)

## Summary

This is a follow-up to https://github.com/astral-sh/ruff/pull/10984 that
implements configuration resolution for editor configuration. By 'editor
configuration', I'm referring to the client settings that correspond to
Ruff configuration/options, like `preview`, `select`, and so on. These
will be combined with 'project configuration' (configuration taken from
project files such as `pyproject.toml`) to generate the final linter and
formatter settings used by `RuffSettings`. Editor configuration takes
priority over project configuration.

In a follow-up pull request, I'll implement a new client setting that
allows project configuration to override editor configuration, as per
[this issue](https://github.com/astral-sh/ruff-vscode/issues/425).

## Review guide

The first commit, e38966d8843becc7234fa7d46009c16af4ba41e9, is just
doing re-arrangement so that we can pass the right things to
`RuffSettings::resolve`. The actual resolution logic is in the second
commit, 0eec9ee75c10e5ec423bd9f5ce1764f4d7a5ad86. It might help to look
at these comments individually since the diff is rather messy.

## Test Plan

For the settings to show up in VS Code, you'll need to checkout this
branch: https://github.com/astral-sh/ruff-vscode/pull/456.

To test that the resolution for a specific setting works as expected,
run through the following scenarios, setting it in project and editor
configuration as needed:

| Set in project configuration? | Set in editor configuration? |
Expected Outcome |

|-------------------------------|--------------------------------------------------|------------------------------------------------------------------------------------------|
| No | No | The editor should behave as if the setting was set to its
default value. |
| Yes | No | The editor should behave as if the setting was set to the
value in project configuration. |
| No | Yes | The editor should behave as if the setting was set to the
value in editor configuration. |
| Yes | Yes (but distinctive from project configuration) | The editor
should behave as if the setting was set to the value in editor
configuration. |

An exception to this is `extendSelect`, which does not have an analog in
TOML configuration. Instead, you should verify that `extendSelect`
amends the `select` setting. If `select` is set in both editor and
project configuration, `extendSelect` will only append to the `select`
value in editor configuration, so make sure to un-set it there if you're
testing `extendSelect` with `select` in project configuration.
This commit is contained in:
Jane Lewis 2024-04-23 11:19:17 -07:00 committed by GitHub
parent f5c7a62aa6
commit 35ca887e02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 127 additions and 61 deletions

View file

@ -6,7 +6,7 @@ pub(super) fn generate_diagnostics(snapshot: &DocumentSnapshot) -> Vec<lsp_types
if snapshot.client_settings().lint() {
crate::lint::check(
snapshot.document(),
&snapshot.settings().linter,
snapshot.settings().linter(),
snapshot.encoding(),
)
} else {

View file

@ -105,7 +105,7 @@ fn fix_all(snapshot: &DocumentSnapshot) -> crate::Result<CodeActionOrCommand> {
document,
snapshot.resolved_client_capabilities(),
snapshot.url(),
&snapshot.settings().linter,
snapshot.settings().linter(),
snapshot.encoding(),
document.version(),
)?),
@ -140,7 +140,7 @@ fn organize_imports(snapshot: &DocumentSnapshot) -> crate::Result<CodeActionOrCo
document,
snapshot.resolved_client_capabilities(),
snapshot.url(),
&snapshot.settings().linter,
snapshot.settings().linter(),
snapshot.encoding(),
document.version(),
)?),

View file

@ -54,7 +54,7 @@ impl super::BackgroundDocumentRequestHandler for CodeActionResolve {
document,
snapshot.resolved_client_capabilities(),
snapshot.url(),
&snapshot.settings().linter,
snapshot.settings().linter(),
snapshot.encoding(),
document.version(),
)
@ -65,7 +65,7 @@ impl super::BackgroundDocumentRequestHandler for CodeActionResolve {
document,
snapshot.resolved_client_capabilities(),
snapshot.url(),
&snapshot.settings().linter,
snapshot.settings().linter(),
snapshot.encoding(),
document.version(),
)

View file

@ -64,7 +64,7 @@ impl super::SyncRequestHandler for ExecuteCommand {
Command::FixAll => {
let edits = super::code_action_resolve::fix_all_edit(
snapshot.document(),
&snapshot.settings().linter,
snapshot.settings().linter(),
snapshot.encoding(),
)
.with_failure_code(ErrorCode::InternalError)?;
@ -83,7 +83,7 @@ impl super::SyncRequestHandler for ExecuteCommand {
Command::OrganizeImports => {
let edits = super::code_action_resolve::organize_imports_edit(
snapshot.document(),
&snapshot.settings().linter,
snapshot.settings().linter(),
snapshot.encoding(),
)
.with_failure_code(ErrorCode::InternalError)?;

View file

@ -26,7 +26,7 @@ impl super::BackgroundDocumentRequestHandler for Format {
pub(super) fn format_document(snapshot: &DocumentSnapshot) -> Result<super::FormatResponse> {
let doc = snapshot.document();
let source = doc.contents();
let formatted = crate::format::format(doc, &snapshot.settings().formatter)
let formatted = crate::format::format(doc, snapshot.settings().formatter())
.with_failure_code(lsp_server::ErrorCode::InternalError)?;
// fast path - if the code is the same, return early
if formatted == source {

View file

@ -22,7 +22,7 @@ impl super::BackgroundDocumentRequestHandler for FormatRange {
let index = document.index();
let range = params.range.to_text_range(text, index, snapshot.encoding());
let formatted_range =
crate::format::format_range(document, &snapshot.settings().formatter, range)
crate::format::format_range(document, snapshot.settings().formatter(), range)
.with_failure_code(lsp_server::ErrorCode::InternalError)?;
Ok(Some(vec![types::TextEdit {
range: formatted_range