use std::collections::BTreeMap;
use sealmap_model::{Codebase, CodebaseStats, Confidence, ContentHash, Fingerprint, SourcePath, Span, SymbolId};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FragmentKind {
Structure,
Sequence,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CallRef {
pub target: SymbolId,
pub confidence: Confidence,
pub line: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub expands: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FragmentEntry {
pub id: String,
pub kind: FragmentKind,
pub document: SourcePath,
pub symbol: SymbolId,
pub span: Span,
pub sig_hash: Fingerprint,
pub body_hash: Fingerprint,
pub participants: Vec<SymbolId>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub calls: Vec<CallRef>,
#[serde(default, skip_serializing_if = "is_zero")]
pub truncated: usize,
pub hash: ContentHash,
}
fn is_zero(n: &usize) -> bool {
*n == 0
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DocumentEntry {
pub source: SourcePath,
pub document: SourcePath,
pub module: SymbolId,
pub source_hash: ContentHash,
pub document_hash: ContentHash,
pub fragments: Vec<FragmentEntry>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Index {
pub schema_version: u32,
pub generator: String,
pub codebase: String,
pub stats: CodebaseStats,
pub documents: Vec<DocumentEntry>,
}
impl Index {
pub(crate) fn new(cb: &Codebase) -> Self {
Self {
schema_version: crate::CORPUS_SCHEMA_VERSION,
generator: format!("sealmap-corpus {}", env!("CARGO_PKG_VERSION")),
codebase: cb.name.clone(),
stats: cb.stats(),
documents: Vec::new(),
}
}
pub(crate) fn link_expansions(&mut self) {
let seqs: BTreeMap<String, ()> =
self.fragments().filter(|f| f.kind == FragmentKind::Sequence).map(|f| (f.id.clone(), ())).collect();
for doc in &mut self.documents {
for frag in &mut doc.fragments {
for call in &mut frag.calls {
let target = call.target.to_string();
if seqs.contains_key(&target) {
call.expands = Some(target);
}
}
}
}
}
pub fn fragments(&self) -> impl Iterator<Item = &FragmentEntry> {
self.documents.iter().flat_map(|d| d.fragments.iter())
}
pub fn fragment(&self, id: &str) -> Option<&FragmentEntry> {
self.fragments().find(|f| f.id == id)
}
}