Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T05:35:57.494Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

console.rs

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