Prepare semantic commands before atomic source adoption

This commit is contained in:
2026-09-05 21:39:25 +03:00
parent 366ce4480d
commit 41d7963d89
3 changed files with 116 additions and 5 deletions
+29 -5
View File
@@ -85,6 +85,31 @@ pub struct Session {
saved: Project,
revision: u64,
}
/// One validated command result, ready for an owning editor or service to adopt.
/// Preparation never mutates the input and allocates creation identities once.
/// A source editor can validate its corresponding document edits before either
/// representation becomes visible.
pub struct PreparedCommand {
pub project: Project,
pub selected: Option<Id>,
}
pub fn prepare_command(
project: &Project,
command: &Command,
) -> Result<PreparedCommand, ModelError> {
let mut candidate = project.clone();
let mut pending_deletions = BTreeSet::new();
let selected = apply_command(&mut candidate, command, 0, &mut pending_deletions)?;
crate::references::finish_deletions(&mut candidate, &pending_deletions);
validate_candidate(&candidate)?;
Ok(PreparedCommand {
project: candidate,
selected,
})
}
impl Session {
pub fn try_new(project: Project) -> Result<Self, ModelError> {
validate_candidate(&project)?;
@@ -143,11 +168,10 @@ impl Session {
Ok(())
}
pub fn execute(&mut self, command: Command) -> Result<Option<Id>, ModelError> {
let mut candidate = self.project.clone();
let mut pending_deletions = BTreeSet::new();
let selected = apply_command(&mut candidate, &command, 0, &mut pending_deletions)?;
crate::references::finish_deletions(&mut candidate, &pending_deletions);
validate_candidate(&candidate)?;
let PreparedCommand {
project: candidate,
selected,
} = prepare_command(&self.project, &command)?;
if candidate != self.project {
self.past
.push(std::mem::replace(&mut self.project, candidate));