ruff server: Fix multiple issues with Neovim and Helix (#11497)

## Summary

Fixes https://github.com/astral-sh/ruff/issues/11236.

This PR fixes several issues, most of which relate to non-VS Code
editors (Helix and Neovim).

1. Global-only initialization options are now correctly deserialized
from Neovim and Helix
2. Empty diagnostics are now published correctly for Neovim and Helix.
3. A workspace folder is created at the current working directory if the
initialization parameters send an empty list of workspace folders.
4. The server now gracefully handles opening files outside of any known
workspace, and will use global fallback settings taken from client
editor settings and a user settings TOML, if it exists.

## Test Plan

I've tested to confirm that each issue has been fixed.

* Global-only initialization options are now correctly deserialized from
Neovim and Helix + the server gracefully handles opening files outside
of any known workspace


4f33477f-20c8-4e50-8214-6608b1a1ea6b

* Empty diagnostics are now published correctly for Neovim and Helix


c93f56a0-f75d-466f-9f40-d77f99cf0637

* A workspace folder is created at the current working directory if the
initialization parameters send an empty list of workspace folders.



b4b2e818-4b0d-40ce-961d-5831478cc726
This commit is contained in:
Jane Lewis 2024-05-22 13:50:58 -07:00 committed by GitHub
parent 519a65007f
commit 94abea4b08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 120 additions and 101 deletions

View file

@ -237,12 +237,27 @@ impl Index {
Ok(())
}
pub(super) fn make_document_ref(&self, key: DocumentKey) -> Option<DocumentQuery> {
pub(super) fn make_document_ref(
&self,
key: DocumentKey,
global_settings: &ClientSettings,
) -> Option<DocumentQuery> {
let path = self.path_for_key(&key)?.clone();
let document_settings = self
.settings_for_path(&path)?
.workspace_settings_index
.get(&path);
.settings_for_path(&path)
.map(|settings| settings.workspace_settings_index.get(&path))
.unwrap_or_else(|| {
tracing::warn!(
"No settings available for {} - falling back to default settings",
path.display()
);
let resolved_global = ResolvedClientSettings::global(global_settings);
let root = path.parent().unwrap_or(&path);
Arc::new(RuffSettings::fallback(
resolved_global.editor_settings(),
root,
))
});
let controller = self.documents.get(&path)?;
let cell_uri = match key {

View file

@ -43,6 +43,32 @@ impl std::fmt::Display for RuffSettings {
}
impl RuffSettings {
pub(crate) fn fallback(editor_settings: &ResolvedEditorSettings, root: &Path) -> RuffSettings {
let fallback = find_user_settings_toml()
.and_then(|user_settings| {
ruff_workspace::resolver::resolve_root_settings(
&user_settings,
Relativity::Cwd,
&EditorConfigurationTransformer(editor_settings, root),
)
.ok()
})
.unwrap_or_else(|| {
let default_configuration = ruff_workspace::configuration::Configuration::default();
EditorConfigurationTransformer(editor_settings, root)
.transform(default_configuration)
.into_settings(root)
.expect(
"editor configuration should merge successfully with default configuration",
)
});
RuffSettings {
formatter: fallback.formatter,
linter: fallback.linter,
}
}
pub(crate) fn linter(&self) -> &ruff_linter::settings::LinterSettings {
&self.linter
}
@ -80,32 +106,9 @@ impl RuffSettingsIndex {
}
}
let fallback = find_user_settings_toml()
.and_then(|user_settings| {
ruff_workspace::resolver::resolve_root_settings(
&user_settings,
Relativity::Cwd,
&EditorConfigurationTransformer(editor_settings, root),
)
.ok()
})
.unwrap_or_else(|| {
let default_configuration = ruff_workspace::configuration::Configuration::default();
EditorConfigurationTransformer(editor_settings, root)
.transform(default_configuration)
.into_settings(root)
.expect(
"editor configuration should merge successfully with default configuration",
)
});
let fallback = Arc::new(RuffSettings::fallback(editor_settings, root));
Self {
index,
fallback: Arc::new(RuffSettings {
formatter: fallback.formatter,
linter: fallback.linter,
}),
}
Self { index, fallback }
}
pub(super) fn get(&self, document_path: &Path) -> Arc<RuffSettings> {
@ -118,11 +121,6 @@ impl RuffSettingsIndex {
return settings.clone();
}
tracing::info!(
"No Ruff settings file found for {}; falling back to default configuration",
document_path.display()
);
self.fallback.clone()
}
}

View file

@ -130,7 +130,8 @@ enum InitializationOptions {
workspace_settings: Vec<WorkspaceSettings>,
},
GlobalOnly {
settings: Option<ClientSettings>,
#[serde(flatten)]
settings: ClientSettings,
},
}
@ -157,7 +158,7 @@ impl AllSettings {
fn from_init_options(options: InitializationOptions) -> Self {
let (global_settings, workspace_settings) = match options {
InitializationOptions::GlobalOnly { settings } => (settings.unwrap_or_default(), None),
InitializationOptions::GlobalOnly { settings } => (settings, None),
InitializationOptions::HasWorkspaces {
global_settings,
workspace_settings,
@ -341,7 +342,9 @@ impl ResolvedClientSettings {
impl Default for InitializationOptions {
fn default() -> Self {
Self::GlobalOnly { settings: None }
Self::GlobalOnly {
settings: ClientSettings::default(),
}
}
}
@ -626,52 +629,50 @@ mod tests {
assert_debug_snapshot!(options, @r###"
GlobalOnly {
settings: Some(
ClientSettings {
configuration: None,
fix_all: Some(
false,
),
organize_imports: None,
lint: Some(
LintOptions {
enable: None,
preview: None,
select: None,
extend_select: None,
ignore: Some(
[
"RUF001",
],
),
},
),
format: None,
code_action: Some(
CodeActionOptions {
disable_rule_comment: Some(
CodeActionParameters {
enable: Some(
false,
),
},
),
fix_violation: None,
},
),
exclude: Some(
[
"third_party",
],
),
line_length: Some(
LineLength(
80,
settings: ClientSettings {
configuration: None,
fix_all: Some(
false,
),
organize_imports: None,
lint: Some(
LintOptions {
enable: None,
preview: None,
select: None,
extend_select: None,
ignore: Some(
[
"RUF001",
],
),
},
),
format: None,
code_action: Some(
CodeActionOptions {
disable_rule_comment: Some(
CodeActionParameters {
enable: Some(
false,
),
},
),
fix_violation: None,
},
),
exclude: Some(
[
"third_party",
],
),
line_length: Some(
LineLength(
80,
),
configuration_preference: None,
},
),
),
configuration_preference: None,
},
}
"###);
}