Skip to content

Commit

Permalink
Use Display for formatter parse errors (#9316)
Browse files Browse the repository at this point in the history
## Summary

This helps a bit with (but does not close) the issues described in
#9311. E.g., now, we at least
see: `error: Failed to format main.py: source contains syntax errors:
invalid syntax. Got unexpected token '=' at byte offset 20`.
  • Loading branch information
charliermarsh authored Dec 29, 2023
1 parent 2895e7d commit 97e9d3c
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 8 deletions.
2 changes: 2 additions & 0 deletions crates/ruff_cli/src/commands/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,11 +408,13 @@ pub(crate) fn format_source(
pub(crate) enum FormatResult {
/// The file was formatted.
Formatted,

/// The file was formatted, [`SourceKind`] contains the formatted code
Diff {
unformatted: SourceKind,
formatted: SourceKind,
},

/// The file was unchanged, as the formatted contents matched the existing contents.
Unchanged,

Expand Down
26 changes: 26 additions & 0 deletions crates/ruff_cli/tests/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,32 @@ OTHER = "OTHER"
Ok(())
}

#[test]
fn syntax_error() -> Result<()> {
let tempdir = TempDir::new()?;

fs::write(
tempdir.path().join("main.py"),
r#"
from module import =
"#,
)?;

assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.current_dir(tempdir.path())
.args(["format", "--no-cache", "--isolated", "--check"])
.arg("main.py"), @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Failed to format main.py: source contains syntax errors: invalid syntax. Got unexpected token '=' at byte offset 20
"###);

Ok(())
}

#[test]
fn messages() -> Result<()> {
let tempdir = TempDir::new()?;
Expand Down
4 changes: 2 additions & 2 deletions crates/ruff_python_formatter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ where

#[derive(Error, Debug)]
pub enum FormatModuleError {
#[error("source contains syntax errors: {0:?}")]
#[error("source contains syntax errors: {0}")]
LexError(LexicalError),
#[error("source contains syntax errors: {0:?}")]
#[error("source contains syntax errors: {0}")]
ParseError(ParseError),
#[error(transparent)]
FormatError(#[from] FormatError),
Expand Down
27 changes: 27 additions & 0 deletions crates/ruff_python_parser/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,31 @@ impl LexicalError {
}
}

impl std::ops::Deref for LexicalError {
type Target = LexicalErrorType;

fn deref(&self) -> &Self::Target {
&self.error
}
}

impl std::error::Error for LexicalError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.error)
}
}

impl std::fmt::Display for LexicalError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{} at byte offset {}",
&self.error,
u32::from(self.location)
)
}
}

/// Represents the different types of errors that can occur during lexing.
#[derive(Debug, Clone, PartialEq)]
pub enum LexicalErrorType {
Expand Down Expand Up @@ -1350,6 +1375,8 @@ pub enum LexicalErrorType {
OtherError(String),
}

impl std::error::Error for LexicalErrorType {}

impl std::fmt::Display for LexicalErrorType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Expand Down
6 changes: 0 additions & 6 deletions crates/ruff_python_parser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,12 +305,6 @@ impl fmt::Display for ParseError {
}
}

impl ParseError {
pub fn error(self) -> ParseErrorType {
self.error
}
}

/// Represents the different types of errors that can occur during parsing.
#[derive(Debug, PartialEq)]
pub enum ParseErrorType {
Expand Down

0 comments on commit 97e9d3c

Please sign in to comment.