use camino::Utf8PathBuf;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ByteRange {
pub start: usize,
pub end: usize,
}
impl ByteRange {
#[must_use]
pub fn new(start: usize, end: usize) -> Self {
Self { start, end }
}
#[must_use]
pub fn len(&self) -> usize {
self.end.saturating_sub(self.start)
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.start >= self.end
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SymbolId(String);
impl SymbolId {
#[must_use]
pub fn new(file: &Utf8PathBuf, name: &str, start: usize) -> Self {
Self(format!("{file}::{name}::{start}"))
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
#[must_use]
pub fn from_raw(raw: String) -> Self {
Self(raw)
}
}
impl std::fmt::Display for SymbolId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SymbolKind {
Function,
Method,
Struct,
Enum,
Trait,
Impl,
Class,
Module,
Variable,
TypeAlias,
Constant,
Interface,
Macro,
Static,
}
impl SymbolKind {
#[must_use]
pub fn as_str(&self) -> &'static str {
match self {
Self::Function => "function",
Self::Method => "method",
Self::Struct => "struct",
Self::Enum => "enum",
Self::Trait => "trait",
Self::Impl => "impl",
Self::Class => "class",
Self::Module => "module",
Self::Variable => "variable",
Self::TypeAlias => "type_alias",
Self::Constant => "constant",
Self::Interface => "interface",
Self::Macro => "macro",
Self::Static => "static",
}
}
}
#[derive(Debug, Clone)]
pub struct Symbol {
pub id: SymbolId,
pub name: String,
pub kind: SymbolKind,
pub file: Utf8PathBuf,
pub range: ByteRange,
pub signature: Option<String>,
pub parent: Option<SymbolId>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ChunkId(pub [u8; 32]);
impl ChunkId {
#[must_use]
pub fn from_text(text: &str) -> Self {
let normalized = normalize_chunk_text(text);
Self(blake3::hash(normalized.as_bytes()).into())
}
#[must_use]
pub fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
}
impl std::fmt::Display for ChunkId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for byte in &self.0 {
write!(f, "{byte:02x}")?;
}
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChunkKind {
FunctionBody,
TypeDef,
TopLevel,
Fallback,
}
#[derive(Debug, Clone)]
pub struct Chunk {
pub id: ChunkId,
pub file: Utf8PathBuf,
pub range: ByteRange,
pub text: String,
pub kind: ChunkKind,
pub language: argyph_fs::Language,
}
#[derive(Debug, Clone)]
pub struct Import {
pub raw: String,
pub module_path: Vec<String>,
pub items: Vec<String>,
pub range: ByteRange,
}
#[derive(Debug, Clone)]
pub struct ParsedFile {
pub symbols: Vec<Symbol>,
pub chunks: Vec<Chunk>,
pub imports: Vec<Import>,
}
fn normalize_chunk_text(text: &str) -> String {
let mut out = String::with_capacity(text.len());
for ch in text.chars() {
if ch.is_whitespace() {
if !out.ends_with(' ') {
out.push(' ');
}
} else {
out.push(ch);
}
}
out.trim().to_string()
}