diff --git a/CHANGELOG.md b/CHANGELOG.md index 26942134803..af278b13a15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -108,6 +108,8 @@ if no error diagnostics are emitted. #### Other changes - The Rome LSP is now able to show diagnostics that belong to JSON lint rules. +- Fix [#4564](https://github.com/rome/tools/issues/4564), now files too large don't emit errors. +- The Rome LSP now sends client messages when files are ignored or too big. ### Formatter diff --git a/crates/rome_lsp/src/diagnostics.rs b/crates/rome_lsp/src/diagnostics.rs new file mode 100644 index 00000000000..cae4caf1faa --- /dev/null +++ b/crates/rome_lsp/src/diagnostics.rs @@ -0,0 +1,60 @@ +use crate::utils::into_lsp_error; +use anyhow::Error; +use rome_service::WorkspaceError; +use std::fmt::{Display, Formatter}; +use tower_lsp::lsp_types::MessageType; + +#[derive(Debug)] +pub enum LspError { + WorkspaceError(WorkspaceError), + Anyhow(anyhow::Error), +} + +impl From for LspError { + fn from(value: WorkspaceError) -> Self { + Self::WorkspaceError(value) + } +} + +impl From for LspError { + fn from(value: Error) -> Self { + Self::Anyhow(value) + } +} + +impl Display for LspError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + LspError::WorkspaceError(err) => { + write!(f, "{}", err) + } + LspError::Anyhow(err) => { + write!(f, "{}", err) + } + } + } +} + +/// Receives an error coming from a LSP query, and converts it into a JSON-RPC error. +/// +/// It accepts a `Client`, so contextual messages are sent to the user. +pub(crate) async fn handle_lsp_error( + err: LspError, + client: &tower_lsp::Client, +) -> Result, tower_lsp::jsonrpc::Error> { + match err { + LspError::WorkspaceError(err) => match err { + // diagnostics that shouldn't raise an hard error, but send a message to the user + WorkspaceError::FormatWithErrorsDisabled(_) + | WorkspaceError::FileIgnored(_) + | WorkspaceError::FileTooLarge(_) => { + let message = format!("{}", err); + client.show_message(MessageType::WARNING, message).await; + Ok(None) + } + + _ => Err(into_lsp_error(err)), + }, + LspError::Anyhow(err) => Err(into_lsp_error(err)), + } +} diff --git a/crates/rome_lsp/src/handlers/formatting.rs b/crates/rome_lsp/src/handlers/formatting.rs index 33aa457f109..a533dde62fc 100644 --- a/crates/rome_lsp/src/handlers/formatting.rs +++ b/crates/rome_lsp/src/handlers/formatting.rs @@ -1,10 +1,8 @@ use crate::converters::{from_proto, to_proto}; +use crate::diagnostics::LspError; use crate::session::Session; -use anyhow::{Context, Error, Result}; -use rome_service::{ - workspace::{FormatFileParams, FormatOnTypeParams, FormatRangeParams}, - WorkspaceError, -}; +use anyhow::Context; +use rome_service::workspace::{FormatFileParams, FormatOnTypeParams, FormatRangeParams}; use tower_lsp::lsp_types::*; use tracing::debug; @@ -12,24 +10,16 @@ use tracing::debug; pub(crate) fn format( session: &Session, params: DocumentFormattingParams, -) -> Result>> { +) -> Result>, LspError> { let url = params.text_document.uri; let rome_path = session.file_path(&url)?; let doc = session.document(&url)?; debug!("Formatting..."); - let result = session + let printed = session .workspace - .format_file(FormatFileParams { path: rome_path }); - - let printed = match result { - Ok(printed) => printed, - Err(WorkspaceError::FormatWithErrorsDisabled(_)) | Err(WorkspaceError::FileIgnored(_)) => { - return Ok(None) - } - Err(err) => return Err(Error::from(err)), - }; + .format_file(FormatFileParams { path: rome_path })?; let num_lines: u32 = doc.line_index.len(); @@ -53,7 +43,7 @@ pub(crate) fn format( pub(crate) fn format_range( session: &Session, params: DocumentRangeFormattingParams, -) -> Result>> { +) -> Result>, LspError> { let url = params.text_document.uri; let rome_path = session.file_path(&url)?; let doc = session.document(&url)?; @@ -67,18 +57,10 @@ pub(crate) fn format_range( ) })?; - let result = session.workspace.format_range(FormatRangeParams { + let formatted = session.workspace.format_range(FormatRangeParams { path: rome_path, range: format_range, - }); - - let formatted = match result { - Ok(formatted) => formatted, - Err(WorkspaceError::FormatWithErrorsDisabled(_)) | Err(WorkspaceError::FileIgnored(_)) => { - return Ok(None) - } - Err(err) => return Err(Error::from(err)), - }; + })?; // Recalculate the actual range that was reformatted from the formatter result let formatted_range = match formatted.range() { @@ -105,7 +87,7 @@ pub(crate) fn format_range( pub(crate) fn format_on_type( session: &Session, params: DocumentOnTypeFormattingParams, -) -> Result>> { +) -> Result>, LspError> { let url = params.text_document_position.text_document.uri; let position = params.text_document_position.position; @@ -116,18 +98,10 @@ pub(crate) fn format_on_type( let offset = from_proto::offset(&doc.line_index, position, position_encoding) .with_context(|| format!("failed to access position {position:?} in document {url}"))?; - let result = session.workspace.format_on_type(FormatOnTypeParams { + let formatted = session.workspace.format_on_type(FormatOnTypeParams { path: rome_path, offset, - }); - - let formatted = match result { - Ok(formatted) => formatted, - Err(WorkspaceError::FormatWithErrorsDisabled(_)) | Err(WorkspaceError::FileIgnored(_)) => { - return Ok(None) - } - Err(err) => return Err(Error::from(err)), - }; + })?; // Recalculate the actual range that was reformatted from the formatter result let formatted_range = match formatted.range() { diff --git a/crates/rome_lsp/src/lib.rs b/crates/rome_lsp/src/lib.rs index e0e17739fcf..bcbdc0edd23 100644 --- a/crates/rome_lsp/src/lib.rs +++ b/crates/rome_lsp/src/lib.rs @@ -1,5 +1,6 @@ mod capabilities; mod converters; +mod diagnostics; mod documents; mod extension_settings; mod handlers; diff --git a/crates/rome_lsp/src/server.rs b/crates/rome_lsp/src/server.rs index df5075a0bc4..f5b206b59c8 100644 --- a/crates/rome_lsp/src/server.rs +++ b/crates/rome_lsp/src/server.rs @@ -1,4 +1,5 @@ use crate::capabilities::server_capabilities; +use crate::diagnostics::{handle_lsp_error, LspError}; use crate::requests::syntax_tree::{SyntaxTreePayload, SYNTAX_TREE_REQUEST}; use crate::session::{ CapabilitySet, CapabilityStatus, ClientInformation, Session, SessionHandle, SessionKey, @@ -8,6 +9,7 @@ use crate::{handlers, requests}; use futures::future::ready; use futures::FutureExt; use rome_console::markup; +use rome_diagnostics::panic::PanicError; use rome_fs::CONFIG_NAME; use rome_service::workspace::{RageEntry, RageParams, RageResult}; use rome_service::{workspace, Workspace}; @@ -192,6 +194,20 @@ impl LSPServer { self.session.register_capabilities(capabilities).await; } + + async fn map_op_error( + &self, + result: Result, LspError>, PanicError>, + ) -> LspResult> { + match result { + Ok(result) => match result { + Ok(result) => Ok(result), + Err(err) => handle_lsp_error(err, &self.session.client).await, + }, + + Err(err) => Err(into_lsp_error(err)), + } + } } #[tower_lsp::async_trait] @@ -340,30 +356,33 @@ impl LanguageServer for LSPServer { &self, params: DocumentFormattingParams, ) -> LspResult>> { - rome_diagnostics::panic::catch_unwind(move || { - handlers::formatting::format(&self.session, params).map_err(into_lsp_error) - }) - .map_err(into_lsp_error)? + let result = rome_diagnostics::panic::catch_unwind(move || { + handlers::formatting::format(&self.session, params) + }); + + self.map_op_error(result).await } async fn range_formatting( &self, params: DocumentRangeFormattingParams, ) -> LspResult>> { - rome_diagnostics::panic::catch_unwind(move || { - handlers::formatting::format_range(&self.session, params).map_err(into_lsp_error) - }) - .map_err(into_lsp_error)? + let result = rome_diagnostics::panic::catch_unwind(move || { + handlers::formatting::format_range(&self.session, params) + }); + + self.map_op_error(result).await } async fn on_type_formatting( &self, params: DocumentOnTypeFormattingParams, ) -> LspResult>> { - rome_diagnostics::panic::catch_unwind(move || { - handlers::formatting::format_on_type(&self.session, params).map_err(into_lsp_error) - }) - .map_err(into_lsp_error)? + let result = rome_diagnostics::panic::catch_unwind(move || { + handlers::formatting::format_on_type(&self.session, params) + }); + + self.map_op_error(result).await } async fn rename(&self, params: RenameParams) -> LspResult> { diff --git a/crates/rome_service/src/diagnostics.rs b/crates/rome_service/src/diagnostics.rs index 754aa3b568b..3b4f9db4424 100644 --- a/crates/rome_service/src/diagnostics.rs +++ b/crates/rome_service/src/diagnostics.rs @@ -386,9 +386,10 @@ pub struct CantReadFile { #[diagnostic( category = "internalError/fs", message( - message("The file "{self.path}" was ignored"), - description = "The file {path} was ignored" - ) + message("The file "{self.path}" was ignored."), + description = "The file {path} was ignored." + ), + severity = Warning )] pub struct FileIgnored { #[location(resource)] diff --git a/crates/rome_service/src/snapshots/file_ignored.snap b/crates/rome_service/src/snapshots/file_ignored.snap index 72c2605867e..d1675ae0236 100644 --- a/crates/rome_service/src/snapshots/file_ignored.snap +++ b/crates/rome_service/src/snapshots/file_ignored.snap @@ -4,7 +4,7 @@ expression: content --- example.js internalError/fs ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - × The file example.js was ignored + ! The file example.js was ignored.