Compare commits
1 Commits
gankra/scr
...
dhruv/work
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d0468137c |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2833,6 +2833,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"shellexpand",
|
"shellexpand",
|
||||||
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ rustc-hash = { workspace = true }
|
|||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
shellexpand = { workspace = true }
|
shellexpand = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-subscriber = { workspace = true }
|
tracing-subscriber = { workspace = true }
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
pub use edit::{DocumentKey, NotebookDocument, PositionEncoding, TextDocument};
|
pub use edit::{DocumentKey, NotebookDocument, PositionEncoding, TextDocument};
|
||||||
use lsp_types::CodeActionKind;
|
use lsp_types::CodeActionKind;
|
||||||
pub use server::Server;
|
pub use server::{Server, Workspaces};
|
||||||
pub use session::{ClientSettings, DocumentQuery, DocumentSnapshot, Session};
|
pub use session::{ClientSettings, DocumentQuery, DocumentSnapshot, Session};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|||||||
@@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
use lsp_server as lsp;
|
use lsp_server as lsp;
|
||||||
use lsp_types as types;
|
use lsp_types as types;
|
||||||
|
use lsp_types::InitializeParams;
|
||||||
|
use lsp_types::WorkspaceFolder;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::panic::PanicInfo;
|
use std::panic::PanicInfo;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use thiserror::Error;
|
||||||
use types::ClientCapabilities;
|
use types::ClientCapabilities;
|
||||||
use types::CodeActionKind;
|
use types::CodeActionKind;
|
||||||
use types::CodeActionOptions;
|
use types::CodeActionOptions;
|
||||||
@@ -18,6 +22,7 @@ use types::OneOf;
|
|||||||
use types::TextDocumentSyncCapability;
|
use types::TextDocumentSyncCapability;
|
||||||
use types::TextDocumentSyncKind;
|
use types::TextDocumentSyncKind;
|
||||||
use types::TextDocumentSyncOptions;
|
use types::TextDocumentSyncOptions;
|
||||||
|
use types::Url;
|
||||||
use types::WorkDoneProgressOptions;
|
use types::WorkDoneProgressOptions;
|
||||||
use types::WorkspaceFoldersServerCapabilities;
|
use types::WorkspaceFoldersServerCapabilities;
|
||||||
|
|
||||||
@@ -29,6 +34,7 @@ use self::schedule::Task;
|
|||||||
use crate::session::AllSettings;
|
use crate::session::AllSettings;
|
||||||
use crate::session::ClientSettings;
|
use crate::session::ClientSettings;
|
||||||
use crate::session::Session;
|
use crate::session::Session;
|
||||||
|
use crate::session::WorkspaceSettingsMap;
|
||||||
use crate::PositionEncoding;
|
use crate::PositionEncoding;
|
||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
@@ -71,9 +77,15 @@ impl Server {
|
|||||||
|
|
||||||
crate::message::init_messenger(connection.make_sender());
|
crate::message::init_messenger(connection.make_sender());
|
||||||
|
|
||||||
|
let InitializeParams {
|
||||||
|
initialization_options,
|
||||||
|
workspace_folders,
|
||||||
|
client_info,
|
||||||
|
..
|
||||||
|
} = init_params;
|
||||||
|
|
||||||
let mut all_settings = AllSettings::from_value(
|
let mut all_settings = AllSettings::from_value(
|
||||||
init_params
|
initialization_options
|
||||||
.initialization_options
|
|
||||||
.unwrap_or_else(|| serde_json::Value::Object(serde_json::Map::default())),
|
.unwrap_or_else(|| serde_json::Value::Object(serde_json::Map::default())),
|
||||||
);
|
);
|
||||||
if let Some(preview) = preview {
|
if let Some(preview) = preview {
|
||||||
@@ -81,7 +93,7 @@ impl Server {
|
|||||||
}
|
}
|
||||||
let AllSettings {
|
let AllSettings {
|
||||||
global_settings,
|
global_settings,
|
||||||
mut workspace_settings,
|
workspace_settings,
|
||||||
} = all_settings;
|
} = all_settings;
|
||||||
|
|
||||||
crate::trace::init_tracing(
|
crate::trace::init_tracing(
|
||||||
@@ -91,34 +103,13 @@ impl Server {
|
|||||||
.log_level
|
.log_level
|
||||||
.unwrap_or(crate::trace::LogLevel::Info),
|
.unwrap_or(crate::trace::LogLevel::Info),
|
||||||
global_settings.tracing.log_file.as_deref(),
|
global_settings.tracing.log_file.as_deref(),
|
||||||
init_params.client_info.as_ref(),
|
client_info.as_ref(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut workspace_for_url = |url: lsp_types::Url| {
|
let workspaces = Workspaces::from_workspace_folders(
|
||||||
let Some(workspace_settings) = workspace_settings.as_mut() else {
|
workspace_folders,
|
||||||
return (url, ClientSettings::default());
|
workspace_settings.unwrap_or_default(),
|
||||||
};
|
)?;
|
||||||
let settings = workspace_settings.remove(&url).unwrap_or_else(|| {
|
|
||||||
tracing::warn!("No workspace settings found for {}", url);
|
|
||||||
ClientSettings::default()
|
|
||||||
});
|
|
||||||
(url, settings)
|
|
||||||
};
|
|
||||||
|
|
||||||
let workspaces = init_params
|
|
||||||
.workspace_folders
|
|
||||||
.filter(|folders| !folders.is_empty())
|
|
||||||
.map(|folders| folders.into_iter().map(|folder| {
|
|
||||||
workspace_for_url(folder.uri)
|
|
||||||
}).collect())
|
|
||||||
.or_else(|| {
|
|
||||||
tracing::warn!("No workspace(s) were provided during initialization. Using the current working directory as a default workspace...");
|
|
||||||
let uri = types::Url::from_file_path(std::env::current_dir().ok()?).ok()?;
|
|
||||||
Some(vec![workspace_for_url(uri)])
|
|
||||||
})
|
|
||||||
.ok_or_else(|| {
|
|
||||||
anyhow::anyhow!("Failed to get the current working directory while creating a default workspace.")
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
connection,
|
connection,
|
||||||
@@ -127,7 +118,7 @@ impl Server {
|
|||||||
&client_capabilities,
|
&client_capabilities,
|
||||||
position_encoding,
|
position_encoding,
|
||||||
global_settings,
|
global_settings,
|
||||||
workspaces,
|
&workspaces,
|
||||||
)?,
|
)?,
|
||||||
client_capabilities,
|
client_capabilities,
|
||||||
})
|
})
|
||||||
@@ -462,3 +453,117 @@ impl FromStr for SupportedCommand {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Workspaces(Vec<Workspace>);
|
||||||
|
|
||||||
|
impl Workspaces {
|
||||||
|
/// Create the workspaces from the provided workspace folders as provided by the client during
|
||||||
|
/// initialization.
|
||||||
|
fn from_workspace_folders(
|
||||||
|
workspace_folders: Option<Vec<WorkspaceFolder>>,
|
||||||
|
mut workspace_settings: WorkspaceSettingsMap,
|
||||||
|
) -> std::result::Result<Workspaces, WorkspacesError> {
|
||||||
|
let mut client_settings_for_url = |url: &Url| {
|
||||||
|
workspace_settings.remove(url).unwrap_or_else(|| {
|
||||||
|
tracing::info!(
|
||||||
|
"No workspace settings found for {}, using default settings",
|
||||||
|
url
|
||||||
|
);
|
||||||
|
ClientSettings::default()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let workspaces =
|
||||||
|
if let Some(folders) = workspace_folders.filter(|folders| !folders.is_empty()) {
|
||||||
|
folders
|
||||||
|
.into_iter()
|
||||||
|
.map(|folder| {
|
||||||
|
let settings = client_settings_for_url(&folder.uri);
|
||||||
|
Workspace::new(folder.uri).with_settings(settings)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
let current_dir = std::env::current_dir().map_err(WorkspacesError::Io)?;
|
||||||
|
tracing::info!(
|
||||||
|
"No workspace(s) were provided during initialization. \
|
||||||
|
Using the current working directory as a default workspace: {}",
|
||||||
|
current_dir.display()
|
||||||
|
);
|
||||||
|
let uri = Url::from_file_path(current_dir)
|
||||||
|
.map_err(|()| WorkspacesError::InvalidCurrentDir)?;
|
||||||
|
let settings = client_settings_for_url(&uri);
|
||||||
|
vec![Workspace::default(uri).with_settings(settings)]
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Workspaces(workspaces))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Workspaces {
|
||||||
|
type Target = [Workspace];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
enum WorkspacesError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
#[error("Failed to create a URL from the current working directory")]
|
||||||
|
InvalidCurrentDir,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Workspace {
|
||||||
|
/// The [`Url`] pointing to the root of the workspace.
|
||||||
|
url: Url,
|
||||||
|
/// The client settings for this workspace.
|
||||||
|
settings: Option<ClientSettings>,
|
||||||
|
/// Whether this is the default workspace as created by the server. This will be the case when
|
||||||
|
/// no workspace folders were provided during initialization.
|
||||||
|
is_default: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Workspace {
|
||||||
|
/// Create a new workspace with the given root URL.
|
||||||
|
pub(crate) fn new(url: Url) -> Self {
|
||||||
|
Self {
|
||||||
|
url,
|
||||||
|
settings: None,
|
||||||
|
is_default: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new default workspace with the given root URL.
|
||||||
|
fn default(url: Url) -> Self {
|
||||||
|
Self {
|
||||||
|
url,
|
||||||
|
settings: None,
|
||||||
|
is_default: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the client settings for this workspace.
|
||||||
|
fn with_settings(mut self, settings: ClientSettings) -> Self {
|
||||||
|
self.settings = Some(settings);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the root URL of the workspace.
|
||||||
|
pub fn url(&self) -> &Url {
|
||||||
|
&self.url
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the client settings for this workspace.
|
||||||
|
pub fn settings(&self) -> Option<&ClientSettings> {
|
||||||
|
self.settings.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if this is the default workspace.
|
||||||
|
pub fn is_default(&self) -> bool {
|
||||||
|
self.is_default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ impl super::SyncNotificationHandler for DidChangeWorkspace {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for types::WorkspaceFolder { uri, .. } in params.event.added {
|
for types::WorkspaceFolder { uri, .. } in params.event.added {
|
||||||
session
|
session
|
||||||
.open_workspace_folder(&uri)
|
.open_workspace_folder(uri)
|
||||||
.with_failure_code(lsp_server::ErrorCode::InvalidParams)?;
|
.with_failure_code(lsp_server::ErrorCode::InvalidParams)?;
|
||||||
}
|
}
|
||||||
for types::WorkspaceFolder { uri, .. } in params.event.removed {
|
for types::WorkspaceFolder { uri, .. } in params.event.removed {
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ use std::sync::Arc;
|
|||||||
use lsp_types::{ClientCapabilities, NotebookDocumentCellChange, Url};
|
use lsp_types::{ClientCapabilities, NotebookDocumentCellChange, Url};
|
||||||
|
|
||||||
use crate::edit::{DocumentKey, DocumentVersion, NotebookDocument};
|
use crate::edit::{DocumentKey, DocumentVersion, NotebookDocument};
|
||||||
|
use crate::server::Workspaces;
|
||||||
use crate::{PositionEncoding, TextDocument};
|
use crate::{PositionEncoding, TextDocument};
|
||||||
|
|
||||||
pub(crate) use self::capabilities::ResolvedClientCapabilities;
|
pub(crate) use self::capabilities::ResolvedClientCapabilities;
|
||||||
pub use self::index::DocumentQuery;
|
pub use self::index::DocumentQuery;
|
||||||
pub(crate) use self::settings::AllSettings;
|
|
||||||
pub use self::settings::ClientSettings;
|
pub use self::settings::ClientSettings;
|
||||||
|
pub(crate) use self::settings::{AllSettings, WorkspaceSettingsMap};
|
||||||
|
|
||||||
mod capabilities;
|
mod capabilities;
|
||||||
mod index;
|
mod index;
|
||||||
@@ -42,11 +43,11 @@ impl Session {
|
|||||||
client_capabilities: &ClientCapabilities,
|
client_capabilities: &ClientCapabilities,
|
||||||
position_encoding: PositionEncoding,
|
position_encoding: PositionEncoding,
|
||||||
global_settings: ClientSettings,
|
global_settings: ClientSettings,
|
||||||
workspace_folders: Vec<(Url, ClientSettings)>,
|
workspaces: &Workspaces,
|
||||||
) -> crate::Result<Self> {
|
) -> crate::Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
position_encoding,
|
position_encoding,
|
||||||
index: index::Index::new(workspace_folders, &global_settings)?,
|
index: index::Index::new(workspaces, &global_settings)?,
|
||||||
global_settings,
|
global_settings,
|
||||||
resolved_client_capabilities: Arc::new(ResolvedClientCapabilities::new(
|
resolved_client_capabilities: Arc::new(ResolvedClientCapabilities::new(
|
||||||
client_capabilities,
|
client_capabilities,
|
||||||
@@ -136,7 +137,7 @@ impl Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Open a workspace folder at the given `url`.
|
/// Open a workspace folder at the given `url`.
|
||||||
pub(crate) fn open_workspace_folder(&mut self, url: &Url) -> crate::Result<()> {
|
pub(crate) fn open_workspace_folder(&mut self, url: Url) -> crate::Result<()> {
|
||||||
self.index.open_workspace_folder(url, &self.global_settings)
|
self.index.open_workspace_folder(url, &self.global_settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use rustc_hash::FxHashMap;
|
|||||||
pub(crate) use ruff_settings::RuffSettings;
|
pub(crate) use ruff_settings::RuffSettings;
|
||||||
|
|
||||||
use crate::edit::LanguageId;
|
use crate::edit::LanguageId;
|
||||||
|
use crate::server::{Workspace, Workspaces};
|
||||||
use crate::{
|
use crate::{
|
||||||
edit::{DocumentKey, DocumentVersion, NotebookDocument},
|
edit::{DocumentKey, DocumentVersion, NotebookDocument},
|
||||||
PositionEncoding, TextDocument,
|
PositionEncoding, TextDocument,
|
||||||
@@ -67,12 +68,12 @@ pub enum DocumentQuery {
|
|||||||
|
|
||||||
impl Index {
|
impl Index {
|
||||||
pub(super) fn new(
|
pub(super) fn new(
|
||||||
workspace_folders: Vec<(Url, ClientSettings)>,
|
workspaces: &Workspaces,
|
||||||
global_settings: &ClientSettings,
|
global_settings: &ClientSettings,
|
||||||
) -> crate::Result<Self> {
|
) -> crate::Result<Self> {
|
||||||
let mut settings = WorkspaceSettingsIndex::default();
|
let mut settings = WorkspaceSettingsIndex::default();
|
||||||
for (url, workspace_settings) in workspace_folders {
|
for workspace in &**workspaces {
|
||||||
settings.register_workspace(&url, Some(workspace_settings), global_settings)?;
|
settings.register_workspace(workspace, global_settings)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -167,11 +168,12 @@ impl Index {
|
|||||||
|
|
||||||
pub(super) fn open_workspace_folder(
|
pub(super) fn open_workspace_folder(
|
||||||
&mut self,
|
&mut self,
|
||||||
url: &Url,
|
url: Url,
|
||||||
global_settings: &ClientSettings,
|
global_settings: &ClientSettings,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
// TODO(jane): Find a way for workspace client settings to be added or changed dynamically.
|
// TODO(jane): Find a way for workspace client settings to be added or changed dynamically.
|
||||||
self.settings.register_workspace(url, None, global_settings)
|
self.settings
|
||||||
|
.register_workspace(&Workspace::new(url), global_settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn num_documents(&self) -> usize {
|
pub(super) fn num_documents(&self) -> usize {
|
||||||
@@ -398,10 +400,10 @@ impl WorkspaceSettingsIndex {
|
|||||||
/// workspace. Otherwise, the global settings are used exclusively.
|
/// workspace. Otherwise, the global settings are used exclusively.
|
||||||
fn register_workspace(
|
fn register_workspace(
|
||||||
&mut self,
|
&mut self,
|
||||||
workspace_url: &Url,
|
workspace: &Workspace,
|
||||||
workspace_settings: Option<ClientSettings>,
|
|
||||||
global_settings: &ClientSettings,
|
global_settings: &ClientSettings,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
let workspace_url = workspace.url();
|
||||||
if workspace_url.scheme() != "file" {
|
if workspace_url.scheme() != "file" {
|
||||||
tracing::info!("Ignoring non-file workspace URL: {workspace_url}");
|
tracing::info!("Ignoring non-file workspace URL: {workspace_url}");
|
||||||
show_warn_msg!("Ruff does not support non-file workspaces; Ignoring {workspace_url}");
|
show_warn_msg!("Ruff does not support non-file workspaces; Ignoring {workspace_url}");
|
||||||
@@ -411,8 +413,8 @@ impl WorkspaceSettingsIndex {
|
|||||||
anyhow!("Failed to convert workspace URL to file path: {workspace_url}")
|
anyhow!("Failed to convert workspace URL to file path: {workspace_url}")
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let client_settings = if let Some(workspace_settings) = workspace_settings {
|
let client_settings = if let Some(workspace_settings) = workspace.settings() {
|
||||||
ResolvedClientSettings::with_workspace(&workspace_settings, global_settings)
|
ResolvedClientSettings::with_workspace(workspace_settings, global_settings)
|
||||||
} else {
|
} else {
|
||||||
ResolvedClientSettings::global(global_settings)
|
ResolvedClientSettings::global(global_settings)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use lsp_types::{
|
|||||||
Position, Range, TextDocumentContentChangeEvent, VersionedTextDocumentIdentifier,
|
Position, Range, TextDocumentContentChangeEvent, VersionedTextDocumentIdentifier,
|
||||||
};
|
};
|
||||||
use ruff_notebook::SourceValue;
|
use ruff_notebook::SourceValue;
|
||||||
use ruff_server::ClientSettings;
|
use ruff_server::{ClientSettings, Workspaces};
|
||||||
|
|
||||||
const SUPER_RESOLUTION_OVERVIEW_PATH: &str =
|
const SUPER_RESOLUTION_OVERVIEW_PATH: &str =
|
||||||
"./resources/test/fixtures/tensorflow_test_notebook.ipynb";
|
"./resources/test/fixtures/tensorflow_test_notebook.ipynb";
|
||||||
@@ -32,10 +32,10 @@ fn super_resolution_overview() {
|
|||||||
&ClientCapabilities::default(),
|
&ClientCapabilities::default(),
|
||||||
ruff_server::PositionEncoding::UTF16,
|
ruff_server::PositionEncoding::UTF16,
|
||||||
ClientSettings::default(),
|
ClientSettings::default(),
|
||||||
vec![(
|
&Workspaces(vec![(
|
||||||
lsp_types::Url::from_file_path(file_path.parent().unwrap()).unwrap(),
|
lsp_types::Url::from_file_path(file_path.parent().unwrap()).unwrap(),
|
||||||
ClientSettings::default(),
|
ClientSettings::default(),
|
||||||
)],
|
)]),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user