use crate::prelude::*;
use std::hash::Hash;
use std::path::Path;
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Reflect, Component)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "tokens", derive(ToTokens))]
pub struct FileSpan {
pub file: WsPathBuf,
pub start: LineCol,
pub end: LineCol,
}
impl std::fmt::Display for FileSpan {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.file.display(), self.start)
}
}
impl FileSpan {
pub fn new(
workspace_file_path: impl AsRef<Path>,
start: LineCol,
end: LineCol,
) -> Self {
Self {
file: WsPathBuf::new(workspace_file_path),
start,
end,
}
}
pub fn new_from_location(location: &std::panic::Location) -> Self {
Self {
file: WsPathBuf::new(location.file()),
start: LineCol::from_location(location),
end: LineCol::from_location(location),
}
}
#[cfg(feature = "tokens")]
pub fn new_from_span(
file: WsPathBuf,
spanned: &impl syn::spanned::Spanned,
) -> Self {
let span = spanned.span();
Self {
file,
start: span.start().into(),
end: span.end().into(),
}
}
pub fn new_for_file(file: impl AsRef<Path>) -> Self {
Self {
file: WsPathBuf::new(file),
start: LineCol::default(),
end: LineCol::default(),
}
}
pub fn new_with_start(
workspace_file_path: impl AsRef<Path>,
line: u32,
col: u32,
) -> Self {
Self {
file: WsPathBuf::new(workspace_file_path),
start: LineCol::new(line, col),
end: LineCol::new(line, col),
}
}
pub fn file(&self) -> &WsPathBuf { &self.file }
pub fn start(&self) -> LineCol { self.start }
pub fn start_line(&self) -> u32 { self.start.line() }
pub fn start_col(&self) -> u32 { self.start.col() }
pub fn end(&self) -> LineCol { self.end }
pub fn end_line(&self) -> u32 { self.end.line() }
pub fn end_col(&self) -> u32 { self.end.col() }
}
pub trait GetSpan {
fn span(&self) -> &FileSpan;
fn span_mut(&mut self) -> &mut FileSpan;
}
impl GetSpan for FileSpan {
fn span(&self) -> &FileSpan { self }
fn span_mut(&mut self) -> &mut FileSpan { self }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Component, Reflect)]
#[reflect(Component)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "tokens", derive(ToTokens))]
pub struct FileSpanOf<C> {
pub value: FileSpan,
#[reflect(ignore)]
pub phantom: std::marker::PhantomData<C>,
}
impl<C> std::ops::Deref for FileSpanOf<C> {
type Target = FileSpan;
fn deref(&self) -> &Self::Target { &self.value }
}
impl<C> FileSpanOf<C> {
pub fn new(value: FileSpan) -> Self {
Self {
value,
phantom: std::marker::PhantomData,
}
}
pub fn take(self) -> FileSpan { self.value }
}