Skip to repository content2529 lines · 70.5 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T04:34:18.451Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
inline_values.rs
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