ryo_plugin_api/lib.rs
1//! # Ryo Plugin API
2//!
3//! WebAssembly Interface Types for ryo mutation plugins.
4//!
5//! ## Overview
6//!
7//! This crate provides the WIT-generated Rust types that define the contract
8//! between the ryo host and WASM mutation plugins. Plugins act as
9//! "Definition Providers" - they supply mutation metadata and transformation logic.
10//!
11//! ## Architecture
12//!
13//! ```text
14//! WASM Plugin (Guest) ryo (Host)
15//! ┌─────────────────────┐ ┌─────────────────────────┐
16//! │ get-manifest() │───WIT───>│ Load mutation metadata │
17//! │ get-pattern-source()│───WIT───>│ Compile pattern matcher │
18//! │ execute-transform() │───WIT───>│ Apply text edits │
19//! └─────────────────────┘ └─────────────────────────┘
20//! ```
21//!
22//! ## Usage
23//!
24//! ### For Plugin Authors (Guest)
25//!
26//! ```rust,ignore
27//! use ryo_plugin_api::*;
28//!
29//! wit_bindgen::generate!({
30//! world: "mutation-plugin",
31//! path: "wit",
32//! exports: {
33//! "ryo:transform/mutation": MyMutation,
34//! }
35//! });
36//!
37//! struct MyMutation;
38//!
39//! impl exports::ryo::transform::mutation::Guest for MyMutation {
40//! fn get_manifest() -> MutationManifest {
41//! MutationManifest {
42//! api_version: CURRENT_API_VERSION,
43//! name: "bool-simplify".into(),
44//! description: "Simplify boolean comparisons".into(),
45//! category: MutationCategory::Idiom,
46//! tier: 1,
47//! pattern: "...".into(),
48//! transform: TransformDef::Template("{{var}}".into()),
49//! }
50//! }
51//!
52//! fn get_pattern_source() -> String {
53//! String::new()
54//! }
55//!
56//! fn execute_transform(
57//! _matches: Vec<MatchResult>,
58//! _context: TransformContext,
59//! ) -> Result<Vec<TextEdit>, TransformError> {
60//! // Only called if transform = WasmExecute
61//! unreachable!()
62//! }
63//! }
64//! ```
65//!
66//! ### For Host Implementation
67//!
68//! ```rust,ignore
69//! use ryo_plugin_loader::PluginLoader;
70//!
71//! let loader = PluginLoader::new()?;
72//! let plugin = loader.load(&wasm_bytes)?;
73//!
74//! // Use manifest
75//! println!("Loaded mutation: {}", plugin.manifest.name);
76//! ```
77//!
78//! ## API Versioning
79//!
80//! The `api_version` field in `MutationManifest` ensures compatibility:
81//!
82//! - Current version: **1**
83//! - Host rejects plugins with mismatched versions
84//! - Breaking changes increment the version number
85
86// Generate WIT bindings
87wit_bindgen::generate!({
88 path: "wit",
89 world: "mutation-plugin",
90});
91
92// Re-export types from WIT interfaces
93pub use exports::ryo::transform::mutation::{
94 Guest, MutationCategory, MutationManifest, TransformContext, TransformDef, TransformError,
95};
96pub use exports::ryo::transform::types::{Capture, MatchResult, NodeKind, TextEdit, TypeHint};
97
98/// Current API version
99///
100/// This constant should match the version used by the host.
101/// Plugins should use this in their manifest:
102///
103/// ```rust,ignore
104/// MutationManifest {
105/// api_version: ryo_plugin_api::CURRENT_API_VERSION,
106/// // ...
107/// }
108/// ```
109pub const CURRENT_API_VERSION: u32 = 1;
110
111// =============================================================================
112// Helper Functions
113// =============================================================================
114
115/// Create a template-based transform definition
116///
117/// Template supports `{{capture_name}}` interpolation.
118///
119/// # Example
120/// ```rust,ignore
121/// let transform = template("{{var}}");
122/// // For match: `x == true` with capture @var="x"
123/// // Result: `x`
124/// ```
125pub fn template(tmpl: &str) -> TransformDef {
126 TransformDef::Template(tmpl.to_string())
127}
128
129/// Create a WASM-execute transform definition
130///
131/// Use this when the transform requires complex logic that can't be
132/// expressed as a simple template.
133pub fn wasm_execute() -> TransformDef {
134 TransformDef::WasmExecute
135}
136
137/// Create a text edit
138pub fn text_edit(start_byte: u64, end_byte: u64, replacement: &str) -> TextEdit {
139 TextEdit {
140 start_byte,
141 end_byte,
142 replacement: replacement.to_string(),
143 }
144}