inline_values.rs

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