mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-09 18:02:19 +00:00

## Summary Configuration is no longer the property of a workspace but rather of individual documents. Just like the Ruff CLI, each document is configured based on the 'nearest' project configuration. See [the Ruff documentation](https://docs.astral.sh/ruff/configuration/#config-file-discovery) for more details. To reduce the amount of times we resolve configuration for a file, we have an index for each workspace that stores a reference-counted pointer to a configuration for a given folder. If another file in the same folder is opened, the configuration is simply re-used rather than us re-resolving it. ## Guide for reviewing The first commit is just the restructuring work, which adds some noise to the diff. If you want to quickly understand what's actually changed, I recommend looking at the two commits that come after it.f7c073d441
makes configuration a property of `DocumentController`/`DocumentRef`, moving it out of `Workspace`, and it also sets up the `ConfigurationIndex`, though it doesn't implement its key function, `get_or_insert`. In the commit after it,fc35618f17
, we implement `get_or_insert`. ## Test Plan The best way to test this would be to ensure that the behavior matches the Ruff CLI. Open a project with multiple configuration files (or add them yourself), and then introduce problems in certain files that won't show due to their configuration. Add those same problems to a section of the project where those rules are run. Confirm that the lint rules are run as expected with `ruff check`. Then, open your editor and confirm that the diagnostics shown match the CLI output. As an example - I have a workspace with two separate folders, `pandas` and `scipy`. I created a `pyproject.toml` file in `pandas/pandas/io` and a `ruff.toml` file in `pandas/pandas/api`. I changed the `select` and `preview` settings in the sub-folder configuration files and confirmed that these were reflected in the diagnostics. I also confirmed that this did not change the diagnostics for the `scipy` folder whatsoever.
132 lines
4.1 KiB
Rust
132 lines
4.1 KiB
Rust
//! Data model, state management, and configuration resolution.
|
|
|
|
mod capabilities;
|
|
mod settings;
|
|
mod workspace;
|
|
|
|
use std::sync::Arc;
|
|
|
|
use anyhow::anyhow;
|
|
use lsp_types::{ClientCapabilities, Url};
|
|
|
|
use crate::edit::DocumentVersion;
|
|
use crate::PositionEncoding;
|
|
|
|
pub(crate) use self::capabilities::ResolvedClientCapabilities;
|
|
pub(crate) use self::settings::{AllSettings, ClientSettings};
|
|
|
|
/// The global state for the LSP
|
|
pub(crate) struct Session {
|
|
/// Workspace folders in the current session, which contain the state of all open files.
|
|
workspaces: workspace::Workspaces,
|
|
/// The global position encoding, negotiated during LSP initialization.
|
|
position_encoding: PositionEncoding,
|
|
/// Global settings provided by the client.
|
|
global_settings: ClientSettings,
|
|
/// Tracks what LSP features the client supports and doesn't support.
|
|
resolved_client_capabilities: Arc<ResolvedClientCapabilities>,
|
|
}
|
|
|
|
/// An immutable snapshot of `Session` that references
|
|
/// a specific document.
|
|
pub(crate) struct DocumentSnapshot {
|
|
resolved_client_capabilities: Arc<ResolvedClientCapabilities>,
|
|
client_settings: settings::ResolvedClientSettings,
|
|
document_ref: workspace::DocumentRef,
|
|
position_encoding: PositionEncoding,
|
|
url: Url,
|
|
}
|
|
|
|
impl Session {
|
|
pub(crate) fn new(
|
|
client_capabilities: &ClientCapabilities,
|
|
position_encoding: PositionEncoding,
|
|
global_settings: ClientSettings,
|
|
workspaces: Vec<(Url, ClientSettings)>,
|
|
) -> crate::Result<Self> {
|
|
Ok(Self {
|
|
position_encoding,
|
|
global_settings,
|
|
resolved_client_capabilities: Arc::new(ResolvedClientCapabilities::new(
|
|
client_capabilities,
|
|
)),
|
|
workspaces: workspace::Workspaces::new(workspaces)?,
|
|
})
|
|
}
|
|
|
|
pub(crate) fn take_snapshot(&self, url: &Url) -> Option<DocumentSnapshot> {
|
|
Some(DocumentSnapshot {
|
|
resolved_client_capabilities: self.resolved_client_capabilities.clone(),
|
|
client_settings: self.workspaces.client_settings(url, &self.global_settings),
|
|
document_ref: self.workspaces.snapshot(url)?,
|
|
position_encoding: self.position_encoding,
|
|
url: url.clone(),
|
|
})
|
|
}
|
|
|
|
pub(crate) fn open_document(&mut self, url: &Url, contents: String, version: DocumentVersion) {
|
|
self.workspaces.open(url, contents, version);
|
|
}
|
|
|
|
pub(crate) fn close_document(&mut self, url: &Url) -> crate::Result<()> {
|
|
self.workspaces.close(url)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) fn document_controller(
|
|
&mut self,
|
|
url: &Url,
|
|
) -> crate::Result<&mut workspace::DocumentController> {
|
|
self.workspaces
|
|
.controller(url)
|
|
.ok_or_else(|| anyhow!("Tried to open unavailable document `{url}`"))
|
|
}
|
|
|
|
pub(crate) fn reload_settings(&mut self, url: &Url) -> crate::Result<()> {
|
|
self.workspaces.reload_settings(url)
|
|
}
|
|
|
|
pub(crate) fn open_workspace_folder(&mut self, url: &Url) -> crate::Result<()> {
|
|
self.workspaces.open_workspace_folder(url)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) fn close_workspace_folder(&mut self, url: &Url) -> crate::Result<()> {
|
|
self.workspaces.close_workspace_folder(url)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub(crate) fn resolved_client_capabilities(&self) -> &ResolvedClientCapabilities {
|
|
&self.resolved_client_capabilities
|
|
}
|
|
|
|
pub(crate) fn encoding(&self) -> PositionEncoding {
|
|
self.position_encoding
|
|
}
|
|
}
|
|
|
|
impl DocumentSnapshot {
|
|
pub(crate) fn settings(&self) -> &workspace::RuffSettings {
|
|
self.document().settings()
|
|
}
|
|
|
|
pub(crate) fn resolved_client_capabilities(&self) -> &ResolvedClientCapabilities {
|
|
&self.resolved_client_capabilities
|
|
}
|
|
|
|
pub(crate) fn client_settings(&self) -> &settings::ResolvedClientSettings {
|
|
&self.client_settings
|
|
}
|
|
|
|
pub(crate) fn document(&self) -> &workspace::DocumentRef {
|
|
&self.document_ref
|
|
}
|
|
|
|
pub(crate) fn encoding(&self) -> PositionEncoding {
|
|
self.position_encoding
|
|
}
|
|
|
|
pub(crate) fn url(&self) -> &Url {
|
|
&self.url
|
|
}
|
|
}
|