1use crate::api::error::ApiError;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4use std::time::{Duration, Instant};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Breakpoint {
8 pub id: String,
9 pub line: usize,
10 pub column: usize,
11 pub condition: Option<String>,
12 pub enabled: bool,
13 pub hit_count: usize,
14}
15
16impl Breakpoint {
17 pub fn new(id: String, line: usize, column: usize) -> Self {
18 Self {
19 id,
20 line,
21 column,
22 condition: None,
23 enabled: true,
24 hit_count: 0,
25 }
26 }
27
28 pub fn with_condition(mut self, condition: String) -> Self {
29 self.condition = Some(condition);
30 self
31 }
32
33 pub fn hit(&mut self) {
34 self.hit_count += 1;
35 }
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct CallFrame {
40 pub function_name: String,
41 pub line: usize,
42 pub column: usize,
43 pub variables: HashMap<String, crate::vm::value::Value>,
44 pub this_value: Option<crate::vm::value::Value>,
45 pub arguments: Vec<crate::vm::value::Value>,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct DebugInfo {
50 pub current_line: usize,
51 pub current_column: usize,
52 pub call_stack: Vec<CallFrame>,
53 pub breakpoints: Vec<Breakpoint>,
54 pub variables: HashMap<String, crate::vm::value::Value>,
55 pub is_paused: bool,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct ProfilingMetrics {
60 pub execution_time: Duration,
61 pub memory_usage: usize,
62 pub instruction_count: usize,
63 pub function_calls: usize,
64 pub gc_cycles: usize,
65}
66
67impl ProfilingMetrics {
68 pub fn generate_report(&self) -> String {
69 format!(
70 "Profiling Report:\n\
71 Execution Time: {:?}\n\
72 Memory Usage: {} bytes\n\
73 Instructions Executed: {}\n\
74 Function Calls: {}\n\
75 GC Cycles: {}\n\
76 Functions Profiled: {}",
77 self.execution_time,
78 self.memory_usage,
79 self.instruction_count,
80 self.function_calls,
81 self.gc_cycles,
82 0 )
84 }
85}
86
87pub struct Debugger {
88 breakpoints: HashMap<String, Breakpoint>,
89 is_enabled: bool,
90 step_mode: bool,
91 current_info: Option<DebugInfo>,
92}
93
94impl Debugger {
95 pub fn new() -> Self {
96 Self {
97 breakpoints: HashMap::new(),
98 is_enabled: false,
99 step_mode: false,
100 current_info: None,
101 }
102 }
103
104 pub fn enable(&mut self) {
105 self.is_enabled = true;
106 }
107
108 pub fn disable(&mut self) {
109 self.is_enabled = false;
110 }
111
112 pub fn add_breakpoint(&mut self, breakpoint: Breakpoint) {
113 self.breakpoints.insert(breakpoint.id.clone(), breakpoint);
114 }
115
116 pub fn remove_breakpoint(&mut self, id: &str) -> Option<Breakpoint> {
117 self.breakpoints.remove(id)
118 }
119
120 pub fn enable_breakpoint(&mut self, id: &str) -> Result<(), ApiError> {
121 if let Some(breakpoint) = self.breakpoints.get_mut(id) {
122 breakpoint.enabled = true;
123 Ok(())
124 } else {
125 Err(ApiError::InvalidInput {
126 message: "Breakpoint not found".to_string(),
127 input: id.to_string(),
128 position: None,
129 })
130 }
131 }
132
133 pub fn disable_breakpoint(&mut self, id: &str) -> Result<(), ApiError> {
134 if let Some(breakpoint) = self.breakpoints.get_mut(id) {
135 breakpoint.enabled = false;
136 Ok(())
137 } else {
138 Err(ApiError::InvalidInput {
139 message: "Breakpoint not found".to_string(),
140 input: id.to_string(),
141 position: None,
142 })
143 }
144 }
145
146 pub fn should_pause(&self, line: usize, column: usize) -> bool {
147 if !self.is_enabled {
148 return false;
149 }
150
151 for breakpoint in self.breakpoints.values() {
152 if breakpoint.enabled && breakpoint.line == line && breakpoint.column == column {
153 return true;
154 }
155 }
156
157 self.step_mode
158 }
159
160 pub fn update_debug_info(&mut self, info: DebugInfo) {
161 self.current_info = Some(info);
162 }
163
164 pub fn get_debug_info(&self) -> Option<&DebugInfo> {
165 self.current_info.as_ref()
166 }
167
168 pub fn step_into(&mut self) {
169 self.step_mode = true;
170 }
171
172 pub fn step_over(&mut self) {
173 self.step_mode = false;
174 }
175
176 pub fn continue_execution(&mut self) {
177 self.step_mode = false;
178 }
179}
180
181impl Default for Debugger {
182 fn default() -> Self {
183 Self::new()
184 }
185}
186
187pub struct Profiler {
188 start_time: Option<Instant>,
189 metrics: ProfilingMetrics,
190 function_timings: HashMap<String, Duration>,
191 memory_snapshots: Vec<(Instant, usize)>,
192}
193
194impl Profiler {
195 pub fn new() -> Self {
196 Self {
197 start_time: None,
198 metrics: ProfilingMetrics {
199 execution_time: Duration::ZERO,
200 memory_usage: 0,
201 instruction_count: 0,
202 function_calls: 0,
203 gc_cycles: 0,
204 },
205 function_timings: HashMap::new(),
206 memory_snapshots: Vec::new(),
207 }
208 }
209
210 pub fn start_profiling(&mut self) {
211 self.start_time = Some(Instant::now());
212 }
213
214 pub fn stop_profiling(&mut self) -> ProfilingMetrics {
215 if let Some(start_time) = self.start_time {
216 self.metrics.execution_time = start_time.elapsed();
217 }
218 self.metrics.clone()
219 }
220
221 pub fn record_function_call(&mut self, function_name: String, duration: Duration) {
222 *self
223 .function_timings
224 .entry(function_name)
225 .or_insert(Duration::ZERO) += duration;
226 self.metrics.function_calls += 1;
227 }
228
229 pub fn record_instruction(&mut self) {
230 self.metrics.instruction_count += 1;
231 }
232
233 pub fn record_memory_usage(&mut self, usage: usize) {
234 self.metrics.memory_usage = usage;
235 self.memory_snapshots.push((Instant::now(), usage));
236 }
237
238 pub fn record_gc_cycle(&mut self) {
239 self.metrics.gc_cycles += 1;
240 }
241
242 pub fn get_function_timings(&self) -> &HashMap<String, Duration> {
243 &self.function_timings
244 }
245
246 pub fn get_memory_snapshots(&self) -> &Vec<(Instant, usize)> {
247 &self.memory_snapshots
248 }
249}
250
251impl Default for Profiler {
252 fn default() -> Self {
253 Self::new()
254 }
255}
256
257pub struct Inspector {
258 debugger: Debugger,
259 profiler: Profiler,
260 event_listeners: HashMap<String, Vec<Box<dyn Fn(String) + Send + Sync>>>,
261}
262
263impl Inspector {
264 pub fn new() -> Self {
265 Self {
266 debugger: Debugger::new(),
267 profiler: Profiler::new(),
268 event_listeners: HashMap::new(),
269 }
270 }
271
272 pub fn get_debugger(&mut self) -> &mut Debugger {
273 &mut self.debugger
274 }
275
276 pub fn get_profiler(&mut self) -> &mut Profiler {
277 &mut self.profiler
278 }
279
280 pub fn add_event_listener(
281 &mut self,
282 event: String,
283 listener: Box<dyn Fn(String) + Send + Sync>,
284 ) {
285 self.event_listeners
286 .entry(event)
287 .or_insert_with(Vec::new)
288 .push(listener);
289 }
290
291 pub fn emit_event(&self, event: &str, data: String) {
292 if let Some(listeners) = self.event_listeners.get(event) {
293 for listener in listeners {
294 listener(data.clone());
295 }
296 }
297 }
298
299 pub fn start_inspection(&mut self) {
300 self.debugger.enable();
301 self.profiler.start_profiling();
302 self.emit_event(
303 "inspection_started",
304 "Debugging and profiling started".to_string(),
305 );
306 }
307
308 pub fn stop_inspection(&mut self) -> String {
309 self.debugger.disable();
310 let report = self.profiler.stop_profiling();
311 self.emit_event(
312 "inspection_stopped",
313 "Debugging and profiling stopped".to_string(),
314 );
315 report.generate_report()
316 }
317}
318
319impl Default for Inspector {
320 fn default() -> Self {
321 Self::new()
322 }
323}
324
325#[cfg(test)]
326mod tests {
327 use super::*;
328 use std::time::Duration;
329
330 #[test]
331 fn test_breakpoint() {
332 let mut breakpoint = Breakpoint::new("bp1".to_string(), 10, 5);
333 breakpoint.hit();
334 assert_eq!(breakpoint.hit_count, 1);
335 }
336
337 #[test]
338 fn test_debugger() {
339 let mut debugger = Debugger::new();
340 let breakpoint = Breakpoint::new("bp1".to_string(), 10, 5);
341 debugger.add_breakpoint(breakpoint);
342
343 debugger.enable();
345
346 assert!(debugger.should_pause(10, 5));
347 assert!(!debugger.should_pause(11, 5));
348 }
349
350 #[test]
351 fn test_profiler() {
352 let mut profiler = Profiler::new();
353 profiler.start_profiling();
354 std::thread::sleep(Duration::from_millis(10));
355 let metrics = profiler.stop_profiling();
356
357 assert!(metrics.execution_time > Duration::ZERO);
358 }
359
360 #[test]
361 fn test_inspector() {
362 let mut inspector = Inspector::new();
363
364 inspector.add_event_listener(
365 "test".to_string(),
366 Box::new(|_| {
367 }),
370 );
371
372 assert!(true); }
375}