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, tree_sitter_python, tree_sitter_rust,
   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(Arc::new(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
1524fn rust_lang() -> Language {
1525    let debug_variables_query = include_str!("../../../languages/src/rust/debugger.scm");
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    .with_debug_variables_query(debug_variables_query)
1538    .unwrap()
1539}
1540
1541#[gpui::test]
1542async fn test_python_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
1543    init_test(cx);
1544
1545    let fs = FakeFs::new(executor.clone());
1546    let source_code = r#"
1547def process_data(untyped_param, typed_param: int, another_typed: str):
1548    # Local variables
1549    x = 10
1550    result = typed_param * 2
1551    text = "Hello, " + another_typed
1552
1553    # For loop with range
1554    sum_value = 0
1555    for i in range(5):
1556        sum_value += i
1557
1558    # Final result
1559    final_result = x + result + sum_value
1560    return final_result
1561"#
1562    .unindent();
1563    fs.insert_tree(path!("/project"), json!({ "main.py": source_code }))
1564        .await;
1565
1566    let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
1567    let workspace = init_test_workspace(&project, cx).await;
1568    workspace
1569        .update(cx, |workspace, window, cx| {
1570            workspace.focus_panel::<DebugPanel>(window, cx);
1571        })
1572        .unwrap();
1573    let cx = &mut VisualTestContext::from_window(*workspace, cx);
1574
1575    let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
1576    let client = session.update(cx, |session, _| session.adapter_client().unwrap());
1577
1578    let project_path = Path::new(path!("/project"));
1579    let worktree = project
1580        .update(cx, |project, cx| project.find_worktree(project_path, cx))
1581        .expect("This worktree should exist in project")
1582        .0;
1583
1584    let worktree_id = workspace
1585        .update(cx, |_, _, cx| worktree.read(cx).id())
1586        .unwrap();
1587
1588    let buffer = project
1589        .update(cx, |project, cx| {
1590            project.open_buffer((worktree_id, rel_path("main.py")), cx)
1591        })
1592        .await
1593        .unwrap();
1594
1595    buffer.update(cx, |buffer, cx| {
1596        buffer.set_language(Some(Arc::new(python_lang())), cx);
1597    });
1598
1599    let (editor, cx) = cx.add_window_view(|window, cx| {
1600        Editor::new(
1601            EditorMode::full(),
1602            MultiBuffer::build_from_buffer(buffer, cx),
1603            Some(project),
1604            window,
1605            cx,
1606        )
1607    });
1608
1609    editor.update(cx, |editor, cx| editor.refresh_inline_values(cx));
1610
1611    client.on_request::<dap::requests::Threads, _>(move |_, _| {
1612        Ok(dap::ThreadsResponse {
1613            threads: vec![dap::Thread {
1614                id: 1,
1615                name: "Thread 1".into(),
1616            }],
1617        })
1618    });
1619
1620    client.on_request::<dap::requests::StackTrace, _>(move |_, args| {
1621        assert_eq!(args.thread_id, 1);
1622        Ok(dap::StackTraceResponse {
1623            stack_frames: vec![StackFrame {
1624                id: 1,
1625                name: "Stack Frame 1".into(),
1626                source: Some(dap::Source {
1627                    name: Some("main.py".into()),
1628                    path: Some(path!("/project/main.py").into()),
1629                    source_reference: None,
1630                    presentation_hint: None,
1631                    origin: None,
1632                    sources: None,
1633                    adapter_data: None,
1634                    checksums: None,
1635                }),
1636                line: 12,
1637                column: 1,
1638                end_line: None,
1639                end_column: None,
1640                can_restart: None,
1641                instruction_pointer_reference: None,
1642                module_id: None,
1643                presentation_hint: None,
1644            }],
1645            total_frames: None,
1646        })
1647    });
1648
1649    client.on_request::<dap::requests::Scopes, _>(move |_, _| {
1650        Ok(dap::ScopesResponse {
1651            scopes: vec![
1652                Scope {
1653                    name: "Local".into(),
1654                    presentation_hint: None,
1655                    variables_reference: 1,
1656                    named_variables: None,
1657                    indexed_variables: None,
1658                    expensive: false,
1659                    source: None,
1660                    line: None,
1661                    column: None,
1662                    end_line: None,
1663                    end_column: None,
1664                },
1665                Scope {
1666                    name: "Global".into(),
1667                    presentation_hint: None,
1668                    variables_reference: 2,
1669                    named_variables: None,
1670                    indexed_variables: None,
1671                    expensive: false,
1672                    source: None,
1673                    line: None,
1674                    column: None,
1675                    end_line: None,
1676                    end_column: None,
1677                },
1678            ],
1679        })
1680    });
1681
1682    client.on_request::<Variables, _>(move |_, args| match args.variables_reference {
1683        1 => Ok(dap::VariablesResponse {
1684            variables: vec![
1685                Variable {
1686                    name: "untyped_param".into(),
1687                    value: "test_value".into(),
1688                    type_: Some("str".into()),
1689                    presentation_hint: None,
1690                    evaluate_name: None,
1691                    variables_reference: 0,
1692                    named_variables: None,
1693                    indexed_variables: None,
1694                    memory_reference: None,
1695                    declaration_location_reference: None,
1696                    value_location_reference: None,
1697                },
1698                Variable {
1699                    name: "typed_param".into(),
1700                    value: "42".into(),
1701                    type_: Some("int".into()),
1702                    presentation_hint: None,
1703                    evaluate_name: None,
1704                    variables_reference: 0,
1705                    named_variables: None,
1706                    indexed_variables: None,
1707                    memory_reference: None,
1708                    declaration_location_reference: None,
1709                    value_location_reference: None,
1710                },
1711                Variable {
1712                    name: "another_typed".into(),
1713                    value: "world".into(),
1714                    type_: Some("str".into()),
1715                    presentation_hint: None,
1716                    evaluate_name: None,
1717                    variables_reference: 0,
1718                    named_variables: None,
1719                    indexed_variables: None,
1720                    memory_reference: None,
1721                    declaration_location_reference: None,
1722                    value_location_reference: None,
1723                },
1724                Variable {
1725                    name: "x".into(),
1726                    value: "10".into(),
1727                    type_: Some("int".into()),
1728                    presentation_hint: None,
1729                    evaluate_name: None,
1730                    variables_reference: 0,
1731                    named_variables: None,
1732                    indexed_variables: None,
1733                    memory_reference: None,
1734                    declaration_location_reference: None,
1735                    value_location_reference: None,
1736                },
1737                Variable {
1738                    name: "result".into(),
1739                    value: "84".into(),
1740                    type_: Some("int".into()),
1741                    presentation_hint: None,
1742                    evaluate_name: None,
1743                    variables_reference: 0,
1744                    named_variables: None,
1745                    indexed_variables: None,
1746                    memory_reference: None,
1747                    declaration_location_reference: None,
1748                    value_location_reference: None,
1749                },
1750                Variable {
1751                    name: "text".into(),
1752                    value: "Hello, world".into(),
1753                    type_: Some("str".into()),
1754                    presentation_hint: None,
1755                    evaluate_name: None,
1756                    variables_reference: 0,
1757                    named_variables: None,
1758                    indexed_variables: None,
1759                    memory_reference: None,
1760                    declaration_location_reference: None,
1761                    value_location_reference: None,
1762                },
1763                Variable {
1764                    name: "sum_value".into(),
1765                    value: "10".into(),
1766                    type_: Some("int".into()),
1767                    presentation_hint: None,
1768                    evaluate_name: None,
1769                    variables_reference: 0,
1770                    named_variables: None,
1771                    indexed_variables: None,
1772                    memory_reference: None,
1773                    declaration_location_reference: None,
1774                    value_location_reference: None,
1775                },
1776                Variable {
1777                    name: "i".into(),
1778                    value: "4".into(),
1779                    type_: Some("int".into()),
1780                    presentation_hint: None,
1781                    evaluate_name: None,
1782                    variables_reference: 0,
1783                    named_variables: None,
1784                    indexed_variables: None,
1785                    memory_reference: None,
1786                    declaration_location_reference: None,
1787                    value_location_reference: None,
1788                },
1789                Variable {
1790                    name: "final_result".into(),
1791                    value: "104".into(),
1792                    type_: Some("int".into()),
1793                    presentation_hint: None,
1794                    evaluate_name: None,
1795                    variables_reference: 0,
1796                    named_variables: None,
1797                    indexed_variables: None,
1798                    memory_reference: None,
1799                    declaration_location_reference: None,
1800                    value_location_reference: None,
1801                },
1802            ],
1803        }),
1804        _ => Ok(dap::VariablesResponse { variables: vec![] }),
1805    });
1806
1807    client
1808        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
1809            reason: dap::StoppedEventReason::Pause,
1810            description: None,
1811            thread_id: Some(1),
1812            preserve_focus_hint: None,
1813            text: None,
1814            all_threads_stopped: None,
1815            hit_breakpoint_ids: None,
1816        }))
1817        .await;
1818
1819    cx.run_until_parked();
1820
1821    editor.update_in(cx, |editor, window, cx| {
1822        pretty_assertions::assert_eq!(
1823            r#"
1824        def process_data(untyped_param: test_value, typed_param: 42: int, another_typed: world: str):
1825            # Local variables
1826            x: 10 = 10
1827            result: 84 = typed_param: 42 * 2
1828            text: Hello, world = "Hello, " + another_typed: world
1829
1830            # For loop with range
1831            sum_value: 10 = 0
1832            for i: 4 in range(5):
1833                sum_value += i
1834
1835            # Final result
1836            final_result = x + result + sum_value
1837            return final_result
1838        "#
1839            .unindent(),
1840            editor.snapshot(window, cx).text()
1841        );
1842    });
1843}
1844
1845fn python_lang() -> Language {
1846    let debug_variables_query = include_str!("../../../languages/src/python/debugger.scm");
1847    Language::new(
1848        LanguageConfig {
1849            name: "Python".into(),
1850            matcher: LanguageMatcher {
1851                path_suffixes: vec!["py".to_string()],
1852                ..Default::default()
1853            },
1854            ..Default::default()
1855        },
1856        Some(tree_sitter_python::LANGUAGE.into()),
1857    )
1858    .with_debug_variables_query(debug_variables_query)
1859    .unwrap()
1860}
1861
1862fn go_lang() -> Language {
1863    let debug_variables_query = include_str!("../../../languages/src/go/debugger.scm");
1864    Language::new(
1865        LanguageConfig {
1866            name: "Go".into(),
1867            matcher: LanguageMatcher {
1868                path_suffixes: vec!["go".to_string()],
1869                ..Default::default()
1870            },
1871            ..Default::default()
1872        },
1873        Some(tree_sitter_go::LANGUAGE.into()),
1874    )
1875    .with_debug_variables_query(debug_variables_query)
1876    .unwrap()
1877}
1878
1879/// Test utility function for inline values testing
1880///
1881/// # Arguments
1882/// * `variables` - List of tuples containing (variable_name, variable_value)
1883/// * `before` - Source code before inline values are applied
1884/// * `after` - Expected source code after inline values are applied
1885/// * `language` - Language configuration to use for parsing
1886/// * `executor` - Background executor for async operations
1887/// * `cx` - Test app context
1888async fn test_inline_values_util(
1889    local_variables: &[(&str, &str)],
1890    global_variables: &[(&str, &str)],
1891    before: &str,
1892    after: &str,
1893    active_debug_line: Option<usize>,
1894    language: Language,
1895    executor: BackgroundExecutor,
1896    cx: &mut TestAppContext,
1897) {
1898    init_test(cx);
1899
1900    let lines_count = before.lines().count();
1901    let stop_line =
1902        active_debug_line.unwrap_or_else(|| if lines_count > 6 { 6 } else { lines_count - 1 });
1903
1904    let fs = FakeFs::new(executor.clone());
1905    fs.insert_tree(path!("/project"), json!({ "main.rs": before.to_string() }))
1906        .await;
1907
1908    let project = Project::test(fs.clone(), [path!("/project").as_ref()], cx).await;
1909    let workspace = init_test_workspace(&project, cx).await;
1910    workspace
1911        .update(cx, |workspace, window, cx| {
1912            workspace.focus_panel::<DebugPanel>(window, cx);
1913        })
1914        .unwrap();
1915    let cx = &mut VisualTestContext::from_window(*workspace, cx);
1916
1917    let session = start_debug_session(&workspace, cx, |_| {}).unwrap();
1918    let client = session.update(cx, |session, _| session.adapter_client().unwrap());
1919
1920    client.on_request::<dap::requests::Threads, _>(|_, _| {
1921        Ok(dap::ThreadsResponse {
1922            threads: vec![dap::Thread {
1923                id: 1,
1924                name: "main".into(),
1925            }],
1926        })
1927    });
1928
1929    client.on_request::<dap::requests::StackTrace, _>(move |_, _| {
1930        Ok(dap::StackTraceResponse {
1931            stack_frames: vec![dap::StackFrame {
1932                id: 1,
1933                name: "main".into(),
1934                source: Some(dap::Source {
1935                    name: Some("main.rs".into()),
1936                    path: Some(path!("/project/main.rs").into()),
1937                    source_reference: None,
1938                    presentation_hint: None,
1939                    origin: None,
1940                    sources: None,
1941                    adapter_data: None,
1942                    checksums: None,
1943                }),
1944                line: stop_line as u64,
1945                column: 1,
1946                end_line: None,
1947                end_column: None,
1948                can_restart: None,
1949                instruction_pointer_reference: None,
1950                module_id: None,
1951                presentation_hint: None,
1952            }],
1953            total_frames: None,
1954        })
1955    });
1956
1957    let local_vars: Vec<Variable> = local_variables
1958        .iter()
1959        .map(|(name, value)| Variable {
1960            name: (*name).into(),
1961            value: (*value).into(),
1962            type_: None,
1963            presentation_hint: None,
1964            evaluate_name: None,
1965            variables_reference: 0,
1966            named_variables: None,
1967            indexed_variables: None,
1968            memory_reference: None,
1969            declaration_location_reference: None,
1970            value_location_reference: None,
1971        })
1972        .collect();
1973
1974    let global_vars: Vec<Variable> = global_variables
1975        .iter()
1976        .map(|(name, value)| Variable {
1977            name: (*name).into(),
1978            value: (*value).into(),
1979            type_: None,
1980            presentation_hint: None,
1981            evaluate_name: None,
1982            variables_reference: 0,
1983            named_variables: None,
1984            indexed_variables: None,
1985            memory_reference: None,
1986            declaration_location_reference: None,
1987            value_location_reference: None,
1988        })
1989        .collect();
1990
1991    client.on_request::<Variables, _>({
1992        let local_vars = Arc::new(local_vars.clone());
1993        let global_vars = Arc::new(global_vars.clone());
1994        move |_, args| {
1995            let variables = match args.variables_reference {
1996                2 => (*local_vars).clone(),
1997                3 => (*global_vars).clone(),
1998                _ => vec![],
1999            };
2000            Ok(dap::VariablesResponse { variables })
2001        }
2002    });
2003
2004    client.on_request::<dap::requests::Scopes, _>(move |_, _| {
2005        Ok(dap::ScopesResponse {
2006            scopes: vec![
2007                Scope {
2008                    name: "Local".into(),
2009                    presentation_hint: None,
2010                    variables_reference: 2,
2011                    named_variables: None,
2012                    indexed_variables: None,
2013                    expensive: false,
2014                    source: None,
2015                    line: None,
2016                    column: None,
2017                    end_line: None,
2018                    end_column: None,
2019                },
2020                Scope {
2021                    name: "Global".into(),
2022                    presentation_hint: None,
2023                    variables_reference: 3,
2024                    named_variables: None,
2025                    indexed_variables: None,
2026                    expensive: false,
2027                    source: None,
2028                    line: None,
2029                    column: None,
2030                    end_line: None,
2031                    end_column: None,
2032                },
2033            ],
2034        })
2035    });
2036
2037    if !global_variables.is_empty() {
2038        let global_evaluate_map: std::collections::HashMap<String, String> = global_variables
2039            .iter()
2040            .map(|(name, value)| (name.to_string(), value.to_string()))
2041            .collect();
2042
2043        client.on_request::<dap::requests::Evaluate, _>(move |_, args| {
2044            let value = global_evaluate_map
2045                .get(&args.expression)
2046                .unwrap_or(&"undefined".to_string())
2047                .clone();
2048
2049            Ok(dap::EvaluateResponse {
2050                result: value,
2051                type_: None,
2052                presentation_hint: None,
2053                variables_reference: 0,
2054                named_variables: None,
2055                indexed_variables: None,
2056                memory_reference: None,
2057                value_location_reference: None,
2058            })
2059        });
2060    }
2061
2062    client
2063        .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent {
2064            reason: dap::StoppedEventReason::Pause,
2065            description: None,
2066            thread_id: Some(1),
2067            preserve_focus_hint: None,
2068            text: None,
2069            all_threads_stopped: None,
2070            hit_breakpoint_ids: None,
2071        }))
2072        .await;
2073
2074    cx.run_until_parked();
2075
2076    let project_path = Path::new(path!("/project"));
2077    let worktree = project
2078        .update(cx, |project, cx| project.find_worktree(project_path, cx))
2079        .expect("This worktree should exist in project")
2080        .0;
2081
2082    let worktree_id = workspace
2083        .update(cx, |_, _, cx| worktree.read(cx).id())
2084        .unwrap();
2085
2086    let buffer = project
2087        .update(cx, |project, cx| {
2088            project.open_buffer((worktree_id, rel_path("main.rs")), cx)
2089        })
2090        .await
2091        .unwrap();
2092
2093    buffer.update(cx, |buffer, cx| {
2094        buffer.set_language(Some(Arc::new(language)), cx);
2095    });
2096
2097    let (editor, cx) = cx.add_window_view(|window, cx| {
2098        Editor::new(
2099            EditorMode::full(),
2100            MultiBuffer::build_from_buffer(buffer, cx),
2101            Some(project),
2102            window,
2103            cx,
2104        )
2105    });
2106
2107    active_debug_session_panel(workspace, cx).update_in(cx, |_, window, cx| {
2108        cx.focus_self(window);
2109    });
2110    cx.run_until_parked();
2111
2112    editor.update(cx, |editor, cx| editor.refresh_inline_values(cx));
2113
2114    cx.run_until_parked();
2115
2116    editor.update_in(cx, |editor, window, cx| {
2117        pretty_assertions::assert_eq!(after, editor.snapshot(window, cx).text());
2118    });
2119}
2120
2121#[gpui::test]
2122async fn test_inline_values_example(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2123    let variables = [("x", "10"), ("y", "20"), ("result", "30")];
2124
2125    let before = r#"
2126fn main() {
2127    let x = 10;
2128    let y = 20;
2129    let result = x + y;
2130    println!("Result: {}", result);
2131}
2132"#
2133    .unindent();
2134
2135    let after = r#"
2136fn main() {
2137    let x: 10 = 10;
2138    let y: 20 = 20;
2139    let result: 30 = x: 10 + y: 20;
2140    println!("Result: {}", result: 30);
2141}
2142"#
2143    .unindent();
2144
2145    test_inline_values_util(
2146        &variables,
2147        &[],
2148        &before,
2149        &after,
2150        None,
2151        rust_lang(),
2152        executor,
2153        cx,
2154    )
2155    .await;
2156}
2157
2158#[gpui::test]
2159async fn test_inline_values_with_globals(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2160    let variables = [("x", "5"), ("y", "10")];
2161
2162    let before = r#"
2163static mut GLOBAL_COUNTER: usize = 42;
2164
2165fn main() {
2166    let x = 5;
2167    let y = 10;
2168    unsafe {
2169        GLOBAL_COUNTER += 1;
2170    }
2171    println!("x={}, y={}, global={}", x, y, unsafe { GLOBAL_COUNTER });
2172}
2173"#
2174    .unindent();
2175
2176    let after = r#"
2177static mut GLOBAL_COUNTER: 42: usize = 42;
2178
2179fn main() {
2180    let x: 5 = 5;
2181    let y: 10 = 10;
2182    unsafe {
2183        GLOBAL_COUNTER += 1;
2184    }
2185    println!("x={}, y={}, global={}", x, y, unsafe { GLOBAL_COUNTER });
2186}
2187"#
2188    .unindent();
2189
2190    test_inline_values_util(
2191        &variables,
2192        &[("GLOBAL_COUNTER", "42")],
2193        &before,
2194        &after,
2195        None,
2196        rust_lang(),
2197        executor,
2198        cx,
2199    )
2200    .await;
2201}
2202
2203#[gpui::test]
2204async fn test_go_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2205    let variables = [("x", "42"), ("y", "hello")];
2206
2207    let before = r#"
2208package main
2209
2210var globalCounter int = 100
2211
2212func main() {
2213    x := 42
2214    y := "hello"
2215    z := x + 10
2216    println(x, y, z)
2217}
2218"#
2219    .unindent();
2220
2221    let after = r#"
2222package main
2223
2224var globalCounter: 100 int = 100
2225
2226func main() {
2227    x: 42 := 42
2228    y := "hello"
2229    z := x + 10
2230    println(x, y, z)
2231}
2232"#
2233    .unindent();
2234
2235    test_inline_values_util(
2236        &variables,
2237        &[("globalCounter", "100")],
2238        &before,
2239        &after,
2240        None,
2241        go_lang(),
2242        executor,
2243        cx,
2244    )
2245    .await;
2246}
2247
2248#[gpui::test]
2249async fn test_trim_multi_line_inline_value(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2250    let variables = [("y", "hello\n world")];
2251
2252    let before = r#"
2253fn main() {
2254    let y = "hello\n world";
2255}
2256"#
2257    .unindent();
2258
2259    let after = r#"
2260fn main() {
2261    let y: hello… = "hello\n world";
2262}
2263"#
2264    .unindent();
2265
2266    test_inline_values_util(
2267        &variables,
2268        &[],
2269        &before,
2270        &after,
2271        None,
2272        rust_lang(),
2273        executor,
2274        cx,
2275    )
2276    .await;
2277}
2278
2279fn javascript_lang() -> Language {
2280    let debug_variables_query = include_str!("../../../languages/src/javascript/debugger.scm");
2281    Language::new(
2282        LanguageConfig {
2283            name: "JavaScript".into(),
2284            matcher: LanguageMatcher {
2285                path_suffixes: vec!["js".to_string()],
2286                ..Default::default()
2287            },
2288            ..Default::default()
2289        },
2290        Some(tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into()),
2291    )
2292    .with_debug_variables_query(debug_variables_query)
2293    .unwrap()
2294}
2295
2296fn typescript_lang() -> Language {
2297    let debug_variables_query = include_str!("../../../languages/src/typescript/debugger.scm");
2298    Language::new(
2299        LanguageConfig {
2300            name: "TypeScript".into(),
2301            matcher: LanguageMatcher {
2302                path_suffixes: vec!["ts".to_string()],
2303                ..Default::default()
2304            },
2305            ..Default::default()
2306        },
2307        Some(tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into()),
2308    )
2309    .with_debug_variables_query(debug_variables_query)
2310    .unwrap()
2311}
2312
2313fn tsx_lang() -> Language {
2314    let debug_variables_query = include_str!("../../../languages/src/tsx/debugger.scm");
2315    Language::new(
2316        LanguageConfig {
2317            name: "TSX".into(),
2318            matcher: LanguageMatcher {
2319                path_suffixes: vec!["tsx".to_string()],
2320                ..Default::default()
2321            },
2322            ..Default::default()
2323        },
2324        Some(tree_sitter_typescript::LANGUAGE_TSX.into()),
2325    )
2326    .with_debug_variables_query(debug_variables_query)
2327    .unwrap()
2328}
2329
2330#[gpui::test]
2331async fn test_javascript_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2332    let variables = [
2333        ("x", "10"),
2334        ("y", "20"),
2335        ("sum", "30"),
2336        ("message", "Hello"),
2337    ];
2338
2339    let before = r#"
2340function calculate() {
2341    const x = 10;
2342    const y = 20;
2343    const sum = x + y;
2344    const message = "Hello";
2345    console.log(message, "Sum:", sum);
2346}
2347"#
2348    .unindent();
2349
2350    let after = r#"
2351function calculate() {
2352    const x: 10 = 10;
2353    const y: 20 = 20;
2354    const sum: 30 = x: 10 + y: 20;
2355    const message: Hello = "Hello";
2356    console.log(message, "Sum:", sum);
2357}
2358"#
2359    .unindent();
2360
2361    test_inline_values_util(
2362        &variables,
2363        &[],
2364        &before,
2365        &after,
2366        None,
2367        javascript_lang(),
2368        executor,
2369        cx,
2370    )
2371    .await;
2372}
2373
2374#[gpui::test]
2375async fn test_typescript_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2376    let variables = [
2377        ("count", "42"),
2378        ("name", "Alice"),
2379        ("result", "84"),
2380        ("i", "3"),
2381    ];
2382
2383    let before = r#"
2384function processData(count: number, name: string): number {
2385    let result = count * 2;
2386    for (let i = 0; i < 5; i++) {
2387        console.log(i);
2388    }
2389    return result;
2390}
2391"#
2392    .unindent();
2393
2394    let after = r#"
2395function processData(count: number, name: string): number {
2396    let result: 84 = count: 42 * 2;
2397    for (let i: 3 = 0; i: 3 < 5; i: 3++) {
2398        console.log(i);
2399    }
2400    return result: 84;
2401}
2402"#
2403    .unindent();
2404
2405    test_inline_values_util(
2406        &variables,
2407        &[],
2408        &before,
2409        &after,
2410        None,
2411        typescript_lang(),
2412        executor,
2413        cx,
2414    )
2415    .await;
2416}
2417
2418#[gpui::test]
2419async fn test_tsx_inline_values(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2420    let variables = [("count", "5"), ("message", "Hello React")];
2421
2422    let before = r#"
2423const Counter = () => {
2424    const count = 5;
2425    const message = "Hello React";
2426    return (
2427        <div>
2428            <p>{message}</p>
2429            <span>{count}</span>
2430        </div>
2431    );
2432};
2433"#
2434    .unindent();
2435
2436    let after = r#"
2437const Counter = () => {
2438    const count: 5 = 5;
2439    const message: Hello React = "Hello React";
2440    return (
2441        <div>
2442            <p>{message: Hello React}</p>
2443            <span>{count}</span>
2444        </div>
2445    );
2446};
2447"#
2448    .unindent();
2449
2450    test_inline_values_util(
2451        &variables,
2452        &[],
2453        &before,
2454        &after,
2455        None,
2456        tsx_lang(),
2457        executor,
2458        cx,
2459    )
2460    .await;
2461}
2462
2463#[gpui::test]
2464async fn test_javascript_arrow_functions(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2465    let variables = [("x", "42"), ("result", "84")];
2466
2467    let before = r#"
2468const double = (x) => {
2469    const result = x * 2;
2470    return result;
2471};
2472"#
2473    .unindent();
2474
2475    let after = r#"
2476const double = (x) => {
2477    const result: 84 = x: 42 * 2;
2478    return result: 84;
2479};
2480"#
2481    .unindent();
2482
2483    test_inline_values_util(
2484        &variables,
2485        &[],
2486        &before,
2487        &after,
2488        None,
2489        javascript_lang(),
2490        executor,
2491        cx,
2492    )
2493    .await;
2494}
2495
2496#[gpui::test]
2497async fn test_typescript_for_in_loop(executor: BackgroundExecutor, cx: &mut TestAppContext) {
2498    let variables = [("key", "name"), ("obj", "{name: 'test'}")];
2499
2500    let before = r#"
2501function iterate() {
2502    const obj = {name: 'test'};
2503    for (const key in obj) {
2504        console.log(key);
2505    }
2506}
2507"#
2508    .unindent();
2509
2510    let after = r#"
2511function iterate() {
2512    const obj: {name: 'test'} = {name: 'test'};
2513    for (const key: name in obj) {
2514        console.log(key);
2515    }
2516}
2517"#
2518    .unindent();
2519
2520    test_inline_values_util(
2521        &variables,
2522        &[],
2523        &before,
2524        &after,
2525        None,
2526        typescript_lang(),
2527        executor,
2528        cx,
2529    )
2530    .await;
2531}