Truncate `SyntaxError`s before newline character (#4124)

This commit is contained in:
Micha Reiser 2023-05-10 08:37:57 +02:00 committed by GitHub
parent b8bb9e8b92
commit d66ce76691
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 5 deletions

View File

@ -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
) )
} }
} }

View File

@ -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),
)); ));