fob_graph/framework_rules/
mod.rs

1//! Framework-aware dead code analysis.
2//!
3//! This module provides a generic trait for marking exports as framework-used,
4//! allowing external tools to implement framework-specific detection logic.
5//!
6//! # Overview
7//!
8//! Framework rules solve the problem of false-positive "unused export" warnings
9//! for exports that frameworks consume through naming conventions rather than
10//! explicit imports. Joy provides the infrastructure (the `FrameworkRule` trait),
11//! while external tools (like Danny) provide the framework-specific knowledge.
12//!
13//! # Custom Rules
14//!
15//! ```rust,ignore
16//! use fob_graph::graph::{FrameworkRule, ModuleGraph};
17//! use async_trait::async_trait;
18//!
19//! struct MyRule;
20//!
21//! #[async_trait]
22//! impl FrameworkRule for MyRule {
23//!     async fn apply(&self, graph: &ModuleGraph) -> Result<()> {
24//!         let modules = graph.modules().await?;
25//!         
26//!         for module in modules {
27//!             let mut updated = module.clone();
28//!             let mut changed = false;
29//!             
30//!             for export in updated.exports.iter_mut() {
31//!                 if export.name.starts_with("server_") {
32//!                     export.mark_framework_used();
33//!                     changed = true;
34//!                 }
35//!             }
36//!             
37//!             if changed {
38//!                 graph.add_module(updated).await?;
39//!             }
40//!         }
41//!         
42//!         Ok(())
43//!     }
44//!
45//!     fn name(&self) -> &'static str { "MyRule" }
46//!     fn description(&self) -> &'static str { "Server actions" }
47//!     fn clone_box(&self) -> Box<dyn FrameworkRule> { Box::new(MyRule) }
48//! }
49//!
50//! // Apply custom rules via AnalyzeOptions
51//! use fob_graph::analysis::{analyze_with_options, AnalyzeOptions};
52//!
53//! let options = AnalyzeOptions {
54//!     framework_rules: vec![Box::new(MyRule)],
55//! };
56//! let result = analyze_with_options(["src/index.tsx"], options).await?;
57//! ```
58
59mod trait_def;
60
61pub use trait_def::FrameworkRule;