1use std::{path::Path, sync::Arc};
2
3use dap::{Scope, StackFrame, Variable, requests::Variables};
4use editor::{Editor, EditorMode, MultiBuffer, actions::ToggleInlineValues};
5use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
6use language::{Language, LanguageConfig, LanguageMatcher, tree_sitter_python, tree_sitter_rust};
7use project::{FakeFs, Project};
8use serde_json::json;
9use unindent::Unindent as _;
10use util::path;
11
12use crate::{
13 debugger_panel::DebugPanel,
14 tests::{active_debug_session_panel, init_test, init_test_workspace, start_debug_session},
15};
16
17#[gpui::test]
18async fn test_rust_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
19 init_test(cx);
20
21 fn stack_frame_for_line(line: u64) -> dap::StackFrame {
22 StackFrame {
23 id: 1,
24 name: "Stack Frame 1".into(),
25 source: Some(dap::Source {
26 name: Some("main.rs".into()),
27 path: Some(path!("/project/main.rs").into()),
28 source_reference: None,
29 presentation_hint: None,
30 origin: None,
31 sources: None,
32 adapter_data: None,
33 checksums: None,
34 }),
35 line,
36 column: 1,
37 end_line: None,
38 end_column: None,
39 can_restart: None,
40 instruction_pointer_reference: None,
41 module_id: None,
42 presentation_hint: None,
43 }
44 }
45
46 let fs = FakeFs::new(executor.clone());
47 let source_code = r#"
48static mut GLOBAL: usize = 1;
49
50fn main() {
51 let x = 10;
52 let value = 42;
53 let y = 4;
54 let tester = {
55 let y = 10;
56 let y = 5;
57 let b = 3;
58 vec![y, 20, 30]
59 };
60
61 let caller = || {
62 let x = 3;
63 println!("x={}", x);
64 };
65
66 caller();
67
68 unsafe {
69 GLOBAL = 2;
70 }
71
72 let result = value * 2 * x;
73 println!("Simple test executed: value={}, result={}", value, result);
74 assert!(true);
75}
76"#
77 .unindent();
78 fs.insert_tree(path!("/project"), json!({ "main.rs": source_code }))
79 .await;
80
81 let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
82 let workspace = init_test_workspace(&project, cx).await;
83 workspace
84 .update(cx, |workspace, window, cx| {
85 workspace.focus_panel::<DebugPanel>(window, cx);
86 })
87 .unwrap();
88 let cx = &mut VisualTestContext::from_window(*workspace, cx);
89
90 let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
91 let client = session.update(cx, |session, _| session.adapter_client().unwrap());
92
93 client.on_request::<dap::requests::Threads, _>(move |_, _| {
94 Ok(dap::ThreadsResponse {
95 threads: vec![dap::Thread {
96 id: 1,
97 name: "Thread 1".into(),
98 }],
99 })
100 });
101
102 client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
103 Ok(dap::StackTraceResponse {
104 stack_frames: vec![stack_frame_for_line(4)],
105 total_frames: None,
106 })
107 });
108
109 client.on_request::<dap::requests::Evaluate, _>(move |_, args| {
110 assert_eq!("GLOBAL", args.expression);
111 Ok(dap::EvaluateResponse {
112 result: "1".into(),
113 type_: None,
114 presentation_hint: None,
115 variables_reference: 0,
116 named_variables: None,
117 indexed_variables: None,
118 memory_reference: None,
119 value_location_reference: None,
120 })
121 });
122
123 let local_variables = vec![
124 Variable {
125 name: "x".into(),
126 value: "10".into(),
127 type_: None,
128 presentation_hint: None,
129 evaluate_name: None,
130 variables_reference: 0,
131 named_variables: None,
132 indexed_variables: None,
133 memory_reference: None,
134 declaration_location_reference: None,
135 value_location_reference: None,
136 },
137 Variable {
138 name: "y".into(),
139 value: "4".into(),
140 type_: None,
141 presentation_hint: None,
142 evaluate_name: None,
143 variables_reference: 0,
144 named_variables: None,
145 indexed_variables: None,
146 memory_reference: None,
147 declaration_location_reference: None,
148 value_location_reference: None,
149 },
150 Variable {
151 name: "value".into(),
152 value: "42".into(),
153 type_: None,
154 presentation_hint: None,
155 evaluate_name: None,
156 variables_reference: 0,
157 named_variables: None,
158 indexed_variables: None,
159 memory_reference: None,
160 declaration_location_reference: None,
161 value_location_reference: None,
162 },
163 ];
164
165 client.on_request::<Variables, _>({
166 let local_variables = Arc::new(local_variables.clone());
167 move |_, _| {
168 Ok(dap::VariablesResponse {
169 variables: (*local_variables).clone(),
170 })
171 }
172 });
173
174 client.on_request::<dap::requests::Scopes, _>(move |_, _| {
175 Ok(dap::ScopesResponse {
176 scopes: vec![Scope {
177 name: "Locale".into(),
178 presentation_hint: None,
179 variables_reference: 2,
180 named_variables: None,
181 indexed_variables: None,
182 expensive: false,
183 source: None,
184 line: None,
185 column: None,
186 end_line: None,
187 end_column: None,
188 }],
189 })
190 });
191
192 client
193 .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
194 reason: dap::StoppedEventReason::Pause,
195 description: None,
196 thread_id: Some(1),
197 preserve_focus_hint: None,
198 text: None,
199 all_threads_stopped: None,
200 hit_breakpoint_ids: None,
201 }))
202 .await;
203
204 cx.run_until_parked();
205
206 let project_path = Path::new(path!("/project"));
207 let worktree = project
208 .update(cx, |project, cx| project.find_worktree(project_path, cx))
209 .expect("This worktree should exist in project")
210 .0;
211
212 let worktree_id = workspace
213 .update(cx, |_, _, cx| worktree.read(cx).id())
214 .unwrap();
215
216 let buffer = project
217 .update(cx, |project, cx| {
218 project.open_buffer((worktree_id, "main.rs"), cx)
219 })
220 .await
221 .unwrap();
222
223 buffer.update(cx, |buffer, cx| {
224 buffer.set_language(Some(Arc::new(rust_lang())), cx);
225 });
226
227 let (editor, cx) = cx.add_window_view(|window, cx| {
228 Editor::new(
229 EditorMode::full(),
230 MultiBuffer::build_from_buffer(buffer, cx),
231 Some(project),
232 window,
233 cx,
234 )
235 });
236
237 active_debug_session_panel(workspace, cx).update_in(cx, |_, window, cx| {
238 cx.focus_self(window);
239 });
240 cx.run_until_parked();
241
242 editor.update_in(cx, |editor, window, cx| {
243 if !editor.inline_values_enabled() {
244 editor.toggle_inline_values(&ToggleInlineValues, window, cx);
245 }
246 });
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: 1: usize = 1;
254
255 fn main() {
256 let x = 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: 1: usize = 1;
311
312 fn main() {
313 let x: 10 = 10;
314 let value = 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: 1: usize = 1;
368
369 fn main() {
370 let x: 10 = 10;
371 let value: 42 = 42;
372 let y = 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: 1: 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: 1: 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 = 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: 1: usize = 1;
589
590 fn main() {
591 let x: 10 = 10;
592 let value: 42 = 42;
593 let y = 4;
594 let tester = {
595 let y: 10 = 10;
596 let y = 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: 1: usize = 1;
696
697 fn main() {
698 let x: 10 = 10;
699 let value: 42 = 42;
700 let y = 4;
701 let tester = {
702 let y = 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: 1: usize = 1;
815
816 fn main() {
817 let x: 10 = 10;
818 let value: 42 = 42;
819 let y = 4;
820 let tester = {
821 let y = 10;
822 let y: 5 = 5;
823 let b: 3 = 3;
824 vec![y, 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: 1: 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: 1: 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: 1: usize = 1;
1123
1124 fn main() {
1125 let x = 10;
1126 let value = 42;
1127 let y = 4;
1128 let tester = {
1129 let y = 10;
1130 let y = 5;
1131 let b = 3;
1132 vec![y, 20, 30]
1133 };
1134
1135 let caller = || {
1136 let x = 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: 1: usize = 1;
1201
1202 fn main() {
1203 let x = 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);
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: 2: 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 * 2 * x;
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: 2: 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 * 2 * x;
1515 println!("Simple test executed: value={}, result={}", value, result);
1516 assert!(true);
1517 }
1518 "#
1519 .unindent(),
1520 editor.snapshot(window, cx).text()
1521 );
1522 });
1523}
1524
1525fn rust_lang() -> Language {
1526 Language::new(
1527 LanguageConfig {
1528 name: "Rust".into(),
1529 matcher: LanguageMatcher {
1530 path_suffixes: vec!["rs".to_string()],
1531 ..Default::default()
1532 },
1533 ..Default::default()
1534 },
1535 Some(tree_sitter_rust::LANGUAGE.into()),
1536 )
1537}
1538
1539#[gpui::test]
1540async fn test_python_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
1541 init_test(cx);
1542
1543 let fs = FakeFs::new(executor.clone());
1544 let source_code = r#"
1545def process_data(untyped_param, typed_param: int, another_typed: str):
1546 # Local variables
1547 x = 10
1548 result = typed_param * 2
1549 text = "Hello, " + another_typed
1550
1551 # For loop with range
1552 sum_value = 0
1553 for i in range(5):
1554 sum_value += i
1555
1556 # Final result
1557 final_result = x + result + sum_value
1558 return final_result
1559"#
1560 .unindent();
1561 fs.insert_tree(path!("/project"), json!({ "main.py": source_code }))
1562 .await;
1563
1564 let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
1565 let workspace = init_test_workspace(&project, cx).await;
1566 workspace
1567 .update(cx, |workspace, window, cx| {
1568 workspace.focus_panel::<DebugPanel>(window, cx);
1569 })
1570 .unwrap();
1571 let cx = &mut VisualTestContext::from_window(*workspace, cx);
1572
1573 let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
1574 let client = session.update(cx, |session, _| session.adapter_client().unwrap());
1575
1576 let project_path = Path::new(path!("/project"));
1577 let worktree = project
1578 .update(cx, |project, cx| project.find_worktree(project_path, cx))
1579 .expect("This worktree should exist in project")
1580 .0;
1581
1582 let worktree_id = workspace
1583 .update(cx, |_, _, cx| worktree.read(cx).id())
1584 .unwrap();
1585
1586 let buffer = project
1587 .update(cx, |project, cx| {
1588 project.open_buffer((worktree_id, "main.py"), cx)
1589 })
1590 .await
1591 .unwrap();
1592
1593 buffer.update(cx, |buffer, cx| {
1594 buffer.set_language(Some(Arc::new(python_lang())), cx);
1595 });
1596
1597 let (editor, cx) = cx.add_window_view(|window, cx| {
1598 Editor::new(
1599 EditorMode::full(),
1600 MultiBuffer::build_from_buffer(buffer, cx),
1601 Some(project),
1602 window,
1603 cx,
1604 )
1605 });
1606
1607 editor.update_in(cx, |editor, window, cx| {
1608 if !editor.inline_values_enabled() {
1609 editor.toggle_inline_values(&ToggleInlineValues, window, cx);
1610 }
1611 });
1612
1613 client.on_request::<dap::requests::Threads, _>(move |_, _| {
1614 Ok(dap::ThreadsResponse {
1615 threads: vec![dap::Thread {
1616 id: 1,
1617 name: "Thread 1".into(),
1618 }],
1619 })
1620 });
1621
1622 client.on_request::<dap::requests::StackTrace, _>(move |_, args| {
1623 assert_eq!(args.thread_id, 1);
1624 Ok(dap::StackTraceResponse {
1625 stack_frames: vec![StackFrame {
1626 id: 1,
1627 name: "Stack Frame 1".into(),
1628 source: Some(dap::Source {
1629 name: Some("main.py".into()),
1630 path: Some(path!("/project/main.py").into()),
1631 source_reference: None,
1632 presentation_hint: None,
1633 origin: None,
1634 sources: None,
1635 adapter_data: None,
1636 checksums: None,
1637 }),
1638 line: 12,
1639 column: 1,
1640 end_line: None,
1641 end_column: None,
1642 can_restart: None,
1643 instruction_pointer_reference: None,
1644 module_id: None,
1645 presentation_hint: None,
1646 }],
1647 total_frames: None,
1648 })
1649 });
1650
1651 client.on_request::<dap::requests::Scopes, _>(move |_, _| {
1652 Ok(dap::ScopesResponse {
1653 scopes: vec![
1654 Scope {
1655 name: "Local".into(),
1656 presentation_hint: None,
1657 variables_reference: 1,
1658 named_variables: None,
1659 indexed_variables: None,
1660 expensive: false,
1661 source: None,
1662 line: None,
1663 column: None,
1664 end_line: None,
1665 end_column: None,
1666 },
1667 Scope {
1668 name: "Global".into(),
1669 presentation_hint: None,
1670 variables_reference: 2,
1671 named_variables: None,
1672 indexed_variables: None,
1673 expensive: false,
1674 source: None,
1675 line: None,
1676 column: None,
1677 end_line: None,
1678 end_column: None,
1679 },
1680 ],
1681 })
1682 });
1683
1684 client.on_request::<Variables, _>(move |_, args| match args.variables_reference {
1685 1 => Ok(dap::VariablesResponse {
1686 variables: vec![
1687 Variable {
1688 name: "untyped_param".into(),
1689 value: "test_value".into(),
1690 type_: Some("str".into()),
1691 presentation_hint: None,
1692 evaluate_name: None,
1693 variables_reference: 0,
1694 named_variables: None,
1695 indexed_variables: None,
1696 memory_reference: None,
1697 declaration_location_reference: None,
1698 value_location_reference: None,
1699 },
1700 Variable {
1701 name: "typed_param".into(),
1702 value: "42".into(),
1703 type_: Some("int".into()),
1704 presentation_hint: None,
1705 evaluate_name: None,
1706 variables_reference: 0,
1707 named_variables: None,
1708 indexed_variables: None,
1709 memory_reference: None,
1710 declaration_location_reference: None,
1711 value_location_reference: None,
1712 },
1713 Variable {
1714 name: "another_typed".into(),
1715 value: "world".into(),
1716 type_: Some("str".into()),
1717 presentation_hint: None,
1718 evaluate_name: None,
1719 variables_reference: 0,
1720 named_variables: None,
1721 indexed_variables: None,
1722 memory_reference: None,
1723 declaration_location_reference: None,
1724 value_location_reference: None,
1725 },
1726 Variable {
1727 name: "x".into(),
1728 value: "10".into(),
1729 type_: Some("int".into()),
1730 presentation_hint: None,
1731 evaluate_name: None,
1732 variables_reference: 0,
1733 named_variables: None,
1734 indexed_variables: None,
1735 memory_reference: None,
1736 declaration_location_reference: None,
1737 value_location_reference: None,
1738 },
1739 Variable {
1740 name: "result".into(),
1741 value: "84".into(),
1742 type_: Some("int".into()),
1743 presentation_hint: None,
1744 evaluate_name: None,
1745 variables_reference: 0,
1746 named_variables: None,
1747 indexed_variables: None,
1748 memory_reference: None,
1749 declaration_location_reference: None,
1750 value_location_reference: None,
1751 },
1752 Variable {
1753 name: "text".into(),
1754 value: "Hello, world".into(),
1755 type_: Some("str".into()),
1756 presentation_hint: None,
1757 evaluate_name: None,
1758 variables_reference: 0,
1759 named_variables: None,
1760 indexed_variables: None,
1761 memory_reference: None,
1762 declaration_location_reference: None,
1763 value_location_reference: None,
1764 },
1765 Variable {
1766 name: "sum_value".into(),
1767 value: "10".into(),
1768 type_: Some("int".into()),
1769 presentation_hint: None,
1770 evaluate_name: None,
1771 variables_reference: 0,
1772 named_variables: None,
1773 indexed_variables: None,
1774 memory_reference: None,
1775 declaration_location_reference: None,
1776 value_location_reference: None,
1777 },
1778 Variable {
1779 name: "i".into(),
1780 value: "4".into(),
1781 type_: Some("int".into()),
1782 presentation_hint: None,
1783 evaluate_name: None,
1784 variables_reference: 0,
1785 named_variables: None,
1786 indexed_variables: None,
1787 memory_reference: None,
1788 declaration_location_reference: None,
1789 value_location_reference: None,
1790 },
1791 Variable {
1792 name: "final_result".into(),
1793 value: "104".into(),
1794 type_: Some("int".into()),
1795 presentation_hint: None,
1796 evaluate_name: None,
1797 variables_reference: 0,
1798 named_variables: None,
1799 indexed_variables: None,
1800 memory_reference: None,
1801 declaration_location_reference: None,
1802 value_location_reference: None,
1803 },
1804 ],
1805 }),
1806 _ => Ok(dap::VariablesResponse { variables: vec![] }),
1807 });
1808
1809 client
1810 .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1811 reason: dap::StoppedEventReason::Pause,
1812 description: None,
1813 thread_id: Some(1),
1814 preserve_focus_hint: None,
1815 text: None,
1816 all_threads_stopped: None,
1817 hit_breakpoint_ids: None,
1818 }))
1819 .await;
1820
1821 cx.run_until_parked();
1822
1823 editor.update_in(cx, |editor, window, cx| {
1824 pretty_assertions::assert_eq!(
1825 r#"
1826 def process_data(untyped_param: test_value, typed_param: 42: int, another_typed: world: str):
1827 # Local variables
1828 x: 10 = 10
1829 result: 84 = typed_param * 2
1830 text: Hello, world = "Hello, " + another_typed
1831
1832 # For loop with range
1833 sum_value: 10 = 0
1834 for i: 4 in range(5):
1835 sum_value += i
1836
1837 # Final result
1838 final_result = x + result + sum_value
1839 return final_result
1840 "#
1841 .unindent(),
1842 editor.snapshot(window, cx).text()
1843 );
1844 });
1845}
1846
1847fn python_lang() -> Language {
1848 Language::new(
1849 LanguageConfig {
1850 name: "Python".into(),
1851 matcher: LanguageMatcher {
1852 path_suffixes: vec!["py".to_string()],
1853 ..Default::default()
1854 },
1855 ..Default::default()
1856 },
1857 Some(tree_sitter_python::LANGUAGE.into()),
1858 )
1859}