diff --git a/crates/ruff/src/commands/format.rs b/crates/ruff/src/commands/format.rs index 20c000a89d..1f79e59339 100644 --- a/crates/ruff/src/commands/format.rs +++ b/crates/ruff/src/commands/format.rs @@ -879,19 +879,7 @@ impl From<&FormatCommandError> for Diagnostic { | FormatCommandError::Write(_, source_error) => { Diagnostic::new(DiagnosticId::Io, Severity::Error, source_error) } - FormatCommandError::Format(_, format_module_error) => match format_module_error { - FormatModuleError::ParseError(parse_error) => Diagnostic::new( - DiagnosticId::InternalError, - Severity::Error, - &parse_error.error, - ), - FormatModuleError::FormatError(format_error) => { - Diagnostic::new(DiagnosticId::InternalError, Severity::Error, format_error) - } - FormatModuleError::PrintError(print_error) => { - Diagnostic::new(DiagnosticId::InternalError, Severity::Error, print_error) - } - }, + FormatCommandError::Format(_, format_module_error) => format_module_error.into(), FormatCommandError::RangeFormatNotebook(_) => Diagnostic::new( DiagnosticId::InvalidCliOption, Severity::Error, diff --git a/crates/ruff_python_formatter/src/lib.rs b/crates/ruff_python_formatter/src/lib.rs index 3dbef73807..e6b2f9e7b8 100644 --- a/crates/ruff_python_formatter/src/lib.rs +++ b/crates/ruff_python_formatter/src/lib.rs @@ -1,3 +1,4 @@ +use ruff_db::diagnostic::{Diagnostic, DiagnosticId, Severity}; use ruff_db::files::File; use ruff_db::parsed::parsed_module; use ruff_db::source::source_text; @@ -10,7 +11,7 @@ use ruff_formatter::{FormatError, Formatted, PrintError, Printed, SourceCode, fo use ruff_python_ast::{AnyNodeRef, Mod}; use ruff_python_parser::{ParseError, ParseOptions, Parsed, parse}; use ruff_python_trivia::CommentRanges; -use ruff_text_size::Ranged; +use ruff_text_size::{Ranged, TextRange}; use crate::comments::{ Comments, SourceComment, has_skip_comment, leading_comments, trailing_comments, @@ -117,6 +118,33 @@ pub enum FormatModuleError { PrintError(#[from] PrintError), } +impl FormatModuleError { + pub fn range(&self) -> Option { + match self { + FormatModuleError::ParseError(parse_error) => Some(parse_error.range()), + FormatModuleError::FormatError(_) | FormatModuleError::PrintError(_) => None, + } + } +} + +impl From<&FormatModuleError> for Diagnostic { + fn from(error: &FormatModuleError) -> Self { + match error { + FormatModuleError::ParseError(parse_error) => Diagnostic::new( + DiagnosticId::InternalError, + Severity::Error, + &parse_error.error, + ), + FormatModuleError::FormatError(format_error) => { + Diagnostic::new(DiagnosticId::InternalError, Severity::Error, format_error) + } + FormatModuleError::PrintError(print_error) => { + Diagnostic::new(DiagnosticId::InternalError, Severity::Error, print_error) + } + } + } +} + #[tracing::instrument(name = "format", level = Level::TRACE, skip_all)] pub fn format_module_source( source: &str, diff --git a/crates/ruff_python_formatter/tests/fixtures.rs b/crates/ruff_python_formatter/tests/fixtures.rs index 776b272d21..33741bd744 100644 --- a/crates/ruff_python_formatter/tests/fixtures.rs +++ b/crates/ruff_python_formatter/tests/fixtures.rs @@ -404,10 +404,18 @@ fn ensure_stability_when_formatting_twice( let reformatted = match format_module_source(formatted_code, options.clone()) { Ok(reformatted) => reformatted, Err(err) => { + let mut diag = Diagnostic::from(&err); + if let Some(range) = err.range() { + let file = + SourceFileBuilder::new(input_path.to_string_lossy(), formatted_code).finish(); + let span = Span::from(file).with_range(range); + diag.annotate(Annotation::primary(span)); + } panic!( "Expected formatted code of {} to be valid syntax: {err}:\ - \n---\n{formatted_code}---\n", - input_path.display() + \n---\n{formatted_code}---\n{}", + input_path.display(), + diag.display(&DummyFileResolver, &DisplayDiagnosticConfig::default()), ); } };