use std::ops::Deref;
use ahash::RandomState;
use lady_deirdre::{
analysis::{ExclusiveTask, MutationAccess, TaskHandle, TriggerHandle},
arena::{Id, Identifiable},
lexis::{ToSite, ToSpan},
};
use crate::{
analysis::{
completions::PROMPT_STRING,
read::ModuleReadSealed,
Completions,
ModuleError,
ModuleRead,
ModuleResult,
ModuleResultEx,
},
runtime::PackageMeta,
syntax::ScriptNode,
};
pub struct ModuleWriteGuard<'a, H: TaskHandle = TriggerHandle> {
pub(super) id: Id,
pub(super) package: &'static PackageMeta,
pub(super) task: ExclusiveTask<'a, ScriptNode, H, RandomState>,
}
impl<'a, H: TaskHandle> Identifiable for ModuleWriteGuard<'a, H> {
#[inline(always)]
fn id(&self) -> Id {
self.id
}
}
impl<'a, H: TaskHandle> ModuleRead<H> for ModuleWriteGuard<'a, H> {
#[inline(always)]
fn package(&self) -> &'static PackageMeta {
self.package
}
}
impl<'a, H: TaskHandle> ModuleWrite<H> for ModuleWriteGuard<'a, H> {}
impl<'a, H: TaskHandle> ModuleReadSealed<H> for ModuleWriteGuard<'a, H> {
type Task = ExclusiveTask<'a, ScriptNode, H, RandomState>;
#[inline(always)]
fn task(&self) -> &Self::Task {
&self.task
}
}
impl<'a, H: TaskHandle> ModuleWriteSealed<H> for ModuleWriteGuard<'a, H> {
#[inline(always)]
fn task_mut(&mut self) -> &mut Self::Task {
&mut self.task
}
}
pub trait ModuleWrite<H: TaskHandle>: ModuleRead<H> + ModuleWriteSealed<H>
where
Self::Task: MutationAccess<ScriptNode, H, RandomState>,
{
fn edit(&mut self, span: impl ToSpan, text: impl AsRef<str>) -> ModuleResult<()> {
let id = self.id();
let span = {
let doc_read = self.read_doc();
match span.to_site_span(doc_read.deref()) {
Some(span) => span,
None => return Err(ModuleError::Cursor(id)),
}
};
self.task_mut()
.write_to_doc(id, span, text)
.into_module_result(id)
}
fn completions(&mut self, site: impl ToSite) -> ModuleResult<Completions> {
let id = self.id();
let site = {
let doc_read = self.read_doc();
match site.to_site(doc_read.deref()) {
Some(site) => site,
None => return Err(ModuleError::Cursor(id)),
}
};
let _ = self
.task_mut()
.write_to_doc(id, site..site, PROMPT_STRING)
.into_module_result(id)?;
let task = self.task();
let result = Completions::analyze(id, site, task).forward();
let _ = self
.task_mut()
.write_to_doc(id, site..(site + PROMPT_STRING.len()), "")
.into_module_result(id)?;
result.into_module_result(id)
}
}
pub trait ModuleWriteSealed<H: TaskHandle>: ModuleReadSealed<H>
where
<Self as ModuleReadSealed<H>>::Task: MutationAccess<ScriptNode, H, RandomState>,
{
fn task_mut(&mut self) -> &mut Self::Task;
}