Make drop notification timing for plugin custom values more consistent (#12341)

# Description
This keeps plugin custom values that have requested drop notification
around during the lifetime of a plugin call / stream by sending them to
a channel that gets persisted during the lifetime of the call.

Before this change, it was very likely that the drop notification would
be sent before the plugin ever had a chance to handle the value it
received.

Tests have been added to make sure this works - see the `custom_values`
plugin.

cc @ayax79 

# User-Facing Changes
This is basically just a bugfix, just a slightly big one.

However, I did add an `as_mut_any()` function for custom values, to
avoid having to clone them. This is a breaking change.
This commit is contained in:
Devyn Cairns
2024-04-04 00:13:25 -07:00
committed by GitHub
parent a6afc89338
commit cbf7feef22
33 changed files with 1115 additions and 368 deletions

View File

@ -1,13 +1,54 @@
use std::ops::Deref;
use miette::SourceSpan;
use serde::{Deserialize, Serialize};
/// A spanned area of interest, generic over what kind of thing is of interest
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Spanned<T> {
pub item: T,
pub span: Span,
}
impl<T> Spanned<T> {
/// Map to a spanned reference of the inner type, i.e. `Spanned<T> -> Spanned<&T>`.
pub fn as_ref(&self) -> Spanned<&T> {
Spanned {
item: &self.item,
span: self.span,
}
}
/// Map to a mutable reference of the inner type, i.e. `Spanned<T> -> Spanned<&mut T>`.
pub fn as_mut(&mut self) -> Spanned<&mut T> {
Spanned {
item: &mut self.item,
span: self.span,
}
}
/// Map to the result of [`.deref()`](std::ops::Deref::deref) on the inner type.
///
/// This can be used for example to turn `Spanned<Vec<T>>` into `Spanned<&[T]>`.
pub fn as_deref(&self) -> Spanned<&<T as Deref>::Target>
where
T: Deref,
{
Spanned {
item: self.item.deref(),
span: self.span,
}
}
/// Map the spanned item with a function.
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Spanned<U> {
Spanned {
item: f(self.item),
span: self.span,
}
}
}
/// Helper trait to create [`Spanned`] more ergonomically.
pub trait IntoSpanned: Sized {
/// Wrap items together with a span into [`Spanned`].

View File

@ -27,6 +27,9 @@ pub trait CustomValue: fmt::Debug + Send + Sync {
/// Any representation used to downcast object to its original type
fn as_any(&self) -> &dyn std::any::Any;
/// Any representation used to downcast object to its original type (mutable reference)
fn as_mut_any(&mut self) -> &mut dyn std::any::Any;
/// Follow cell path by numeric index (e.g. rows)
fn follow_path_int(
&self,