1use anyhow::Result;
9use console::style;
10use serde::Serialize;
11
12use crate::cache::Cache;
13use crate::config::Config;
14
15#[derive(Debug, Clone)]
17pub enum BridgeSubcommand {
18 Status { json: bool },
20}
21
22#[derive(Debug, Clone)]
24pub struct BridgeOptions {
25 pub cache: std::path::PathBuf,
27 pub subcommand: BridgeSubcommand,
29}
30
31#[derive(Debug, Serialize)]
33#[serde(rename_all = "camelCase")]
34struct BridgeStatusJson {
35 enabled: bool,
36 precedence: String,
37 summary: BridgeSummaryJson,
38 by_format: std::collections::HashMap<String, u64>,
39}
40
41#[derive(Debug, Serialize)]
42#[serde(rename_all = "camelCase")]
43struct BridgeSummaryJson {
44 total_annotations: u64,
45 explicit_count: u64,
46 converted_count: u64,
47 merged_count: u64,
48}
49
50pub fn execute_bridge(options: BridgeOptions, config: Config) -> Result<()> {
52 match options.subcommand {
53 BridgeSubcommand::Status { json } => execute_status(&options.cache, &config, json),
54 }
55}
56
57fn execute_status(cache_path: &std::path::Path, config: &Config, json_output: bool) -> Result<()> {
59 let cache = if cache_path.exists() {
61 Some(Cache::from_json(cache_path)?)
62 } else {
63 None
64 };
65
66 if json_output {
67 output_status_json(config, cache.as_ref())
68 } else {
69 output_status_text(config, cache.as_ref())
70 }
71}
72
73fn output_status_json(config: &Config, cache: Option<&Cache>) -> Result<()> {
75 let status = if let Some(cache) = cache {
76 BridgeStatusJson {
77 enabled: config.bridge.enabled,
78 precedence: config.bridge.precedence.to_string(),
79 summary: BridgeSummaryJson {
80 total_annotations: cache.bridge.summary.total_annotations,
81 explicit_count: cache.bridge.summary.explicit_count,
82 converted_count: cache.bridge.summary.converted_count,
83 merged_count: cache.bridge.summary.merged_count,
84 },
85 by_format: cache.bridge.by_format.clone(),
86 }
87 } else {
88 BridgeStatusJson {
89 enabled: config.bridge.enabled,
90 precedence: config.bridge.precedence.to_string(),
91 summary: BridgeSummaryJson {
92 total_annotations: 0,
93 explicit_count: 0,
94 converted_count: 0,
95 merged_count: 0,
96 },
97 by_format: std::collections::HashMap::new(),
98 }
99 };
100
101 println!("{}", serde_json::to_string_pretty(&status)?);
102 Ok(())
103}
104
105fn output_status_text(config: &Config, cache: Option<&Cache>) -> Result<()> {
107 println!("{}", style("Bridge Configuration:").bold());
108 println!(
109 " Enabled: {}",
110 if config.bridge.enabled {
111 style("yes").green()
112 } else {
113 style("no").yellow()
114 }
115 );
116 println!(" Precedence: {}", config.bridge.precedence);
117 println!(" Strictness: {:?}", config.bridge.strictness);
118 println!();
119
120 println!("{}", style("Language Support:").bold());
121 println!(
122 " JSDoc/TSDoc: {}",
123 if config.bridge.jsdoc.enabled {
124 style("enabled").green()
125 } else {
126 style("disabled").dim()
127 }
128 );
129 println!(
130 " Python: {}",
131 if config.bridge.python.enabled {
132 style("enabled").green()
133 } else {
134 style("disabled").dim()
135 }
136 );
137 if config.bridge.python.enabled {
138 println!(" Style: {:?}", config.bridge.python.docstring_style);
139 }
140 println!(
141 " Rust: {}",
142 if config.bridge.rust.enabled {
143 style("enabled").green()
144 } else {
145 style("disabled").dim()
146 }
147 );
148 println!();
149
150 if let Some(cache) = cache {
151 let total = cache.bridge.summary.total_annotations;
152 if total > 0 {
153 println!("{}", style("Statistics:").bold());
154 println!(" Total annotations: {}", total);
155
156 let explicit = cache.bridge.summary.explicit_count;
157 let converted = cache.bridge.summary.converted_count;
158 let merged = cache.bridge.summary.merged_count;
159
160 println!(
161 " Explicit (ACP only): {:>5} ({:>5.1}%)",
162 explicit,
163 (explicit as f64 / total as f64) * 100.0
164 );
165 println!(
166 " Converted (from native): {:>5} ({:>5.1}%)",
167 converted,
168 (converted as f64 / total as f64) * 100.0
169 );
170 println!(
171 " Merged (ACP + native): {:>5} ({:>5.1}%)",
172 merged,
173 (merged as f64 / total as f64) * 100.0
174 );
175 println!();
176
177 if !cache.bridge.by_format.is_empty() {
178 println!("{}", style("By Format:").bold());
179 for (format, count) in &cache.bridge.by_format {
180 println!(" {}: {}", format, count);
181 }
182 }
183 } else {
184 println!("{}", style("Statistics:").bold());
185 println!(" No bridged annotations found.");
186 if !config.bridge.enabled {
187 println!();
188 println!(
189 " {} Run `acp index --bridge` to enable bridging",
190 style("Hint:").cyan()
191 );
192 }
193 }
194 } else {
195 println!("{}", style("Statistics:").bold());
196 println!(" Cache not found. Run `acp index` first.");
197 }
198
199 Ok(())
200}