use {
crate::{
core::{Ident, SymbolPath, SymbolSortKey, Value},
partitions::{
records::ResolutionEntry, resolution::SymbolResolution, symbols::Symbols,
},
},
laburnum::database::{
HasPartition, PartitionKey, PartitionWriteContextRef, RecordHandle,
storage::Partitions,
},
};
pub trait ResolutionWriteExt<P: Partitions> {
fn clear_resolutions<V, I, Path>(
&mut self,
prefix: &Path,
) where
V: Value<I>,
I: Ident,
Path: SymbolPath,
P::Stores: HasPartition<SymbolResolution<V, I, Path>>;
fn write_resolution<V, I, Path>(
&mut self,
reference_path: Path,
target_path: Path,
target_handle: RecordHandle<Symbols<V, I, Path>>,
) where
V: Value<I>,
I: Ident,
Path: SymbolPath,
P::Stores: HasPartition<SymbolResolution<V, I, Path>>;
}
impl<P: Partitions> ResolutionWriteExt<P> for PartitionWriteContextRef<'_, P> {
fn clear_resolutions<V, I, Path>(
&mut self,
prefix: &Path,
) where
V: Value<I>,
I: Ident,
Path: SymbolPath,
P::Stores: HasPartition<SymbolResolution<V, I, Path>>,
{
self.clear_prefix(
SymbolResolution::<V, I, Path>::KEY,
SymbolSortKey::from_path(prefix),
);
}
fn write_resolution<V, I, Path>(
&mut self,
reference_path: Path,
target_path: Path,
target_handle: RecordHandle<Symbols<V, I, Path>>,
) where
V: Value<I>,
I: Ident,
Path: SymbolPath,
P::Stores: HasPartition<SymbolResolution<V, I, Path>>,
{
let entry = ResolutionEntry::new(target_path, target_handle);
self.index_entry::<SymbolResolution<V, I, Path>>(
SymbolSortKey::from_path(&reference_path),
entry,
);
}
}
#[cfg(test)]
mod tests {
use crate::{
Symbol, SymbolVisibility,
partitions::{
SymbolResolution, Symbols,
test_support::{TestPartitions, TestStores},
},
test_helpers::{DV, SI, TP, test_span, test_span_cache},
};
use laburnum::database::{
HasPartition, PartitionWriteContextRef,
chunk::RecordWriter,
};
use super::ResolutionWriteExt;
use crate::SymboliqueWriteExt;
fn make_writer() -> RecordWriter<TestPartitions> {
RecordWriter::<TestPartitions>::new(laburnum::Ident::new("test"))
}
#[test]
fn write_resolution_round_trip() {
let mut writer = make_writer();
let mut cache = test_span_cache();
let span = test_span(&mut cache, 0);
{
let mut ctx = PartitionWriteContextRef::new(&mut writer);
let target_handle = ctx.write_symbol_definition::<DV, SI, TP>(
"file|fn|target".to_string(),
span,
SI::new("target"),
None,
SymbolVisibility::Public,
);
ctx.write_resolution::<DV, SI, TP>(
"file|ref|call_target".to_string(),
"file|fn|target".to_string(),
target_handle,
);
}
let chunk = writer.build();
let stores = chunk.storage();
let res_store =
<TestStores as HasPartition<SymbolResolution<DV, SI, TP>>>::store(
stores,
);
let entry = res_store.index_get("file|ref|call_target");
assert!(entry.is_some());
let entry = entry.as_ref();
assert_eq!(
entry.map(|e| e.target_path.as_str()),
Some("file|fn|target"),
);
let sym_store =
<TestStores as HasPartition<Symbols<DV, SI, TP>>>::store(stores);
let record = entry
.and_then(|e| sym_store.get_by_handle(&e.target))
.as_ref()
.and_then(|r| r.record())
.cloned();
match record {
Some(Symbol::Definition { name, .. }) => {
assert_eq!(name.as_str(), "target");
}
_ => panic!("expected Definition"),
}
}
#[test]
fn clear_resolutions_records_prefix() {
let mut writer = make_writer();
{
let mut ctx = PartitionWriteContextRef::new(&mut writer);
ctx.clear_resolutions::<DV, SI, TP>(
&"file|".to_string(),
);
}
let prefixes = writer.clear_prefixes();
assert_eq!(prefixes.len(), 1);
assert_eq!(prefixes[0].1, "file|");
}
}