pub use syn;
use syn::ItemMod;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SourceLocation {
pub file: String,
pub line: usize,
pub column: usize,
}
impl SourceLocation {
pub fn new(file: String, line: usize, column: usize) -> Self {
Self { file, line, column }
}
pub fn unknown() -> Self {
Self {
file: String::new(),
line: 0,
column: 0,
}
}
pub fn is_known(&self) -> bool {
self.line > 0 && !self.file.is_empty()
}
}
impl std::fmt::Display for SourceLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_known() {
write!(f, "{}:{}:{}", self.file, self.line, self.column)
} else {
write!(f, "<unknown>")
}
}
}
#[derive(Debug, Clone)]
pub struct SpanBase {
pub file: String,
pub base_line: usize,
pub base_col: usize,
}
impl SpanBase {
pub fn new(file: String, base_line: usize, base_col: usize) -> Self {
Self {
file,
base_line,
base_col,
}
}
pub fn unknown() -> Self {
Self {
file: String::new(),
base_line: 0,
base_col: 0,
}
}
pub fn is_known(&self) -> bool {
self.base_line > 0 && !self.file.is_empty()
}
pub fn resolve(&self, str_line: usize, str_col: usize) -> SourceLocation {
if !self.is_known() || str_line == 0 {
return SourceLocation::unknown();
}
let abs_line = self.base_line + (str_line - 1);
let abs_col = if str_line == 1 {
self.base_col + str_col
} else {
str_col
};
SourceLocation::new(self.file.clone(), abs_line, abs_col)
}
pub fn resolve_span(&self, span: &proc_macro2::Span) -> SourceLocation {
let start = span.start();
self.resolve(start.line, start.column)
}
pub fn module_location(&self) -> SourceLocation {
if self.is_known() {
SourceLocation::new(self.file.clone(), self.base_line, self.base_col)
} else {
SourceLocation::unknown()
}
}
}
impl Default for SpanBase {
fn default() -> Self {
Self::unknown()
}
}
pub struct Module {
name: &'static str,
absolute_path: String,
ast: ItemMod,
span_base: SpanBase,
}
impl Module {
pub fn new(name: &'static str, ast: ItemMod) -> Self {
Self {
name,
absolute_path: String::new(),
ast,
span_base: SpanBase::unknown(),
}
}
pub fn with_span_base(name: &'static str, ast: ItemMod, span_base: SpanBase) -> Self {
Self {
name,
absolute_path: String::new(),
ast,
span_base,
}
}
pub fn set_absolute_path(&mut self, path: String) {
self.absolute_path = path;
}
pub fn absolute_path(&self) -> &str {
if self.absolute_path.is_empty() {
self.name
} else {
&self.absolute_path
}
}
pub fn name(&self) -> &str {
self.name
}
pub fn ast(&self) -> &ItemMod {
&self.ast
}
pub fn span_base(&self) -> &SpanBase {
&self.span_base
}
pub fn resolve_span(&self, span: &proc_macro2::Span) -> SourceLocation {
self.span_base.resolve_span(span)
}
}