Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T05:37:07.425Z 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

inline_values.rs

2529 lines · 70.5 KB · rust
1#![expect(clippy::result_large_err)]
2use std::{path::Path, sync::Arc};
3
4use dap::{Scope, StackFrame, Variable, requests::Variables};
5use editor::{Editor, EditorMode, MultiBuffer};
6use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
7use language::{
8    Language, LanguageConfig, LanguageMatcher, rust_lang, tree_sitter_python,
9    tree_sitter_typescript,
10};
11use project::{FakeFs, Project};
12use serde_json::json;
13use unindent::Unindent as _;
14use util::{path, rel_path::rel_path};
15
16use crate::{
17    debugger_panel::DebugPanel,
18    tests::{active_debug_session_panel, init_test, init_test_workspace, start_debug_session},
19};
20
21#[gpui::test]
22async fn test_rust_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
23    init_test(cx);
24
25    fn stack_frame_for_line(line: u64) -> dap::StackFrame {
26        StackFrame {
27            id: 1,
28            name: "Stack Frame 1".into(),
29            source: Some(dap::Source {
30                name: Some("main.rs".into()),
31                path: Some(path!("/project/main.rs").into()),
32                source_reference: None,
33                presentation_hint: None,
34                origin: None,
35                sources: None,
36                adapter_data: None,
37                checksums: None,
38            }),
39            line,
40            column: 1,
41            end_line: None,
42            end_column: None,
43            can_restart: None,
44            instruction_pointer_reference: None,
45            module_id: None,
46            presentation_hint: None,
47        }
48    }
49
50    let fs = FakeFs::new(executor.clone());
51    let source_code = r#"
52static mut GLOBAL: usize = 1;
53
54fn main() {
55    let x = 10;
56    let value = 42;
57    let y = 4;
58    let tester = {
59        let y = 10;
60        let y = 5;
61        let b = 3;
62        vec![y, 20, 30]
63    };
64
65    let caller = || {
66        let x = 3;
67        println!("x={}", x);
68    };
69
70    caller();
71
72    unsafe {
73        GLOBAL = 2;
74    }
75
76    let result = value * 2 * x;
77    println!("Simple test executed: value={}, result={}", value, result);
78    assert!(true);
79}
80"#
81    .unindent();
82    fs.insert_tree(path!("/project"), json!({ "main.rs": source_code }))
83        .await;
84
85    let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
86    let workspace = init_test_workspace(&project, cx).await;
87    workspace
88        .update(cx, |workspace, window, cx| {
89            workspace.focus_panel::<DebugPanel>(window, cx);
90        })
91        .unwrap();
92    let cx = &mut VisualTestContext::from_window(*workspace, cx);
93
94    let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
95    let client = session.update(cx, |session, _| session.adapter_client().unwrap());
96
97    client.on_request::<dap::requests::Threads, _>(move |_, _| {
98        Ok(dap::ThreadsResponse {
99            threads: vec![dap::Thread {
100                id: 1,
101                name: "Thread 1".into(),
102            }],
103        })
104    });
105
106    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
107        Ok(dap::StackTraceResponse {
108            stack_frames: vec![stack_frame_for_line(4)],
109            total_frames: None,
110        })
111    });
112
113    client.on_request::<dap::requests::Evaluate, _>(move |_, args| {
114        assert_eq!("GLOBAL", args.expression);
115        Ok(dap::EvaluateResponse {
116            result: "1".into(),
117            type_: None,
118            presentation_hint: None,
119            variables_reference: 0,
120            named_variables: None,
121            indexed_variables: None,
122            memory_reference: None,
123            value_location_reference: None,
124        })
125    });
126
127    let local_variables = vec![
128        Variable {
129            name: "x".into(),
130            value: "10".into(),
131            type_: None,
132            presentation_hint: None,
133            evaluate_name: None,
134            variables_reference: 0,
135            named_variables: None,
136            indexed_variables: None,
137            memory_reference: None,
138            declaration_location_reference: None,
139            value_location_reference: None,
140        },
141        Variable {
142            name: "y".into(),
143            value: "4".into(),
144            type_: None,
145            presentation_hint: None,
146            evaluate_name: None,
147            variables_reference: 0,
148            named_variables: None,
149            indexed_variables: None,
150            memory_reference: None,
151            declaration_location_reference: None,
152            value_location_reference: None,
153        },
154        Variable {
155            name: "value".into(),
156            value: "42".into(),
157            type_: None,
158            presentation_hint: None,
159            evaluate_name: None,
160            variables_reference: 0,
161            named_variables: None,
162            indexed_variables: None,
163            memory_reference: None,
164            declaration_location_reference: None,
165            value_location_reference: None,
166        },
167    ];
168
169    client.on_request::<Variables, _>({
170        let local_variables = Arc::new(local_variables.clone());
171        move |_, _| {
172            Ok(dap::VariablesResponse {
173                variables: (*local_variables).clone(),
174            })
175        }
176    });
177
178    client.on_request::<dap::requests::Scopes, _>(move |_, _| {
179        Ok(dap::ScopesResponse {
180            scopes: vec![Scope {
181                name: "Locale".into(),
182                presentation_hint: None,
183                variables_reference: 2,
184                named_variables: None,
185                indexed_variables: None,
186                expensive: false,
187                source: None,
188                line: None,
189                column: None,
190                end_line: None,
191                end_column: None,
192            }],
193        })
194    });
195
196    client
197        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
198            reason: dap::StoppedEventReason::Pause,
199            description: None,
200            thread_id: Some(1),
201            preserve_focus_hint: None,
202            text: None,
203            all_threads_stopped: None,
204            hit_breakpoint_ids: None,
205        }))
206        .await;
207
208    cx.run_until_parked();
209
210    let project_path = Path::new(path!("/project"));
211    let worktree = project
212        .update(cx, |project, cx| project.find_worktree(project_path, cx))
213        .expect("This worktree should exist in project")
214        .0;
215
216    let worktree_id = workspace
217        .update(cx, |_, _, cx| worktree.read(cx).id())
218        .unwrap();
219
220    let buffer = project
221        .update(cx, |project, cx| {
222            project.open_buffer((worktree_id, rel_path("main.rs")), cx)
223        })
224        .await
225        .unwrap();
226
227    buffer.update(cx, |buffer, cx| {
228        buffer.set_language(Some(rust_lang()), cx);
229    });
230
231    let (editor, cx) = cx.add_window_view(|window, cx| {
232        Editor::new(
233            EditorMode::full(),
234            MultiBuffer::build_from_buffer(buffer, cx),
235            Some(project),
236            window,
237            cx,
238        )
239    });
240
241    active_debug_session_panel(workspace, cx).update_in(cx, |_, window, cx| {
242        cx.focus_self(window);
243    });
244    cx.run_until_parked();
245
246    editor.update(cx, |editor, cx| editor.refresh_inline_values(cx));
247
248    cx.run_until_parked();
249
250    editor.update_in(cx, |editor, window, cx| {
251        pretty_assertions::assert_eq!(
252            r#"
253    static mut GLOBAL: usize = 1;
254
255    fn main() {
256        let x: 10 = 10;
257        let value = 42;
258        let y = 4;
259        let tester = {
260            let y = 10;
261            let y = 5;
262            let b = 3;
263            vec![y, 20, 30]
264        };
265
266        let caller = || {
267            let x = 3;
268            println!("x={}", x);
269        };
270
271        caller();
272
273        unsafe {
274            GLOBAL = 2;
275        }
276
277        let result = value * 2 * x;
278        println!("Simple test executed: value={}, result={}", value, result);
279        assert!(true);
280    }
281    "#
282            .unindent(),
283            editor.snapshot(window, cx).text()
284        );
285    });
286
287    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
288        Ok(dap::StackTraceResponse {
289            stack_frames: vec![stack_frame_for_line(5)],
290            total_frames: None,
291        })
292    });
293    client
294        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
295            reason: dap::StoppedEventReason::Pause,
296            description: None,
297            thread_id: Some(1),
298            preserve_focus_hint: None,
299            text: None,
300            all_threads_stopped: None,
301            hit_breakpoint_ids: None,
302        }))
303        .await;
304
305    cx.run_until_parked();
306
307    editor.update_in(cx, |editor, window, cx| {
308        pretty_assertions::assert_eq!(
309            r#"
310    static mut GLOBAL: usize = 1;
311
312    fn main() {
313        let x: 10 = 10;
314        let value: 42 = 42;
315        let y = 4;
316        let tester = {
317            let y = 10;
318            let y = 5;
319            let b = 3;
320            vec![y, 20, 30]
321        };
322
323        let caller = || {
324            let x = 3;
325            println!("x={}", x);
326        };
327
328        caller();
329
330        unsafe {
331            GLOBAL = 2;
332        }
333
334        let result = value * 2 * x;
335        println!("Simple test executed: value={}, result={}", value, result);
336        assert!(true);
337    }
338    "#
339            .unindent(),
340            editor.snapshot(window, cx).text()
341        );
342    });
343
344    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
345        Ok(dap::StackTraceResponse {
346            stack_frames: vec![stack_frame_for_line(6)],
347            total_frames: None,
348        })
349    });
350    client
351        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
352            reason: dap::StoppedEventReason::Pause,
353            description: None,
354            thread_id: Some(1),
355            preserve_focus_hint: None,
356            text: None,
357            all_threads_stopped: None,
358            hit_breakpoint_ids: None,
359        }))
360        .await;
361
362    cx.run_until_parked();
363
364    editor.update_in(cx, |editor, window, cx| {
365        pretty_assertions::assert_eq!(
366            r#"
367    static mut GLOBAL: usize = 1;
368
369    fn main() {
370        let x: 10 = 10;
371        let value: 42 = 42;
372        let y: 4 = 4;
373        let tester = {
374            let y = 10;
375            let y = 5;
376            let b = 3;
377            vec![y, 20, 30]
378        };
379
380        let caller = || {
381            let x = 3;
382            println!("x={}", x);
383        };
384
385        caller();
386
387        unsafe {
388            GLOBAL = 2;
389        }
390
391        let result = value * 2 * x;
392        println!("Simple test executed: value={}, result={}", value, result);
393        assert!(true);
394    }
395    "#
396            .unindent(),
397            editor.snapshot(window, cx).text()
398        );
399    });
400
401    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
402        Ok(dap::StackTraceResponse {
403            stack_frames: vec![stack_frame_for_line(7)],
404            total_frames: None,
405        })
406    });
407    client
408        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
409            reason: dap::StoppedEventReason::Pause,
410            description: None,
411            thread_id: Some(1),
412            preserve_focus_hint: None,
413            text: None,
414            all_threads_stopped: None,
415            hit_breakpoint_ids: None,
416        }))
417        .await;
418
419    cx.run_until_parked();
420
421    editor.update_in(cx, |editor, window, cx| {
422        pretty_assertions::assert_eq!(
423            r#"
424    static mut GLOBAL: usize = 1;
425
426    fn main() {
427        let x: 10 = 10;
428        let value: 42 = 42;
429        let y: 4 = 4;
430        let tester = {
431            let y = 10;
432            let y = 5;
433            let b = 3;
434            vec![y, 20, 30]
435        };
436
437        let caller = || {
438            let x = 3;
439            println!("x={}", x);
440        };
441
442        caller();
443
444        unsafe {
445            GLOBAL = 2;
446        }
447
448        let result = value * 2 * x;
449        println!("Simple test executed: value={}, result={}", value, result);
450        assert!(true);
451    }
452    "#
453            .unindent(),
454            editor.snapshot(window, cx).text()
455        );
456    });
457
458    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
459        Ok(dap::StackTraceResponse {
460            stack_frames: vec![stack_frame_for_line(8)],
461            total_frames: None,
462        })
463    });
464    client
465        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
466            reason: dap::StoppedEventReason::Pause,
467            description: None,
468            thread_id: Some(1),
469            preserve_focus_hint: None,
470            text: None,
471            all_threads_stopped: None,
472            hit_breakpoint_ids: None,
473        }))
474        .await;
475
476    cx.run_until_parked();
477
478    editor.update_in(cx, |editor, window, cx| {
479        pretty_assertions::assert_eq!(
480            r#"
481    static mut GLOBAL: usize = 1;
482
483    fn main() {
484        let x: 10 = 10;
485        let value: 42 = 42;
486        let y: 4 = 4;
487        let tester = {
488            let y: 4 = 10;
489            let y = 5;
490            let b = 3;
491            vec![y, 20, 30]
492        };
493
494        let caller = || {
495            let x = 3;
496            println!("x={}", x);
497        };
498
499        caller();
500
501        unsafe {
502            GLOBAL = 2;
503        }
504
505        let result = value * 2 * x;
506        println!("Simple test executed: value={}, result={}", value, result);
507        assert!(true);
508    }
509    "#
510            .unindent(),
511            editor.snapshot(window, cx).text()
512        );
513    });
514
515    let local_variables = vec![
516        Variable {
517            name: "x".into(),
518            value: "10".into(),
519            type_: None,
520            presentation_hint: None,
521            evaluate_name: None,
522            variables_reference: 0,
523            named_variables: None,
524            indexed_variables: None,
525            memory_reference: None,
526            declaration_location_reference: None,
527            value_location_reference: None,
528        },
529        Variable {
530            name: "y".into(),
531            value: "10".into(),
532            type_: None,
533            presentation_hint: None,
534            evaluate_name: None,
535            variables_reference: 0,
536            named_variables: None,
537            indexed_variables: None,
538            memory_reference: None,
539            declaration_location_reference: None,
540            value_location_reference: None,
541        },
542        Variable {
543            name: "value".into(),
544            value: "42".into(),
545            type_: None,
546            presentation_hint: None,
547            evaluate_name: None,
548            variables_reference: 0,
549            named_variables: None,
550            indexed_variables: None,
551            memory_reference: None,
552            declaration_location_reference: None,
553            value_location_reference: None,
554        },
555    ];
556
557    client.on_request::<Variables, _>({
558        let local_variables = Arc::new(local_variables.clone());
559        move |_, _| {
560            Ok(dap::VariablesResponse {
561                variables: (*local_variables).clone(),
562            })
563        }
564    });
565    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
566        Ok(dap::StackTraceResponse {
567            stack_frames: vec![stack_frame_for_line(9)],
568            total_frames: None,
569        })
570    });
571    client
572        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
573            reason: dap::StoppedEventReason::Pause,
574            description: None,
575            thread_id: Some(1),
576            preserve_focus_hint: None,
577            text: None,
578            all_threads_stopped: None,
579            hit_breakpoint_ids: None,
580        }))
581        .await;
582
583    cx.run_until_parked();
584
585    editor.update_in(cx, |editor, window, cx| {
586        pretty_assertions::assert_eq!(
587            r#"
588    static mut GLOBAL: usize = 1;
589
590    fn main() {
591        let x: 10 = 10;
592        let value: 42 = 42;
593        let y: 10 = 4;
594        let tester = {
595            let y: 10 = 10;
596            let y: 10 = 5;
597            let b = 3;
598            vec![y, 20, 30]
599        };
600
601        let caller = || {
602            let x = 3;
603            println!("x={}", x);
604        };
605
606        caller();
607
608        unsafe {
609            GLOBAL = 2;
610        }
611
612        let result = value * 2 * x;
613        println!("Simple test executed: value={}, result={}", value, result);
614        assert!(true);
615    }
616    "#
617            .unindent(),
618            editor.snapshot(window, cx).text()
619        );
620    });
621
622    let local_variables = vec![
623        Variable {
624            name: "x".into(),
625            value: "10".into(),
626            type_: None,
627            presentation_hint: None,
628            evaluate_name: None,
629            variables_reference: 0,
630            named_variables: None,
631            indexed_variables: None,
632            memory_reference: None,
633            declaration_location_reference: None,
634            value_location_reference: None,
635        },
636        Variable {
637            name: "y".into(),
638            value: "5".into(),
639            type_: None,
640            presentation_hint: None,
641            evaluate_name: None,
642            variables_reference: 0,
643            named_variables: None,
644            indexed_variables: None,
645            memory_reference: None,
646            declaration_location_reference: None,
647            value_location_reference: None,
648        },
649        Variable {
650            name: "value".into(),
651            value: "42".into(),
652            type_: None,
653            presentation_hint: None,
654            evaluate_name: None,
655            variables_reference: 0,
656            named_variables: None,
657            indexed_variables: None,
658            memory_reference: None,
659            declaration_location_reference: None,
660            value_location_reference: None,
661        },
662    ];
663
664    client.on_request::<Variables, _>({
665        let local_variables = Arc::new(local_variables.clone());
666        move |_, _| {
667            Ok(dap::VariablesResponse {
668                variables: (*local_variables).clone(),
669            })
670        }
671    });
672    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
673        Ok(dap::StackTraceResponse {
674            stack_frames: vec![stack_frame_for_line(10)],
675            total_frames: None,
676        })
677    });
678    client
679        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
680            reason: dap::StoppedEventReason::Pause,
681            description: None,
682            thread_id: Some(1),
683            preserve_focus_hint: None,
684            text: None,
685            all_threads_stopped: None,
686            hit_breakpoint_ids: None,
687        }))
688        .await;
689
690    cx.run_until_parked();
691
692    editor.update_in(cx, |editor, window, cx| {
693        pretty_assertions::assert_eq!(
694            r#"
695    static mut GLOBAL: usize = 1;
696
697    fn main() {
698        let x: 10 = 10;
699        let value: 42 = 42;
700        let y: 5 = 4;
701        let tester = {
702            let y: 5 = 10;
703            let y: 5 = 5;
704            let b = 3;
705            vec![y, 20, 30]
706        };
707
708        let caller = || {
709            let x = 3;
710            println!("x={}", x);
711        };
712
713        caller();
714
715        unsafe {
716            GLOBAL = 2;
717        }
718
719        let result = value * 2 * x;
720        println!("Simple test executed: value={}, result={}", value, result);
721        assert!(true);
722    }
723    "#
724            .unindent(),
725            editor.snapshot(window, cx).text()
726        );
727    });
728
729    let local_variables = vec![
730        Variable {
731            name: "x".into(),
732            value: "10".into(),
733            type_: None,
734            presentation_hint: None,
735            evaluate_name: None,
736            variables_reference: 0,
737            named_variables: None,
738            indexed_variables: None,
739            memory_reference: None,
740            declaration_location_reference: None,
741            value_location_reference: None,
742        },
743        Variable {
744            name: "y".into(),
745            value: "5".into(),
746            type_: None,
747            presentation_hint: None,
748            evaluate_name: None,
749            variables_reference: 0,
750            named_variables: None,
751            indexed_variables: None,
752            memory_reference: None,
753            declaration_location_reference: None,
754            value_location_reference: None,
755        },
756        Variable {
757            name: "value".into(),
758            value: "42".into(),
759            type_: None,
760            presentation_hint: None,
761            evaluate_name: None,
762            variables_reference: 0,
763            named_variables: None,
764            indexed_variables: None,
765            memory_reference: None,
766            declaration_location_reference: None,
767            value_location_reference: None,
768        },
769        Variable {
770            name: "b".into(),
771            value: "3".into(),
772            type_: None,
773            presentation_hint: None,
774            evaluate_name: None,
775            variables_reference: 0,
776            named_variables: None,
777            indexed_variables: None,
778            memory_reference: None,
779            declaration_location_reference: None,
780            value_location_reference: None,
781        },
782    ];
783    client.on_request::<Variables, _>({
784        let local_variables = Arc::new(local_variables.clone());
785        move |_, _| {
786            Ok(dap::VariablesResponse {
787                variables: (*local_variables).clone(),
788            })
789        }
790    });
791    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
792        Ok(dap::StackTraceResponse {
793            stack_frames: vec![stack_frame_for_line(11)],
794            total_frames: None,
795        })
796    });
797    client
798        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
799            reason: dap::StoppedEventReason::Pause,
800            description: None,
801            thread_id: Some(1),
802            preserve_focus_hint: None,
803            text: None,
804            all_threads_stopped: None,
805            hit_breakpoint_ids: None,
806        }))
807        .await;
808
809    cx.run_until_parked();
810
811    editor.update_in(cx, |editor, window, cx| {
812        pretty_assertions::assert_eq!(
813            r#"
814    static mut GLOBAL: usize = 1;
815
816    fn main() {
817        let x: 10 = 10;
818        let value: 42 = 42;
819        let y: 5 = 4;
820        let tester = {
821            let y: 5 = 10;
822            let y: 5 = 5;
823            let b: 3 = 3;
824            vec![y: 5, 20, 30]
825        };
826
827        let caller = || {
828            let x = 3;
829            println!("x={}", x);
830        };
831
832        caller();
833
834        unsafe {
835            GLOBAL = 2;
836        }
837
838        let result = value * 2 * x;
839        println!("Simple test executed: value={}, result={}", value, result);
840        assert!(true);
841    }
842    "#
843            .unindent(),
844            editor.snapshot(window, cx).text()
845        );
846    });
847
848    let local_variables = vec![
849        Variable {
850            name: "x".into(),
851            value: "10".into(),
852            type_: None,
853            presentation_hint: None,
854            evaluate_name: None,
855            variables_reference: 0,
856            named_variables: None,
857            indexed_variables: None,
858            memory_reference: None,
859            declaration_location_reference: None,
860            value_location_reference: None,
861        },
862        Variable {
863            name: "y".into(),
864            value: "4".into(),
865            type_: None,
866            presentation_hint: None,
867            evaluate_name: None,
868            variables_reference: 0,
869            named_variables: None,
870            indexed_variables: None,
871            memory_reference: None,
872            declaration_location_reference: None,
873            value_location_reference: None,
874        },
875        Variable {
876            name: "value".into(),
877            value: "42".into(),
878            type_: None,
879            presentation_hint: None,
880            evaluate_name: None,
881            variables_reference: 0,
882            named_variables: None,
883            indexed_variables: None,
884            memory_reference: None,
885            declaration_location_reference: None,
886            value_location_reference: None,
887        },
888        Variable {
889            name: "tester".into(),
890            value: "size=3".into(),
891            type_: None,
892            presentation_hint: None,
893            evaluate_name: None,
894            variables_reference: 0,
895            named_variables: None,
896            indexed_variables: None,
897            memory_reference: None,
898            declaration_location_reference: None,
899            value_location_reference: None,
900        },
901    ];
902    client.on_request::<Variables, _>({
903        let local_variables = Arc::new(local_variables.clone());
904        move |_, _| {
905            Ok(dap::VariablesResponse {
906                variables: (*local_variables).clone(),
907            })
908        }
909    });
910    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
911        Ok(dap::StackTraceResponse {
912            stack_frames: vec![stack_frame_for_line(14)],
913            total_frames: None,
914        })
915    });
916    client
917        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
918            reason: dap::StoppedEventReason::Pause,
919            description: None,
920            thread_id: Some(1),
921            preserve_focus_hint: None,
922            text: None,
923            all_threads_stopped: None,
924            hit_breakpoint_ids: None,
925        }))
926        .await;
927
928    cx.run_until_parked();
929
930    editor.update_in(cx, |editor, window, cx| {
931        pretty_assertions::assert_eq!(
932            r#"
933    static mut GLOBAL: usize = 1;
934
935    fn main() {
936        let x: 10 = 10;
937        let value: 42 = 42;
938        let y: 4 = 4;
939        let tester: size=3 = {
940            let y = 10;
941            let y = 5;
942            let b = 3;
943            vec![y, 20, 30]
944        };
945
946        let caller = || {
947            let x = 3;
948            println!("x={}", x);
949        };
950
951        caller();
952
953        unsafe {
954            GLOBAL = 2;
955        }
956
957        let result = value * 2 * x;
958        println!("Simple test executed: value={}, result={}", value, result);
959        assert!(true);
960    }
961    "#
962            .unindent(),
963            editor.snapshot(window, cx).text()
964        );
965    });
966
967    let local_variables = vec![
968        Variable {
969            name: "x".into(),
970            value: "10".into(),
971            type_: None,
972            presentation_hint: None,
973            evaluate_name: None,
974            variables_reference: 0,
975            named_variables: None,
976            indexed_variables: None,
977            memory_reference: None,
978            declaration_location_reference: None,
979            value_location_reference: None,
980        },
981        Variable {
982            name: "y".into(),
983            value: "4".into(),
984            type_: None,
985            presentation_hint: None,
986            evaluate_name: None,
987            variables_reference: 0,
988            named_variables: None,
989            indexed_variables: None,
990            memory_reference: None,
991            declaration_location_reference: None,
992            value_location_reference: None,
993        },
994        Variable {
995            name: "value".into(),
996            value: "42".into(),
997            type_: None,
998            presentation_hint: None,
999            evaluate_name: None,
1000            variables_reference: 0,
1001            named_variables: None,
1002            indexed_variables: None,
1003            memory_reference: None,
1004            declaration_location_reference: None,
1005            value_location_reference: None,
1006        },
1007        Variable {
1008            name: "tester".into(),
1009            value: "size=3".into(),
1010            type_: None,
1011            presentation_hint: None,
1012            evaluate_name: None,
1013            variables_reference: 0,
1014            named_variables: None,
1015            indexed_variables: None,
1016            memory_reference: None,
1017            declaration_location_reference: None,
1018            value_location_reference: None,
1019        },
1020        Variable {
1021            name: "caller".into(),
1022            value: "<not available>".into(),
1023            type_: None,
1024            presentation_hint: None,
1025            evaluate_name: None,
1026            variables_reference: 0,
1027            named_variables: None,
1028            indexed_variables: None,
1029            memory_reference: None,
1030            declaration_location_reference: None,
1031            value_location_reference: None,
1032        },
1033    ];
1034    client.on_request::<Variables, _>({
1035        let local_variables = Arc::new(local_variables.clone());
1036        move |_, _| {
1037            Ok(dap::VariablesResponse {
1038                variables: (*local_variables).clone(),
1039            })
1040        }
1041    });
1042    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
1043        Ok(dap::StackTraceResponse {
1044            stack_frames: vec![stack_frame_for_line(19)],
1045            total_frames: None,
1046        })
1047    });
1048    client
1049        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1050            reason: dap::StoppedEventReason::Pause,
1051            description: None,
1052            thread_id: Some(1),
1053            preserve_focus_hint: None,
1054            text: None,
1055            all_threads_stopped: None,
1056            hit_breakpoint_ids: None,
1057        }))
1058        .await;
1059
1060    cx.run_until_parked();
1061
1062    editor.update_in(cx, |editor, window, cx| {
1063        pretty_assertions::assert_eq!(
1064            r#"
1065    static mut GLOBAL: usize = 1;
1066
1067    fn main() {
1068        let x: 10 = 10;
1069        let value: 42 = 42;
1070        let y: 4 = 4;
1071        let tester: size=3 = {
1072            let y = 10;
1073            let y = 5;
1074            let b = 3;
1075            vec![y, 20, 30]
1076        };
1077
1078        let caller: <not available> = || {
1079            let x = 3;
1080            println!("x={}", x);
1081        };
1082
1083        caller();
1084
1085        unsafe {
1086            GLOBAL = 2;
1087        }
1088
1089        let result = value * 2 * x;
1090        println!("Simple test executed: value={}, result={}", value, result);
1091        assert!(true);
1092    }
1093    "#
1094            .unindent(),
1095            editor.snapshot(window, cx).text()
1096        );
1097    });
1098
1099    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
1100        Ok(dap::StackTraceResponse {
1101            stack_frames: vec![stack_frame_for_line(15)],
1102            total_frames: None,
1103        })
1104    });
1105    client
1106        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1107            reason: dap::StoppedEventReason::Pause,
1108            description: None,
1109            thread_id: Some(1),
1110            preserve_focus_hint: None,
1111            text: None,
1112            all_threads_stopped: None,
1113            hit_breakpoint_ids: None,
1114        }))
1115        .await;
1116
1117    cx.run_until_parked();
1118
1119    editor.update_in(cx, |editor, window, cx| {
1120        pretty_assertions::assert_eq!(
1121            r#"
1122    static mut GLOBAL: usize = 1;
1123
1124    fn main() {
1125        let x: 10 = 10;
1126        let value: 42 = 42;
1127        let y: 4 = 4;
1128        let tester: size=3 = {
1129            let y = 10;
1130            let y = 5;
1131            let b = 3;
1132            vec![y, 20, 30]
1133        };
1134
1135        let caller: <not available> = || {
1136            let x: 10 = 3;
1137            println!("x={}", x);
1138        };
1139
1140        caller();
1141
1142        unsafe {
1143            GLOBAL = 2;
1144        }
1145
1146        let result = value * 2 * x;
1147        println!("Simple test executed: value={}, result={}", value, result);
1148        assert!(true);
1149    }
1150    "#
1151            .unindent(),
1152            editor.snapshot(window, cx).text()
1153        );
1154    });
1155
1156    let local_variables = vec![Variable {
1157        name: "x".into(),
1158        value: "3".into(),
1159        type_: None,
1160        presentation_hint: None,
1161        evaluate_name: None,
1162        variables_reference: 0,
1163        named_variables: None,
1164        indexed_variables: None,
1165        memory_reference: None,
1166        declaration_location_reference: None,
1167        value_location_reference: None,
1168    }];
1169    client.on_request::<Variables, _>({
1170        let local_variables = Arc::new(local_variables.clone());
1171        move |_, _| {
1172            Ok(dap::VariablesResponse {
1173                variables: (*local_variables).clone(),
1174            })
1175        }
1176    });
1177    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
1178        Ok(dap::StackTraceResponse {
1179            stack_frames: vec![stack_frame_for_line(16)],
1180            total_frames: None,
1181        })
1182    });
1183    client
1184        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1185            reason: dap::StoppedEventReason::Pause,
1186            description: None,
1187            thread_id: Some(1),
1188            preserve_focus_hint: None,
1189            text: None,
1190            all_threads_stopped: None,
1191            hit_breakpoint_ids: None,
1192        }))
1193        .await;
1194
1195    cx.run_until_parked();
1196
1197    editor.update_in(cx, |editor, window, cx| {
1198        pretty_assertions::assert_eq!(
1199            r#"
1200    static mut GLOBAL: usize = 1;
1201
1202    fn main() {
1203        let x: 3 = 10;
1204        let value = 42;
1205        let y = 4;
1206        let tester = {
1207            let y = 10;
1208            let y = 5;
1209            let b = 3;
1210            vec![y, 20, 30]
1211        };
1212
1213        let caller = || {
1214            let x: 3 = 3;
1215            println!("x={}", x: 3);
1216        };
1217
1218        caller();
1219
1220        unsafe {
1221            GLOBAL = 2;
1222        }
1223
1224        let result = value * 2 * x;
1225        println!("Simple test executed: value={}, result={}", value, result);
1226        assert!(true);
1227    }
1228    "#
1229            .unindent(),
1230            editor.snapshot(window, cx).text()
1231        );
1232    });
1233
1234    let local_variables = vec![
1235        Variable {
1236            name: "x".into(),
1237            value: "10".into(),
1238            type_: None,
1239            presentation_hint: None,
1240            evaluate_name: None,
1241            variables_reference: 0,
1242            named_variables: None,
1243            indexed_variables: None,
1244            memory_reference: None,
1245            declaration_location_reference: None,
1246            value_location_reference: None,
1247        },
1248        Variable {
1249            name: "y".into(),
1250            value: "4".into(),
1251            type_: None,
1252            presentation_hint: None,
1253            evaluate_name: None,
1254            variables_reference: 0,
1255            named_variables: None,
1256            indexed_variables: None,
1257            memory_reference: None,
1258            declaration_location_reference: None,
1259            value_location_reference: None,
1260        },
1261        Variable {
1262            name: "value".into(),
1263            value: "42".into(),
1264            type_: None,
1265            presentation_hint: None,
1266            evaluate_name: None,
1267            variables_reference: 0,
1268            named_variables: None,
1269            indexed_variables: None,
1270            memory_reference: None,
1271            declaration_location_reference: None,
1272            value_location_reference: None,
1273        },
1274        Variable {
1275            name: "tester".into(),
1276            value: "size=3".into(),
1277            type_: None,
1278            presentation_hint: None,
1279            evaluate_name: None,
1280            variables_reference: 0,
1281            named_variables: None,
1282            indexed_variables: None,
1283            memory_reference: None,
1284            declaration_location_reference: None,
1285            value_location_reference: None,
1286        },
1287        Variable {
1288            name: "caller".into(),
1289            value: "<not available>".into(),
1290            type_: None,
1291            presentation_hint: None,
1292            evaluate_name: None,
1293            variables_reference: 0,
1294            named_variables: None,
1295            indexed_variables: None,
1296            memory_reference: None,
1297            declaration_location_reference: None,
1298            value_location_reference: None,
1299        },
1300    ];
1301    client.on_request::<Variables, _>({
1302        let local_variables = Arc::new(local_variables.clone());
1303        move |_, _| {
1304            Ok(dap::VariablesResponse {
1305                variables: (*local_variables).clone(),
1306            })
1307        }
1308    });
1309    client.on_request::<dap::requests::Evaluate, _>(move |_, args| {
1310        assert_eq!("GLOBAL", args.expression);
1311        Ok(dap::EvaluateResponse {
1312            result: "2".into(),
1313            type_: None,
1314            presentation_hint: None,
1315            variables_reference: 0,
1316            named_variables: None,
1317            indexed_variables: None,
1318            memory_reference: None,
1319            value_location_reference: None,
1320        })
1321    });
1322    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
1323        Ok(dap::StackTraceResponse {
1324            stack_frames: vec![stack_frame_for_line(25)],
1325            total_frames: None,
1326        })
1327    });
1328    client
1329        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1330            reason: dap::StoppedEventReason::Pause,
1331            description: None,
1332            thread_id: Some(1),
1333            preserve_focus_hint: None,
1334            text: None,
1335            all_threads_stopped: None,
1336            hit_breakpoint_ids: None,
1337        }))
1338        .await;
1339
1340    cx.run_until_parked();
1341
1342    editor.update_in(cx, |editor, window, cx| {
1343        pretty_assertions::assert_eq!(
1344            r#"
1345    static mut GLOBAL: usize = 1;
1346
1347    fn main() {
1348        let x: 10 = 10;
1349        let value: 42 = 42;
1350        let y: 4 = 4;
1351        let tester: size=3 = {
1352            let y = 10;
1353            let y = 5;
1354            let b = 3;
1355            vec![y, 20, 30]
1356        };
1357
1358        let caller: <not available> = || {
1359            let x = 3;
1360            println!("x={}", x);
1361        };
1362
1363        caller();
1364
1365        unsafe {
1366            GLOBAL = 2;
1367        }
1368
1369        let result = value: 42 * 2 * x: 10;
1370        println!("Simple test executed: value={}, result={}", value, result);
1371        assert!(true);
1372    }
1373    "#
1374            .unindent(),
1375            editor.snapshot(window, cx).text()
1376        );
1377    });
1378
1379    let local_variables = vec![
1380        Variable {
1381            name: "x".into(),
1382            value: "10".into(),
1383            type_: None,
1384            presentation_hint: None,
1385            evaluate_name: None,
1386            variables_reference: 0,
1387            named_variables: None,
1388            indexed_variables: None,
1389            memory_reference: None,
1390            declaration_location_reference: None,
1391            value_location_reference: None,
1392        },
1393        Variable {
1394            name: "y".into(),
1395            value: "4".into(),
1396            type_: None,
1397            presentation_hint: None,
1398            evaluate_name: None,
1399            variables_reference: 0,
1400            named_variables: None,
1401            indexed_variables: None,
1402            memory_reference: None,
1403            declaration_location_reference: None,
1404            value_location_reference: None,
1405        },
1406        Variable {
1407            name: "value".into(),
1408            value: "42".into(),
1409            type_: None,
1410            presentation_hint: None,
1411            evaluate_name: None,
1412            variables_reference: 0,
1413            named_variables: None,
1414            indexed_variables: None,
1415            memory_reference: None,
1416            declaration_location_reference: None,
1417            value_location_reference: None,
1418        },
1419        Variable {
1420            name: "tester".into(),
1421            value: "size=3".into(),
1422            type_: None,
1423            presentation_hint: None,
1424            evaluate_name: None,
1425            variables_reference: 0,
1426            named_variables: None,
1427            indexed_variables: None,
1428            memory_reference: None,
1429            declaration_location_reference: None,
1430            value_location_reference: None,
1431        },
1432        Variable {
1433            name: "caller".into(),
1434            value: "<not available>".into(),
1435            type_: None,
1436            presentation_hint: None,
1437            evaluate_name: None,
1438            variables_reference: 0,
1439            named_variables: None,
1440            indexed_variables: None,
1441            memory_reference: None,
1442            declaration_location_reference: None,
1443            value_location_reference: None,
1444        },
1445        Variable {
1446            name: "result".into(),
1447            value: "840".into(),
1448            type_: None,
1449            presentation_hint: None,
1450            evaluate_name: None,
1451            variables_reference: 0,
1452            named_variables: None,
1453            indexed_variables: None,
1454            memory_reference: None,
1455            declaration_location_reference: None,
1456            value_location_reference: None,
1457        },
1458    ];
1459    client.on_request::<Variables, _>({
1460        let local_variables = Arc::new(local_variables.clone());
1461        move |_, _| {
1462            Ok(dap::VariablesResponse {
1463                variables: (*local_variables).clone(),
1464            })
1465        }
1466    });
1467    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
1468        Ok(dap::StackTraceResponse {
1469            stack_frames: vec![stack_frame_for_line(26)],
1470            total_frames: None,
1471        })
1472    });
1473    client
1474        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1475            reason: dap::StoppedEventReason::Pause,
1476            description: None,
1477            thread_id: Some(1),
1478            preserve_focus_hint: None,
1479            text: None,
1480            all_threads_stopped: None,
1481            hit_breakpoint_ids: None,
1482        }))
1483        .await;
1484
1485    cx.run_until_parked();
1486
1487    editor.update_in(cx, |editor, window, cx| {
1488        pretty_assertions::assert_eq!(
1489            r#"
1490    static mut GLOBAL: usize = 1;
1491
1492    fn main() {
1493        let x: 10 = 10;
1494        let value: 42 = 42;
1495        let y: 4 = 4;
1496        let tester: size=3 = {
1497            let y = 10;
1498            let y = 5;
1499            let b = 3;
1500            vec![y, 20, 30]
1501        };
1502
1503        let caller: <not available> = || {
1504            let x = 3;
1505            println!("x={}", x);
1506        };
1507
1508        caller();
1509
1510        unsafe {
1511            GLOBAL = 2;
1512        }
1513
1514        let result: 840 = value: 42 * 2 * x: 10;
1515        println!("Simple test executed: value={}, result={}", value: 42, result: 840);
1516        assert!(true);
1517    }
1518    "#
1519            .unindent(),
1520            editor.snapshot(window, cx).text()
1521        );
1522    });
1523}
1524
1525#[gpui::test]
1526async fn test_python_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
1527    init_test(cx);
1528
1529    let fs = FakeFs::new(executor.clone());
1530    let source_code = r#"
1531def process_data(untyped_param, typed_param: int, another_typed: str):
1532    # Local variables
1533    x = 10
1534    result = typed_param * 2
1535    text = "Hello, " + another_typed
1536
1537    # For loop with range
1538    sum_value = 0
1539    for i in range(5):
1540        sum_value += i
1541
1542    # Final result
1543    final_result = x + result + sum_value
1544    return final_result
1545"#
1546    .unindent();
1547    fs.insert_tree(path!("/project"), json!({ "main.py": source_code }))
1548        .await;
1549
1550    let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
1551    let workspace = init_test_workspace(&project, cx).await;
1552    workspace
1553        .update(cx, |workspace, window, cx| {
1554            workspace.focus_panel::<DebugPanel>(window, cx);
1555        })
1556        .unwrap();
1557    let cx = &mut VisualTestContext::from_window(*workspace, cx);
1558
1559    let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
1560    let client = session.update(cx, |session, _| session.adapter_client().unwrap());
1561
1562    let project_path = Path::new(path!("/project"));
1563    let worktree = project
1564        .update(cx, |project, cx| project.find_worktree(project_path, cx))
1565        .expect("This worktree should exist in project")
1566        .0;
1567
1568    let worktree_id = workspace
1569        .update(cx, |_, _, cx| worktree.read(cx).id())
1570        .unwrap();
1571
1572    let buffer = project
1573        .update(cx, |project, cx| {
1574            project.open_buffer((worktree_id, rel_path("main.py")), cx)
1575        })
1576        .await
1577        .unwrap();
1578
1579    buffer.update(cx, |buffer, cx| {
1580        buffer.set_language(Some(Arc::new(python_lang())), cx);
1581    });
1582
1583    let (editor, cx) = cx.add_window_view(|window, cx| {
1584        Editor::new(
1585            EditorMode::full(),
1586            MultiBuffer::build_from_buffer(buffer, cx),
1587            Some(project),
1588            window,
1589            cx,
1590        )
1591    });
1592
1593    editor.update(cx, |editor, cx| editor.refresh_inline_values(cx));
1594
1595    client.on_request::<dap::requests::Threads, _>(move |_, _| {
1596        Ok(dap::ThreadsResponse {
1597            threads: vec![dap::Thread {
1598                id: 1,
1599                name: "Thread 1".into(),
1600            }],
1601        })
1602    });
1603
1604    client.on_request::<dap::requests::StackTrace, _>(move |_, args| {
1605        assert_eq!(args.thread_id, 1);
1606        Ok(dap::StackTraceResponse {
1607            stack_frames: vec![StackFrame {
1608                id: 1,
1609                name: "Stack Frame 1".into(),
1610                source: Some(dap::Source {
1611                    name: Some("main.py".into()),
1612                    path: Some(path!("/project/main.py").into()),
1613                    source_reference: None,
1614                    presentation_hint: None,
1615                    origin: None,
1616                    sources: None,
1617                    adapter_data: None,
1618                    checksums: None,
1619                }),
1620                line: 12,
1621                column: 1,
1622                end_line: None,
1623                end_column: None,
1624                can_restart: None,
1625                instruction_pointer_reference: None,
1626                module_id: None,
1627                presentation_hint: None,
1628            }],
1629            total_frames: None,
1630        })
1631    });
1632
1633    client.on_request::<dap::requests::Scopes, _>(move |_, _| {
1634        Ok(dap::ScopesResponse {
1635            scopes: vec![
1636                Scope {
1637                    name: "Local".into(),
1638                    presentation_hint: None,
1639                    variables_reference: 1,
1640                    named_variables: None,
1641                    indexed_variables: None,
1642                    expensive: false,
1643                    source: None,
1644                    line: None,
1645                    column: None,
1646                    end_line: None,
1647                    end_column: None,
1648                },
1649                Scope {
1650                    name: "Global".into(),
1651                    presentation_hint: None,
1652                    variables_reference: 2,
1653                    named_variables: None,
1654                    indexed_variables: None,
1655                    expensive: false,
1656                    source: None,
1657                    line: None,
1658                    column: None,
1659                    end_line: None,
1660                    end_column: None,
1661                },
1662            ],
1663        })
1664    });
1665
1666    client.on_request::<Variables, _>(move |_, args| match args.variables_reference {
1667        1 => Ok(dap::VariablesResponse {
1668            variables: vec![
1669                Variable {
1670                    name: "untyped_param".into(),
1671                    value: "test_value".into(),
1672                    type_: Some("str".into()),
1673                    presentation_hint: None,
1674                    evaluate_name: None,
1675                    variables_reference: 0,
1676                    named_variables: None,
1677                    indexed_variables: None,
1678                    memory_reference: None,
1679                    declaration_location_reference: None,
1680                    value_location_reference: None,
1681                },
1682                Variable {
1683                    name: "typed_param".into(),
1684                    value: "42".into(),
1685                    type_: Some("int".into()),
1686                    presentation_hint: None,
1687                    evaluate_name: None,
1688                    variables_reference: 0,
1689                    named_variables: None,
1690                    indexed_variables: None,
1691                    memory_reference: None,
1692                    declaration_location_reference: None,
1693                    value_location_reference: None,
1694                },
1695                Variable {
1696                    name: "another_typed".into(),
1697                    value: "world".into(),
1698                    type_: Some("str".into()),
1699                    presentation_hint: None,
1700                    evaluate_name: None,
1701                    variables_reference: 0,
1702                    named_variables: None,
1703                    indexed_variables: None,
1704                    memory_reference: None,
1705                    declaration_location_reference: None,
1706                    value_location_reference: None,
1707                },
1708                Variable {
1709                    name: "x".into(),
1710                    value: "10".into(),
1711                    type_: Some("int".into()),
1712                    presentation_hint: None,
1713                    evaluate_name: None,
1714                    variables_reference: 0,
1715                    named_variables: None,
1716                    indexed_variables: None,
1717                    memory_reference: None,
1718                    declaration_location_reference: None,
1719                    value_location_reference: None,
1720                },
1721                Variable {
1722                    name: "result".into(),
1723                    value: "84".into(),
1724                    type_: Some("int".into()),
1725                    presentation_hint: None,
1726                    evaluate_name: None,
1727                    variables_reference: 0,
1728                    named_variables: None,
1729                    indexed_variables: None,
1730                    memory_reference: None,
1731                    declaration_location_reference: None,
1732                    value_location_reference: None,
1733                },
1734                Variable {
1735                    name: "text".into(),
1736                    value: "Hello, world".into(),
1737                    type_: Some("str".into()),
1738                    presentation_hint: None,
1739                    evaluate_name: None,
1740                    variables_reference: 0,
1741                    named_variables: None,
1742                    indexed_variables: None,
1743                    memory_reference: None,
1744                    declaration_location_reference: None,
1745                    value_location_reference: None,
1746                },
1747                Variable {
1748                    name: "sum_value".into(),
1749                    value: "10".into(),
1750                    type_: Some("int".into()),
1751                    presentation_hint: None,
1752                    evaluate_name: None,
1753                    variables_reference: 0,
1754                    named_variables: None,
1755                    indexed_variables: None,
1756                    memory_reference: None,
1757                    declaration_location_reference: None,
1758                    value_location_reference: None,
1759                },
1760                Variable {
1761                    name: "i".into(),
1762                    value: "4".into(),
1763                    type_: Some("int".into()),
1764                    presentation_hint: None,
1765                    evaluate_name: None,
1766                    variables_reference: 0,
1767                    named_variables: None,
1768                    indexed_variables: None,
1769                    memory_reference: None,
1770                    declaration_location_reference: None,
1771                    value_location_reference: None,
1772                },
1773                Variable {
1774                    name: "final_result".into(),
1775                    value: "104".into(),
1776                    type_: Some("int".into()),
1777                    presentation_hint: None,
1778                    evaluate_name: None,
1779                    variables_reference: 0,
1780                    named_variables: None,
1781                    indexed_variables: None,
1782                    memory_reference: None,
1783                    declaration_location_reference: None,
1784                    value_location_reference: None,
1785                },
1786            ],
1787        }),
1788        _ => Ok(dap::VariablesResponse { variables: vec![] }),
1789    });
1790
1791    client
1792        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1793            reason: dap::StoppedEventReason::Pause,
1794            description: None,
1795            thread_id: Some(1),
1796            preserve_focus_hint: None,
1797            text: None,
1798            all_threads_stopped: None,
1799            hit_breakpoint_ids: None,
1800        }))
1801        .await;
1802
1803    cx.run_until_parked();
1804
1805    editor.update_in(cx, |editor, window, cx| {
1806        pretty_assertions::assert_eq!(
1807            r#"
1808        def process_data(untyped_param: test_value, typed_param: 42: int, another_typed: world: str):
1809            # Local variables
1810            x: 10 = 10
1811            result: 84 = typed_param: 42 * 2
1812            text: Hello, world = "Hello, " + another_typed: world
1813
1814            # For loop with range
1815            sum_value: 10 = 0
1816            for i: 4 in range(5):
1817                sum_value += i
1818
1819            # Final result
1820            final_result = x + result + sum_value
1821            return final_result
1822        "#
1823            .unindent(),
1824            editor.snapshot(window, cx).text()
1825        );
1826    });
1827}
1828
1829fn python_lang() -> Language {
1830    let debug_variables_query = include_str!("../../../grammars/src/python/debugger.scm");
1831    Language::new(
1832        LanguageConfig {
1833            name: "Python".into(),
1834            matcher: (LanguageMatcher {
1835                path_suffixes: vec!["py".to_string()],
1836                ..Default::default()
1837            })
1838            .into(),
1839            ..Default::default()
1840        },
1841        Some(tree_sitter_python::LANGUAGE.into()),
1842    )
1843    .with_debug_variables_query(debug_variables_query)
1844    .unwrap()
1845}
1846
1847fn go_lang() -> Arc<Language> {
1848    let debug_variables_query = include_str!("../../../grammars/src/go/debugger.scm");
1849    Arc::new(
1850        Language::new(
1851            LanguageConfig {
1852                name: "Go".into(),
1853                matcher: (LanguageMatcher {
1854                    path_suffixes: vec!["go".to_string()],
1855                    ..Default::default()
1856                })
1857                .into(),
1858                ..Default::default()
1859            },
1860            Some(tree_sitter_go::LANGUAGE.into()),
1861        )
1862        .with_debug_variables_query(debug_variables_query)
1863        .unwrap(),
1864    )
1865}
1866
1867/// Test utility function for inline values testing
1868///
1869/// # Arguments
1870/// * `variables` - List of tuples containing (variable_name, variable_value)
1871/// * `before` - Source code before inline values are applied
1872/// * `after` - Expected source code after inline values are applied
1873/// * `language` - Language configuration to use for parsing
1874/// * `executor` - Background executor for async operations
1875/// * `cx` - Test app context
1876async fn test_inline_values_util(
1877    local_variables: &[(&str, &str)],
1878    global_variables: &[(&str, &str)],
1879    before: &str,
1880    after: &str,
1881    active_debug_line: Option<usize>,
1882    language: Arc<Language>,
1883    executor: BackgroundExecutor,
1884    cx: &mut TestAppContext,
1885) {
1886    init_test(cx);
1887
1888    let lines_count = before.lines().count();
1889    let stop_line =
1890        active_debug_line.unwrap_or_else(|| if lines_count > 6 { 6 } else { lines_count - 1 });
1891
1892    let fs = FakeFs::new(executor.clone());
1893    fs.insert_tree(path!("/project"), json!({ "main.rs": before.to_string() }))
1894        .await;
1895
1896    let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
1897    let workspace = init_test_workspace(&project, cx).await;
1898    workspace
1899        .update(cx, |workspace, window, cx| {
1900            workspace.focus_panel::<DebugPanel>(window, cx);
1901        })
1902        .unwrap();
1903    let cx = &mut VisualTestContext::from_window(*workspace, cx);
1904
1905    let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
1906    let client = session.update(cx, |session, _| session.adapter_client().unwrap());
1907
1908    client.on_request::<dap::requests::Threads, _>(|_, _| {
1909        Ok(dap::ThreadsResponse {
1910            threads: vec![dap::Thread {
1911                id: 1,
1912                name: "main".into(),
1913            }],
1914        })
1915    });
1916
1917    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
1918        Ok(dap::StackTraceResponse {
1919            stack_frames: vec![dap::StackFrame {
1920                id: 1,
1921                name: "main".into(),
1922                source: Some(dap::Source {
1923                    name: Some("main.rs".into()),
1924                    path: Some(path!("/project/main.rs").into()),
1925                    source_reference: None,
1926                    presentation_hint: None,
1927                    origin: None,
1928                    sources: None,
1929                    adapter_data: None,
1930                    checksums: None,
1931                }),
1932                line: stop_line as u64,
1933                column: 1,
1934                end_line: None,
1935                end_column: None,
1936                can_restart: None,
1937                instruction_pointer_reference: None,
1938                module_id: None,
1939                presentation_hint: None,
1940            }],
1941            total_frames: None,
1942        })
1943    });
1944
1945    let local_vars: Vec<Variable> = local_variables
1946        .iter()
1947        .map(|(name, value)| Variable {
1948            name: (*name).into(),
1949            value: (*value).into(),
1950            type_: None,
1951            presentation_hint: None,
1952            evaluate_name: None,
1953            variables_reference: 0,
1954            named_variables: None,
1955            indexed_variables: None,
1956            memory_reference: None,
1957            declaration_location_reference: None,
1958            value_location_reference: None,
1959        })
1960        .collect();
1961
1962    let global_vars: Vec<Variable> = global_variables
1963        .iter()
1964        .map(|(name, value)| Variable {
1965            name: (*name).into(),
1966            value: (*value).into(),
1967            type_: None,
1968            presentation_hint: None,
1969            evaluate_name: None,
1970            variables_reference: 0,
1971            named_variables: None,
1972            indexed_variables: None,
1973            memory_reference: None,
1974            declaration_location_reference: None,
1975            value_location_reference: None,
1976        })
1977        .collect();
1978
1979    client.on_request::<Variables, _>({
1980        let local_vars = Arc::new(local_vars.clone());
1981        let global_vars = Arc::new(global_vars.clone());
1982        move |_, args| {
1983            let variables = match args.variables_reference {
1984                2 => (*local_vars).clone(),
1985                3 => (*global_vars).clone(),
1986                _ => vec![],
1987            };
1988            Ok(dap::VariablesResponse { variables })
1989        }
1990    });
1991
1992    client.on_request::<dap::requests::Scopes, _>(move |_, _| {
1993        Ok(dap::ScopesResponse {
1994            scopes: vec![
1995                Scope {
1996                    name: "Local".into(),
1997                    presentation_hint: None,
1998                    variables_reference: 2,
1999                    named_variables: None,
2000                    indexed_variables: None,
2001                    expensive: false,
2002                    source: None,
2003                    line: None,
2004                    column: None,
2005                    end_line: None,
2006                    end_column: None,
2007                },
2008                Scope {
2009                    name: "Global".into(),
2010                    presentation_hint: None,
2011                    variables_reference: 3,
2012                    named_variables: None,
2013                    indexed_variables: None,
2014                    expensive: false,
2015                    source: None,
2016                    line: None,
2017                    column: None,
2018                    end_line: None,
2019                    end_column: None,
2020                },
2021            ],
2022        })
2023    });
2024
2025    if !global_variables.is_empty() {
2026        let global_evaluate_map: std::collections::HashMap<String, String> = global_variables
2027            .iter()
2028            .map(|(name, value)| (name.to_string(), value.to_string()))
2029            .collect();
2030
2031        client.on_request::<dap::requests::Evaluate, _>(move |_, args| {
2032            let value = global_evaluate_map
2033                .get(&args.expression)
2034                .unwrap_or(&"undefined".to_string())
2035                .clone();
2036
2037            Ok(dap::EvaluateResponse {
2038                result: value,
2039                type_: None,
2040                presentation_hint: None,
2041                variables_reference: 0,
2042                named_variables: None,
2043                indexed_variables: None,
2044                memory_reference: None,
2045                value_location_reference: None,
2046            })
2047        });
2048    }
2049
2050    client
2051        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
2052            reason: dap::StoppedEventReason::Pause,
2053            description: None,
2054            thread_id: Some(1),
2055            preserve_focus_hint: None,
2056            text: None,
2057            all_threads_stopped: None,
2058            hit_breakpoint_ids: None,
2059        }))
2060        .await;
2061
2062    cx.run_until_parked();
2063
2064    let project_path = Path::new(path!("/project"));
2065    let worktree = project
2066        .update(cx, |project, cx| project.find_worktree(project_path, cx))
2067        .expect("This worktree should exist in project")
2068        .0;
2069
2070    let worktree_id = workspace
2071        .update(cx, |_, _, cx| worktree.read(cx).id())
2072        .unwrap();
2073
2074    let buffer = project
2075        .update(cx, |project, cx| {
2076            project.open_buffer((worktree_id, rel_path("main.rs")), cx)
2077        })
2078        .await
2079        .unwrap();
2080
2081    buffer.update(cx, |buffer, cx| {
2082        buffer.set_language(Some(language), cx);
2083    });
2084
2085    let (editor, cx) = cx.add_window_view(|window, cx| {
2086        Editor::new(
2087            EditorMode::full(),
2088            MultiBuffer::build_from_buffer(buffer, cx),
2089            Some(project),
2090            window,
2091            cx,
2092        )
2093    });
2094
2095    active_debug_session_panel(workspace, cx).update_in(cx, |_, window, cx| {
2096        cx.focus_self(window);
2097    });
2098    cx.run_until_parked();
2099
2100    editor.update(cx, |editor, cx| editor.refresh_inline_values(cx));
2101
2102    cx.run_until_parked();
2103
2104    editor.update_in(cx, |editor, window, cx| {
2105        pretty_assertions::assert_eq!(after, editor.snapshot(window, cx).text());
2106    });
2107}
2108
2109#[gpui::test]
2110async fn test_inline_values_example(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2111    let variables = [("x", "10"), ("y", "20"), ("result", "30")];
2112
2113    let before = r#"
2114fn main() {
2115    let x = 10;
2116    let y = 20;
2117    let result = x + y;
2118    println!("Result: {}", result);
2119}
2120"#
2121    .unindent();
2122
2123    let after = r#"
2124fn main() {
2125    let x: 10 = 10;
2126    let y: 20 = 20;
2127    let result: 30 = x: 10 + y: 20;
2128    println!("Result: {}", result: 30);
2129}
2130"#
2131    .unindent();
2132
2133    test_inline_values_util(
2134        &variables,
2135        &[],
2136        &before,
2137        &after,
2138        None,
2139        rust_lang(),
2140        executor,
2141        cx,
2142    )
2143    .await;
2144}
2145
2146#[gpui::test]
2147async fn test_inline_values_with_globals(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2148    let variables = [("x", "5"), ("y", "10")];
2149
2150    let before = r#"
2151static mut GLOBAL_COUNTER: usize = 42;
2152
2153fn main() {
2154    let x = 5;
2155    let y = 10;
2156    unsafe {
2157        GLOBAL_COUNTER += 1;
2158    }
2159    println!("x={}, y={}, global={}", x, y, unsafe { GLOBAL_COUNTER });
2160}
2161"#
2162    .unindent();
2163
2164    let after = r#"
2165static mut GLOBAL_COUNTER: 42: usize = 42;
2166
2167fn main() {
2168    let x: 5 = 5;
2169    let y: 10 = 10;
2170    unsafe {
2171        GLOBAL_COUNTER += 1;
2172    }
2173    println!("x={}, y={}, global={}", x, y, unsafe { GLOBAL_COUNTER });
2174}
2175"#
2176    .unindent();
2177
2178    test_inline_values_util(
2179        &variables,
2180        &[("GLOBAL_COUNTER", "42")],
2181        &before,
2182        &after,
2183        None,
2184        rust_lang(),
2185        executor,
2186        cx,
2187    )
2188    .await;
2189}
2190
2191#[gpui::test]
2192async fn test_go_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2193    let variables = [("x", "42"), ("y", "hello")];
2194
2195    let before = r#"
2196package main
2197
2198var globalCounter int = 100
2199
2200func main() {
2201    x := 42
2202    y := "hello"
2203    z := x + 10
2204    println(x, y, z)
2205}
2206"#
2207    .unindent();
2208
2209    let after = r#"
2210package main
2211
2212var globalCounter: 100 int = 100
2213
2214func main() {
2215    x: 42 := 42
2216    y := "hello"
2217    z := x + 10
2218    println(x, y, z)
2219}
2220"#
2221    .unindent();
2222
2223    test_inline_values_util(
2224        &variables,
2225        &[("globalCounter", "100")],
2226        &before,
2227        &after,
2228        None,
2229        go_lang(),
2230        executor,
2231        cx,
2232    )
2233    .await;
2234}
2235
2236#[gpui::test]
2237async fn test_trim_multi_line_inline_value(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2238    let variables = [("y", "hello\n world")];
2239
2240    let before = r#"
2241fn main() {
2242    let y = "hello\n world";
2243}
2244"#
2245    .unindent();
2246
2247    let after = r#"
2248fn main() {
2249    let y: hello… = "hello\n world";
2250}
2251"#
2252    .unindent();
2253
2254    test_inline_values_util(
2255        &variables,
2256        &[],
2257        &before,
2258        &after,
2259        None,
2260        rust_lang(),
2261        executor,
2262        cx,
2263    )
2264    .await;
2265}
2266
2267fn javascript_lang() -> Arc<Language> {
2268    let debug_variables_query = include_str!("../../../grammars/src/javascript/debugger.scm");
2269    Arc::new(
2270        Language::new(
2271            LanguageConfig {
2272                name: "JavaScript".into(),
2273                matcher: (LanguageMatcher {
2274                    path_suffixes: vec!["js".to_string()],
2275                    ..Default::default()
2276                })
2277                .into(),
2278                ..Default::default()
2279            },
2280            Some(tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into()),
2281        )
2282        .with_debug_variables_query(debug_variables_query)
2283        .unwrap(),
2284    )
2285}
2286
2287fn typescript_lang() -> Arc<Language> {
2288    let debug_variables_query = include_str!("../../../grammars/src/typescript/debugger.scm");
2289    Arc::new(
2290        Language::new(
2291            LanguageConfig {
2292                name: "TypeScript".into(),
2293                matcher: (LanguageMatcher {
2294                    path_suffixes: vec!["ts".to_string()],
2295                    ..Default::default()
2296                })
2297                .into(),
2298                ..Default::default()
2299            },
2300            Some(tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into()),
2301        )
2302        .with_debug_variables_query(debug_variables_query)
2303        .unwrap(),
2304    )
2305}
2306
2307fn tsx_lang() -> Arc<Language> {
2308    let debug_variables_query = include_str!("../../../grammars/src/tsx/debugger.scm");
2309    Arc::new(
2310        Language::new(
2311            LanguageConfig {
2312                name: "TSX".into(),
2313                matcher: (LanguageMatcher {
2314                    path_suffixes: vec!["tsx".to_string()],
2315                    ..Default::default()
2316                })
2317                .into(),
2318                ..Default::default()
2319            },
2320            Some(tree_sitter_typescript::LANGUAGE_TSX.into()),
2321        )
2322        .with_debug_variables_query(debug_variables_query)
2323        .unwrap(),
2324    )
2325}
2326
2327#[gpui::test]
2328async fn test_javascript_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2329    let variables = [
2330        ("x", "10"),
2331        ("y", "20"),
2332        ("sum", "30"),
2333        ("message", "Hello"),
2334    ];
2335
2336    let before = r#"
2337function calculate() {
2338    const x = 10;
2339    const y = 20;
2340    const sum = x + y;
2341    const message = "Hello";
2342    console.log(message, "Sum:", sum);
2343}
2344"#
2345    .unindent();
2346
2347    let after = r#"
2348function calculate() {
2349    const x: 10 = 10;
2350    const y: 20 = 20;
2351    const sum: 30 = x: 10 + y: 20;
2352    const message: Hello = "Hello";
2353    console.log(message, "Sum:", sum);
2354}
2355"#
2356    .unindent();
2357
2358    test_inline_values_util(
2359        &variables,
2360        &[],
2361        &before,
2362        &after,
2363        None,
2364        javascript_lang(),
2365        executor,
2366        cx,
2367    )
2368    .await;
2369}
2370
2371#[gpui::test]
2372async fn test_typescript_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2373    let variables = [
2374        ("count", "42"),
2375        ("name", "Alice"),
2376        ("result", "84"),
2377        ("i", "3"),
2378    ];
2379
2380    let before = r#"
2381function processData(count: number, name: string): number {
2382    let result = count * 2;
2383    for (let i = 0; i < 5; i++) {
2384        console.log(i);
2385    }
2386    return result;
2387}
2388"#
2389    .unindent();
2390
2391    let after = r#"
2392function processData(count: number, name: string): number {
2393    let result: 84 = count: 42 * 2;
2394    for (let i: 3 = 0; i: 3 < 5; i: 3++) {
2395        console.log(i);
2396    }
2397    return result: 84;
2398}
2399"#
2400    .unindent();
2401
2402    test_inline_values_util(
2403        &variables,
2404        &[],
2405        &before,
2406        &after,
2407        None,
2408        typescript_lang(),
2409        executor,
2410        cx,
2411    )
2412    .await;
2413}
2414
2415#[gpui::test]
2416async fn test_tsx_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2417    let variables = [("count", "5"), ("message", "Hello React")];
2418
2419    let before = r#"
2420const Counter = () => {
2421    const count = 5;
2422    const message = "Hello React";
2423    return (
2424        <div>
2425            <p>{message}</p>
2426            <span>{count}</span>
2427        </div>
2428    );
2429};
2430"#
2431    .unindent();
2432
2433    let after = r#"
2434const Counter = () => {
2435    const count: 5 = 5;
2436    const message: Hello React = "Hello React";
2437    return (
2438        <div>
2439            <p>{message: Hello React}</p>
2440            <span>{count}</span>
2441        </div>
2442    );
2443};
2444"#
2445    .unindent();
2446
2447    test_inline_values_util(
2448        &variables,
2449        &[],
2450        &before,
2451        &after,
2452        None,
2453        tsx_lang(),
2454        executor,
2455        cx,
2456    )
2457    .await;
2458}
2459
2460#[gpui::test]
2461async fn test_javascript_arrow_functions(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2462    let variables = [("x", "42"), ("result", "84")];
2463
2464    let before = r#"
2465const double = (x) => {
2466    const result = x * 2;
2467    return result;
2468};
2469"#
2470    .unindent();
2471
2472    let after = r#"
2473const double = (x) => {
2474    const result: 84 = x: 42 * 2;
2475    return result: 84;
2476};
2477"#
2478    .unindent();
2479
2480    test_inline_values_util(
2481        &variables,
2482        &[],
2483        &before,
2484        &after,
2485        None,
2486        javascript_lang(),
2487        executor,
2488        cx,
2489    )
2490    .await;
2491}
2492
2493#[gpui::test]
2494async fn test_typescript_for_in_loop(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2495    let variables = [("key", "name"), ("obj", "{name: 'test'}")];
2496
2497    let before = r#"
2498function iterate() {
2499    const obj = {name: 'test'};
2500    for (const key in obj) {
2501        console.log(key);
2502    }
2503}
2504"#
2505    .unindent();
2506
2507    let after = r#"
2508function iterate() {
2509    const obj: {name: 'test'} = {name: 'test'};
2510    for (const key: name in obj) {
2511        console.log(key);
2512    }
2513}
2514"#
2515    .unindent();
2516
2517    test_inline_values_util(
2518        &variables,
2519        &[],
2520        &before,
2521        &after,
2522        None,
2523        typescript_lang(),
2524        executor,
2525        cx,
2526    )
2527    .await;
2528}
2529
Served at tenant.openagents/omega Member data and write actions are omitted.