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