Skip to main content

perl_dap/
protocol.rs

1//! DAP Protocol Types
2//!
3//! This module defines the JSON-RPC 2.0 message types for the Debug Adapter Protocol.
4//! It follows the DAP 1.x specification with support for Perl-specific features.
5//!
6//! # Message Transport
7//!
8//! Messages are framed using Content-Length headers:
9//! ```text
10//! Content-Length: <length>\r\n
11//! \r\n
12//! <JSON message>
13//! ```
14//!
15//! # References
16//!
17//! - [DAP Protocol Schema](../../docs/reference/DAP_PROTOCOL_SCHEMA.md)
18//! - [Debug Adapter Protocol Specification](https://microsoft.github.io/debug-adapter-protocol/)
19
20use serde::{Deserialize, Serialize};
21use std::collections::HashMap;
22
23/// Base request message
24///
25/// All DAP requests follow this structure with command-specific arguments.
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct Request {
29    /// Sequence number (incremented for each message)
30    pub seq: i64,
31    /// Message type (always "request")
32    #[serde(rename = "type")]
33    pub msg_type: String,
34    /// Command name (e.g., "initialize", "setBreakpoints")
35    pub command: String,
36    /// Command-specific arguments
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub arguments: Option<serde_json::Value>,
39}
40
41/// Base response message
42///
43/// All DAP responses follow this structure with command-specific body.
44#[derive(Debug, Clone, Serialize, Deserialize)]
45#[serde(rename_all = "camelCase")]
46pub struct Response {
47    /// Sequence number
48    pub seq: i64,
49    /// Message type (always "response")
50    #[serde(rename = "type")]
51    pub msg_type: String,
52    /// Sequence number of corresponding request
53    pub request_seq: i64,
54    /// Whether the request succeeded
55    pub success: bool,
56    /// Command name
57    pub command: String,
58    /// Error message (if success=false)
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub message: Option<String>,
61    /// Command-specific response body
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub body: Option<serde_json::Value>,
64}
65
66/// Base event message
67///
68/// DAP events notify the client of state changes.
69#[derive(Debug, Clone, Serialize, Deserialize)]
70#[serde(rename_all = "camelCase")]
71pub struct Event {
72    /// Sequence number
73    pub seq: i64,
74    /// Message type (always "event")
75    #[serde(rename = "type")]
76    pub msg_type: String,
77    /// Event name (e.g., "initialized", "stopped")
78    pub event: String,
79    /// Event-specific body
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub body: Option<serde_json::Value>,
82}
83
84// ============================================================================
85// Breakpoint Request/Response Types (AC7)
86// ============================================================================
87
88/// Source reference in breakpoint requests
89#[derive(Debug, Clone, Serialize, Deserialize)]
90#[serde(rename_all = "camelCase")]
91pub struct Source {
92    /// Absolute file path
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub path: Option<String>,
95    /// File name (optional)
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub name: Option<String>,
98}
99
100/// Source breakpoint in request
101#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(rename_all = "camelCase")]
103pub struct SourceBreakpoint {
104    /// Line number (1-based)
105    pub line: i64,
106    /// Column number (0-based, optional)
107    #[serde(skip_serializing_if = "Option::is_none")]
108    pub column: Option<i64>,
109    /// Breakpoint condition (optional)
110    #[serde(skip_serializing_if = "Option::is_none")]
111    pub condition: Option<String>,
112    /// Hit-condition expression (optional), e.g. `>= 10` or `%2`.
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub hit_condition: Option<String>,
115    /// Logpoint message (optional). When present, breakpoint logs and continues.
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub log_message: Option<String>,
118}
119
120/// Arguments for setBreakpoints request
121#[derive(Debug, Clone, Serialize, Deserialize)]
122#[serde(rename_all = "camelCase")]
123pub struct SetBreakpointsArguments {
124    /// Source file reference
125    pub source: Source,
126    /// Array of breakpoints to set (REPLACE semantics: clears existing)
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub breakpoints: Option<Vec<SourceBreakpoint>>,
129    /// Whether source file was modified
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub source_modified: Option<bool>,
132}
133
134/// Verified breakpoint in response
135#[derive(Debug, Clone, Serialize, Deserialize)]
136#[serde(rename_all = "camelCase")]
137pub struct Breakpoint {
138    /// Unique breakpoint identifier
139    pub id: i64,
140    /// Whether breakpoint was successfully verified
141    pub verified: bool,
142    /// Actual line number (may differ from requested if adjusted)
143    pub line: i64,
144    /// Actual column number (optional)
145    #[serde(skip_serializing_if = "Option::is_none")]
146    pub column: Option<i64>,
147    /// Error/warning message if not verified or adjusted
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub message: Option<String>,
150}
151
152/// Response body for setBreakpoints request
153#[derive(Debug, Clone, Serialize, Deserialize)]
154#[serde(rename_all = "camelCase")]
155pub struct SetBreakpointsResponseBody {
156    /// Array of verified breakpoints (SAME ORDER as request)
157    pub breakpoints: Vec<Breakpoint>,
158}
159
160// ============================================================================
161// Inline Values Request/Response Types (Custom)
162// ============================================================================
163
164/// Arguments for inlineValues request
165///
166/// This request is a lightweight, Perl-specific extension that mirrors the
167/// LSP inlineValue provider using a source file and line range.
168#[derive(Debug, Clone, Serialize, Deserialize)]
169#[serde(rename_all = "camelCase")]
170pub struct InlineValuesArguments {
171    /// Source file reference
172    pub source: Source,
173    /// Start line (1-based, inclusive)
174    pub start_line: i64,
175    /// End line (1-based, inclusive)
176    pub end_line: i64,
177}
178
179/// Inline value hint for a single variable
180#[derive(Debug, Clone, Serialize, Deserialize)]
181#[serde(rename_all = "camelCase")]
182pub struct InlineValueText {
183    /// Line number (1-based)
184    pub line: i64,
185    /// Column number (1-based)
186    pub column: i64,
187    /// Rendered inline value text
188    pub text: String,
189}
190
191/// Response body for inlineValues request
192#[derive(Debug, Clone, Serialize, Deserialize)]
193#[serde(rename_all = "camelCase")]
194pub struct InlineValuesResponseBody {
195    /// Inline values for the requested range
196    pub inline_values: Vec<InlineValueText>,
197}
198
199// ============================================================================
200// Initialize Request/Response Types (AC5)
201// ============================================================================
202
203/// Arguments for initialize request
204#[derive(Debug, Clone, Serialize, Deserialize)]
205#[serde(rename_all = "camelCase")]
206pub struct InitializeRequestArguments {
207    /// Client ID (e.g., "vscode")
208    #[serde(rename = "clientID", alias = "clientId")]
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub client_id: Option<String>,
211    /// Client name (e.g., "Visual Studio Code")
212    #[serde(skip_serializing_if = "Option::is_none")]
213    pub client_name: Option<String>,
214    /// Adapter ID (e.g., "perl-rs")
215    #[serde(rename = "adapterID", alias = "adapterId")]
216    pub adapter_id: String,
217    /// Locale (e.g., "en-US")
218    #[serde(skip_serializing_if = "Option::is_none")]
219    pub locale: Option<String>,
220    /// Lines are 1-based
221    #[serde(skip_serializing_if = "Option::is_none")]
222    pub lines_start_at1: Option<bool>,
223    /// Columns are 1-based
224    #[serde(skip_serializing_if = "Option::is_none")]
225    pub columns_start_at1: Option<bool>,
226    /// Path format ("path" or "uri")
227    #[serde(skip_serializing_if = "Option::is_none")]
228    pub path_format: Option<String>,
229}
230
231/// Response body for initialize request
232#[derive(Debug, Clone, Serialize, Deserialize)]
233#[serde(rename_all = "camelCase")]
234pub struct Capabilities {
235    /// Supports configuration done request
236    #[serde(skip_serializing_if = "Option::is_none")]
237    pub supports_configuration_done_request: Option<bool>,
238    /// Supports evaluate for hovers
239    #[serde(skip_serializing_if = "Option::is_none")]
240    pub supports_evaluate_for_hovers: Option<bool>,
241    /// Supports conditional breakpoints
242    #[serde(skip_serializing_if = "Option::is_none")]
243    pub supports_conditional_breakpoints: Option<bool>,
244    /// Supports hit-conditional breakpoints
245    #[serde(skip_serializing_if = "Option::is_none")]
246    pub supports_hit_conditional_breakpoints: Option<bool>,
247    /// Supports logpoints
248    #[serde(skip_serializing_if = "Option::is_none")]
249    pub supports_log_points: Option<bool>,
250    /// Supports exception breakpoint options
251    #[serde(skip_serializing_if = "Option::is_none")]
252    pub supports_exception_options: Option<bool>,
253    /// Supports exception filter options
254    #[serde(skip_serializing_if = "Option::is_none")]
255    pub supports_exception_filter_options: Option<bool>,
256    /// Supports terminate request
257    #[serde(skip_serializing_if = "Option::is_none")]
258    pub supports_terminate_request: Option<bool>,
259    /// Supports custom inlineValues request for inline debug hints
260    #[serde(skip_serializing_if = "Option::is_none")]
261    pub supports_inline_values: Option<bool>,
262    /// Supports function breakpoints
263    #[serde(skip_serializing_if = "Option::is_none")]
264    pub supports_function_breakpoints: Option<bool>,
265    /// Supports setting variables
266    #[serde(skip_serializing_if = "Option::is_none")]
267    pub supports_set_variable: Option<bool>,
268    /// Supports value formatting options
269    #[serde(skip_serializing_if = "Option::is_none")]
270    pub supports_value_formatting_options: Option<bool>,
271    /// Supports terminating the debuggee on disconnect
272    #[serde(skip_serializing_if = "Option::is_none")]
273    pub support_terminate_debuggee: Option<bool>,
274    /// Supports stepping backwards
275    #[serde(skip_serializing_if = "Option::is_none")]
276    pub supports_step_back: Option<bool>,
277    /// Supports data breakpoints
278    #[serde(skip_serializing_if = "Option::is_none")]
279    pub supports_data_breakpoints: Option<bool>,
280    /// Exception breakpoint filters
281    #[serde(skip_serializing_if = "Option::is_none")]
282    pub exception_breakpoint_filters: Option<Vec<ExceptionBreakpointFilter>>,
283}
284
285// ============================================================================
286// Launch Request/Response Types
287// ============================================================================
288
289/// Arguments for launch request
290#[derive(Debug, Clone, Serialize, Deserialize)]
291#[serde(rename_all = "camelCase")]
292pub struct LaunchRequestArguments {
293    /// Absolute path to Perl script
294    pub program: String,
295    /// Command-line arguments
296    #[serde(skip_serializing_if = "Option::is_none")]
297    pub args: Option<Vec<String>>,
298    /// Working directory
299    #[serde(skip_serializing_if = "Option::is_none")]
300    pub cwd: Option<String>,
301    /// Environment variables
302    #[serde(skip_serializing_if = "Option::is_none")]
303    pub env: Option<HashMap<String, String>>,
304    /// Path to Perl executable
305    #[serde(skip_serializing_if = "Option::is_none")]
306    pub perl_path: Option<String>,
307    /// Stop on entry
308    #[serde(skip_serializing_if = "Option::is_none")]
309    pub stop_on_entry: Option<bool>,
310}
311
312// ============================================================================
313// Attach Request/Response Types
314// ============================================================================
315
316/// Arguments for attach request
317#[derive(Debug, Clone, Serialize, Deserialize)]
318#[serde(rename_all = "camelCase")]
319pub struct AttachRequestArguments {
320    /// Process ID to attach to
321    #[serde(skip_serializing_if = "Option::is_none")]
322    pub process_id: Option<u32>,
323    /// Host to connect to (for TCP attachment)
324    #[serde(skip_serializing_if = "Option::is_none")]
325    pub host: Option<String>,
326    /// Port number for TCP attachment
327    #[serde(skip_serializing_if = "Option::is_none")]
328    pub port: Option<u16>,
329    /// Connection timeout in milliseconds
330    #[serde(skip_serializing_if = "Option::is_none")]
331    pub timeout: Option<u32>,
332    /// If true, pause at the first available program location after attaching.
333    #[serde(skip_serializing_if = "Option::is_none")]
334    pub stop_on_entry: Option<bool>,
335}
336
337// ============================================================================
338// Stack/Variables/Scopes Request Arguments (AC8)
339// ============================================================================
340
341/// Arguments for stackTrace request
342#[derive(Debug, Clone, Serialize, Deserialize)]
343#[serde(rename_all = "camelCase")]
344pub struct StackTraceArguments {
345    /// Thread to retrieve the stack trace for
346    pub thread_id: i64,
347    /// Index of the first frame to return (0-based)
348    #[serde(skip_serializing_if = "Option::is_none")]
349    pub start_frame: Option<i64>,
350    /// Maximum number of frames to return
351    #[serde(skip_serializing_if = "Option::is_none")]
352    pub levels: Option<i64>,
353}
354
355/// Arguments for scopes request
356#[derive(Debug, Clone, Serialize, Deserialize)]
357#[serde(rename_all = "camelCase")]
358pub struct ScopesArguments {
359    /// Frame identifier to retrieve scopes for
360    pub frame_id: i64,
361}
362
363/// Arguments for variables request
364#[derive(Debug, Clone, Serialize, Deserialize)]
365#[serde(rename_all = "camelCase")]
366pub struct VariablesArguments {
367    /// Reference to the variable container
368    pub variables_reference: i64,
369    /// Optional filter ("indexed" or "named")
370    #[serde(skip_serializing_if = "Option::is_none")]
371    pub filter: Option<String>,
372    /// Start index of variables to return
373    #[serde(skip_serializing_if = "Option::is_none")]
374    pub start: Option<i64>,
375    /// Number of variables to return
376    #[serde(skip_serializing_if = "Option::is_none")]
377    pub count: Option<i64>,
378}
379
380/// Arguments for evaluate request
381#[derive(Debug, Clone, Serialize, Deserialize)]
382#[serde(rename_all = "camelCase")]
383pub struct EvaluateArguments {
384    /// Expression to evaluate
385    pub expression: String,
386    /// Stack frame context for evaluation
387    #[serde(skip_serializing_if = "Option::is_none")]
388    pub frame_id: Option<i64>,
389    /// Evaluation context ("watch", "repl", "hover", "clipboard")
390    #[serde(skip_serializing_if = "Option::is_none")]
391    pub context: Option<String>,
392    /// Whether side effects are allowed during evaluation
393    #[serde(skip_serializing_if = "Option::is_none")]
394    pub allow_side_effects: Option<bool>,
395}
396
397// ============================================================================
398// Control Flow Request Arguments (AC9)
399// ============================================================================
400
401/// Arguments for continue request
402#[derive(Debug, Clone, Serialize, Deserialize)]
403#[serde(rename_all = "camelCase")]
404pub struct ContinueArguments {
405    /// Thread to continue
406    pub thread_id: i64,
407}
408
409/// Arguments for next (step over) request
410#[derive(Debug, Clone, Serialize, Deserialize)]
411#[serde(rename_all = "camelCase")]
412pub struct NextArguments {
413    /// Thread to step
414    pub thread_id: i64,
415}
416
417/// Arguments for stepIn request
418#[derive(Debug, Clone, Serialize, Deserialize)]
419#[serde(rename_all = "camelCase")]
420pub struct StepInArguments {
421    /// Thread to step into
422    pub thread_id: i64,
423}
424
425/// Arguments for stepOut request
426#[derive(Debug, Clone, Serialize, Deserialize)]
427#[serde(rename_all = "camelCase")]
428pub struct StepOutArguments {
429    /// Thread to step out of
430    pub thread_id: i64,
431}
432
433/// Arguments for pause request
434#[derive(Debug, Clone, Serialize, Deserialize)]
435#[serde(rename_all = "camelCase")]
436pub struct PauseArguments {
437    /// Thread to pause
438    pub thread_id: i64,
439}
440
441// ============================================================================
442// Variable Modification Request Arguments (AC8)
443// ============================================================================
444
445/// Arguments for setVariable request
446#[derive(Debug, Clone, Serialize, Deserialize)]
447#[serde(rename_all = "camelCase")]
448pub struct SetVariableArguments {
449    /// Reference to the variable container
450    pub variables_reference: i64,
451    /// Name of the variable to set
452    pub name: String,
453    /// New value for the variable
454    pub value: String,
455}
456
457// ============================================================================
458// Session Lifecycle Request Arguments (AC5)
459// ============================================================================
460
461/// Arguments for disconnect request
462#[derive(Debug, Clone, Serialize, Deserialize)]
463#[serde(rename_all = "camelCase")]
464pub struct DisconnectArguments {
465    /// Whether to restart the debug session
466    #[serde(skip_serializing_if = "Option::is_none")]
467    pub restart: Option<bool>,
468    /// Whether to terminate the debuggee process
469    #[serde(skip_serializing_if = "Option::is_none")]
470    pub terminate_debuggee: Option<bool>,
471}
472
473/// Arguments for terminate request
474#[derive(Debug, Clone, Serialize, Deserialize)]
475#[serde(rename_all = "camelCase")]
476pub struct TerminateArguments {
477    /// Whether to restart after termination
478    #[serde(skip_serializing_if = "Option::is_none")]
479    pub restart: Option<bool>,
480}
481
482// ============================================================================
483// Extended Breakpoint Request Arguments (AC7)
484// ============================================================================
485
486/// Arguments for setFunctionBreakpoints request
487#[derive(Debug, Clone, Serialize, Deserialize)]
488#[serde(rename_all = "camelCase")]
489pub struct SetFunctionBreakpointsArguments {
490    /// Function breakpoints to set
491    pub breakpoints: Vec<FunctionBreakpoint>,
492}
493
494/// Arguments for setExceptionBreakpoints request
495#[derive(Debug, Clone, Serialize, Deserialize)]
496#[serde(rename_all = "camelCase")]
497pub struct SetExceptionBreakpointsArguments {
498    /// Exception filter IDs to activate
499    pub filters: Vec<String>,
500    /// Additional exception filter options
501    #[serde(skip_serializing_if = "Option::is_none")]
502    pub filter_options: Option<Vec<ExceptionFilterOption>>,
503}
504
505// ============================================================================
506// Supporting Types
507// ============================================================================
508
509/// Function breakpoint specification
510#[derive(Debug, Clone, Serialize, Deserialize)]
511#[serde(rename_all = "camelCase")]
512pub struct FunctionBreakpoint {
513    /// Name of the function to break on
514    pub name: String,
515    /// Breakpoint condition expression
516    #[serde(skip_serializing_if = "Option::is_none")]
517    pub condition: Option<String>,
518    /// Hit-condition expression
519    #[serde(skip_serializing_if = "Option::is_none")]
520    pub hit_condition: Option<String>,
521}
522
523/// Exception filter option for fine-grained exception breakpoints
524#[derive(Debug, Clone, Serialize, Deserialize)]
525#[serde(rename_all = "camelCase")]
526pub struct ExceptionFilterOption {
527    /// ID of the exception filter
528    pub filter_id: String,
529    /// Condition expression for the filter
530    #[serde(skip_serializing_if = "Option::is_none")]
531    pub condition: Option<String>,
532}
533
534/// Exception breakpoint filter descriptor (reported in capabilities)
535#[derive(Debug, Clone, Serialize, Deserialize)]
536#[serde(rename_all = "camelCase")]
537pub struct ExceptionBreakpointFilter {
538    /// Unique filter identifier
539    pub filter: String,
540    /// Human-readable label for the filter
541    pub label: String,
542    /// Whether this filter is enabled by default
543    #[serde(skip_serializing_if = "Option::is_none")]
544    pub default: Option<bool>,
545}
546
547/// A thread in the debuggee
548#[derive(Debug, Clone, Serialize, Deserialize)]
549#[serde(rename_all = "camelCase")]
550pub struct Thread {
551    /// Thread identifier
552    pub id: i64,
553    /// Human-readable thread name
554    pub name: String,
555}
556
557/// A scope within a stack frame
558#[derive(Debug, Clone, Serialize, Deserialize)]
559#[serde(rename_all = "camelCase")]
560pub struct Scope {
561    /// Scope name (e.g., "Locals", "Globals")
562    pub name: String,
563    /// Presentation hint ("arguments", "locals", "registers")
564    #[serde(skip_serializing_if = "Option::is_none")]
565    pub presentation_hint: Option<String>,
566    /// Reference to the variables in this scope
567    pub variables_reference: i64,
568    /// Whether fetching variables is expensive
569    pub expensive: bool,
570    /// Number of named child variables; can be used as a hint for the client to optimize pagination
571    #[serde(skip_serializing_if = "Option::is_none")]
572    pub named_variables: Option<i64>,
573    /// Number of indexed child variables; can be used as a hint for the client to optimize pagination
574    #[serde(skip_serializing_if = "Option::is_none")]
575    pub indexed_variables: Option<i64>,
576}
577
578/// A variable in the debuggee
579#[derive(Debug, Clone, Serialize, Deserialize)]
580#[serde(rename_all = "camelCase")]
581pub struct ProtocolVariable {
582    /// Variable name
583    pub name: String,
584    /// String representation of the variable value
585    pub value: String,
586    /// Type of the variable
587    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
588    pub type_: Option<String>,
589    /// Reference for child variables (0 means no children)
590    pub variables_reference: i64,
591    /// Number of named child variables
592    #[serde(skip_serializing_if = "Option::is_none")]
593    pub named_variables: Option<i64>,
594    /// Number of indexed child variables
595    #[serde(skip_serializing_if = "Option::is_none")]
596    pub indexed_variables: Option<i64>,
597}
598
599/// A stack frame in the call stack
600#[derive(Debug, Clone, Serialize, Deserialize)]
601#[serde(rename_all = "camelCase")]
602pub struct ProtocolStackFrame {
603    /// Frame identifier
604    pub id: i64,
605    /// Name of the frame (typically the function name)
606    pub name: String,
607    /// Source location of the frame
608    #[serde(skip_serializing_if = "Option::is_none")]
609    pub source: Option<Source>,
610    /// Line number (1-based)
611    pub line: i64,
612    /// Column number (1-based)
613    pub column: i64,
614    /// End line number (optional)
615    #[serde(skip_serializing_if = "Option::is_none")]
616    pub end_line: Option<i64>,
617    /// End column number (optional)
618    #[serde(skip_serializing_if = "Option::is_none")]
619    pub end_column: Option<i64>,
620}
621
622// ============================================================================
623// Response Body Types
624// ============================================================================
625
626/// Response body for threads request
627#[derive(Debug, Clone, Serialize, Deserialize)]
628#[serde(rename_all = "camelCase")]
629pub struct ThreadsResponseBody {
630    /// All threads in the debuggee
631    pub threads: Vec<Thread>,
632}
633
634/// Response body for stackTrace request
635#[derive(Debug, Clone, Serialize, Deserialize)]
636#[serde(rename_all = "camelCase")]
637pub struct StackTraceResponseBody {
638    /// Stack frames in the call stack
639    pub stack_frames: Vec<ProtocolStackFrame>,
640    /// Total number of frames available
641    #[serde(skip_serializing_if = "Option::is_none")]
642    pub total_frames: Option<i64>,
643}
644
645/// Response body for scopes request
646#[derive(Debug, Clone, Serialize, Deserialize)]
647#[serde(rename_all = "camelCase")]
648pub struct ScopesResponseBody {
649    /// Scopes in the specified stack frame
650    pub scopes: Vec<Scope>,
651}
652
653/// Response body for variables request
654#[derive(Debug, Clone, Serialize, Deserialize)]
655#[serde(rename_all = "camelCase")]
656pub struct VariablesResponseBody {
657    /// Variables in the specified scope or container
658    pub variables: Vec<ProtocolVariable>,
659    /// Total number of variables available (before pagination)
660    #[serde(skip_serializing_if = "Option::is_none")]
661    pub total_variables: Option<i64>,
662}
663
664/// Response body for continue request
665#[derive(Debug, Clone, Serialize, Deserialize)]
666#[serde(rename_all = "camelCase")]
667pub struct ContinueResponseBody {
668    /// Whether all threads were continued
669    pub all_threads_continued: bool,
670}
671
672/// Response body for evaluate request
673#[derive(Debug, Clone, Serialize, Deserialize)]
674#[serde(rename_all = "camelCase")]
675pub struct EvaluateResponseBody {
676    /// String representation of the evaluation result
677    pub result: String,
678    /// Type of the result
679    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
680    pub type_: Option<String>,
681    /// Reference for structured result (0 means no children)
682    pub variables_reference: i64,
683}
684
685/// Response body for setVariable request
686#[derive(Debug, Clone, Serialize, Deserialize)]
687#[serde(rename_all = "camelCase")]
688pub struct SetVariableResponseBody {
689    /// New string representation of the variable value
690    pub value: String,
691    /// Type of the variable after setting
692    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
693    pub type_: Option<String>,
694    /// Reference for child variables (0 means no children)
695    pub variables_reference: i64,
696}
697
698// ============================================================================
699// Breakpoint Locations Request/Response Types
700// ============================================================================
701
702/// Arguments for `breakpointLocations` request
703#[derive(Debug, Clone, Serialize, Deserialize)]
704#[serde(rename_all = "camelCase")]
705pub struct BreakpointLocationsArguments {
706    /// The source location of the breakpoints
707    pub source: Source,
708    /// Start line of range to query (1-based)
709    pub line: i64,
710    /// Optional end line of range (1-based, defaults to line)
711    #[serde(skip_serializing_if = "Option::is_none")]
712    pub end_line: Option<i64>,
713}
714
715/// A breakpoint location
716#[derive(Debug, Clone, Serialize, Deserialize)]
717#[serde(rename_all = "camelCase")]
718pub struct BreakpointLocation {
719    /// Line number (1-based)
720    pub line: i64,
721    /// Optional column number (1-based)
722    #[serde(skip_serializing_if = "Option::is_none")]
723    pub column: Option<i64>,
724    /// Optional end line
725    #[serde(skip_serializing_if = "Option::is_none")]
726    pub end_line: Option<i64>,
727    /// Optional end column
728    #[serde(skip_serializing_if = "Option::is_none")]
729    pub end_column: Option<i64>,
730}
731
732/// Response body for `breakpointLocations` request
733#[derive(Debug, Clone, Serialize, Deserialize)]
734#[serde(rename_all = "camelCase")]
735pub struct BreakpointLocationsResponseBody {
736    /// Sorted set of possible breakpoint locations
737    pub breakpoints: Vec<BreakpointLocation>,
738}
739
740// ============================================================================
741// Source Request/Response Types
742// ============================================================================
743
744/// Arguments for `source` request
745#[derive(Debug, Clone, Serialize, Deserialize)]
746#[serde(rename_all = "camelCase")]
747pub struct SourceArguments {
748    /// Source reference (> 0)
749    #[serde(skip_serializing_if = "Option::is_none")]
750    pub source_reference: Option<i64>,
751    /// The source to retrieve content for
752    #[serde(skip_serializing_if = "Option::is_none")]
753    pub source: Option<Source>,
754}
755
756/// Response body for `source` request
757#[derive(Debug, Clone, Serialize, Deserialize)]
758#[serde(rename_all = "camelCase")]
759pub struct SourceResponseBody {
760    /// Content of the source
761    pub content: String,
762    /// MIME type of the content
763    #[serde(skip_serializing_if = "Option::is_none")]
764    pub mime_type: Option<String>,
765}
766
767// ============================================================================
768// Step In Targets Request/Response Types
769// ============================================================================
770
771/// Arguments for `stepInTargets` request
772#[derive(Debug, Clone, Serialize, Deserialize)]
773#[serde(rename_all = "camelCase")]
774pub struct StepInTargetsArguments {
775    /// The frame for which to retrieve step-in targets
776    pub frame_id: i64,
777}
778
779/// A step-in target
780#[derive(Debug, Clone, Serialize, Deserialize)]
781#[serde(rename_all = "camelCase")]
782pub struct StepInTarget {
783    /// Unique identifier for this target
784    pub id: i64,
785    /// The name of the target
786    pub label: String,
787}
788
789/// Response body for `stepInTargets` request
790#[derive(Debug, Clone, Serialize, Deserialize)]
791#[serde(rename_all = "camelCase")]
792pub struct StepInTargetsResponseBody {
793    /// The step-in targets
794    pub targets: Vec<StepInTarget>,
795}
796
797// ============================================================================
798// Goto Targets Request/Response Types
799// ============================================================================
800
801/// Arguments for `gotoTargets` request
802#[derive(Debug, Clone, Serialize, Deserialize)]
803#[serde(rename_all = "camelCase")]
804pub struct GotoTargetsArguments {
805    /// The source for which to find targets
806    pub source: Source,
807    /// The line for which to find targets
808    pub line: i64,
809    /// Optional column for which to find targets
810    #[serde(skip_serializing_if = "Option::is_none")]
811    pub column: Option<i64>,
812}
813
814/// A goto target
815#[derive(Debug, Clone, Serialize, Deserialize)]
816#[serde(rename_all = "camelCase")]
817pub struct GotoTarget {
818    /// Unique identifier for this target
819    pub id: i64,
820    /// The name of the target
821    pub label: String,
822    /// The line of the target
823    pub line: i64,
824    /// Optional column of the target
825    #[serde(skip_serializing_if = "Option::is_none")]
826    pub column: Option<i64>,
827    /// Optional end line of the target
828    #[serde(skip_serializing_if = "Option::is_none")]
829    pub end_line: Option<i64>,
830    /// Optional end column of the target
831    #[serde(skip_serializing_if = "Option::is_none")]
832    pub end_column: Option<i64>,
833}
834
835/// Response body for `gotoTargets` request
836#[derive(Debug, Clone, Serialize, Deserialize)]
837#[serde(rename_all = "camelCase")]
838pub struct GotoTargetsResponseBody {
839    /// The goto targets
840    pub targets: Vec<GotoTarget>,
841}
842
843// ============================================================================
844// Exception Info Request/Response Types
845// ============================================================================
846
847/// Arguments for `exceptionInfo` request
848#[derive(Debug, Clone, Serialize, Deserialize)]
849#[serde(rename_all = "camelCase")]
850pub struct ExceptionInfoArguments {
851    /// Thread for which to retrieve exception info
852    pub thread_id: i64,
853}
854
855/// Detailed information about an exception
856#[derive(Debug, Clone, Serialize, Deserialize)]
857#[serde(rename_all = "camelCase")]
858pub struct ExceptionDetails {
859    /// Message contained in the exception
860    #[serde(skip_serializing_if = "Option::is_none")]
861    pub message: Option<String>,
862    /// Short type name of the exception object
863    #[serde(rename = "typeName", skip_serializing_if = "Option::is_none")]
864    pub type_name: Option<String>,
865    /// Formatted stack trace for the exception
866    #[serde(skip_serializing_if = "Option::is_none")]
867    pub stack_trace: Option<String>,
868}
869
870/// Response body for `exceptionInfo` request
871#[derive(Debug, Clone, Serialize, Deserialize)]
872#[serde(rename_all = "camelCase")]
873pub struct ExceptionInfoResponseBody {
874    /// ID of the exception that was thrown
875    pub exception_id: String,
876    /// Descriptive text for the exception
877    #[serde(skip_serializing_if = "Option::is_none")]
878    pub description: Option<String>,
879    /// Mode that caused the exception notification (never, always, unhandled, userUnhandled)
880    pub break_mode: String,
881    /// Detailed information about the exception
882    #[serde(skip_serializing_if = "Option::is_none")]
883    pub details: Option<ExceptionDetails>,
884}
885
886// ============================================================================
887// Set Expression Request/Response Types
888// ============================================================================
889
890/// Arguments for `setExpression` request
891#[derive(Debug, Clone, Serialize, Deserialize)]
892#[serde(rename_all = "camelCase")]
893pub struct SetExpressionArguments {
894    /// The l-value expression to assign to
895    pub expression: String,
896    /// The value expression to assign
897    pub value: String,
898    /// Evaluate the expressions in the scope of this stack frame (optional)
899    #[serde(skip_serializing_if = "Option::is_none")]
900    pub frame_id: Option<i64>,
901}
902
903/// Response body for `setExpression` request
904#[derive(Debug, Clone, Serialize, Deserialize)]
905#[serde(rename_all = "camelCase")]
906pub struct SetExpressionResponseBody {
907    /// The new value of the expression
908    pub value: String,
909    /// The type of the value
910    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
911    pub type_: Option<String>,
912    /// Reference for structured result (0 means no children)
913    pub variables_reference: i64,
914}
915
916// ============================================================================
917// Restart Request Types
918// ============================================================================
919
920/// Arguments for `restart` request
921#[derive(Debug, Clone, Serialize, Deserialize)]
922#[serde(rename_all = "camelCase")]
923pub struct RestartArguments {
924    /// Updated launch/attach configuration arguments (optional)
925    #[serde(skip_serializing_if = "Option::is_none")]
926    pub arguments: Option<serde_json::Value>,
927}
928
929// ============================================================================
930// Loaded Sources Request/Response Types
931// ============================================================================
932
933/// Response body for `loadedSources` request
934#[derive(Debug, Clone, Serialize, Deserialize)]
935#[serde(rename_all = "camelCase")]
936pub struct LoadedSourcesResponseBody {
937    /// Set of loaded sources
938    pub sources: Vec<Source>,
939}
940
941// ============================================================================
942// Modules Request/Response Types
943// ============================================================================
944
945/// Arguments for `modules` request
946#[derive(Debug, Clone, Serialize, Deserialize)]
947#[serde(rename_all = "camelCase")]
948pub struct ModulesArguments {
949    /// Index of the first module to return (0-based)
950    #[serde(skip_serializing_if = "Option::is_none")]
951    pub start_module: Option<i64>,
952    /// Number of modules to return
953    #[serde(skip_serializing_if = "Option::is_none")]
954    pub module_count: Option<i64>,
955}
956
957/// A module in the debuggee
958#[derive(Debug, Clone, Serialize, Deserialize)]
959#[serde(rename_all = "camelCase")]
960pub struct Module {
961    /// Unique identifier for the module
962    pub id: String,
963    /// Module name (e.g., "Foo::Bar")
964    pub name: String,
965    /// Absolute path on disk
966    #[serde(skip_serializing_if = "Option::is_none")]
967    pub path: Option<String>,
968}
969
970/// Response body for `modules` request
971#[derive(Debug, Clone, Serialize, Deserialize)]
972#[serde(rename_all = "camelCase")]
973pub struct ModulesResponseBody {
974    /// All modules
975    pub modules: Vec<Module>,
976    /// Total number of modules available
977    #[serde(skip_serializing_if = "Option::is_none")]
978    pub total_modules: Option<i64>,
979}
980
981// ============================================================================
982// Completions Request/Response Types
983// ============================================================================
984
985/// Arguments for `completions` request
986#[derive(Debug, Clone, Serialize, Deserialize)]
987#[serde(rename_all = "camelCase")]
988pub struct CompletionsArguments {
989    /// The text to compute completions for
990    pub text: String,
991    /// The column position (0-based) within `text` for which to compute completions
992    pub column: i64,
993    /// Frame ID for context (optional)
994    #[serde(skip_serializing_if = "Option::is_none")]
995    pub frame_id: Option<i64>,
996    /// Line number (optional, for multi-line text)
997    #[serde(skip_serializing_if = "Option::is_none")]
998    pub line: Option<i64>,
999}
1000
1001/// A single completion item
1002#[derive(Debug, Clone, Serialize, Deserialize)]
1003#[serde(rename_all = "camelCase")]
1004pub struct CompletionItem {
1005    /// The label of this completion item (shown in the UI)
1006    pub label: String,
1007    /// Type classification of this item
1008    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
1009    pub type_: Option<String>,
1010    /// Replacement text (if different from label)
1011    #[serde(skip_serializing_if = "Option::is_none")]
1012    pub text: Option<String>,
1013    /// Sort text used for ordering
1014    #[serde(skip_serializing_if = "Option::is_none")]
1015    pub sort_text: Option<String>,
1016    /// Detailed information about this item
1017    #[serde(skip_serializing_if = "Option::is_none")]
1018    pub detail: Option<String>,
1019    /// Start position for text replacement (0-based column)
1020    #[serde(skip_serializing_if = "Option::is_none")]
1021    pub start: Option<i64>,
1022    /// Number of characters to replace
1023    #[serde(skip_serializing_if = "Option::is_none")]
1024    pub length: Option<i64>,
1025}
1026
1027/// Response body for `completions` request
1028#[derive(Debug, Clone, Serialize, Deserialize)]
1029#[serde(rename_all = "camelCase")]
1030pub struct CompletionsResponseBody {
1031    /// The completion items
1032    pub targets: Vec<CompletionItem>,
1033}
1034
1035// ============================================================================
1036// Data Breakpoint Info Request/Response Types
1037// ============================================================================
1038
1039/// Arguments for `dataBreakpointInfo` request
1040#[derive(Debug, Clone, Serialize, Deserialize)]
1041#[serde(rename_all = "camelCase")]
1042pub struct DataBreakpointInfoArguments {
1043    /// Variable name to get data breakpoint info for
1044    pub name: String,
1045    /// Reference to the variable container
1046    #[serde(skip_serializing_if = "Option::is_none")]
1047    pub variables_reference: Option<i64>,
1048    /// Frame ID for context
1049    #[serde(skip_serializing_if = "Option::is_none")]
1050    pub frame_id: Option<i64>,
1051}
1052
1053/// Response body for `dataBreakpointInfo` request
1054#[derive(Debug, Clone, Serialize, Deserialize)]
1055#[serde(rename_all = "camelCase")]
1056pub struct DataBreakpointInfoResponseBody {
1057    /// Identifier for the data (null/None means not available)
1058    #[serde(skip_serializing_if = "Option::is_none")]
1059    pub data_id: Option<String>,
1060    /// Description of the data
1061    pub description: String,
1062    /// Available access types for this data
1063    #[serde(skip_serializing_if = "Option::is_none")]
1064    pub access_types: Option<Vec<String>>,
1065}
1066
1067// ============================================================================
1068// Set Data Breakpoints Request/Response Types
1069// ============================================================================
1070
1071/// A data breakpoint in the request
1072#[derive(Debug, Clone, Serialize, Deserialize)]
1073#[serde(rename_all = "camelCase")]
1074pub struct DataBreakpoint {
1075    /// Identifier obtained from `dataBreakpointInfo`
1076    pub data_id: String,
1077    /// Access type (e.g., "write", "read", "readWrite")
1078    #[serde(skip_serializing_if = "Option::is_none")]
1079    pub access_type: Option<String>,
1080    /// Optional condition expression
1081    #[serde(skip_serializing_if = "Option::is_none")]
1082    pub condition: Option<String>,
1083    /// Optional hit condition
1084    #[serde(skip_serializing_if = "Option::is_none")]
1085    pub hit_condition: Option<String>,
1086}
1087
1088/// Arguments for `setDataBreakpoints` request
1089#[derive(Debug, Clone, Serialize, Deserialize)]
1090#[serde(rename_all = "camelCase")]
1091pub struct SetDataBreakpointsArguments {
1092    /// The data breakpoints to set (replaces all existing)
1093    pub breakpoints: Vec<DataBreakpoint>,
1094}
1095
1096/// Response body for `setDataBreakpoints` request
1097#[derive(Debug, Clone, Serialize, Deserialize)]
1098#[serde(rename_all = "camelCase")]
1099pub struct SetDataBreakpointsResponseBody {
1100    /// Information about the data breakpoints (same order as request)
1101    pub breakpoints: Vec<Breakpoint>,
1102}
1103
1104// ============================================================================
1105// Goto Request Types
1106// ============================================================================
1107
1108/// Arguments for goto request
1109#[derive(Debug, Clone, Serialize, Deserialize)]
1110#[serde(rename_all = "camelCase")]
1111pub struct GotoArguments {
1112    /// Thread to perform the goto on
1113    pub thread_id: i64,
1114    /// Target obtained from gotoTargets
1115    pub target_id: i64,
1116}
1117
1118// ============================================================================
1119// Cancel Request Types
1120// ============================================================================
1121
1122/// Arguments for cancel request
1123#[derive(Debug, Clone, Serialize, Deserialize)]
1124#[serde(rename_all = "camelCase")]
1125pub struct CancelArguments {
1126    /// ID of the request to cancel
1127    #[serde(skip_serializing_if = "Option::is_none")]
1128    pub request_id: Option<i64>,
1129    /// ID of the progress to cancel
1130    #[serde(skip_serializing_if = "Option::is_none")]
1131    pub progress_id: Option<String>,
1132}
1133
1134// ============================================================================
1135// Restart Frame Request Types
1136// ============================================================================
1137
1138/// Arguments for restartFrame request
1139#[derive(Debug, Clone, Serialize, Deserialize)]
1140#[serde(rename_all = "camelCase")]
1141pub struct RestartFrameArguments {
1142    /// Frame to restart
1143    pub frame_id: i64,
1144}
1145
1146// ============================================================================
1147// Terminate Threads Request Types
1148// ============================================================================
1149
1150/// Arguments for terminateThreads request
1151#[derive(Debug, Clone, Serialize, Deserialize)]
1152#[serde(rename_all = "camelCase")]
1153pub struct TerminateThreadsArguments {
1154    /// IDs of threads to terminate
1155    #[serde(skip_serializing_if = "Option::is_none")]
1156    pub thread_ids: Option<Vec<i64>>,
1157}