use std::path::Path;
use super::index::GraphIndex;
use super::member::MemberCandidate;
use super::refs::{build_refs_model_inner, RefsModel, RefsResult};
use super::refs_tables::{DEFAULT_CAP, INBOUND_CAP, OUTBOUND_CAP};
#[derive(Debug, Clone, PartialEq)]
pub struct ReadSpan {
pub file: String,
pub start_line: usize,
pub end_line: usize,
pub source: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ReadModel {
pub refs: RefsModel,
pub span: Option<ReadSpan>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ReadResult {
Resolved(Box<ReadModel>),
Members(Vec<RefsModel>),
Ambiguous(Vec<String>),
MemberAmbiguous(Vec<MemberCandidate>),
NotFound,
}
fn read_span(root: &Path, model: &RefsModel, end_line: usize) -> Option<ReadSpan> {
let site = model.sites.first()?;
if end_line < site.line {
return None;
}
let body = std::fs::read_to_string(root.join(&site.file)).ok()?;
let lines: Vec<&str> = body.split('\n').collect();
if site.line < 1 || site.line > lines.len() {
return None;
}
let end = end_line.min(lines.len());
let mut start_text = lines[site.line - 1];
if site.line == 1 {
start_text = start_text.strip_prefix('\u{feff}').unwrap_or(start_text);
}
let mut source = String::from(start_text);
for line in &lines[site.line..end] {
source.push('\n');
source.push_str(line);
}
Some(ReadSpan {
file: site.file.clone(),
start_line: site.line,
end_line: end,
source,
})
}
pub fn build_read_model(index: &GraphIndex, query: &str) -> ReadResult {
match build_refs_model_inner(
index,
query,
false,
DEFAULT_CAP,
INBOUND_CAP,
OUTBOUND_CAP,
false,
true,
) {
RefsResult::Resolved(m) => {
let end_line = index.def(&m.id).map(|d| d.end_line).unwrap_or(0);
let span = if end_line > 0 {
read_span(&index.root, &m, end_line)
} else {
None
};
ReadResult::Resolved(Box::new(ReadModel { refs: m, span }))
}
RefsResult::Members(models) => ReadResult::Members(models),
RefsResult::Ambiguous(ids) => ReadResult::Ambiguous(ids),
RefsResult::MemberAmbiguous(candidates) => ReadResult::MemberAmbiguous(candidates),
RefsResult::NotFound => ReadResult::NotFound,
}
}