ryo-mutations 0.1.0

[experimental] Code transformation primitives for Rust source code
Documentation
//! Clippy Integration: Bridge between Clippy diagnostics and ryo-mutations
//!
//! This module provides integration with [Clippy](https://github.com/rust-lang/rust-clippy),
//! Rust's official linting tool. It enables automatic code transformations based on
//! Clippy's suggestions.
//!
//! # Architecture
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────┐
//! │                     Clippy Integration                       │
//! ├─────────────────────────────────────────────────────────────┤
//! │  cargo clippy --message-format=json                         │
//! │         ↓                                                    │
//! │  ┌─────────────────────────────────────────────────────┐    │
//! │  │ ClippyDiagnostic                                    │    │
//! │  │  - lint_name: "bool_comparison"                     │    │
//! │  │  - applicability: MachineApplicable                 │    │
//! │  │  - suggestion_span: ByteRange                       │    │
//! │  │  - replacement: String                              │    │
//! │  └─────────────────────────────────────────────────────┘    │
//! │         ↓                                                    │
//! │  ┌─────────────────────────────────────────────────────┐    │
//! │  │ ClippyToMutation::convert()                         │    │
//! │  │  - Parse span to locate in PureFile                 │    │
//! │  │  - Generate appropriate Mutation                    │    │
//! │  └─────────────────────────────────────────────────────┘    │
//! │         ↓                                                    │
//! │  Box<dyn Mutation>                                          │
//! └─────────────────────────────────────────────────────────────┘
//! ```
//!
//! # Integration Modes
//!
//! ## Direct Mode
//! Apply Clippy's suggestion text directly (text-based replacement).
//! Fastest but less semantic understanding.
//!
//! ```rust,ignore
//! // Clippy provides: span=(10, 20), replacement="x"
//! // Direct mode: replace bytes 10..20 with "x"
//! ```
//!
//! ## Semantic Mode
//! Generate appropriate Mutation based on lint type (AST-level transformation).
//! More robust and composable with other mutations.
//!
//! ```rust,ignore
//! // Clippy reports: lint="bool_comparison"
//! // Semantic mode: generate BoolSimplifyMutation
//! ```
//!
//! ## Hybrid Mode (Recommended)
//! - MachineApplicable lints → Direct Mode (safe, fast)
//! - Other lints → Semantic Mode (needs human review)
//!
//! # Supported Lints
//!
//! ## Tier 1: High-frequency, MachineApplicable
//!
//! | Lint | Transformation | Idiom Mutation |
//! |------|----------------|----------------|
//! | `bool_comparison` | `x == true` → `x` | [`BoolSimplifyMutation`] |
//! | `collapsible_if` | `if a { if b { } }` → `if a && b { }` | [`CollapsibleIfMutation`] |
//! | `comparison_to_empty` | `s == ""` → `s.is_empty()` | [`ComparisonToMethodMutation`] |
//! | `assign_op_pattern` | `a = a + b` → `a += b` | [`AssignOpMutation`] |
//! | `clone_on_copy` | Remove `.clone()` on Copy types | [`CloneOnCopyMutation`] |
//! | `redundant_closure` | `\|x\| foo(x)` → `foo` | [`RedundantClosureMutation`] |
//!
//! ## Tier 2: Iterator Chain Optimization
//!
//! | Lint | Transformation | Idiom Mutation |
//! |------|----------------|----------------|
//! | `map_clone` | `.map(\|x\| x.clone())` → `.cloned()` | [`MapClonedMutation`] |
//! | `iter_cloned_collect` | `.iter().cloned().collect()` → `.to_vec()` | [`IterClonedCollectMutation`] |
//! | `bind_instead_of_map` | `.and_then(\|x\| Some(y))` → `.map(\|x\| y)` | [`BindToMapMutation`] |
//! | `option_map_unwrap_or` | `.map(f).unwrap_or(d)` → `.map_or(d, f)` | [`MapUnwrapOrMutation`] |
//! | `manual_filter_map` | `.filter(p).map(f)` → `.filter_map(...)` | [`ManualFilterMapMutation`] |
//!
//! ## Tier 3: Manual Pattern Detection
//!
//! | Lint | Transformation | Idiom Mutation |
//! |------|----------------|----------------|
//! | `manual_map` | `match opt { Some(x) => Some(f(x)), None => None }` → `opt.map(f)` | [`ManualMapMutation`] |
//! | `manual_unwrap_or` | `match opt { Some(x) => x, None => default }` → `opt.unwrap_or(default)` | (planned) |
//!
//! # CLI Usage (Planned)
//!
//! ```bash
//! # Apply all MachineApplicable Clippy fixes
//! ryo fix --clippy
//!
//! # Apply specific lint category
//! ryo fix --clippy --category idiom
//! ryo fix --clippy --category perf
//!
//! # Apply specific lint
//! ryo fix --lint bool_comparison
//!
//! # Dry-run (preview changes)
//! ryo fix --clippy --dry-run
//!
//! # Interactive mode (select which fixes to apply)
//! ryo fix --clippy --interactive
//! ```
//!
//! # Example: Programmatic Usage
//!
//! ```rust,ignore
//! use ryo_mutations::clippy::{ClippyRunner, ClippyConfig};
//!
//! // Run clippy and collect diagnostics
//! let config = ClippyConfig::default()
//!     .with_category(LintCategory::Idiom)
//!     .machine_applicable_only();
//!
//! let runner = ClippyRunner::new(config);
//! let diagnostics = runner.run(".")?;
//!
//! // Convert to mutations
//! for diag in diagnostics {
//!     if let Some(mutation) = diag.to_mutation() {
//!         println!("Would apply: {}", mutation.describe());
//!     }
//! }
//! ```
//!
//! # Relationship with rust-analyzer
//!
//! While Clippy focuses on linting and suggestions, rust-analyzer provides
//! code actions (assists) for refactoring. Some transformations overlap:
//!
//! | Transformation | Clippy | rust-analyzer |
//! |----------------|--------|---------------|
//! | `if let` ↔ `match` | `single_match` | `replace_if_let_with_match` |
//! | `unwrap` → `?` | `unwrap_used` | (n/a) |
//! | Iterator patterns | Various | `convert_iter_for_each_to_for` |
//!
//! The Idiom mutations in [`crate::idiom`] can be invoked directly
//! without running Clippy, enabling use in automated pipelines or editors
//! without external tool dependencies.
//!
//! # Future Extensions
//!
//! - [ ] Parse `cargo clippy --message-format=json` output
//! - [ ] Batch application with conflict detection
//! - [ ] Integration with workspace-wide refactoring
//! - [ ] Custom lint rule to Mutation mapping

mod diagnostic;
mod runner;

pub use diagnostic::{Applicability, ClippyDiagnostic, LintCategory, Suggestion};
pub use runner::{ClippyConfig, ClippyRunner};

/// Lint names for direct reference
pub mod lints {
    // Tier 1: High-frequency
    pub const BOOL_COMPARISON: &str = "clippy::bool_comparison";
    pub const COLLAPSIBLE_IF: &str = "clippy::collapsible_if";
    pub const COMPARISON_TO_EMPTY: &str = "clippy::comparison_to_empty";
    pub const ASSIGN_OP_PATTERN: &str = "clippy::assign_op_pattern";
    pub const CLONE_ON_COPY: &str = "clippy::clone_on_copy";
    pub const REDUNDANT_CLOSURE: &str = "clippy::redundant_closure";

    // Tier 2: Iterator optimization
    pub const MAP_CLONE: &str = "clippy::map_clone";
    pub const ITER_CLONED_COLLECT: &str = "clippy::iter_cloned_collect";
    pub const BIND_INSTEAD_OF_MAP: &str = "clippy::bind_instead_of_map";
    pub const OPTION_MAP_UNWRAP_OR: &str = "clippy::option_map_unwrap_or";
    pub const MANUAL_FILTER_MAP: &str = "clippy::manual_filter_map";
    pub const MANUAL_FIND_MAP: &str = "clippy::manual_find_map";

    // Tier 3: Manual pattern detection
    pub const MANUAL_MAP: &str = "clippy::manual_map";
    pub const MANUAL_UNWRAP_OR: &str = "clippy::manual_unwrap_or";

    // Perf
    pub const BOX_COLLECTION: &str = "clippy::box_collection";
    pub const BOXED_LOCAL: &str = "clippy::boxed_local";
}