mirror of https://github.com/astral-sh/ruff
Truncate `SyntaxError`s before newline character (#4124)
This commit is contained in:
parent
b8bb9e8b92
commit
d66ce76691
|
|
@ -1,4 +1,4 @@
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ use fern;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use ruff_python_ast::source_code::SourceCode;
|
use ruff_python_ast::source_code::SourceCode;
|
||||||
use rustpython_parser::ParseError;
|
use rustpython_parser::{ParseError, ParseErrorType};
|
||||||
|
|
||||||
pub(crate) static WARNINGS: Lazy<Mutex<Vec<&'static str>>> = Lazy::new(Mutex::default);
|
pub(crate) static WARNINGS: Lazy<Mutex<Vec<&'static str>>> = Lazy::new(Mutex::default);
|
||||||
|
|
||||||
|
|
@ -150,12 +150,84 @@ impl Display for DisplayParseError<'_> {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{header} {path}{colon}{row}{colon}{column}{colon} {inner}",
|
"{header} {path}{colon}{row}{colon}{column}{colon} {inner}",
|
||||||
header = "Failed to parse ".bold(),
|
header = "Failed to parse".bold(),
|
||||||
path = fs::relativize_path(Path::new(&self.error.source_path)).bold(),
|
path = fs::relativize_path(Path::new(&self.error.source_path)).bold(),
|
||||||
row = source_location.row,
|
row = source_location.row,
|
||||||
column = source_location.column,
|
column = source_location.column,
|
||||||
colon = ":".cyan(),
|
colon = ":".cyan(),
|
||||||
inner = &self.error.error
|
inner = &DisplayParseErrorType(&self.error.error)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct DisplayParseErrorType<'a>(&'a ParseErrorType);
|
||||||
|
|
||||||
|
impl<'a> DisplayParseErrorType<'a> {
|
||||||
|
pub(crate) fn new(error: &'a ParseErrorType) -> Self {
|
||||||
|
Self(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for DisplayParseErrorType<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self.0 {
|
||||||
|
ParseErrorType::Eof => write!(f, "Expected token but reached end of file."),
|
||||||
|
ParseErrorType::ExtraToken(ref tok) => write!(
|
||||||
|
f,
|
||||||
|
"Got extraneous token: {tok}",
|
||||||
|
tok = TruncateAtNewline(&tok)
|
||||||
|
),
|
||||||
|
ParseErrorType::InvalidToken => write!(f, "Got invalid token"),
|
||||||
|
ParseErrorType::UnrecognizedToken(ref tok, ref expected) => {
|
||||||
|
if let Some(expected) = expected.as_ref() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"expected '{expected}', but got {tok}",
|
||||||
|
tok = TruncateAtNewline(&tok)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
write!(f, "unexpected token {tok}", tok = TruncateAtNewline(&tok))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ParseErrorType::Lexical(ref error) => write!(f, "{error}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Truncates the display text before the first newline character to avoid line breaks.
|
||||||
|
struct TruncateAtNewline<'a>(&'a dyn Display);
|
||||||
|
|
||||||
|
impl Display for TruncateAtNewline<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
struct TruncateAdapter<'a> {
|
||||||
|
inner: &'a mut dyn std::fmt::Write,
|
||||||
|
after_new_line: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Write for TruncateAdapter<'_> {
|
||||||
|
fn write_str(&mut self, s: &str) -> std::fmt::Result {
|
||||||
|
if self.after_new_line {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
if let Some(end) = s.find(['\n', '\r']) {
|
||||||
|
self.inner.write_str(&s[..end])?;
|
||||||
|
self.inner.write_str("\u{23ce}...")?;
|
||||||
|
self.after_new_line = true;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
self.inner.write_str(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(
|
||||||
|
TruncateAdapter {
|
||||||
|
inner: f,
|
||||||
|
after_new_line: false,
|
||||||
|
},
|
||||||
|
"{}",
|
||||||
|
self.0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
use rustpython_parser::ParseError;
|
use rustpython_parser::ParseError;
|
||||||
|
|
||||||
|
use crate::logging::DisplayParseErrorType;
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::source_code::Locator;
|
use ruff_python_ast::source_code::Locator;
|
||||||
|
|
@ -50,7 +51,7 @@ pub fn syntax_error(
|
||||||
|
|
||||||
diagnostics.push(Diagnostic::new(
|
diagnostics.push(Diagnostic::new(
|
||||||
SyntaxError {
|
SyntaxError {
|
||||||
message: parse_error.error.to_string(),
|
message: format!("{}", DisplayParseErrorType::new(&parse_error.error)),
|
||||||
},
|
},
|
||||||
TextRange::at(parse_error.location, len),
|
TextRange::at(parse_error.location, len),
|
||||||
));
|
));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue