Project compiles, yay

This commit is contained in:
Piotr Osiewicz
2025-02-17 12:50:55 +01:00
parent a0c91d620a
commit 45db28a5ce
5 changed files with 253 additions and 266 deletions

View File

@@ -12,7 +12,7 @@ use gpui::{
actions, div, App, AppContext, Context, Empty, Entity, EventEmitter, FocusHandle, Focusable,
IntoElement, ParentElement, Render, SharedString, Styled, Subscription, WeakEntity, Window,
};
use project::{search::SearchQuery, Project};
use project::{debugger::client::Client, search::SearchQuery, Project};
use settings::Settings as _;
use std::{
borrow::Cow,
@@ -166,19 +166,17 @@ impl LogStore {
this.projects.remove(&weak_project);
}),
cx.subscribe(project, |this, project, event, cx| match event {
project::Event::DebugClientStarted((_, client_id)) => {
this.add_debug_client(
*client_id,
project.update(cx, |project, cx| {
project.dap_store().update(cx, |store, cx| {
store.client_by_id(client_id, cx).and_then(
|(session, client)| {
Some((session, client.read(cx).adapter_client()?))
},
)
})
}),
);
project::Event::DebugClientStarted(client_id) => {
let client = project.update(cx, |project, cx| {
project.dap_store().update(cx, |store, cx| {
store
.client_by_id(client_id)
.and_then(|client| Some(client))
})
});
if let Some(client) = client {
this.add_debug_client(*client_id, client, cx);
}
}
project::Event::DebugClientShutdown(client_id) => {
this.remove_debug_client(*client_id, cx);
@@ -292,35 +290,35 @@ impl LogStore {
fn add_debug_client(
&mut self,
client_id: DebugAdapterClientId,
session_and_client: Option<(Entity<DebugSession>, Arc<DebugAdapterClient>)>,
client: Entity<Client>,
cx: &App,
) -> Option<&mut DebugAdapterState> {
let client_state = self
.debug_clients
.entry(client_id)
.or_insert_with(DebugAdapterState::new);
if let Some((_, client)) = session_and_client {
let io_tx = self.rpc_tx.clone();
let io_tx = self.rpc_tx.clone();
client.add_log_handler(
move |io_kind, message| {
io_tx
.unbounded_send((client_id, io_kind, message.to_string()))
.ok();
},
LogKind::Rpc,
);
let client = client.read(cx).adapter_client()?;
client.add_log_handler(
move |io_kind, message| {
io_tx
.unbounded_send((client_id, io_kind, message.to_string()))
.ok();
},
LogKind::Rpc,
);
let log_io_tx = self.adapter_log_tx.clone();
client.add_log_handler(
move |io_kind, message| {
log_io_tx
.unbounded_send((client_id, io_kind, message.to_string()))
.ok();
},
LogKind::Adapter,
);
}
let log_io_tx = self.adapter_log_tx.clone();
client.add_log_handler(
move |io_kind, message| {
log_io_tx
.unbounded_send((client_id, io_kind, message.to_string()))
.ok();
},
LogKind::Adapter,
);
Some(client_state)
}

View File

@@ -207,7 +207,7 @@ impl Mode {
/// Represents a current state of a single debug adapter and provides ways to mutate it.
pub struct Client {
mode: Mode,
config: DebugAdapterConfig,
pub(super) capabilities: Capabilities,
client_id: DebugAdapterClientId,
ignore_breakpoints: bool,
@@ -293,13 +293,14 @@ impl CompletionsQuery {
}
impl Client {
pub(crate) fn local(adapter: Arc<DebugAdapterClient>, capabilities: Capabilities) -> Self {
pub(crate) fn local(adapter: Arc<DebugAdapterClient>, config: DebugAdapterConfig) -> Self {
let client_id = adapter.id();
Self {
mode: Mode::Local(adapter),
client_id,
capabilities,
config,
capabilities: unimplemented!(),
ignore_breakpoints: false,
requests: HashMap::default(),
modules: Vec::default(),
@@ -326,6 +327,7 @@ impl Client {
modules: Vec::default(),
loaded_sources: Vec::default(),
threads: IndexMap::default(),
config: todo!(),
}
}
@@ -333,7 +335,7 @@ impl Client {
&self.capabilities
}
pub fn configuration(&self) -> DebugAdapterConfig {
DebugAdapterConfig::default()
self.config.clone()
}
pub(crate) fn _wait_for_request<R: DapCommand + PartialEq + Eq + Hash>(

View File

@@ -93,6 +93,109 @@ impl LocalDapStore {
fn next_client_id(&self) -> DebugAdapterClientId {
DebugAdapterClientId(self.next_client_id.fetch_add(1, SeqCst))
}
pub fn respond_to_start_debugging(
&mut self,
client: &Entity<Client>,
seq: u64,
args: Option<StartDebuggingRequestArguments>,
cx: &mut Context<Self>,
) -> Task<Result<()>> {
let config = client.read(cx).configuration();
let request_args = args.unwrap_or_else(|| StartDebuggingRequestArguments {
configuration: config.initialize_args.clone().unwrap_or_default(),
request: match config.request {
DebugRequestType::Launch => StartDebuggingRequestArgumentsRequest::Launch,
DebugRequestType::Attach(_) => StartDebuggingRequestArgumentsRequest::Attach,
},
});
// Merge the new configuration over the existing configuration
let mut initialize_args = config.initialize_args.clone().unwrap_or_default();
merge_json_value_into(request_args.configuration, &mut initialize_args);
let new_config = DebugAdapterConfig {
label: config.label.clone(),
kind: config.kind.clone(),
request: match &request_args.request {
StartDebuggingRequestArgumentsRequest::Launch => DebugRequestType::Launch,
StartDebuggingRequestArgumentsRequest::Attach => DebugRequestType::Attach(
if let DebugRequestType::Attach(attach_config) = &config.request {
attach_config.clone()
} else {
AttachConfig::default()
},
),
},
program: config.program.clone(),
cwd: config.cwd.clone(),
initialize_args: Some(initialize_args),
supports_attach: true,
};
cx.spawn(|this, mut cx| async move {
let (success, body) = {
let reconnect_task = this.update(&mut cx, |store, cx| {
if !unimplemented!("client.adapter().supports_attach()")
&& matches!(new_config.request, DebugRequestType::Attach(_))
{
Task::<Result<()>>::ready(Err(anyhow!(
"Debug adapter does not support `attach` request"
)))
} else {
unimplemented!(
"store.reconnect_client(client.binary().clone(), new_config, cx)"
);
}
});
match reconnect_task {
Ok(task) => match task.await {
Ok(_) => (true, None),
Err(error) => (
false,
Some(serde_json::to_value(ErrorResponse {
error: Some(dap::Message {
id: seq,
format: error.to_string(),
variables: None,
send_telemetry: None,
show_user: None,
url: None,
url_label: None,
}),
})?),
),
},
Err(error) => (
false,
Some(serde_json::to_value(ErrorResponse {
error: Some(dap::Message {
id: seq,
format: error.to_string(),
variables: None,
send_telemetry: None,
show_user: None,
url: None,
url_label: None,
}),
})?),
),
}
};
unimplemented!();
Ok(())
/*client
.send_message(Message::Response(Response {
seq,
body,
success,
request_seq: seq,
command: StartDebugging::COMMAND.to_string(),
}))
.await*/
})
}
}
pub struct RemoteDapStore {
@@ -407,58 +510,58 @@ impl DapStore {
}
}
fn reconnect_client(
&mut self,
adapter: Arc<dyn DebugAdapter>,
binary: DebugAdapterBinary,
config: DebugAdapterConfig,
cx: &mut Context<Self>,
) -> Task<Result<()>> {
if !adapter.supports_attach() && matches!(config.request, DebugRequestType::Attach(_)) {
return Task::ready(Err(anyhow!(
"Debug adapter does not support `attach` request"
)));
}
// fn reconnect_client(
// &mut self,
// adapter: Arc<dyn DebugAdapter>,
// binary: DebugAdapterBinary,
// config: DebugAdapterConfig,
// cx: &mut Context<Self>,
// ) -> Task<Result<()>> {
// if !config.supports_attach && matches!(config.request, DebugRequestType::Attach(_)) {
// return Task::ready(Err(anyhow!(
// "Debug adapter does not support `attach` request"
// )));
// }
let client_id = self.as_local().unwrap().next_client_id();
// let client_id = self.as_local().unwrap().next_client_id();
cx.spawn(|dap_store, mut cx| async move {
let mut client = DebugAdapterClient::new(client_id, adapter, binary, &cx);
// cx.spawn(|dap_store, mut cx| async move {
// let mut client = DebugAdapterClient::new(client_id, adapter, binary, &cx);
client
.reconnect(
{
let dap_store = dap_store.clone();
move |message, cx| {
dap_store
.update(cx, |_, cx| {
cx.emit(DapStoreEvent::DebugClientEvent { client_id, message })
})
.log_err();
}
},
&mut cx,
)
.await?;
// client
// .reconnect(
// {
// let dap_store = dap_store.clone();
// move |message, cx| {
// dap_store
// .update(cx, |_, cx| {
// cx.emit(DapStoreEvent::DebugClientEvent { client_id, message })
// })
// .log_err();
// }
// },
// &mut cx,
// )
// .await?;
dap_store.update(&mut cx, |store, cx| {
cx.new(|cx| {
let client_state =
debugger::client::Client::local(Arc::new(client), capabilities);
});
// dap_store.update(&mut cx, |store, cx| {
// cx.new(|cx| {
// let client_state =
// debugger::client::Client::local(Arc::new(client), capabilities);
// });
store.clients.insert(Arc::new(client), client_id);
// store.clients.insert(Arc::new(client), client_id);
// don't emit this event ourself in tests, so we can add request,
// response and event handlers for this client
if !cfg!(any(test, feature = "test-support")) {
cx.emit(DapStoreEvent::DebugClientStarted(client_id));
}
// // don't emit this event ourself in tests, so we can add request,
// // response and event handlers for this client
// if !cfg!(any(test, feature = "test-support")) {
// cx.emit(DapStoreEvent::DebugClientStarted(client_id));
// }
cx.notify();
})
})
}
// cx.notify();
// })
// })
// }
fn start_client_internal(
&mut self,
@@ -475,7 +578,9 @@ impl DapStore {
cx.spawn(|this, mut cx| async move {
let adapter = build_adapter(&config.kind).await?;
if !adapter.supports_attach() && matches!(config.request, DebugRequestType::Attach(_)) {
if !unimplemented!("adapter.supports_attach()")
&& matches!(config.request, DebugRequestType::Attach(_))
{
bail!("Debug adapter does not support `attach` request");
}
@@ -577,7 +682,7 @@ impl DapStore {
this.update(&mut cx, |store, cx| {
let client_id = client.id();
store.clients.insert(client_id, client);
unimplemented!("store.clients.insert(client_id, client);");
cx.emit(DapStoreEvent::DebugClientStarted(client_id));
cx.notify();
@@ -640,44 +745,38 @@ impl DapStore {
}
}
pub fn launch(
pub fn new_session(
&mut self,
client_id: DebugAdapterClientId,
config: DebugAdapterConfig,
cx: &mut Context<Self>,
) -> Task<Result<()>> {
let Some(client) = self
.client_by_id(client_id)
.and_then(|client| Some(client.read(cx).adapter_client()?))
else {
return Task::ready(Err(anyhow!("Could not find debug client: {:?}", client_id)));
};
// let config = session.read(cx).as_local().unwrap().configuration();
// let mut adapter_args = client.adapter().request_args(&config);
// if let Some(args) = config.initialize_args.clone() {
// merge_json_value_into(args, &mut adapter_args);
// }
let config = session.read(cx).as_local().unwrap().configuration();
let mut adapter_args = client.adapter().request_args(&config);
if let Some(args) = config.initialize_args.clone() {
merge_json_value_into(args, &mut adapter_args);
}
// // TODO(debugger): GDB starts the debuggee program on launch instead of configurationDone
// // causing our sent breakpoints to not be valid. This delay should eventually be taken out
// let delay = if &client.adapter_id() == "gdb" {
// Some(
// cx.background_executor()
// .timer(std::time::Duration::from_millis(20u64)),
// )
// } else {
// None
// };
// TODO(debugger): GDB starts the debuggee program on launch instead of configurationDone
// causing our sent breakpoints to not be valid. This delay should eventually be taken out
let delay = if &client.adapter_id() == "gdb" {
Some(
cx.background_executor()
.timer(std::time::Duration::from_millis(20u64)),
)
} else {
None
};
// cx.background_executor().spawn(async move {
// if let Some(delay) = delay {
// delay.await;
// }
cx.background_executor().spawn(async move {
if let Some(delay) = delay {
delay.await;
}
client
.request::<Launch>(LaunchRequestArguments { raw: adapter_args })
.await
})
// client
// .request::<Launch>(LaunchRequestArguments { raw: adapter_args })
// .await
// })
Task::ready(Ok(()))
}
pub fn attach(
@@ -686,157 +785,42 @@ impl DapStore {
process_id: u32,
cx: &mut Context<Self>,
) -> Task<Result<()>> {
let Some(client) = self
.client_by_id(client_id)
.and_then(|client| Some(client.read(cx).adapter_client()?))
else {
return Task::ready(Err(
anyhow!("Could not find debug client: {:?}", client_id,),
));
};
unimplemented!();
// let Some(client) = self
// .client_by_id(client_id)
// .and_then(|client| Some(client.read(cx).adapter_client()?))
// else {
// return Task::ready(Err(
// anyhow!("Could not find debug client: {:?}", client_id,),
// ));
// };
// update the process id on the config, so when the `startDebugging` reverse request
// comes in we send another `attach` request with the already selected PID
// If we don't do this the user has to select the process twice if the adapter sends a `startDebugging` request
session.update(cx, |session, cx| {
session.as_local_mut().unwrap().update_configuration(
|config| {
config.request = DebugRequestType::Attach(task::AttachConfig {
process_id: Some(process_id),
});
},
cx,
);
});
// // update the process id on the config, so when the `startDebugging` reverse request
// // comes in we send another `attach` request with the already selected PID
// // If we don't do this the user has to select the process twice if the adapter sends a `startDebugging` request
// session.update(cx, |session, cx| {
// session.as_local_mut().unwrap().update_configuration(
// |config| {
// config.request = DebugRequestType::Attach(task::AttachConfig {
// process_id: Some(process_id),
// });
// },
// cx,
// );
// });
let config = session.read(cx).as_local().unwrap().configuration();
let mut adapter_args = client.adapter().request_args(&config);
// let config = session.read(cx).as_local().unwrap().configuration();
// let mut adapter_args = client.adapter().request_args(&config);
if let Some(args) = config.initialize_args.clone() {
merge_json_value_into(args, &mut adapter_args);
}
// if let Some(args) = config.initialize_args.clone() {
// merge_json_value_into(args, &mut adapter_args);
// }
cx.background_executor().spawn(async move {
client
.request::<Attach>(AttachRequestArguments { raw: adapter_args })
.await
})
}
pub fn respond_to_start_debugging(
&mut self,
client_id: DebugAdapterClientId,
seq: u64,
args: Option<StartDebuggingRequestArguments>,
cx: &mut Context<Self>,
) -> Task<Result<()>> {
let Some((client, adapter)) = self
.client_by_id(client_id)
.and_then(|client| Some((client, client.read(cx).adapter_client()?)))
else {
return Task::ready(Err(
anyhow!("Could not find debug client: {:?}", client_id,),
));
};
let config = client.read(cx).configuration();
let request_args = args.unwrap_or_else(|| StartDebuggingRequestArguments {
configuration: config.initialize_args.clone().unwrap_or_default(),
request: match config.request {
DebugRequestType::Launch => StartDebuggingRequestArgumentsRequest::Launch,
DebugRequestType::Attach(_) => StartDebuggingRequestArgumentsRequest::Attach,
},
});
// Merge the new configuration over the existing configuration
let mut initialize_args = config.initialize_args.clone().unwrap_or_default();
merge_json_value_into(request_args.configuration, &mut initialize_args);
let new_config = DebugAdapterConfig {
label: config.label.clone(),
kind: config.kind.clone(),
request: match &request_args.request {
StartDebuggingRequestArgumentsRequest::Launch => DebugRequestType::Launch,
StartDebuggingRequestArgumentsRequest::Attach => DebugRequestType::Attach(
if let DebugRequestType::Attach(attach_config) = &config.request {
attach_config.clone()
} else {
AttachConfig::default()
},
),
},
program: config.program.clone(),
cwd: config.cwd.clone(),
initialize_args: Some(initialize_args),
};
cx.spawn(|this, mut cx| async move {
let (success, body) = {
let reconnect_task = this.update(&mut cx, |store, cx| {
if !client.adapter().supports_attach()
&& matches!(new_config.request, DebugRequestType::Attach(_))
{
Task::ready(Err(anyhow!(
"Debug adapter does not support `attach` request"
)))
} else {
store.reconnect_client(client.binary().clone(), new_config, cx)
}
});
match reconnect_task {
Ok(task) => match task.await {
Ok(_) => (true, None),
Err(error) => {
this.update(&mut cx, |_, cx| {
cx.emit(DapStoreEvent::Notification(error.to_string()));
})
.log_err();
(
false,
Some(serde_json::to_value(ErrorResponse {
error: Some(dap::Message {
id: seq,
format: error.to_string(),
variables: None,
send_telemetry: None,
show_user: None,
url: None,
url_label: None,
}),
})?),
)
}
},
Err(error) => (
false,
Some(serde_json::to_value(ErrorResponse {
error: Some(dap::Message {
id: seq,
format: error.to_string(),
variables: None,
send_telemetry: None,
show_user: None,
url: None,
url_label: None,
}),
})?),
),
}
};
client
.send_message(Message::Response(Response {
seq,
body,
success,
request_seq: seq,
command: StartDebugging::COMMAND.to_string(),
}))
.await
})
// cx.background_executor().spawn(async move {
// client
// .request::<Attach>(AttachRequestArguments { raw: adapter_args })
// .await
// })
}
pub fn respond_to_run_in_terminal(

View File

@@ -1102,7 +1102,7 @@ impl Project {
let mut dap_store =
DapStore::new_remote(remote_id, client.clone().into(), breakpoint_store.clone());
dap_store.request_active_debug_sessions(cx);
unimplemented!("dap_store.request_active_debug_sessions(cx)");
dap_store
})?;

View File

@@ -131,6 +131,8 @@ pub struct DebugAdapterConfig {
pub cwd: Option<PathBuf>,
/// Additional initialization arguments to be sent on DAP initialization
pub initialize_args: Option<serde_json::Value>,
/// Whether the debug adapter supports attaching to a running process.
pub supports_attach: bool,
}
/// Represents the type of the debugger adapter connection
@@ -176,6 +178,7 @@ impl DebugTaskDefinition {
program: self.program,
cwd: cwd.clone(),
initialize_args: self.initialize_args,
supports_attach: true,
});
let args: Vec<String> = Vec::new();