Skip to content

Commit

Permalink
[red-knot] Support files outside of any workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruvmanila committed Aug 22, 2024
1 parent d1d0678 commit 028cb68
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 37 deletions.
5 changes: 5 additions & 0 deletions crates/red_knot_server/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ impl Server {
anyhow::anyhow!("Failed to get the current working directory while creating a default workspace.")
})?;

if workspaces.len() > 1 {
// TODO(dhruvmanila): Support multi-root workspaces
anyhow::bail!("Multi-root workspaces are not supported yet");
}

Ok(Self {
connection,
worker_threads,
Expand Down
8 changes: 4 additions & 4 deletions crates/red_knot_server/src/server/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ mod requests;
mod traits;

use notifications as notification;
use red_knot_workspace::db::RootDatabase;
use requests as request;

use self::traits::{NotificationHandler, RequestHandler};
Expand Down Expand Up @@ -85,9 +84,10 @@ fn background_request_task<'a, R: traits::BackgroundDocumentRequestHandler>(
let Ok(path) = url_to_system_path(&url) else {
return Box::new(|_, _| {});
};
let db = session
.workspace_db_for_path(path.as_std_path())
.map(RootDatabase::snapshot);
let db = match session.workspace_db_for_path(path.as_std_path()) {
Some(db) => db.snapshot(),
None => session.default_workspace_db().snapshot(),
};

let Some(snapshot) = session.take_snapshot(url) else {
return Box::new(|_, _| {});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use lsp_server::ErrorCode;
use lsp_types::notification::DidCloseTextDocument;
use lsp_types::DidCloseTextDocumentParams;

use ruff_db::files::File;

use crate::server::api::diagnostics::clear_diagnostics;
use crate::server::api::traits::{NotificationHandler, SyncNotificationHandler};
use crate::server::api::LSPResult;
Expand All @@ -25,7 +23,7 @@ impl SyncNotificationHandler for DidCloseTextDocumentHandler {
_requester: &mut Requester,
params: DidCloseTextDocumentParams,
) -> Result<()> {
let Ok(path) = url_to_system_path(&params.text_document.uri) else {
let Ok(_path) = url_to_system_path(&params.text_document.uri) else {
return Ok(());
};

Expand All @@ -34,10 +32,6 @@ impl SyncNotificationHandler for DidCloseTextDocumentHandler {
.close_document(&key)
.with_failure_code(ErrorCode::InternalError)?;

if let Some(db) = session.workspace_db_for_path_mut(path.as_std_path()) {
File::sync_path(db, &path);
}

clear_diagnostics(key.url(), &notifier)?;

Ok(())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use lsp_types::notification::DidCloseNotebookDocument;
use lsp_types::DidCloseNotebookDocumentParams;

use ruff_db::files::File;

use crate::server::api::traits::{NotificationHandler, SyncNotificationHandler};
use crate::server::api::LSPResult;
use crate::server::client::{Notifier, Requester};
Expand All @@ -23,7 +21,7 @@ impl SyncNotificationHandler for DidCloseNotebookHandler {
_requester: &mut Requester,
params: DidCloseNotebookDocumentParams,
) -> Result<()> {
let Ok(path) = url_to_system_path(&params.notebook_document.uri) else {
let Ok(_path) = url_to_system_path(&params.notebook_document.uri) else {
return Ok(());
};

Expand All @@ -32,10 +30,6 @@ impl SyncNotificationHandler for DidCloseNotebookHandler {
.close_document(&key)
.with_failure_code(lsp_server::ErrorCode::InternalError)?;

if let Some(db) = session.workspace_db_for_path_mut(path.as_std_path()) {
File::sync_path(db, &path);
}

Ok(())
}
}
12 changes: 6 additions & 6 deletions crates/red_knot_server/src/server/api/notifications/did_open.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use lsp_types::notification::DidOpenTextDocument;
use lsp_types::DidOpenTextDocumentParams;

use ruff_db::files::system_path_to_file;
use red_knot_workspace::watch::ChangeEvent;

use crate::server::api::traits::{NotificationHandler, SyncNotificationHandler};
use crate::server::client::{Notifier, Requester};
Expand Down Expand Up @@ -30,11 +30,11 @@ impl SyncNotificationHandler for DidOpenTextDocumentHandler {
let document = TextDocument::new(params.text_document.text, params.text_document.version);
session.open_text_document(params.text_document.uri, document);

if let Some(db) = session.workspace_db_for_path_mut(path.as_std_path()) {
// TODO(dhruvmanila): Store the `file` in `DocumentController`
let file = system_path_to_file(db, &path).unwrap();
file.sync(db);
}
let db = match session.workspace_db_for_path_mut(path.as_std_path()) {
Some(db) => db,
None => session.default_workspace_db_mut(),
};
db.apply_changes(vec![ChangeEvent::file_created(path)], None);

// TODO(dhruvmanila): Publish diagnostics if the client doesn't support pull diagnostics

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use lsp_server::ErrorCode;
use lsp_types::notification::DidOpenNotebookDocument;
use lsp_types::DidOpenNotebookDocumentParams;

use ruff_db::files::system_path_to_file;
use red_knot_workspace::watch::ChangeEvent;

use crate::edit::NotebookDocument;
use crate::server::api::traits::{NotificationHandler, SyncNotificationHandler};
Expand Down Expand Up @@ -38,11 +38,11 @@ impl SyncNotificationHandler for DidOpenNotebookHandler {
.with_failure_code(ErrorCode::InternalError)?;
session.open_notebook_document(params.notebook_document.uri.clone(), notebook);

if let Some(db) = session.workspace_db_for_path_mut(path.as_std_path()) {
// TODO(dhruvmanila): Store the `file` in `DocumentController`
let file = system_path_to_file(db, &path).unwrap();
file.sync(db);
}
let db = match session.workspace_db_for_path_mut(path.as_std_path()) {
Some(db) => db,
None => session.default_workspace_db_mut(),
};
db.apply_changes(vec![ChangeEvent::file_created(path)], None);

// TODO(dhruvmanila): Publish diagnostics if the client doesn't support pull diagnostics

Expand Down
10 changes: 4 additions & 6 deletions crates/red_knot_server/src/server/api/requests/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@ impl BackgroundDocumentRequestHandler for DocumentDiagnosticRequestHandler {

fn run_with_snapshot(
snapshot: DocumentSnapshot,
db: Option<RootDatabase>,
db: RootDatabase,
_notifier: Notifier,
_params: DocumentDiagnosticParams,
) -> Result<DocumentDiagnosticReportResult> {
let diagnostics = db
.map(|db| compute_diagnostics(&snapshot, &db))
.unwrap_or_default();
let diagnostics = compute_diagnostics(&snapshot, &db);

Ok(DocumentDiagnosticReportResult::Report(
DocumentDiagnosticReport::Full(RelatedFullDocumentDiagnosticReport {
Expand Down Expand Up @@ -66,11 +64,11 @@ fn to_lsp_diagnostic(message: &str) -> Diagnostic {

let (range, message) = match words.as_slice() {
[_filename, line, column, message] => {
let line = line.parse::<u32>().unwrap_or_default();
let line = line.parse::<u32>().unwrap_or_default().saturating_sub(1);
let column = column.parse::<u32>().unwrap_or_default();
(
Range::new(
Position::new(line.saturating_sub(1), column.saturating_sub(1)),
Position::new(line, column.saturating_sub(1)),
Position::new(line, column),
),
message.trim(),
Expand Down
2 changes: 1 addition & 1 deletion crates/red_knot_server/src/server/api/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub(super) trait BackgroundDocumentRequestHandler: RequestHandler {

fn run_with_snapshot(
snapshot: DocumentSnapshot,
db: Option<RootDatabase>,
db: RootDatabase,
notifier: Notifier,
params: <<Self as RequestHandler>::RequestType as Request>::Params,
) -> super::Result<<<Self as RequestHandler>::RequestType as Request>::Result>;
Expand Down
17 changes: 17 additions & 0 deletions crates/red_knot_server/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,17 @@ impl Session {
})
}

/// Returns a reference to the workspace [`RootDatabase`] corresponding to the given path, if
/// any.
pub(crate) fn workspace_db_for_path(&self, path: impl AsRef<Path>) -> Option<&RootDatabase> {
self.workspaces
.range(..=path.as_ref().to_path_buf())
.next_back()
.map(|(_, db)| db)
}

/// Returns a mutable reference to the workspace [`RootDatabase`] corresponding to the given
/// path, if any.
pub(crate) fn workspace_db_for_path_mut(
&mut self,
path: impl AsRef<Path>,
Expand All @@ -99,6 +103,19 @@ impl Session {
.map(|(_, db)| db)
}

/// Returns a reference to the default workspace [`RootDatabase`]. The default workspace is the
/// minimum root path in the workspace map.
pub(crate) fn default_workspace_db(&self) -> &RootDatabase {
// SAFETY: Currently, red knot only support a single workspace.
self.workspaces.values().next().unwrap()
}

/// Returns a mutable reference to the default workspace [`RootDatabase`].
pub(crate) fn default_workspace_db_mut(&mut self) -> &mut RootDatabase {
// SAFETY: Currently, red knot only support a single workspace.
self.workspaces.values_mut().next().unwrap()
}

pub fn key_from_url(&self, url: Url) -> DocumentKey {
self.index().key_from_url(url)
}
Expand Down
10 changes: 10 additions & 0 deletions crates/red_knot_workspace/src/watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ pub enum ChangeEvent {
}

impl ChangeEvent {
/// Creates a new [`Created`] event for a file at the given path.
///
/// [`Created`]: ChangeEvent::Created
pub fn file_created(path: SystemPathBuf) -> ChangeEvent {
ChangeEvent::Created {
path,
kind: CreatedKind::File,
}
}

pub fn file_name(&self) -> Option<&str> {
self.path().and_then(|path| path.file_name())
}
Expand Down

0 comments on commit 028cb68

Please sign in to comment.