diff --git a/crates/debugger_ui/src/session/running/variable_list.rs b/crates/debugger_ui/src/session/running/variable_list.rs index 6e8315c7f5..a3f09d16e2 100644 --- a/crates/debugger_ui/src/session/running/variable_list.rs +++ b/crates/debugger_ui/src/session/running/variable_list.rs @@ -889,13 +889,30 @@ impl VariableList { return; }; - let variable_value = match &entry.entry { - DapEntry::Variable(dap) => dap.value.clone(), - DapEntry::Watcher(watcher) => watcher.value.to_string(), + match &entry.entry { + DapEntry::Variable(dap) => { + let fallback_value = dap.value.clone(); + let expression = dap + .evaluate_name + .clone() + .unwrap_or_else(|| dap.name.clone()); + let frame_id = self.selected_stack_frame_id; + let task = self.session.update(cx, |session, cx| { + session.evaluate_variable_value(expression, frame_id, cx) + }); + cx.spawn(async move |_, cx| { + let value = task.await.unwrap_or(fallback_value); + cx.update(|cx| { + cx.write_to_clipboard(ClipboardItem::new_string(value)); + }); + }) + .detach(); + } + DapEntry::Watcher(watcher) => { + cx.write_to_clipboard(ClipboardItem::new_string(watcher.value.to_string())); + } DapEntry::Scope(_) => return, - }; - - cx.write_to_clipboard(ClipboardItem::new_string(variable_value)); + } } fn edit_variable(&mut self, _: &EditVariable, window: &mut Window, cx: &mut Context) { diff --git a/crates/debugger_ui/src/tests/variable_list.rs b/crates/debugger_ui/src/tests/variable_list.rs index 5b88637306..9d5062a445 100644 --- a/crates/debugger_ui/src/tests/variable_list.rs +++ b/crates/debugger_ui/src/tests/variable_list.rs @@ -2592,3 +2592,58 @@ async fn test_refresh_watchers(executor: BackgroundExecutor, cx: &mut TestAppCon assert_eq!(3, watcher.variables_reference); }); } + +#[gpui::test] +async fn test_evaluate_variable_value_uses_clipboard_context( + executor: BackgroundExecutor, + cx: &mut TestAppContext, +) { + init_test(cx); + + let fs = FakeFs::new(executor.clone()); + fs.insert_tree( + path!("/project"), + json!({ + "index.js": "const debug = { foo: 1 };", + }), + ) + .await; + + let project = Project::test(fs, [path!("/project").as_ref()], cx).await; + let workspace = init_test_workspace(&project, cx).await; + let cx = &mut VisualTestContext::from_window(*workspace, cx); + let session = start_debug_session(&workspace, cx, |client| { + client.on_request::(move |_, _| { + Ok(dap::Capabilities { + supports_clipboard_context: Some(true), + ..Default::default() + }) + }); + }) + .unwrap(); + + let client = session.update(cx, |session, _| session.adapter_client().unwrap()); + client.on_request::(move |_, args| { + assert_eq!("debug", args.expression); + assert_eq!(Some(dap::EvaluateArgumentsContext::Clipboard), args.context); + + Ok(dap::EvaluateResponse { + result: "full value".to_string(), + type_: None, + presentation_hint: None, + variables_reference: 0, + named_variables: None, + indexed_variables: None, + memory_reference: None, + value_location_reference: None, + }) + }); + + let value = session + .update(cx, |session, cx| { + session.evaluate_variable_value("debug".to_string(), Some(1), cx) + }) + .await; + + assert_eq!(Some("full value".to_string()), value); +} diff --git a/crates/project/src/debugger/session.rs b/crates/project/src/debugger/session.rs index 6aa115d607..90b3c61046 100644 --- a/crates/project/src/debugger/session.rs +++ b/crates/project/src/debugger/session.rs @@ -2863,6 +2863,38 @@ impl Session { }) } + /// Evaluates an expression to obtain its full value for copying. + pub fn evaluate_variable_value( + &mut self, + expression: String, + frame_id: Option, + cx: &mut Context, + ) -> Task> { + let context = if self + .capabilities + .supports_clipboard_context + .unwrap_or_default() + { + EvaluateArgumentsContext::Clipboard + } else { + EvaluateArgumentsContext::Variables + }; + let request = self.request( + EvaluateCommand { + expression, + frame_id, + context: Some(context), + source: None, + }, + |_, response, _| response.ok(), + cx, + ); + cx.background_spawn(async move { + let response = request.await?; + Some(response.result) + }) + } + pub fn location( &mut self, reference: u64,