Skip to content

Commit c15704f

Browse files
committed
Inject debug environment in search path completions
1 parent 6a433c2 commit c15704f

File tree

3 files changed

+36
-9
lines changed

3 files changed

+36
-9
lines changed

crates/ark/src/interface.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,11 @@ pub struct RMain {
255255
/// The stack of frames we saw the last time we stopped. Used as a mostly
256256
/// reliable indication of whether we moved since last time.
257257
debug_last_stack: Vec<FrameInfoId>,
258+
259+
/// Current topmost environment on the stack while waiting for input in the
260+
/// debugger. This is `Some()` only when R is idle and in a `browser()`
261+
/// prompt.
262+
pub(crate) debug_env: Option<RObject>,
258263
}
259264

260265
/// Represents the currently active execution request from the frontend. It
@@ -588,6 +593,7 @@ impl RMain {
588593
captured_output: String::new(),
589594
debug_preserve_focus: false,
590595
debug_last_stack: vec![],
596+
debug_env: None,
591597
}
592598
}
593599

@@ -774,6 +780,13 @@ impl RMain {
774780
if info.browser {
775781
match self.dap.stack_info() {
776782
Ok(stack) => {
783+
if let Some(frame) = stack.first() {
784+
if let Some(ref env) = frame.environment {
785+
// This is reset on exit in the cleanup phase, see `r_read_console()`
786+
self.debug_env = Some(env.get().clone());
787+
}
788+
}
789+
777790
// Figure out whether we changed location since last time,
778791
// e.g. because the user evaluated an expression that hit
779792
// another breakpoint. In that case we do want to move
@@ -961,6 +974,11 @@ impl RMain {
961974
};
962975
}
963976

977+
fn read_console_cleanup(&mut self) {
978+
// The debug environment is only valid while R is idle
979+
self.debug_env = None;
980+
}
981+
964982
/// Returns:
965983
/// - `None` if we should fall through to the event loop to wait for more user input
966984
/// - `Some(ConsoleResult)` if we should immediately exit `read_console()`
@@ -2124,6 +2142,7 @@ pub extern "C-unwind" fn r_read_console(
21242142
) -> i32 {
21252143
let main = RMain::get_mut();
21262144
let result = r_sandbox(|| main.read_console(prompt, buf, buflen, hist));
2145+
main.read_console_cleanup();
21272146

21282147
let result = unwrap!(result, Err(err) => {
21292148
panic!("Unexpected longjump while reading console: {err:?}");

crates/ark/src/lsp/completions/sources/composite/search_path.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use libr::R_lsInternal;
1818
use libr::ENCLOS;
1919
use tower_lsp::lsp_types::CompletionItem;
2020

21+
use crate::interface::RMain;
2122
use crate::lsp::completions::completion_context::CompletionContext;
2223
use crate::lsp::completions::completion_item::completion_item_from_package;
2324
use crate::lsp::completions::completion_item::completion_item_from_symbol;
@@ -58,14 +59,21 @@ fn completions_from_search_path(
5859

5960
unsafe {
6061
// Iterate through environments starting from the global environment.
61-
let mut envir = R_GlobalEnv;
62+
let mut env = R_GlobalEnv;
6263

63-
while envir != R_EmptyEnv {
64-
let is_pkg_env = r_env_is_pkg_env(envir);
64+
// If we're waiting for input in `read_console()` with a debugger
65+
// prompt, start from current environment
66+
if let Some(debug_env) = &RMain::get().debug_env {
67+
// Mem-Safety: Object protected by `RMain` for the duration of the `r_task()`
68+
env = debug_env.sexp;
69+
}
70+
71+
while env != R_EmptyEnv {
72+
let is_pkg_env = r_env_is_pkg_env(env);
6573

6674
// Get package environment name, if there is one
6775
let name = if is_pkg_env {
68-
let name = RObject::from(r_pkg_env_name(envir));
76+
let name = RObject::from(r_pkg_env_name(env));
6977
let name = String::try_from(name)?;
7078
Some(name)
7179
} else {
@@ -84,7 +92,7 @@ fn completions_from_search_path(
8492
};
8593

8694
// List symbols in the environment.
87-
let symbols = R_lsInternal(envir, 1);
95+
let symbols = R_lsInternal(env, 1);
8896

8997
// Create completion items for each.
9098
let vector = CharacterVector::new(symbols)?;
@@ -103,9 +111,9 @@ fn completions_from_search_path(
103111
// Add the completion item.
104112
match completion_item_from_symbol(
105113
symbol,
106-
envir,
114+
env,
107115
name,
108-
promise_strategy.clone(),
116+
promise_strategy,
109117
parameter_hints,
110118
) {
111119
Ok(item) => completions.push(item),
@@ -118,7 +126,7 @@ fn completions_from_search_path(
118126
}
119127

120128
// Get the next environment.
121-
envir = ENCLOS(envir);
129+
env = ENCLOS(env);
122130
}
123131

124132
// Include installed packages as well.

crates/ark/src/lsp/completions/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub(super) enum CompletionData {
5454
Unknown,
5555
}
5656

57-
#[derive(Clone, Debug, PartialEq)]
57+
#[derive(Copy, Clone, Debug, PartialEq)]
5858
pub(crate) enum PromiseStrategy {
5959
Simple,
6060
Force,

0 commit comments

Comments
 (0)