1use crate::{
2 tests::{active_debug_session_panel, start_debug_session},
3 *,
4};
5use dap::requests::StackTrace;
6use editor::{DisplayPoint, display_map::DisplayRow};
7use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
8use project::{FakeFs, Project};
9use serde_json::json;
10use tests::{init_test, init_test_workspace};
11use util::path;
12
13#[gpui::test]
14async fn test_handle_output_event(executor: BackgroundExecutor, cx: &mut TestAppContext) {
15 init_test(cx);
16
17 let fs = FakeFs::new(executor.clone());
18
19 fs.insert_tree(
20 path!("/project"),
21 json!({
22 "main.rs": "First line\nSecond line\nThird line\nFourth line",
23 }),
24 )
25 .await;
26
27 let project = Project::test(fs, [path!("/project").as_ref()], cx).await;
28 let workspace = init_test_workspace(&project, cx).await;
29 let cx = &mut VisualTestContext::from_window(*workspace, cx);
30 workspace
31 .update(cx, |workspace, window, cx| {
32 workspace.focus_panel::<DebugPanel>(window, cx);
33 })
34 .unwrap();
35
36 let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
37 let client = session.read_with(cx, |session, _| session.adapter_client().unwrap());
38
39 client.on_request::<StackTrace, _>(move |_, _| {
40 Ok(dap::StackTraceResponse {
41 stack_frames: Vec::default(),
42 total_frames: None,
43 })
44 });
45
46 client
47 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
48 category: None,
49 output: "First console output line before thread stopped!".to_string(),
50 data: None,
51 variables_reference: None,
52 source: None,
53 line: None,
54 column: None,
55 group: None,
56 location_reference: None,
57 }))
58 .await;
59
60 client
61 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
62 category: Some(dap::OutputEventCategory::Stdout),
63 output: "First output line before thread stopped!".to_string(),
64 data: None,
65 variables_reference: None,
66 source: None,
67 line: None,
68 column: None,
69 group: None,
70 location_reference: None,
71 }))
72 .await;
73
74 client
75 .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
76 reason: dap::StoppedEventReason::Pause,
77 description: None,
78 thread_id: Some(1),
79 preserve_focus_hint: None,
80 text: None,
81 all_threads_stopped: None,
82 hit_breakpoint_ids: None,
83 }))
84 .await;
85
86 cx.run_until_parked();
87
88 let running_state =
89 active_debug_session_panel(workspace, cx).update_in(cx, |item, window, cx| {
90 cx.focus_self(window);
91 item.running_state().clone()
92 });
93
94 cx.run_until_parked();
95
96 // assert we have output from before the thread stopped
97 workspace
98 .update(cx, |workspace, _window, cx| {
99 let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
100 let active_debug_session_panel = debug_panel
101 .update(cx, |this, _| this.active_session())
102 .unwrap();
103
104 assert_eq!(
105 "First console output line before thread stopped!\nFirst output line before thread stopped!\n",
106 active_debug_session_panel.read(cx).running_state().read(cx).console().read(cx).editor().read(cx).text(cx).as_str()
107 );
108 })
109 .unwrap();
110
111 client
112 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
113 category: Some(dap::OutputEventCategory::Stdout),
114 output: "\tSecond output line after thread stopped!".to_string(),
115 data: None,
116 variables_reference: None,
117 source: None,
118 line: None,
119 column: None,
120 group: None,
121 location_reference: None,
122 }))
123 .await;
124
125 client
126 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
127 category: Some(dap::OutputEventCategory::Console),
128 output: "\tSecond console output line after thread stopped!".to_string(),
129 data: None,
130 variables_reference: None,
131 source: None,
132 line: None,
133 column: None,
134 group: None,
135 location_reference: None,
136 }))
137 .await;
138
139 cx.run_until_parked();
140 running_state.update(cx, |_, cx| {
141 cx.refresh_windows();
142 });
143 cx.run_until_parked();
144
145 // assert we have output from before and after the thread stopped
146 workspace
147 .update(cx, |workspace, _window, cx| {
148 let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
149 let active_session_panel = debug_panel
150 .update(cx, |this, _| this.active_session())
151 .unwrap();
152
153 assert_eq!(
154 "First console output line before thread stopped!\nFirst output line before thread stopped!\n\tSecond output line after thread stopped!\n\tSecond console output line after thread stopped!\n",
155 active_session_panel.read(cx).running_state().read(cx).console().read(cx).editor().read(cx).text(cx).as_str()
156 );
157 })
158 .unwrap();
159}
160
161#[gpui::test]
162async fn test_escape_code_processing(executor: BackgroundExecutor, cx: &mut TestAppContext) {
163 init_test(cx);
164
165 let fs = FakeFs::new(executor.clone());
166
167 fs.insert_tree(
168 path!("/project"),
169 json!({
170 "main.rs": "First line\nSecond line\nThird line\nFourth line",
171 }),
172 )
173 .await;
174
175 let project = Project::test(fs, [path!("/project").as_ref()], cx).await;
176 let workspace = init_test_workspace(&project, cx).await;
177 let cx = &mut VisualTestContext::from_window(*workspace, cx);
178 workspace
179 .update(cx, |workspace, window, cx| {
180 workspace.focus_panel::<DebugPanel>(window, cx);
181 })
182 .unwrap();
183
184 let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
185 let client = session.read_with(cx, |session, _| session.adapter_client().unwrap());
186
187 client.on_request::<StackTrace, _>(move |_, _| {
188 Ok(dap::StackTraceResponse {
189 stack_frames: Vec::default(),
190 total_frames: None,
191 })
192 });
193
194 client
195 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
196 category: None,
197 output: "Checking latest version of JavaScript...".to_string(),
198 data: None,
199 variables_reference: None,
200 source: None,
201 line: None,
202 column: None,
203 group: None,
204 location_reference: None,
205 }))
206 .await;
207 client
208 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
209 category: None,
210 output: " \u{1b}[1m\u{1b}[38;2;173;127;168m▲ Next.js 15.1.5\u{1b}[39m\u{1b}[22m"
211 .to_string(),
212 data: None,
213 variables_reference: None,
214 source: None,
215 line: None,
216 column: None,
217 group: None,
218 location_reference: None,
219 }))
220 .await;
221 client
222 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
223 category: None,
224 output: " - Local: http://localhost:3000\n - Network: http://192.168.1.144:3000\n\n \u{1b}[32m\u{1b}[1m✓\u{1b}[22m\u{1b}[39m Starting..."
225 .to_string(),
226 data: None,
227 variables_reference: None,
228 source: None,
229 line: None,
230 column: None,
231 group: None,
232 location_reference: None,
233 }))
234 .await;
235 client
236 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
237 category: None,
238 output: "Something else...".to_string(),
239 data: None,
240 variables_reference: None,
241 source: None,
242 line: None,
243 column: None,
244 group: None,
245 location_reference: None,
246 }))
247 .await;
248 client
249 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
250 category: None,
251 output: " \u{1b}[32m\u{1b}[1m✓\u{1b}[22m\u{1b}[39m Ready in 1009ms\n".to_string(),
252 data: None,
253 variables_reference: None,
254 source: None,
255 line: None,
256 column: None,
257 group: None,
258 location_reference: None,
259 }))
260 .await;
261
262 client
263 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
264 category: None,
265 output: "\u{1b}[41m\u{1b}[37mBoth background and foreground!".to_string(),
266 data: None,
267 variables_reference: None,
268 source: None,
269 line: None,
270 column: None,
271 group: None,
272 location_reference: None,
273 }))
274 .await;
275 client
276 .fake_event(dap::messages::Events::Output(dap::OutputEvent {
277 category: None,
278 output: "Even more...".to_string(),
279 data: None,
280 variables_reference: None,
281 source: None,
282 line: None,
283 column: None,
284 group: None,
285 location_reference: None,
286 }))
287 .await;
288
289 cx.run_until_parked();
290
291 let _running_state =
292 active_debug_session_panel(workspace, cx).update_in(cx, |item, window, cx| {
293 cx.focus_self(window);
294 item.running_state().update(cx, |this, cx| {
295 this.console()
296 .update(cx, |this, cx| this.update_output(window, cx));
297 });
298
299 item.running_state().clone()
300 });
301
302 cx.run_until_parked();
303
304 workspace
305 .update(cx, |workspace, window, cx| {
306 let debug_panel = workspace.panel::<DebugPanel>(cx).unwrap();
307 let active_debug_session_panel = debug_panel
308 .update(cx, |this, _| this.active_session())
309 .unwrap();
310
311 let editor =
312 active_debug_session_panel
313 .read(cx)
314 .running_state()
315 .read(cx)
316 .console()
317 .read(cx)
318 .editor().clone();
319
320 assert_eq!(
321 "Checking latest version of JavaScript...\n ▲ Next.js 15.1.5\n - Local: http://localhost:3000\n - Network: http://192.168.1.144:3000\n\n ✓ Starting...\nSomething else...\n ✓ Ready in 1009ms\nBoth background and foreground!\nEven more...\n",
322 editor
323 .read(cx)
324 .text(cx)
325 .as_str()
326 );
327
328 let text_highlights = editor.update(cx, |editor, cx| {
329 let mut text_highlights = editor.all_text_highlights(window, cx).into_iter().flat_map(|(_, ranges)| ranges).collect::<Vec<_>>();
330 text_highlights.sort_by(|a, b| a.start.cmp(&b.start));
331 text_highlights
332 });
333 pretty_assertions::assert_eq!(
334 text_highlights,
335 [
336 DisplayPoint::new(DisplayRow(1), 3)..DisplayPoint::new(DisplayRow(1), 21),
337 DisplayPoint::new(DisplayRow(1), 21)..DisplayPoint::new(DisplayRow(2), 0),
338 DisplayPoint::new(DisplayRow(5), 1)..DisplayPoint::new(DisplayRow(5), 4),
339 DisplayPoint::new(DisplayRow(5), 4)..DisplayPoint::new(DisplayRow(6), 0),
340 DisplayPoint::new(DisplayRow(7), 1)..DisplayPoint::new(DisplayRow(7), 4),
341 DisplayPoint::new(DisplayRow(7), 4)..DisplayPoint::new(DisplayRow(8), 0),
342 DisplayPoint::new(DisplayRow(8), 0)..DisplayPoint::new(DisplayRow(9), 0),
343 ]
344 );
345
346 let background_highlights = editor.update(cx, |editor, cx| {
347 editor.all_text_background_highlights(window, cx).into_iter().map(|(range, _)| range).collect::<Vec<_>>()
348 });
349 pretty_assertions::assert_eq!(
350 background_highlights,
351 [
352 DisplayPoint::new(DisplayRow(8), 0)..DisplayPoint::new(DisplayRow(9), 0),
353 ]
354 )
355 })
356 .unwrap();
357}
358
359// #[gpui::test]
360// async fn test_grouped_output(executor: BackgroundExecutor, cx: &mut TestAppContext) {
361// init_test(cx);
362
363// let fs = FakeFs::new(executor.clone());
364
365// fs.insert_tree(
366// "/project",
367// json!({
368// "main.rs": "First line\nSecond line\nThird line\nFourth line",
369// }),
370// )
371// .await;
372
373// let project = Project::test(fs, ["/project".as_ref()], cx).await;
374// let workspace = init_test_workspace(&project, cx).await;
375// let cx = &mut VisualTestContext::from_window(*workspace, cx);
376
377// let task = project.update(cx, |project, cx| {
378// project.start_debug_session(
379// dap::test_config(dap::DebugRequestType::Launch, None, None),
380// cx,
381// )
382// });
383
384// let session = task.await.unwrap();
385// let client = session.update(cx, |session, _| session.adapter_client().unwrap());
386
387// client
388// .on_request::<StackTrace, _>(move |_, _| {
389// Ok(dap::StackTraceResponse {
390// stack_frames: Vec::default(),
391// total_frames: None,
392// })
393// })
394// .await;
395
396// client
397// .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
398// reason: dap::StoppedEventReason::Pause,
399// description: None,
400// thread_id: Some(1),
401// preserve_focus_hint: None,
402// text: None,
403// all_threads_stopped: None,
404// hit_breakpoint_ids: None,
405// }))
406// .await;
407
408// client
409// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
410// category: None,
411// output: "First line".to_string(),
412// data: None,
413// variables_reference: None,
414// source: None,
415// line: None,
416// column: None,
417// group: None,
418// location_reference: None,
419// }))
420// .await;
421
422// client
423// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
424// category: Some(dap::OutputEventCategory::Stdout),
425// output: "First group".to_string(),
426// data: None,
427// variables_reference: None,
428// source: None,
429// line: None,
430// column: None,
431// group: Some(dap::OutputEventGroup::Start),
432// location_reference: None,
433// }))
434// .await;
435
436// client
437// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
438// category: Some(dap::OutputEventCategory::Stdout),
439// output: "First item in group 1".to_string(),
440// data: None,
441// variables_reference: None,
442// source: None,
443// line: None,
444// column: None,
445// group: None,
446// location_reference: None,
447// }))
448// .await;
449
450// client
451// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
452// category: Some(dap::OutputEventCategory::Stdout),
453// output: "Second item in group 1".to_string(),
454// data: None,
455// variables_reference: None,
456// source: None,
457// line: None,
458// column: None,
459// group: None,
460// location_reference: None,
461// }))
462// .await;
463
464// client
465// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
466// category: Some(dap::OutputEventCategory::Stdout),
467// output: "Second group".to_string(),
468// data: None,
469// variables_reference: None,
470// source: None,
471// line: None,
472// column: None,
473// group: Some(dap::OutputEventGroup::Start),
474// location_reference: None,
475// }))
476// .await;
477
478// client
479// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
480// category: Some(dap::OutputEventCategory::Stdout),
481// output: "First item in group 2".to_string(),
482// data: None,
483// variables_reference: None,
484// source: None,
485// line: None,
486// column: None,
487// group: None,
488// location_reference: None,
489// }))
490// .await;
491
492// client
493// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
494// category: Some(dap::OutputEventCategory::Stdout),
495// output: "Second item in group 2".to_string(),
496// data: None,
497// variables_reference: None,
498// source: None,
499// line: None,
500// column: None,
501// group: None,
502// location_reference: None,
503// }))
504// .await;
505
506// client
507// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
508// category: Some(dap::OutputEventCategory::Stdout),
509// output: "End group 2".to_string(),
510// data: None,
511// variables_reference: None,
512// source: None,
513// line: None,
514// column: None,
515// group: Some(dap::OutputEventGroup::End),
516// location_reference: None,
517// }))
518// .await;
519
520// client
521// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
522// category: Some(dap::OutputEventCategory::Stdout),
523// output: "Third group".to_string(),
524// data: None,
525// variables_reference: None,
526// source: None,
527// line: None,
528// column: None,
529// group: Some(dap::OutputEventGroup::StartCollapsed),
530// location_reference: None,
531// }))
532// .await;
533
534// client
535// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
536// category: Some(dap::OutputEventCategory::Stdout),
537// output: "First item in group 3".to_string(),
538// data: None,
539// variables_reference: None,
540// source: None,
541// line: None,
542// column: None,
543// group: None,
544// location_reference: None,
545// }))
546// .await;
547
548// client
549// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
550// category: Some(dap::OutputEventCategory::Stdout),
551// output: "Second item in group 3".to_string(),
552// data: None,
553// variables_reference: None,
554// source: None,
555// line: None,
556// column: None,
557// group: None,
558// location_reference: None,
559// }))
560// .await;
561
562// client
563// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
564// category: Some(dap::OutputEventCategory::Stdout),
565// output: "End group 3".to_string(),
566// data: None,
567// variables_reference: None,
568// source: None,
569// line: None,
570// column: None,
571// group: Some(dap::OutputEventGroup::End),
572// location_reference: None,
573// }))
574// .await;
575
576// client
577// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
578// category: Some(dap::OutputEventCategory::Stdout),
579// output: "Third item in group 1".to_string(),
580// data: None,
581// variables_reference: None,
582// source: None,
583// line: None,
584// column: None,
585// group: None,
586// location_reference: None,
587// }))
588// .await;
589
590// client
591// .fake_event(dap::messages::Events::Output(dap::OutputEvent {
592// category: Some(dap::OutputEventCategory::Stdout),
593// output: "Second item".to_string(),
594// data: None,
595// variables_reference: None,
596// source: None,
597// line: None,
598// column: None,
599// group: Some(dap::OutputEventGroup::End),
600// location_reference: None,
601// }))
602// .await;
603
604// cx.run_until_parked();
605
606// active_debug_session_panel(workspace, cx).update(cx, |debug_panel_item, cx| {
607// debug_panel_item
608// .mode()
609// .as_running()
610// .unwrap()
611// .update(cx, |running_state, cx| {
612// running_state.console().update(cx, |console, cx| {
613// console.editor().update(cx, |editor, cx| {
614// pretty_assertions::assert_eq!(
615// "
616// First line
617// First group
618// First item in group 1
619// Second item in group 1
620// Second group
621// First item in group 2
622// Second item in group 2
623// End group 2
624// ⋯ End group 3
625// Third item in group 1
626// Second item
627// "
628// .unindent(),
629// editor.display_text(cx)
630// );
631// })
632// });
633// });
634// });
635
636// let shutdown_session = project.update(cx, |project, cx| {
637// project.dap_store().update(cx, |dap_store, cx| {
638// dap_store.shutdown_session(session.read(cx).session_id(), cx)
639// })
640// });
641
642// shutdown_session.await.unwrap();
643// }
644
645// todo(debugger): enable this again
646// #[gpui::test]
647// async fn test_evaluate_expression(executor: BackgroundExecutor, cx: &mut TestAppContext) {
648// init_test(cx);
649
650// const NEW_VALUE: &str = "{nested1: \"Nested 1 updated\", nested2: \"Nested 2 updated\"}";
651
652// let called_evaluate = Arc::new(AtomicBool::new(false));
653
654// let fs = FakeFs::new(executor.clone());
655
656// let test_file_content = r#"
657// const variable1 = {
658// nested1: "Nested 1",
659// nested2: "Nested 2",
660// };
661// const variable2 = "Value 2";
662// const variable3 = "Value 3";
663// "#
664// .unindent();
665
666// fs.insert_tree(
667// "/project",
668// json!({
669// "src": {
670// "test.js": test_file_content,
671// }
672// }),
673// )
674// .await;
675
676// let project = Project::test(fs, ["/project".as_ref()], cx).await;
677// let workspace = init_test_workspace(&project, cx).await;
678// let cx = &mut VisualTestContext::from_window(*workspace, cx);
679
680// let task = project.update(cx, |project, cx| {
681// project.start_debug_session(dap::test_config(None), cx)
682// });
683
684// let session = task.await.unwrap();
685// let client = session.update(cx, |session, _| session.adapter_client().unwrap());
686
687// client
688// .on_request::<Threads, _>(move |_, _| {
689// Ok(dap::ThreadsResponse {
690// threads: vec![dap::Thread {
691// id: 1,
692// name: "Thread 1".into(),
693// }],
694// })
695// })
696// .await;
697
698// let stack_frames = vec![StackFrame {
699// id: 1,
700// name: "Stack Frame 1".into(),
701// source: Some(dap::Source {
702// name: Some("test.js".into()),
703// path: Some("/project/src/test.js".into()),
704// source_reference: None,
705// presentation_hint: None,
706// origin: None,
707// sources: None,
708// adapter_data: None,
709// checksums: None,
710// }),
711// line: 3,
712// column: 1,
713// end_line: None,
714// end_column: None,
715// can_restart: None,
716// instruction_pointer_reference: None,
717// module_id: None,
718// presentation_hint: None,
719// }];
720
721// client
722// .on_request::<StackTrace, _>({
723// let stack_frames = Arc::new(stack_frames.clone());
724// move |_, args| {
725// assert_eq!(1, args.thread_id);
726
727// Ok(dap::StackTraceResponse {
728// stack_frames: (*stack_frames).clone(),
729// total_frames: None,
730// })
731// }
732// })
733// .await;
734
735// let scopes = vec![
736// Scope {
737// name: "Scope 1".into(),
738// presentation_hint: None,
739// variables_reference: 2,
740// named_variables: None,
741// indexed_variables: None,
742// expensive: false,
743// source: None,
744// line: None,
745// column: None,
746// end_line: None,
747// end_column: None,
748// },
749// Scope {
750// name: "Scope 2".into(),
751// presentation_hint: None,
752// variables_reference: 4,
753// named_variables: None,
754// indexed_variables: None,
755// expensive: false,
756// source: None,
757// line: None,
758// column: None,
759// end_line: None,
760// end_column: None,
761// },
762// ];
763
764// client
765// .on_request::<Scopes, _>({
766// let scopes = Arc::new(scopes.clone());
767// move |_, args| {
768// assert_eq!(1, args.frame_id);
769
770// Ok(dap::ScopesResponse {
771// scopes: (*scopes).clone(),
772// })
773// }
774// })
775// .await;
776
777// let scope1_variables = Arc::new(Mutex::new(vec![
778// Variable {
779// name: "variable1".into(),
780// value: "{nested1: \"Nested 1\", nested2: \"Nested 2\"}".into(),
781// type_: None,
782// presentation_hint: None,
783// evaluate_name: None,
784// variables_reference: 3,
785// named_variables: None,
786// indexed_variables: None,
787// memory_reference: None,
788// declaration_location_reference: None,
789// value_location_reference: None,
790// },
791// Variable {
792// name: "variable2".into(),
793// value: "Value 2".into(),
794// type_: None,
795// presentation_hint: None,
796// evaluate_name: None,
797// variables_reference: 0,
798// named_variables: None,
799// indexed_variables: None,
800// memory_reference: None,
801// declaration_location_reference: None,
802// value_location_reference: None,
803// },
804// ]));
805
806// let nested_variables = vec![
807// Variable {
808// name: "nested1".into(),
809// value: "Nested 1".into(),
810// type_: None,
811// presentation_hint: None,
812// evaluate_name: None,
813// variables_reference: 0,
814// named_variables: None,
815// indexed_variables: None,
816// memory_reference: None,
817// declaration_location_reference: None,
818// value_location_reference: None,
819// },
820// Variable {
821// name: "nested2".into(),
822// value: "Nested 2".into(),
823// type_: None,
824// presentation_hint: None,
825// evaluate_name: None,
826// variables_reference: 0,
827// named_variables: None,
828// indexed_variables: None,
829// memory_reference: None,
830// declaration_location_reference: None,
831// value_location_reference: None,
832// },
833// ];
834
835// let scope2_variables = vec![Variable {
836// name: "variable3".into(),
837// value: "Value 3".into(),
838// type_: None,
839// presentation_hint: None,
840// evaluate_name: None,
841// variables_reference: 0,
842// named_variables: None,
843// indexed_variables: None,
844// memory_reference: None,
845// declaration_location_reference: None,
846// value_location_reference: None,
847// }];
848
849// client
850// .on_request::<Variables, _>({
851// let scope1_variables = scope1_variables.clone();
852// let nested_variables = Arc::new(nested_variables.clone());
853// let scope2_variables = Arc::new(scope2_variables.clone());
854// move |_, args| match args.variables_reference {
855// 4 => Ok(dap::VariablesResponse {
856// variables: (*scope2_variables).clone(),
857// }),
858// 3 => Ok(dap::VariablesResponse {
859// variables: (*nested_variables).clone(),
860// }),
861// 2 => Ok(dap::VariablesResponse {
862// variables: scope1_variables.lock().unwrap().clone(),
863// }),
864// id => unreachable!("unexpected variables reference {id}"),
865// }
866// })
867// .await;
868
869// client
870// .on_request::<Evaluate, _>({
871// let called_evaluate = called_evaluate.clone();
872// let scope1_variables = scope1_variables.clone();
873// move |_, args| {
874// called_evaluate.store(true, Ordering::SeqCst);
875
876// assert_eq!(format!("$variable1 = {}", NEW_VALUE), args.expression);
877// assert_eq!(Some(1), args.frame_id);
878// assert_eq!(Some(dap::EvaluateArgumentsContext::Variables), args.context);
879
880// scope1_variables.lock().unwrap()[0].value = NEW_VALUE.to_string();
881
882// Ok(dap::EvaluateResponse {
883// result: NEW_VALUE.into(),
884// type_: None,
885// presentation_hint: None,
886// variables_reference: 0,
887// named_variables: None,
888// indexed_variables: None,
889// memory_reference: None,
890// value_location_reference: None,
891// })
892// }
893// })
894// .await;
895
896// client
897// .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
898// reason: dap::StoppedEventReason::Pause,
899// description: None,
900// thread_id: Some(1),
901// preserve_focus_hint: None,
902// text: None,
903// all_threads_stopped: None,
904// hit_breakpoint_ids: None,
905// }))
906// .await;
907
908// cx.run_until_parked();
909
910// // toggle nested variables for scope 1
911// active_debug_session_panel(workspace, cx).update(cx, |debug_panel_item, cx| {
912// debug_panel_item
913// .mode()
914// .as_running()
915// .unwrap()
916// .update(cx, |running_state, cx| {
917// running_state
918// .variable_list()
919// .update(cx, |variable_list, cx| {
920// variable_list.toggle_variable(
921// &VariablePath {
922// indices: Arc::from([scopes[0].variables_reference]),
923// },
924// cx,
925// );
926// });
927// });
928// });
929
930// cx.run_until_parked();
931
932// active_debug_session_panel(workspace, cx).update_in(cx, |debug_panel_item, window, cx| {
933// debug_panel_item
934// .mode()
935// .as_running()
936// .unwrap()
937// .update(cx, |running_state, cx| {
938// running_state.console().update(cx, |console, item_cx| {
939// console
940// .query_bar()
941// .update(item_cx, |query_bar, console_cx| {
942// query_bar.set_text(
943// format!("$variable1 = {}", NEW_VALUE),
944// window,
945// console_cx,
946// );
947// });
948
949// console.evaluate(&menu::Confirm, window, item_cx);
950// });
951// });
952// });
953
954// cx.run_until_parked();
955
956// active_debug_session_panel(workspace, cx).update(cx, |debug_panel_item, cx| {
957// assert_eq!(
958// "",
959// debug_panel_item
960// .mode()
961// .as_running()
962// .unwrap()
963// .read(cx)
964// .console()
965// .read(cx)
966// .query_bar()
967// .read(cx)
968// .text(cx)
969// .as_str()
970// );
971
972// assert_eq!(
973// format!("{}\n", NEW_VALUE),
974// debug_panel_item
975// .mode()
976// .as_running()
977// .unwrap()
978// .read(cx)
979// .console()
980// .read(cx)
981// .editor()
982// .read(cx)
983// .text(cx)
984// .as_str()
985// );
986
987// debug_panel_item
988// .mode()
989// .as_running()
990// .unwrap()
991// .update(cx, |running_state, cx| {
992// running_state
993// .variable_list()
994// .update(cx, |variable_list, _| {
995// let scope1_variables = scope1_variables.lock().unwrap().clone();
996
997// // scope 1
998// // assert_eq!(
999// // vec![
1000// // VariableContainer {
1001// // container_reference: scopes[0].variables_reference,
1002// // variable: scope1_variables[0].clone(),
1003// // depth: 1,
1004// // },
1005// // VariableContainer {
1006// // container_reference: scope1_variables[0].variables_reference,
1007// // variable: nested_variables[0].clone(),
1008// // depth: 2,
1009// // },
1010// // VariableContainer {
1011// // container_reference: scope1_variables[0].variables_reference,
1012// // variable: nested_variables[1].clone(),
1013// // depth: 2,
1014// // },
1015// // VariableContainer {
1016// // container_reference: scopes[0].variables_reference,
1017// // variable: scope1_variables[1].clone(),
1018// // depth: 1,
1019// // },
1020// // ],
1021// // variable_list.variables_by_scope(1, 2).unwrap().variables()
1022// // );
1023
1024// // scope 2
1025// // assert_eq!(
1026// // vec![VariableContainer {
1027// // container_reference: scopes[1].variables_reference,
1028// // variable: scope2_variables[0].clone(),
1029// // depth: 1,
1030// // }],
1031// // variable_list.variables_by_scope(1, 4).unwrap().variables()
1032// // );
1033
1034// variable_list.assert_visual_entries(vec![
1035// "v Scope 1",
1036// " v variable1",
1037// " > nested1",
1038// " > nested2",
1039// " > variable2",
1040// ]);
1041
1042// // assert visual entries
1043// // assert_eq!(
1044// // vec![
1045// // VariableListEntry::Scope(scopes[0].clone()),
1046// // VariableListEntry::Variable {
1047// // depth: 1,
1048// // scope: Arc::new(scopes[0].clone()),
1049// // has_children: true,
1050// // variable: Arc::new(scope1_variables[0].clone()),
1051// // container_reference: scopes[0].variables_reference,
1052// // },
1053// // VariableListEntry::Variable {
1054// // depth: 2,
1055// // scope: Arc::new(scopes[0].clone()),
1056// // has_children: false,
1057// // variable: Arc::new(nested_variables[0].clone()),
1058// // container_reference: scope1_variables[0].variables_reference,
1059// // },
1060// // VariableListEntry::Variable {
1061// // depth: 2,
1062// // scope: Arc::new(scopes[0].clone()),
1063// // has_children: false,
1064// // variable: Arc::new(nested_variables[1].clone()),
1065// // container_reference: scope1_variables[0].variables_reference,
1066// // },
1067// // VariableListEntry::Variable {
1068// // depth: 1,
1069// // scope: Arc::new(scopes[0].clone()),
1070// // has_children: false,
1071// // variable: Arc::new(scope1_variables[1].clone()),
1072// // container_reference: scopes[0].variables_reference,
1073// // },
1074// // VariableListEntry::Scope(scopes[1].clone()),
1075// // ],
1076// // variable_list.entries().get(&1).unwrap().clone()
1077// // );
1078// });
1079// });
1080// });
1081
1082// assert!(
1083// called_evaluate.load(std::sync::atomic::Ordering::SeqCst),
1084// "Expected evaluate request to be called"
1085// );
1086
1087// let shutdown_session = project.update(cx, |project, cx| {
1088// project.dap_store().update(cx, |dap_store, cx| {
1089// dap_store.shutdown_session(&session.read(cx).session_id(), cx)
1090// })
1091// });
1092
1093// shutdown_session.await.unwrap();
1094// }