|
|
@ -18,6 +18,12 @@ pub fn dap_pos_to_pos(doc: &helix_core::Rope, line: usize, column: usize) -> Opt
|
|
|
|
Some(pos)
|
|
|
|
Some(pos)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn resume_application(debugger: &mut Client) {
|
|
|
|
|
|
|
|
debugger.is_running = true; // TODO: set state running for debugger.thread_id
|
|
|
|
|
|
|
|
debugger.active_frame = None;
|
|
|
|
|
|
|
|
debugger.thread_id = None;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub async fn select_thread_id(editor: &mut Editor, thread_id: usize, force: bool) {
|
|
|
|
pub async fn select_thread_id(editor: &mut Editor, thread_id: usize, force: bool) {
|
|
|
|
let debugger = match &mut editor.debugger {
|
|
|
|
let debugger = match &mut editor.debugger {
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
Some(debugger) => debugger,
|
|
|
@ -243,7 +249,11 @@ pub fn dap_toggle_breakpoint(cx: &mut Context) {
|
|
|
|
// TODO: need to map breakpoints over edits and update them?
|
|
|
|
// TODO: need to map breakpoints over edits and update them?
|
|
|
|
// we shouldn't really allow editing while debug is running though
|
|
|
|
// we shouldn't really allow editing while debug is running though
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
|
|
|
|
None => return,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let breakpoints = debugger.breakpoints.entry(path.clone()).or_default();
|
|
|
|
let breakpoints = debugger.breakpoints.entry(path.clone()).or_default();
|
|
|
|
if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
|
|
|
|
if let Some(pos) = breakpoints.iter().position(|b| b.line == breakpoint.line) {
|
|
|
|
breakpoints.remove(pos);
|
|
|
|
breakpoints.remove(pos);
|
|
|
@ -259,10 +269,13 @@ pub fn dap_toggle_breakpoint(cx: &mut Context) {
|
|
|
|
.set_error(format!("Failed to set breakpoints: {:?}", e));
|
|
|
|
.set_error(format!("Failed to set breakpoints: {:?}", e));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dap_run(cx: &mut Context) {
|
|
|
|
pub fn dap_run(cx: &mut Context) {
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
|
|
|
|
None => return,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if debugger.is_running {
|
|
|
|
if debugger.is_running {
|
|
|
|
cx.editor
|
|
|
|
cx.editor
|
|
|
|
.set_status("Debuggee is already running".to_owned());
|
|
|
|
.set_status("Debuggee is already running".to_owned());
|
|
|
@ -275,33 +288,33 @@ pub fn dap_run(cx: &mut Context) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
debugger.is_running = true;
|
|
|
|
debugger.is_running = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dap_continue(cx: &mut Context) {
|
|
|
|
pub fn dap_continue(cx: &mut Context) {
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
if debugger.is_running {
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
cx.editor
|
|
|
|
None => return,
|
|
|
|
.set_status("Debuggee is already running".to_owned());
|
|
|
|
};
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(thread_id) = debugger.thread_id {
|
|
|
|
if let Some(thread_id) = debugger.thread_id {
|
|
|
|
let request = debugger.continue_thread(debugger.thread_id.unwrap());
|
|
|
|
let request = debugger.continue_thread(thread_id);
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
cx.editor.set_error(format!("Failed to continue: {:?}", e));
|
|
|
|
cx.editor.set_error(format!("Failed to continue: {:?}", e));
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
debugger.is_running = true;
|
|
|
|
resume_application(debugger);
|
|
|
|
debugger.stack_frames.remove(&thread_id);
|
|
|
|
debugger.stack_frames.remove(&thread_id);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
cx.editor
|
|
|
|
cx.editor
|
|
|
|
.set_error("Currently active thread is not stopped. Switch the thread.".into());
|
|
|
|
.set_error("Currently active thread is not stopped. Switch the thread.".into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dap_pause(cx: &mut Context) {
|
|
|
|
pub fn dap_pause(cx: &mut Context) {
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
|
|
|
|
None => return,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if !debugger.is_running {
|
|
|
|
if !debugger.is_running {
|
|
|
|
cx.editor.set_status("Debuggee is not running".to_owned());
|
|
|
|
cx.editor.set_status("Debuggee is not running".to_owned());
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -313,55 +326,73 @@ pub fn dap_pause(cx: &mut Context) {
|
|
|
|
cx.editor.set_error(format!("Failed to pause: {:?}", e));
|
|
|
|
cx.editor.set_error(format!("Failed to pause: {:?}", e));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dap_step_in(cx: &mut Context) {
|
|
|
|
pub fn dap_step_in(cx: &mut Context) {
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
if debugger.is_running {
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
cx.editor
|
|
|
|
None => return,
|
|
|
|
.set_status("Debuggee is already running".to_owned());
|
|
|
|
};
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let request = debugger.step_in(debugger.thread_id.unwrap());
|
|
|
|
if let Some(thread_id) = debugger.thread_id {
|
|
|
|
|
|
|
|
let request = debugger.step_in(thread_id);
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
cx.editor.set_error(format!("Failed to step: {:?}", e));
|
|
|
|
cx.editor.set_error(format!("Failed to continue: {:?}", e));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
resume_application(debugger);
|
|
|
|
|
|
|
|
debugger.stack_frames.remove(&thread_id);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
cx.editor
|
|
|
|
|
|
|
|
.set_error("Currently active thread is not stopped. Switch the thread.".into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dap_step_out(cx: &mut Context) {
|
|
|
|
pub fn dap_step_out(cx: &mut Context) {
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
if debugger.is_running {
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
cx.editor
|
|
|
|
None => return,
|
|
|
|
.set_status("Debuggee is already running".to_owned());
|
|
|
|
};
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let request = debugger.step_out(debugger.thread_id.unwrap());
|
|
|
|
if let Some(thread_id) = debugger.thread_id {
|
|
|
|
|
|
|
|
let request = debugger.step_out(thread_id);
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
cx.editor.set_error(format!("Failed to step: {:?}", e));
|
|
|
|
cx.editor.set_error(format!("Failed to continue: {:?}", e));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
resume_application(debugger);
|
|
|
|
|
|
|
|
debugger.stack_frames.remove(&thread_id);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
cx.editor
|
|
|
|
|
|
|
|
.set_error("Currently active thread is not stopped. Switch the thread.".into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dap_next(cx: &mut Context) {
|
|
|
|
pub fn dap_next(cx: &mut Context) {
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
if debugger.is_running {
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
cx.editor
|
|
|
|
None => return,
|
|
|
|
.set_status("Debuggee is already running".to_owned());
|
|
|
|
};
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let request = debugger.next(debugger.thread_id.unwrap());
|
|
|
|
if let Some(thread_id) = debugger.thread_id {
|
|
|
|
|
|
|
|
let request = debugger.next(thread_id);
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
cx.editor.set_error(format!("Failed to step: {:?}", e));
|
|
|
|
cx.editor.set_error(format!("Failed to continue: {:?}", e));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
resume_application(debugger);
|
|
|
|
|
|
|
|
debugger.stack_frames.remove(&thread_id);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
cx.editor
|
|
|
|
|
|
|
|
.set_error("Currently active thread is not stopped. Switch the thread.".into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dap_variables(cx: &mut Context) {
|
|
|
|
pub fn dap_variables(cx: &mut Context) {
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
|
|
|
|
None => return,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if debugger.is_running {
|
|
|
|
if debugger.is_running {
|
|
|
|
cx.editor
|
|
|
|
cx.editor
|
|
|
|
.set_status("Cannot access variables while target is running".to_owned());
|
|
|
|
.set_status("Cannot access variables while target is running".to_owned());
|
|
|
@ -391,6 +422,7 @@ pub fn dap_variables(cx: &mut Context) {
|
|
|
|
let response = block_on(debugger.variables(scope.variables_reference));
|
|
|
|
let response = block_on(debugger.variables(scope.variables_reference));
|
|
|
|
|
|
|
|
|
|
|
|
if let Ok(vars) = response {
|
|
|
|
if let Ok(vars) = response {
|
|
|
|
|
|
|
|
variables.reserve(vars.len());
|
|
|
|
for var in vars {
|
|
|
|
for var in vars {
|
|
|
|
let prefix = match var.data_type {
|
|
|
|
let prefix = match var.data_type {
|
|
|
|
Some(data_type) => format!("{} ", data_type),
|
|
|
|
Some(data_type) => format!("{} ", data_type),
|
|
|
@ -406,10 +438,13 @@ pub fn dap_variables(cx: &mut Context) {
|
|
|
|
cx.editor.variables_page = 0;
|
|
|
|
cx.editor.variables_page = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dap_terminate(cx: &mut Context) {
|
|
|
|
pub fn dap_terminate(cx: &mut Context) {
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
|
|
|
|
None => return,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let request = debugger.disconnect();
|
|
|
|
let request = debugger.disconnect();
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
if let Err(e) = block_on(request) {
|
|
|
|
cx.editor
|
|
|
|
cx.editor
|
|
|
@ -418,10 +453,13 @@ pub fn dap_terminate(cx: &mut Context) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cx.editor.debugger = None;
|
|
|
|
cx.editor.debugger = None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dap_switch_thread(cx: &mut Context) {
|
|
|
|
pub fn dap_switch_thread(cx: &mut Context) {
|
|
|
|
if let Some(debugger) = &mut cx.editor.debugger {
|
|
|
|
let debugger = match &mut cx.editor.debugger {
|
|
|
|
|
|
|
|
Some(debugger) => debugger,
|
|
|
|
|
|
|
|
None => return,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let request = debugger.threads();
|
|
|
|
let request = debugger.threads();
|
|
|
|
let threads = match block_on(request) {
|
|
|
|
let threads = match block_on(request) {
|
|
|
|
Ok(threads) => threads,
|
|
|
|
Ok(threads) => threads,
|
|
|
@ -442,4 +480,3 @@ pub fn dap_switch_thread(cx: &mut Context) {
|
|
|
|
);
|
|
|
|
);
|
|
|
|
cx.push_layer(Box::new(picker))
|
|
|
|
cx.push_layer(Box::new(picker))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|