Skip to content

Commit 46b38d5

Browse files
committed
Move debugger to separate file
1 parent 56b91f9 commit 46b38d5

File tree

2 files changed

+196
-195
lines changed

2 files changed

+196
-195
lines changed

src/debugger.rs

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
use dap::events::{Event, StoppedEventBody};
2+
use dap::prelude::{Command, Request, ResponseBody};
3+
use dap::responses::{
4+
EvaluateResponse, ScopesResponse, SetBreakpointsResponse, StackTraceResponse, ThreadsResponse,
5+
VariablesResponse,
6+
};
7+
use dap::types::{Breakpoint, Capabilities, Source, StackFrame, StoppedEventReason, Thread};
8+
use tracing::trace;
9+
10+
use crate::connection::Connection;
11+
12+
pub struct CairoDebugger {
13+
connection: Connection,
14+
}
15+
16+
enum ServerResponse {
17+
Success(ResponseBody),
18+
Error(String),
19+
Event(Event),
20+
SuccessThenEvent(ResponseBody, Event),
21+
}
22+
23+
impl CairoDebugger {
24+
pub fn connect() -> anyhow::Result<Self> {
25+
let connection = Connection::new()?;
26+
Ok(Self { connection })
27+
}
28+
29+
pub fn run(&mut self) -> anyhow::Result<()> {
30+
while let Ok(req) = self.connection.next_request() {
31+
match handle_request(&req) {
32+
ServerResponse::Success(body) => self.connection.send_success(req, body)?,
33+
ServerResponse::Error(msg) => self.connection.send_error(req, &msg)?,
34+
ServerResponse::Event(event) => self.connection.send_event(event)?,
35+
ServerResponse::SuccessThenEvent(body, event) => {
36+
self.connection.send_success(req, body)?;
37+
self.connection.send_event(event)?;
38+
}
39+
}
40+
}
41+
42+
Ok(())
43+
}
44+
}
45+
46+
fn handle_request(request: &Request) -> ServerResponse {
47+
match &request.command {
48+
// We have not yet decided if we want to support these.
49+
Command::BreakpointLocations(_)
50+
| Command::Cancel(_)
51+
| Command::Completions(_)
52+
| Command::DataBreakpointInfo(_)
53+
| Command::Disassemble(_)
54+
| Command::Disconnect(_)
55+
| Command::Goto(_)
56+
| Command::ExceptionInfo(_)
57+
| Command::GotoTargets(_)
58+
| Command::LoadedSources
59+
| Command::Modules(_)
60+
| Command::ReadMemory(_)
61+
| Command::RestartFrame(_)
62+
| Command::SetDataBreakpoints(_)
63+
| Command::Restart(_)
64+
| Command::SetExceptionBreakpoints(_)
65+
| Command::TerminateThreads(_)
66+
| Command::Terminate(_)
67+
| Command::StepInTargets(_)
68+
| Command::SetVariable(_)
69+
| Command::SetInstructionBreakpoints(_)
70+
| Command::SetExpression(_)
71+
| Command::WriteMemory(_) => {
72+
// If we receive these with current capabilities, it is the client's fault.
73+
let msg = format!("Received an unsupported request: {request:?}");
74+
ServerResponse::Error(msg)
75+
}
76+
77+
// These may be supported after the MVP.
78+
// Nonetheless, if we receive these with current capabilities,
79+
// it is the client's fault.
80+
Command::ReverseContinue(_) => {
81+
ServerResponse::Error("Step back is not yet supported".into())
82+
}
83+
Command::StepBack(_) => ServerResponse::Error("Step back is not yet supported".into()),
84+
Command::SetFunctionBreakpoints(_) => {
85+
ServerResponse::Error("Set function breakpoints is not yet supported".into())
86+
}
87+
88+
// It makes no sense to send `attach` in the current architecture.
89+
Command::Attach(_) => ServerResponse::Error("Attach is not supported".into()),
90+
91+
// Supported requests.
92+
Command::Initialize(args) => {
93+
trace!("Initialized a client: {:?}", args.client_name);
94+
95+
ServerResponse::Success(ResponseBody::Initialize(Capabilities {
96+
supports_configuration_done_request: Some(true),
97+
..Default::default()
98+
}))
99+
}
100+
Command::ConfigurationDone => {
101+
trace!("Configuration done");
102+
ServerResponse::Success(ResponseBody::ConfigurationDone)
103+
}
104+
Command::Continue(_) => {
105+
todo!()
106+
}
107+
Command::Launch(_) => {
108+
// Start running the Cairo program here.
109+
ServerResponse::SuccessThenEvent(ResponseBody::Launch, Event::Initialized)
110+
}
111+
Command::Next(_) => {
112+
todo!()
113+
}
114+
Command::Pause(_) => ServerResponse::Event(Event::Stopped(StoppedEventBody {
115+
reason: StoppedEventReason::Pause,
116+
thread_id: Some(0),
117+
description: None,
118+
preserve_focus_hint: None,
119+
text: None,
120+
all_threads_stopped: Some(true),
121+
hit_breakpoint_ids: None,
122+
})),
123+
Command::SetBreakpoints(args) => {
124+
let mut response_bps = Vec::new();
125+
if let Some(requested_bps) = &args.breakpoints {
126+
for bp in requested_bps {
127+
// For now accept every breakpoint as valid
128+
response_bps.push(Breakpoint {
129+
verified: true,
130+
source: Some(args.source.clone()),
131+
line: Some(bp.line),
132+
..Default::default()
133+
});
134+
}
135+
}
136+
ServerResponse::Success(ResponseBody::SetBreakpoints(SetBreakpointsResponse {
137+
breakpoints: response_bps,
138+
}))
139+
}
140+
Command::Source(_) => {
141+
todo!()
142+
}
143+
Command::StackTrace(_) => {
144+
ServerResponse::Success(ResponseBody::StackTrace(StackTraceResponse {
145+
stack_frames: vec![StackFrame {
146+
id: 1,
147+
name: "test".to_string(),
148+
// Replace it with the actual source path.
149+
// Otherwise, the debugger will crush after returning this response.
150+
source: Some(Source { name: None, path: None, ..Default::default() }),
151+
line: 1,
152+
column: 1,
153+
..Default::default()
154+
}],
155+
total_frames: Some(1),
156+
}))
157+
}
158+
Command::StepIn(_) => {
159+
todo!()
160+
}
161+
Command::StepOut(_) => {
162+
todo!()
163+
}
164+
165+
Command::Evaluate(_) => {
166+
ServerResponse::Success(ResponseBody::Evaluate(EvaluateResponse {
167+
// Return whatever since we cannot opt out of supporting this request.
168+
result: "".to_string(),
169+
type_field: None,
170+
presentation_hint: None,
171+
variables_reference: 0,
172+
named_variables: None,
173+
indexed_variables: None,
174+
memory_reference: None,
175+
}))
176+
}
177+
Command::Threads => {
178+
ServerResponse::Success(ResponseBody::Threads(ThreadsResponse {
179+
// Return a single thread.
180+
threads: vec![Thread { id: 0, name: "".to_string() }],
181+
}))
182+
}
183+
Command::Variables(_) => {
184+
ServerResponse::Success(ResponseBody::Variables(VariablesResponse {
185+
// Return no variables.
186+
variables: vec![],
187+
}))
188+
}
189+
Command::Scopes(_) => {
190+
// Return no scopes.
191+
ServerResponse::Success(ResponseBody::Scopes(ScopesResponse { scopes: vec![] }))
192+
}
193+
}
194+
}

src/lib.rs

Lines changed: 2 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -1,197 +1,4 @@
1-
use anyhow::Result;
2-
use connection::Connection;
3-
use dap::events::{Event, StoppedEventBody};
4-
use dap::prelude::{Command, Request, ResponseBody};
5-
use dap::responses::{
6-
EvaluateResponse, ScopesResponse, SetBreakpointsResponse, StackTraceResponse, ThreadsResponse,
7-
VariablesResponse,
8-
};
9-
use dap::types::{Breakpoint, Capabilities, Source, StackFrame, StoppedEventReason, Thread};
10-
use tracing::trace;
11-
121
mod connection;
2+
mod debugger;
133

14-
// TODO: add vm, add handlers for requests.
15-
pub struct CairoDebugger {
16-
connection: Connection,
17-
}
18-
19-
enum ServerResponse {
20-
Success(ResponseBody),
21-
Error(String),
22-
Event(Event),
23-
SuccessThenEvent(ResponseBody, Event),
24-
}
25-
26-
impl CairoDebugger {
27-
pub fn connect() -> Result<Self> {
28-
let connection = Connection::new()?;
29-
Ok(Self { connection })
30-
}
31-
32-
pub fn run(&mut self) -> Result<()> {
33-
while let Ok(req) = self.connection.next_request() {
34-
match handle_request(&req) {
35-
ServerResponse::Success(body) => self.connection.send_success(req, body)?,
36-
ServerResponse::Error(msg) => self.connection.send_error(req, &msg)?,
37-
ServerResponse::Event(event) => self.connection.send_event(event)?,
38-
ServerResponse::SuccessThenEvent(body, event) => {
39-
self.connection.send_success(req, body)?;
40-
self.connection.send_event(event)?;
41-
}
42-
}
43-
}
44-
45-
Ok(())
46-
}
47-
}
48-
49-
fn handle_request(request: &Request) -> ServerResponse {
50-
match &request.command {
51-
// We have not yet decided if we want to support these.
52-
Command::BreakpointLocations(_)
53-
| Command::Cancel(_)
54-
| Command::Completions(_)
55-
| Command::DataBreakpointInfo(_)
56-
| Command::Disassemble(_)
57-
| Command::Disconnect(_)
58-
| Command::Goto(_)
59-
| Command::ExceptionInfo(_)
60-
| Command::GotoTargets(_)
61-
| Command::LoadedSources
62-
| Command::Modules(_)
63-
| Command::ReadMemory(_)
64-
| Command::RestartFrame(_)
65-
| Command::SetDataBreakpoints(_)
66-
| Command::Restart(_)
67-
| Command::SetExceptionBreakpoints(_)
68-
| Command::TerminateThreads(_)
69-
| Command::Terminate(_)
70-
| Command::StepInTargets(_)
71-
| Command::SetVariable(_)
72-
| Command::SetInstructionBreakpoints(_)
73-
| Command::SetExpression(_)
74-
| Command::WriteMemory(_) => {
75-
// If we receive these with current capabilities, it is the client's fault.
76-
let msg = format!("Received an unsupported request: {request:?}");
77-
ServerResponse::Error(msg)
78-
}
79-
80-
// These may be supported after the MVP.
81-
// Nonetheless, if we receive these with current capabilities,
82-
// it is the client's fault.
83-
Command::ReverseContinue(_) => {
84-
ServerResponse::Error("Step back is not yet supported".into())
85-
}
86-
Command::StepBack(_) => ServerResponse::Error("Step back is not yet supported".into()),
87-
Command::SetFunctionBreakpoints(_) => {
88-
ServerResponse::Error("Set function breakpoints is not yet supported".into())
89-
}
90-
91-
// It makes no sense to send `attach` in the current architecture.
92-
Command::Attach(_) => ServerResponse::Error("Attach is not supported".into()),
93-
94-
// Supported requests.
95-
Command::Initialize(args) => {
96-
trace!("Initialized a client: {:?}", args.client_name);
97-
98-
ServerResponse::Success(ResponseBody::Initialize(Capabilities {
99-
supports_configuration_done_request: Some(true),
100-
..Default::default()
101-
}))
102-
}
103-
Command::ConfigurationDone => {
104-
trace!("Configuration done");
105-
ServerResponse::Success(ResponseBody::ConfigurationDone)
106-
}
107-
Command::Continue(_) => {
108-
todo!()
109-
}
110-
Command::Launch(_) => {
111-
// Start running the Cairo program here.
112-
ServerResponse::SuccessThenEvent(ResponseBody::Launch, Event::Initialized)
113-
}
114-
Command::Next(_) => {
115-
todo!()
116-
}
117-
Command::Pause(_) => ServerResponse::Event(Event::Stopped(StoppedEventBody {
118-
reason: StoppedEventReason::Pause,
119-
thread_id: Some(0),
120-
description: None,
121-
preserve_focus_hint: None,
122-
text: None,
123-
all_threads_stopped: Some(true),
124-
hit_breakpoint_ids: None,
125-
})),
126-
Command::SetBreakpoints(args) => {
127-
let mut response_bps = Vec::new();
128-
if let Some(requested_bps) = &args.breakpoints {
129-
for bp in requested_bps {
130-
// For now accept every breakpoint as valid
131-
response_bps.push(Breakpoint {
132-
verified: true,
133-
source: Some(args.source.clone()),
134-
line: Some(bp.line),
135-
..Default::default()
136-
});
137-
}
138-
}
139-
ServerResponse::Success(ResponseBody::SetBreakpoints(SetBreakpointsResponse {
140-
breakpoints: response_bps,
141-
}))
142-
}
143-
Command::Source(_) => {
144-
todo!()
145-
}
146-
Command::StackTrace(_) => {
147-
ServerResponse::Success(ResponseBody::StackTrace(StackTraceResponse {
148-
stack_frames: vec![StackFrame {
149-
id: 1,
150-
name: "test".to_string(),
151-
// Replace it with the actual source path.
152-
// Otherwise, the debugger will crush after returning this response.
153-
source: Some(Source { name: None, path: None, ..Default::default() }),
154-
line: 1,
155-
column: 1,
156-
..Default::default()
157-
}],
158-
total_frames: Some(1),
159-
}))
160-
}
161-
Command::StepIn(_) => {
162-
todo!()
163-
}
164-
Command::StepOut(_) => {
165-
todo!()
166-
}
167-
168-
Command::Evaluate(_) => {
169-
ServerResponse::Success(ResponseBody::Evaluate(EvaluateResponse {
170-
// Return whatever since we cannot opt out of supporting this request.
171-
result: "".to_string(),
172-
type_field: None,
173-
presentation_hint: None,
174-
variables_reference: 0,
175-
named_variables: None,
176-
indexed_variables: None,
177-
memory_reference: None,
178-
}))
179-
}
180-
Command::Threads => {
181-
ServerResponse::Success(ResponseBody::Threads(ThreadsResponse {
182-
// Return a single thread.
183-
threads: vec![Thread { id: 0, name: "".to_string() }],
184-
}))
185-
}
186-
Command::Variables(_) => {
187-
ServerResponse::Success(ResponseBody::Variables(VariablesResponse {
188-
// Return no variables.
189-
variables: vec![],
190-
}))
191-
}
192-
Command::Scopes(_) => {
193-
// Return no scopes.
194-
ServerResponse::Success(ResponseBody::Scopes(ScopesResponse { scopes: vec![] }))
195-
}
196-
}
197-
}
4+
pub use debugger::CairoDebugger;

0 commit comments

Comments
 (0)