debugger: Run build in terminal (#29645)

Currently contains the pre-work of making sessions creatable without a
definition, but still need to change the spawn in terminal
to use the running session

Release Notes:

- N/A

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This commit is contained in:
Conrad Irwin 2025-05-05 21:08:14 +01:00 committed by GitHub
parent c12e6376b8
commit ff215b4f11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 695 additions and 622 deletions

View file

@ -50,7 +50,7 @@ use std::{
sync::{Arc, Once},
};
use task::{DebugScenario, SpawnInTerminal};
use util::ResultExt as _;
use util::{ResultExt as _, merge_json_value_into};
use worktree::Worktree;
#[derive(Debug)]
@ -393,7 +393,8 @@ impl DapStore {
pub fn new_session(
&mut self,
template: DebugTaskDefinition,
label: SharedString,
adapter: DebugAdapterName,
parent_session: Option<Entity<Session>>,
cx: &mut Context<Self>,
) -> Entity<Session> {
@ -409,7 +410,8 @@ impl DapStore {
self.breakpoint_store.clone(),
session_id,
parent_session,
template.clone(),
label,
adapter,
cx,
);
@ -435,6 +437,7 @@ impl DapStore {
pub fn boot_session(
&self,
session: Entity<Session>,
definition: DebugTaskDefinition,
cx: &mut Context<Self>,
) -> Task<Result<()>> {
let Some(worktree) = self.worktree_store.read(cx).visible_worktrees(cx).next() else {
@ -442,17 +445,20 @@ impl DapStore {
};
let dap_store = cx.weak_entity();
let definition = session.read(cx).definition();
cx.spawn({
let session = session.clone();
async move |this, cx| {
let binary = this
let mut binary = this
.update(cx, |this, cx| {
this.get_debug_adapter_binary(definition.clone(), cx)
})?
.await?;
if let Some(args) = definition.initialize_args {
merge_json_value_into(args, &mut binary.request_args.configuration);
}
session
.update(cx, |session, cx| {
session.boot(binary, worktree, dap_store, cx)

View file

@ -12,7 +12,7 @@ use super::dap_command::{
use super::dap_store::DapStore;
use anyhow::{Context as _, Result, anyhow};
use collections::{HashMap, HashSet, IndexMap, IndexSet};
use dap::adapters::{DebugAdapterBinary, DebugTaskDefinition};
use dap::adapters::{DebugAdapterBinary, DebugAdapterName};
use dap::messages::Response;
use dap::requests::{Request, RunInTerminal, StartDebugging};
use dap::{
@ -32,7 +32,7 @@ use gpui::{
Task, WeakEntity,
};
use serde_json::{Value, json};
use serde_json::Value;
use smol::stream::StreamExt;
use std::any::TypeId;
use std::collections::BTreeMap;
@ -45,7 +45,7 @@ use std::{
sync::Arc,
};
use text::{PointUtf16, ToPointUtf16};
use util::{ResultExt, merge_json_value_into};
use util::ResultExt;
use worktree::Worktree;
#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)]
@ -307,18 +307,11 @@ impl LocalMode {
fn initialize_sequence(
&self,
capabilities: &Capabilities,
definition: &DebugTaskDefinition,
initialized_rx: oneshot::Receiver<()>,
dap_store: WeakEntity<DapStore>,
breakpoint_store: Entity<BreakpointStore>,
cx: &App,
) -> Task<Result<()>> {
let mut raw = self.binary.request_args.clone();
merge_json_value_into(
definition.initialize_args.clone().unwrap_or(json!({})),
&mut raw.configuration,
);
let raw = self.binary.request_args.clone();
// Of relevance: https://github.com/microsoft/vscode/issues/4902#issuecomment-368583522
let launch = match raw.request {
@ -349,6 +342,8 @@ impl LocalMode {
let worktree = self.worktree().clone();
let configuration_sequence = cx.spawn({
async move |cx| {
let breakpoint_store =
dap_store.update(cx, |dap_store, _| dap_store.breakpoint_store().clone())?;
initialized_rx.await?;
let errors_by_path = cx
.update(|cx| this.send_source_breakpoints(false, &breakpoint_store, cx))?
@ -505,9 +500,10 @@ pub struct OutputToken(pub usize);
/// Represents a current state of a single debug adapter and provides ways to mutate it.
pub struct Session {
pub mode: Mode,
definition: DebugTaskDefinition,
pub(super) capabilities: Capabilities,
id: SessionId,
label: SharedString,
adapter: DebugAdapterName,
pub(super) capabilities: Capabilities,
child_session_ids: HashSet<SessionId>,
parent_session: Option<Entity<Session>>,
modules: Vec<dap::Module>,
@ -636,7 +632,8 @@ impl Session {
breakpoint_store: Entity<BreakpointStore>,
session_id: SessionId,
parent_session: Option<Entity<Session>>,
template: DebugTaskDefinition,
label: SharedString,
adapter: DebugAdapterName,
cx: &mut App,
) -> Entity<Self> {
cx.new::<Self>(|cx| {
@ -685,7 +682,8 @@ impl Session {
ignore_breakpoints: false,
breakpoint_store,
exception_breakpoints: Default::default(),
definition: template,
label,
adapter,
};
this
@ -805,16 +803,12 @@ impl Session {
&local_mode.binary
}
pub fn adapter_name(&self) -> SharedString {
self.definition.adapter.clone()
pub fn adapter(&self) -> DebugAdapterName {
self.adapter.clone()
}
pub fn label(&self) -> SharedString {
self.definition.label.clone()
}
pub fn definition(&self) -> DebugTaskDefinition {
self.definition.clone()
self.label.clone()
}
pub fn is_terminated(&self) -> bool {
@ -943,7 +937,7 @@ impl Session {
}
pub(super) fn request_initialize(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
let adapter_id = String::from(self.definition.adapter.clone());
let adapter_id = self.adapter().to_string();
let request = Initialize { adapter_id };
match &self.mode {
Mode::Running(local_mode) => {
@ -983,14 +977,9 @@ impl Session {
cx: &mut Context<Self>,
) -> Task<Result<()>> {
match &self.mode {
Mode::Running(local_mode) => local_mode.initialize_sequence(
&self.capabilities,
&self.definition,
initialize_rx,
dap_store,
self.breakpoint_store.clone(),
cx,
),
Mode::Running(local_mode) => {
local_mode.initialize_sequence(&self.capabilities, initialize_rx, dap_store, cx)
}
Mode::Building => Task::ready(Err(anyhow!("cannot initialize, still building"))),
}
}

View file

@ -66,7 +66,7 @@ use image_store::{ImageItemEvent, ImageStoreEvent};
use ::git::{blame::Blame, status::FileStatus};
use gpui::{
AnyEntity, App, AppContext, AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Hsla,
SharedString, Task, WeakEntity, Window, prelude::FluentBuilder,
SharedString, Task, WeakEntity, Window,
};
use itertools::Itertools;
use language::{
@ -3565,10 +3565,9 @@ impl Project {
) -> Task<anyhow::Result<Vec<InlayHint>>> {
let snapshot = buffer_handle.read(cx).snapshot();
let Some(inline_value_provider) = session
.read(cx)
.adapter_name()
.map(|adapter_name| DapRegistry::global(cx).adapter(&adapter_name))
let adapter = session.read(cx).adapter();
let Some(inline_value_provider) = DapRegistry::global(cx)
.adapter(&adapter)
.and_then(|adapter| adapter.inline_value_provider())
else {
return Task::ready(Err(anyhow::anyhow!("Inline value provider not found")));