Skip to content

Commit

Permalink
Cider changes (#1798)
Browse files Browse the repository at this point in the history
* Added Disconnect Command

* Added create threads and started two dummy threads, added pause command

* Implemented StackTrace, Continue, Next, StepIn and StepOut

* Corrected Disconnect, minor changes

* PR revisions

---------

Co-authored-by: root <root@EliasSP>
  • Loading branch information
eliascxstro and root authored Dec 5, 2023
1 parent 75302d5 commit 7550493
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 12 deletions.
12 changes: 12 additions & 0 deletions cider-dap/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub struct MyAdapter {
file: File,
breakpoints: Vec<(Source, i64)>, //This field is a placeholder
break_count: Counter,
thread_count: Counter,
threads: Vec<Thread>, //This field is a placeholder
}

Expand All @@ -14,6 +15,7 @@ impl MyAdapter {
file,
breakpoints: Vec::new(),
break_count: Counter::new(),
thread_count: Counter::new(),
threads: Vec::new(),
}
}
Expand Down Expand Up @@ -43,6 +45,16 @@ impl MyAdapter {
out_vec
}

///Creates a thread using the parameter name.
pub fn create_thread(&mut self, name: String) -> Thread {
let thread = Thread {
id: self.thread_count.increment(),
name,
};
self.threads.push(thread.clone());
thread
}

/// Clone threads
pub fn clone_threads(&self) -> Vec<Thread> {
self.threads.clone()
Expand Down
9 changes: 8 additions & 1 deletion cider-dap/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use dap::errors::ServerError;
use dap::requests::Command;

#[allow(dead_code)] // remove this later
#[derive(thiserror::Error, Debug)]
#[derive(thiserror::Error)]
pub enum MyAdapterError {
/// Represents an unhandled command error.
#[error("Unhandled command: {0:?}")]
Expand Down Expand Up @@ -37,5 +37,12 @@ pub enum MyAdapterError {
ServerError(#[from] ServerError),
}

// Needed to properly display messages in output
impl std::fmt::Debug for MyAdapterError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self, f)
}
}

/// A type alias for the result returned by the adapter functions.
pub type AdapterResult<T> = Result<T, MyAdapterError>;
124 changes: 113 additions & 11 deletions cider-dap/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ mod adapter;
mod error;

use adapter::MyAdapter;
use dap::events::{ExitedEventBody, StoppedEventBody, ThreadEventBody};
use dap::responses::{
SetBreakpointsResponse, SetExceptionBreakpointsResponse, ThreadsResponse,
ContinueResponse, SetBreakpointsResponse, SetExceptionBreakpointsResponse,
StackTraceResponse, ThreadsResponse,
};
use error::MyAdapterError;

Expand Down Expand Up @@ -119,7 +121,23 @@ where
let file = File::open(program_path)?;

// Construct the adapter
let adapter = MyAdapter::new(file);
let mut adapter = MyAdapter::new(file);

//Make two threads to make threads visible on call stack, subject to change.
let thread = &adapter.create_thread(String::from("Main"));
let thread2 = &adapter.create_thread(String::from("Thread 1"));

// Notify server of first thread
server.send_event(Event::Thread(ThreadEventBody {
reason: types::ThreadEventReason::Started,
thread_id: thread.id,
}))?;

//Notify server of second thread
server.send_event(Event::Thread(ThreadEventBody {
reason: types::ThreadEventReason::Started,
thread_id: thread2.id,
}))?;

// Return the adapter instead of running the server
Ok(adapter)
Expand All @@ -142,20 +160,20 @@ fn run_server<R: Read, W: Write>(
}

Command::SetBreakpoints(args) => {
//Add breakpoints
// Add breakpoints
if let Some(breakpoint) = &args.breakpoints {
let out =
adapter.set_breakpoint(args.source.clone(), breakpoint);

//Success
// Success
let rsp = req.success(ResponseBody::SetBreakpoints(
SetBreakpointsResponse { breakpoints: (out) },
));
server.respond(rsp)?;
}
}

//TODO: Implement this request fully when adapter becomes functional
// TODO: Implement this request fully when adapter becomes functional
Command::SetExceptionBreakpoints(_) => {
let rsp = req.success(ResponseBody::SetExceptionBreakpoints(
SetExceptionBreakpointsResponse {
Expand All @@ -164,18 +182,89 @@ fn run_server<R: Read, W: Write>(
));
server.respond(rsp)?;
}

//Retrieve a list of all threads
// Retrieve a list of all threads
Command::Threads => {
let rsp = req.success(ResponseBody::Threads(ThreadsResponse {
threads: adapter.clone_threads(),
}));
server.respond(rsp)?;
}
// Here, can add a match pattern for a disconnect or exit command
// to break out of the loop and close the server.
// Command::Disconnect(_) => break,
// ...
// Disconnect the server AND exit the debugger
Command::Disconnect(_) => {
let rsp = req.success(ResponseBody::Disconnect);
server.send_event(Event::Exited(ExitedEventBody {
exit_code: 0,
}))?;
server.respond(rsp)?;

//Exit
eprintln!("exited debugger");
return Ok(());
}
// Send StackTrace, may be useful to make it more robust in the future
Command::StackTrace(_args) => {
let rsp =
req.success(ResponseBody::StackTrace(StackTraceResponse {
stack_frames: vec![],
total_frames: None,
}));
server.respond(rsp)?;
}
// Continue the debugger
Command::Continue(_args) => {
let rsp =
req.success(ResponseBody::Continue(ContinueResponse {
all_threads_continued: None,
}));
server.respond(rsp)?;
}
// Send a Stopped event with reason Pause
Command::Pause(args) => {
// Get ID before rsp takes ownership
let thread_id = args.thread_id;
let rsp = req.success(ResponseBody::Pause);
// Send response first
server.respond(rsp)?;
// Send event
let stopped = create_stopped(String::from("Paused"), thread_id);
server.send_event(stopped)?;
}
// Step over
Command::Next(args) => {
// Get ID before rsp takes ownership
let thread_id = args.thread_id;
let rsp = req.success(ResponseBody::Next);
// Send response first
server.respond(rsp)?;
// Send event
let stopped =
create_stopped(String::from("Continue"), thread_id);
server.send_event(stopped)?;
}
// Step in
Command::StepIn(args) => {
// Get ID before rsp takes ownership
let thread_id = args.thread_id;
// Send response first
let rsp = req.success(ResponseBody::StepIn);
server.respond(rsp)?;
// Send event
let stopped =
create_stopped(String::from("Paused on step"), thread_id);
server.send_event(stopped)?;
}
// Step out
Command::StepOut(args) => {
// Get ID before rsp takes ownership
let thread_id = args.thread_id;
// Send response first
let rsp = req.success(ResponseBody::StepOut);
server.respond(rsp)?;
// Send event
let stopped =
create_stopped(String::from("Paused on step"), thread_id);
server.send_event(stopped)?;
}
unknown_command => {
return Err(MyAdapterError::UnhandledCommandError(
unknown_command.clone(),
Expand All @@ -184,3 +273,16 @@ fn run_server<R: Read, W: Write>(
}
}
}

/// Helper function used to create a Stopped event
fn create_stopped(reason: String, thread_id: i64) -> Event {
Event::Stopped(StoppedEventBody {
reason: types::StoppedEventReason::Step,
description: Some(reason),
thread_id: Some(thread_id),
preserve_focus_hint: None,
text: None,
all_threads_stopped: None,
hit_breakpoint_ids: None,
})
}

0 comments on commit 7550493

Please sign in to comment.