inline_values.rs

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