use std::{path::PathBuf, rc::Rc};
use serde::{Deserialize, Serialize};
use crate::lex::Token;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
pub struct Position {
pub start_offset: usize,
pub end_offset: usize,
pub line_number: usize,
pub end_line_number: usize,
pub column: usize,
pub end_column: usize,
pub path: Rc<PathBuf>,
}
impl std::fmt::Debug for Position {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if std::env::var("VERBOSE").is_ok() {
f.debug_struct("Position")
.field("start_offset", &self.start_offset)
.field("end_offset", &self.end_offset)
.field("line_number", &self.line_number)
.field("end_line_number", &self.end_line_number)
.field("path", &self.path)
.finish()
} else {
f.write_str("Position { ... }")
}
}
}
impl Position {
pub fn todo(path: Rc<PathBuf>) -> Self {
Self {
start_offset: 0,
end_offset: 0,
line_number: 0,
column: 0,
end_column: 0,
end_line_number: 0,
path,
}
}
pub fn merge(first: &Self, second: &Self) -> Self {
Self {
start_offset: first.start_offset,
end_offset: std::cmp::max(first.end_offset, second.end_offset),
line_number: first.line_number,
end_line_number: std::cmp::max(first.end_line_number, second.end_line_number),
column: first.column,
end_column: if first.end_offset > second.end_offset {
first.end_column
} else {
second.end_column
},
path: first.path.clone(),
}
}
pub fn merge_token(first: &Token, second: &Self) -> Self {
let mut first_pos = first.position.clone();
if let Some((comment_pos, _)) = first.preceding_comments.first() {
first_pos = comment_pos.clone();
}
Self::merge(&first_pos, second)
}
pub fn as_ide_string(&self) -> String {
format!(
"{}:{}",
self.path.display(),
self.line_number + 1,
)
}
pub fn contains_offset(&self, offset: usize) -> bool {
self.start_offset <= offset && offset <= self.end_offset
}
}