use {
crate::{
core::{Ident, Symbol, SymbolPath, Value, Visibility},
partitions::{
FileSymbols, ResolutionWriteExt, SymbolEntry, SymbolResolution,
SymboliqueReadExt, Symbols,
},
resolution::{ResolveCtx, Resolution, SymboliqueResolver},
},
laburnum::database::{
HasPartition, PartitionWriteContextRef, query::QueryClient,
storage::Partitions,
},
std::hash::Hash,
};
pub struct QueryResolveCtx<'q, P: Partitions> {
query: &'q QueryClient<P>,
}
impl<'q, P: Partitions> QueryResolveCtx<'q, P> {
pub fn new(query: &'q QueryClient<P>) -> Self {
Self { query }
}
}
impl<P, V, I, Path, S> ResolveCtx<V, I, Path, S> for QueryResolveCtx<'_, P>
where
P: Partitions,
V: Value<I> + 'static,
I: Ident + Hash,
Path: SymbolPath + 'static,
S: Visibility,
P::Stores: HasPartition<FileSymbols<V, I, Path, S>>
+ HasPartition<Symbols<V, I, Path, S>>,
{
fn lookup(&self, path: &Path) -> Option<SymbolEntry<V, I, Path, S>> {
self
.query
.file_symbol_at_path::<V, I, Path, S>(path)
}
fn visibility_of(&self, entry: &SymbolEntry<V, I, Path, S>) -> Option<S> {
let record = self.query.resolve_file_symbol::<V, I, Path, S>(entry)?;
match record.record()? {
| Symbol::Definition { visibility, .. } => Some(*visibility),
| _ => None,
}
}
}
pub struct ResolutionFailure<V, I, P, S>
where
V: Value<I>,
I: Ident + Hash,
P: SymbolPath,
S: Visibility,
{
pub reference_path: P,
pub target_path: P,
pub span: laburnum::Span,
pub resolution: Resolution<V, I, P, S>,
}
pub fn resolve_references<P, R, V, I, Path, S>(
query: &QueryClient<P>,
writer: &mut PartitionWriteContextRef<'_, P>,
resolver: &R,
) -> Vec<ResolutionFailure<V, I, Path, S>>
where
P: Partitions,
R: SymboliqueResolver<V, I, Path, S>,
V: Value<I> + 'static,
I: Ident + Hash,
Path: SymbolPath + 'static,
S: Visibility,
P::Stores: HasPartition<FileSymbols<V, I, Path, S>>
+ HasPartition<Symbols<V, I, Path, S>>
+ HasPartition<SymbolResolution<V, I, Path, S>>,
SymbolResolution<V, I, Path, S>: laburnum::database::partitions::SortKeyOf<P>
+ laburnum::database::Partition<
SortKey = Path,
IndexEntry = crate::partitions::records::ResolutionEntry<V, I, Path, S>,
>,
{
let ctx = QueryResolveCtx::new(query);
let mut failures = Vec::new();
let entries =
query.index_entries::<FileSymbols<V, I, Path, S>>();
for (_key, entry) in &entries {
let Some(record) =
query.get::<Symbols<V, I, Path, S>>(entry.symbol.content_hash())
else {
continue;
};
let Some(Symbol::Reference {
path,
target_path,
nameable: true,
..
}) = record.record()
else {
continue;
};
match resolver.resolve(&ctx, target_path, path, entry.clone()) {
| Resolution::Resolved(target) => {
writer.write_resolution::<V, I, Path, S>(
path.clone(),
target_path.clone(),
target.symbol,
);
},
| Resolution::Deferred => {},
| resolution => {
failures.push(ResolutionFailure {
reference_path: path.clone(),
target_path: target_path.clone(),
span: entry.span,
resolution,
});
},
}
}
failures
}