use crate::GroupId;
use crate::prelude::TagKind;
use ruff_text_size::TextRange;
use std::error::Error;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FormatError {
SyntaxError { message: &'static str },
RangeError { input: TextRange, tree: TextRange },
InvalidDocument(InvalidDocumentError),
PoorLayout,
}
impl std::fmt::Display for FormatError {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FormatError::SyntaxError { message } => {
std::write!(fmt, "syntax error: {message}")
}
FormatError::RangeError { input, tree } => std::write!(
fmt,
"formatting range {input:?} is larger than syntax tree {tree:?}"
),
FormatError::InvalidDocument(error) => std::write!(
fmt,
"Invalid document: {error}\n\n This is an internal Ruff error. Please report if necessary."
),
FormatError::PoorLayout => {
std::write!(
fmt,
"Poor layout: The formatter wasn't able to pick a good layout for your document. This is an internal Ruff error. Please report if necessary."
)
}
}
}
}
impl Error for FormatError {}
impl From<PrintError> for FormatError {
fn from(error: PrintError) -> Self {
FormatError::from(&error)
}
}
impl From<&PrintError> for FormatError {
fn from(error: &PrintError) -> Self {
match error {
PrintError::InvalidDocument(reason) => FormatError::InvalidDocument(*reason),
}
}
}
impl FormatError {
pub fn syntax_error(message: &'static str) -> Self {
Self::SyntaxError { message }
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum InvalidDocumentError {
StartEndTagMismatch {
start_kind: TagKind,
end_kind: TagKind,
},
StartTagMissing {
kind: TagKind,
},
ExpectedStart {
expected_start: TagKind,
actual: ActualStart,
},
UnknownGroupId {
group_id: GroupId,
},
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ActualStart {
Content,
Start(TagKind),
End(TagKind),
EndOfDocument,
}
impl std::fmt::Display for InvalidDocumentError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
InvalidDocumentError::StartEndTagMismatch {
start_kind,
end_kind,
} => {
std::write!(
f,
"Expected end tag of kind {start_kind:?} but found {end_kind:?}."
)
}
InvalidDocumentError::StartTagMissing { kind } => {
std::write!(f, "End tag of kind {kind:?} without matching start tag.")
}
InvalidDocumentError::ExpectedStart {
expected_start,
actual,
} => match actual {
ActualStart::EndOfDocument => {
std::write!(
f,
"Expected start tag of kind {expected_start:?} but at the end of document."
)
}
ActualStart::Start(start) => {
std::write!(
f,
"Expected start tag of kind {expected_start:?} but found start tag of kind {start:?}."
)
}
ActualStart::End(end) => {
std::write!(
f,
"Expected start tag of kind {expected_start:?} but found end tag of kind {end:?}."
)
}
ActualStart::Content => {
std::write!(
f,
"Expected start tag of kind {expected_start:?} but found non-tag element."
)
}
},
InvalidDocumentError::UnknownGroupId { group_id } => {
std::write!(
f,
"Encountered unknown group id {group_id:?}. Ensure that the group with the id {group_id:?} exists and that the group is a parent of or comes before the element referring to it."
)
}
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PrintError {
InvalidDocument(InvalidDocumentError),
}
impl Error for PrintError {}
impl std::fmt::Display for PrintError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PrintError::InvalidDocument(inner) => {
std::write!(f, "Invalid document: {inner}")
}
}
}
}