// re-export our public interface pub use ruff_source_location::*; pub type LineNumber = OneIndexed; #[derive(Debug, Copy, Clone)] pub struct SourceRange { pub start: SourceLocation, pub end: Option, } impl SourceRange { pub fn new(start: SourceLocation, end: SourceLocation) -> Self { Self { start, end: Some(end), } } pub fn unwrap_end(&self) -> SourceLocation { self.end.unwrap() } } impl From> for SourceRange { fn from(value: std::ops::Range) -> Self { Self { start: value.start, end: Some(value.end), } } } /// Converts source code byte-offset to Python convention line and column numbers. pub struct SourceLocator<'a> { pub source: &'a str, index: LineIndex, } impl<'a> SourceLocator<'a> { #[inline] pub fn new(source: &'a str) -> Self { let index = LineIndex::from_source_text(source); Self { source, index } } pub fn to_source_code(&self) -> SourceCode { SourceCode::new(self.source, &self.index) } pub fn locate(&mut self, offset: crate::text_size::TextSize) -> SourceLocation { let offset = offset.to_u32().into(); self.to_source_code().source_location(offset) } pub fn locate_error(&mut self, base: crate::error::BaseError) -> LocatedError where T: Into, { let location = self.locate(base.offset); LocatedError { error: base.error.into(), location: Some(location), source_path: base.source_path, } } } #[derive(Debug, PartialEq, Eq)] pub struct LocatedError { pub error: T, pub location: Option, pub source_path: String, } impl LocatedError { pub fn error(self) -> T { self.error } pub fn from(obj: LocatedError) -> Self where U: Into, { Self { error: obj.error.into(), location: obj.location, source_path: obj.source_path, } } pub fn into(self) -> LocatedError where T: Into, { LocatedError::from(self) } pub fn python_location(&self) -> (usize, usize) { if let Some(location) = self.location { (location.row.to_usize(), location.column.to_usize()) } else { (0, 0) } } } impl std::fmt::Display for LocatedError where T: std::fmt::Display, { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let (row, column) = self .location .map_or((0, 0), |l| (l.row.to_usize(), l.column.to_usize())); write!(f, "{} at row {} col {}", &self.error, row, column,) } } impl std::error::Error for LocatedError where T: std::error::Error + 'static, { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.error) } }