Split the plugin crate (#12563)

# Description

This breaks `nu-plugin` up into four crates:

- `nu-plugin-protocol`: just the type definitions for the protocol, no
I/O. If someone wanted to wire up something more bare metal, maybe for
async I/O, they could use this.
- `nu-plugin-core`: the shared stuff between engine/plugin. Less stable
interface.
- `nu-plugin-engine`: everything required for the engine to talk to
plugins. Less stable interface.
- `nu-plugin`: everything required for the plugin to talk to the engine,
what plugin developers use. Should be the most stable interface.

No changes are made to the interface exposed by `nu-plugin` - it should
all still be there. Re-exports from `nu-plugin-protocol` or
`nu-plugin-core` are used as required. Plugins shouldn't ever have to
use those crates directly.

This should be somewhat faster to compile as `nu-plugin-engine` and
`nu-plugin` can compile in parallel, and the engine doesn't need
`nu-plugin` and plugins don't need `nu-plugin-engine` (except for test
support), so that should reduce what needs to be compiled too.

The only significant change here other than splitting stuff up was to
break the `source` out of `PluginCustomValue` and create a new
`PluginCustomValueWithSource` type that contains that instead. One bonus
of that is we get rid of the option and it's now more type-safe, but it
also means that the logic for that stuff (actually running the plugin
for custom value ops) can live entirely within the `nu-plugin-engine`
crate.

# User-Facing Changes
- New crates.
- Added `local-socket` feature for `nu` to try to make it possible to
compile without that support if needed.

# Tests + Formatting
- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`
This commit is contained in:
Devyn Cairns
2024-04-27 10:08:12 -07:00
committed by GitHub
parent 884d5312bb
commit 0c4d5330ee
74 changed files with 3514 additions and 3110 deletions

View File

@ -6,6 +6,9 @@ license = "MIT"
description = "Testing support for Nushell plugins"
repository = "https://github.com/nushell/nushell/tree/main/crates/nu-plugin-test-support"
[lib]
bench = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -13,6 +16,9 @@ nu-engine = { path = "../nu-engine", version = "0.92.3", features = ["plugin"] }
nu-protocol = { path = "../nu-protocol", version = "0.92.3", features = ["plugin"] }
nu-parser = { path = "../nu-parser", version = "0.92.3", features = ["plugin"] }
nu-plugin = { path = "../nu-plugin", version = "0.92.3" }
nu-plugin-core = { path = "../nu-plugin-core", version = "0.92.3" }
nu-plugin-engine = { path = "../nu-plugin-engine", version = "0.92.3" }
nu-plugin-protocol = { path = "../nu-plugin-protocol", version = "0.92.3" }
nu-cmd-lang = { path = "../nu-cmd-lang", version = "0.92.3" }
nu-ansi-term = { workspace = true }
similar = "2.5"

View File

@ -3,7 +3,7 @@ use std::{
sync::{Arc, OnceLock},
};
use nu_plugin::{GetPlugin, PluginInterface};
use nu_plugin_engine::{GetPlugin, PluginInterface};
use nu_protocol::{
engine::{EngineState, Stack},
PluginGcConfig, PluginIdentity, RegisteredPlugin, ShellError,

View File

@ -1,6 +1,7 @@
use std::{ops::Deref, sync::Arc};
use nu_plugin::{create_plugin_signature, Plugin, PluginDeclaration};
use nu_plugin::{create_plugin_signature, Plugin};
use nu_plugin_engine::PluginDeclaration;
use nu_protocol::{engine::StateWorkingSet, RegisteredPlugin, ShellError};
use crate::{fake_persistent_plugin::FakePersistentPlugin, spawn_fake_plugin::spawn_fake_plugin};

View File

@ -4,7 +4,9 @@ use nu_ansi_term::Style;
use nu_cmd_lang::create_default_context;
use nu_engine::eval_block;
use nu_parser::parse;
use nu_plugin::{Plugin, PluginCommand, PluginCustomValue, PluginSource};
use nu_plugin::{Plugin, PluginCommand};
use nu_plugin_engine::{PluginCustomValueWithSource, PluginSource, WithSource};
use nu_plugin_protocol::PluginCustomValue;
use nu_protocol::{
debugger::WithoutDebug,
engine::{EngineState, Stack, StateWorkingSet},
@ -135,13 +137,14 @@ impl PluginTest {
// Serialize custom values in the input
let source = self.source.clone();
let input = input.map(
move |mut value| match PluginCustomValue::serialize_custom_values_in(&mut value) {
Ok(()) => {
move |mut value| {
let result = PluginCustomValue::serialize_custom_values_in(&mut value)
// Make sure to mark them with the source so they pass correctly, too.
let _ = PluginCustomValue::add_source_in(&mut value, &source);
value
.and_then(|_| PluginCustomValueWithSource::add_source_in(&mut value, &source));
match result {
Ok(()) => value,
Err(err) => Value::error(err, value.span()),
}
Err(err) => Value::error(err, value.span()),
},
None,
)?;
@ -151,7 +154,9 @@ impl PluginTest {
eval_block::<WithoutDebug>(&self.engine_state, &mut stack, &block, input)?.map(
|mut value| {
// Make sure to deserialize custom values
match PluginCustomValue::deserialize_custom_values_in(&mut value) {
let result = PluginCustomValueWithSource::remove_source_in(&mut value)
.and_then(|_| PluginCustomValue::deserialize_custom_values_in(&mut value));
match result {
Ok(()) => value,
Err(err) => Value::error(err, value.span()),
}
@ -284,12 +289,12 @@ impl PluginTest {
match (a, b) {
(Value::Custom { val, .. }, _) => {
// We have to serialize both custom values before handing them to the plugin
let mut serialized =
PluginCustomValue::serialize_from_custom_value(val.as_ref(), a.span())?;
serialized.set_source(Some(self.source.clone()));
let serialized =
PluginCustomValue::serialize_from_custom_value(val.as_ref(), a.span())?
.with_source(self.source.clone());
let mut b_serialized = b.clone();
PluginCustomValue::serialize_custom_values_in(&mut b_serialized)?;
PluginCustomValue::add_source_in(&mut b_serialized, &self.source)?;
PluginCustomValueWithSource::add_source_in(&mut b_serialized, &self.source)?;
// Now get the plugin reference and execute the comparison
let persistent = self.source.persistent(None)?.get_plugin(None)?;
let ordering = persistent.custom_value_partial_cmp(serialized, b_serialized)?;
@ -354,8 +359,8 @@ impl PluginTest {
val: &dyn CustomValue,
span: Span,
) -> Result<Value, ShellError> {
let mut serialized = PluginCustomValue::serialize_from_custom_value(val, span)?;
serialized.set_source(Some(self.source.clone()));
let serialized = PluginCustomValue::serialize_from_custom_value(val, span)?
.with_source(self.source.clone());
let persistent = self.source.persistent(None)?.get_plugin(None)?;
persistent.custom_value_to_base_value(serialized.into_spanned(span))
}

View File

@ -1,9 +1,9 @@
use std::sync::{mpsc, Arc};
use nu_plugin::{
InterfaceManager, Plugin, PluginInput, PluginInterfaceManager, PluginOutput, PluginRead,
PluginSource, PluginWrite,
};
use nu_plugin::Plugin;
use nu_plugin_core::{InterfaceManager, PluginRead, PluginWrite};
use nu_plugin_engine::{PluginInterfaceManager, PluginSource};
use nu_plugin_protocol::{PluginInput, PluginOutput};
use nu_protocol::{PluginIdentity, ShellError};
use crate::fake_persistent_plugin::FakePersistentPlugin;