Show tasks in debugger: start (#30584)
- **Show relevant tasks in debugger: start** - **Add history too** Closes #ISSUE Release Notes: - N/A --------- Co-authored-by: Cole <cole@zed.dev> Co-authored-by: Anthony <anthony@zed.dev>
This commit is contained in:
parent
7eb226b3fc
commit
1fd8fbe6d1
8 changed files with 272 additions and 159 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4167,6 +4167,7 @@ dependencies = [
|
|||
"editor",
|
||||
"env_logger 0.11.8",
|
||||
"feature_flags",
|
||||
"file_icons",
|
||||
"futures 0.3.31",
|
||||
"fuzzy",
|
||||
"gpui",
|
||||
|
|
|
@ -36,6 +36,7 @@ dap_adapters = { workspace = true, optional = true }
|
|||
db.workspace = true
|
||||
editor.workspace = true
|
||||
feature_flags.workspace = true
|
||||
file_icons.workspace = true
|
||||
futures.workspace = true
|
||||
fuzzy.workspace = true
|
||||
gpui.workspace = true
|
||||
|
|
|
@ -218,6 +218,18 @@ impl DebugPanel {
|
|||
cx,
|
||||
)
|
||||
});
|
||||
if let Some(inventory) = self
|
||||
.project
|
||||
.read(cx)
|
||||
.task_store()
|
||||
.read(cx)
|
||||
.task_inventory()
|
||||
.cloned()
|
||||
{
|
||||
inventory.update(cx, |inventory, _| {
|
||||
inventory.scenario_scheduled(scenario.clone());
|
||||
})
|
||||
}
|
||||
let task = cx.spawn_in(window, {
|
||||
let session = session.clone();
|
||||
async move |this, cx| {
|
||||
|
|
|
@ -3,7 +3,6 @@ use std::{
|
|||
borrow::Cow,
|
||||
ops::Not,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
usize,
|
||||
};
|
||||
|
@ -50,7 +49,6 @@ pub(super) struct NewSessionModal {
|
|||
attach_mode: Entity<AttachMode>,
|
||||
custom_mode: Entity<CustomMode>,
|
||||
debugger: Option<DebugAdapterName>,
|
||||
task_contexts: Arc<TaskContexts>,
|
||||
save_scenario_state: Option<SaveScenarioState>,
|
||||
_subscriptions: [Subscription; 2],
|
||||
}
|
||||
|
@ -85,14 +83,6 @@ impl NewSessionModal {
|
|||
let task_store = workspace.project().read(cx).task_store().clone();
|
||||
|
||||
cx.spawn_in(window, async move |workspace, cx| {
|
||||
let task_contexts = Arc::from(
|
||||
workspace
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
tasks_ui::task_contexts(workspace, window, cx)
|
||||
})?
|
||||
.await,
|
||||
);
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let workspace_handle = workspace.weak_handle();
|
||||
workspace.toggle_modal(window, cx, |window, cx| {
|
||||
|
@ -100,12 +90,7 @@ impl NewSessionModal {
|
|||
|
||||
let launch_picker = cx.new(|cx| {
|
||||
Picker::uniform_list(
|
||||
DebugScenarioDelegate::new(
|
||||
debug_panel.downgrade(),
|
||||
workspace_handle.clone(),
|
||||
task_store,
|
||||
task_contexts.clone(),
|
||||
),
|
||||
DebugScenarioDelegate::new(debug_panel.downgrade(), task_store),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
|
@ -124,11 +109,38 @@ impl NewSessionModal {
|
|||
),
|
||||
];
|
||||
|
||||
let active_cwd = task_contexts
|
||||
.active_context()
|
||||
.and_then(|context| context.cwd.clone());
|
||||
let custom_mode = CustomMode::new(None, window, cx);
|
||||
|
||||
let custom_mode = CustomMode::new(None, active_cwd, window, cx);
|
||||
cx.spawn_in(window, {
|
||||
let workspace_handle = workspace_handle.clone();
|
||||
async move |this, cx| {
|
||||
let task_contexts = workspace_handle
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
tasks_ui::task_contexts(workspace, window, cx)
|
||||
})?
|
||||
.await;
|
||||
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
if let Some(active_cwd) = task_contexts
|
||||
.active_context()
|
||||
.and_then(|context| context.cwd.clone())
|
||||
{
|
||||
this.custom_mode.update(cx, |custom, cx| {
|
||||
custom.load(active_cwd, window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
this.launch_picker.update(cx, |picker, cx| {
|
||||
picker
|
||||
.delegate
|
||||
.task_contexts_loaded(task_contexts, window, cx);
|
||||
picker.refresh(window, cx);
|
||||
cx.notify();
|
||||
});
|
||||
})
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
Self {
|
||||
launch_picker,
|
||||
|
@ -138,7 +150,6 @@ impl NewSessionModal {
|
|||
mode: NewSessionMode::Launch,
|
||||
debug_panel: debug_panel.downgrade(),
|
||||
workspace: workspace_handle,
|
||||
task_contexts,
|
||||
save_scenario_state: None,
|
||||
_subscriptions,
|
||||
}
|
||||
|
@ -205,8 +216,6 @@ impl NewSessionModal {
|
|||
|
||||
fn start_new_session(&self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let Some(debugger) = self.debugger.as_ref() else {
|
||||
// todo(debugger): show in UI.
|
||||
log::error!("No debugger selected");
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -223,10 +232,12 @@ impl NewSessionModal {
|
|||
};
|
||||
|
||||
let debug_panel = self.debug_panel.clone();
|
||||
let task_contexts = self.task_contexts.clone();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let Some(task_contexts) = self.task_contexts(cx) else {
|
||||
return;
|
||||
};
|
||||
let task_context = task_contexts.active_context().cloned().unwrap_or_default();
|
||||
let worktree_id = task_contexts.worktree();
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
debug_panel.update_in(cx, |debug_panel, window, cx| {
|
||||
debug_panel.start_session(config, task_context, None, worktree_id, window, cx)
|
||||
})?;
|
||||
|
@ -260,6 +271,11 @@ impl NewSessionModal {
|
|||
cx.notify();
|
||||
})
|
||||
}
|
||||
|
||||
fn task_contexts<'a>(&self, cx: &'a mut Context<Self>) -> Option<&'a TaskContexts> {
|
||||
self.launch_picker.read(cx).delegate.task_contexts.as_ref()
|
||||
}
|
||||
|
||||
fn adapter_drop_down_menu(
|
||||
&mut self,
|
||||
window: &mut Window,
|
||||
|
@ -267,15 +283,14 @@ impl NewSessionModal {
|
|||
) -> ui::DropdownMenu {
|
||||
let workspace = self.workspace.clone();
|
||||
let weak = cx.weak_entity();
|
||||
let active_buffer_language = self
|
||||
.task_contexts
|
||||
.active_item_context
|
||||
let active_buffer = self.task_contexts(cx).and_then(|tc| {
|
||||
tc.active_item_context
|
||||
.as_ref()
|
||||
.and_then(|item| {
|
||||
item.1
|
||||
.as_ref()
|
||||
.and_then(|location| location.buffer.read(cx).language())
|
||||
})
|
||||
.and_then(|aic| aic.1.as_ref().map(|l| l.buffer.clone()))
|
||||
});
|
||||
|
||||
let active_buffer_language = active_buffer
|
||||
.and_then(|buffer| buffer.read(cx).language())
|
||||
.cloned();
|
||||
|
||||
let mut available_adapters = workspace
|
||||
|
@ -515,7 +530,10 @@ impl Render for NewSessionModal {
|
|||
.debugger
|
||||
.as_ref()
|
||||
.and_then(|debugger| this.debug_scenario(&debugger, cx))
|
||||
.zip(this.task_contexts.worktree())
|
||||
.zip(
|
||||
this.task_contexts(cx)
|
||||
.and_then(|tcx| tcx.worktree()),
|
||||
)
|
||||
.and_then(|(scenario, worktree_id)| {
|
||||
this.debug_panel
|
||||
.update(cx, |panel, cx| {
|
||||
|
@ -715,13 +733,12 @@ pub(super) struct CustomMode {
|
|||
impl CustomMode {
|
||||
pub(super) fn new(
|
||||
past_launch_config: Option<LaunchRequest>,
|
||||
active_cwd: Option<PathBuf>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Entity<Self> {
|
||||
let (past_program, past_cwd) = past_launch_config
|
||||
.map(|config| (Some(config.program), config.cwd))
|
||||
.unwrap_or_else(|| (None, active_cwd));
|
||||
.unwrap_or_else(|| (None, None));
|
||||
|
||||
let program = cx.new(|cx| Editor::single_line(window, cx));
|
||||
program.update(cx, |this, cx| {
|
||||
|
@ -745,6 +762,14 @@ impl CustomMode {
|
|||
})
|
||||
}
|
||||
|
||||
fn load(&mut self, cwd: PathBuf, window: &mut Window, cx: &mut App) {
|
||||
self.cwd.update(cx, |editor, cx| {
|
||||
if editor.is_empty(cx) {
|
||||
editor.set_text(cwd.to_string_lossy(), window, cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub(super) fn debug_request(&self, cx: &App) -> task::LaunchRequest {
|
||||
let path = self.cwd.read(cx).text(cx);
|
||||
if cfg!(windows) {
|
||||
|
@ -894,33 +919,64 @@ impl AttachMode {
|
|||
|
||||
pub(super) struct DebugScenarioDelegate {
|
||||
task_store: Entity<TaskStore>,
|
||||
candidates: Option<Vec<(TaskSourceKind, DebugScenario)>>,
|
||||
candidates: Vec<(Option<TaskSourceKind>, DebugScenario)>,
|
||||
selected_index: usize,
|
||||
matches: Vec<StringMatch>,
|
||||
prompt: String,
|
||||
debug_panel: WeakEntity<DebugPanel>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
task_contexts: Arc<TaskContexts>,
|
||||
task_contexts: Option<TaskContexts>,
|
||||
divider_index: Option<usize>,
|
||||
last_used_candidate_index: Option<usize>,
|
||||
}
|
||||
|
||||
impl DebugScenarioDelegate {
|
||||
pub(super) fn new(
|
||||
debug_panel: WeakEntity<DebugPanel>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
task_store: Entity<TaskStore>,
|
||||
task_contexts: Arc<TaskContexts>,
|
||||
) -> Self {
|
||||
pub(super) fn new(debug_panel: WeakEntity<DebugPanel>, task_store: Entity<TaskStore>) -> Self {
|
||||
Self {
|
||||
task_store,
|
||||
candidates: None,
|
||||
candidates: Vec::default(),
|
||||
selected_index: 0,
|
||||
matches: Vec::new(),
|
||||
prompt: String::new(),
|
||||
debug_panel,
|
||||
workspace,
|
||||
task_contexts,
|
||||
task_contexts: None,
|
||||
divider_index: None,
|
||||
last_used_candidate_index: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn task_contexts_loaded(
|
||||
&mut self,
|
||||
task_contexts: TaskContexts,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
) {
|
||||
self.task_contexts = Some(task_contexts);
|
||||
|
||||
let (recent, scenarios) = self
|
||||
.task_store
|
||||
.update(cx, |task_store, cx| {
|
||||
task_store.task_inventory().map(|inventory| {
|
||||
inventory.update(cx, |inventory, cx| {
|
||||
inventory.list_debug_scenarios(self.task_contexts.as_ref().unwrap(), cx)
|
||||
})
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
if !recent.is_empty() {
|
||||
self.last_used_candidate_index = Some(recent.len() - 1);
|
||||
}
|
||||
|
||||
self.candidates = recent
|
||||
.into_iter()
|
||||
.map(|scenario| (None, scenario))
|
||||
.chain(
|
||||
scenarios
|
||||
.into_iter()
|
||||
.map(|(kind, scenario)| (Some(kind), scenario)),
|
||||
)
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
impl PickerDelegate for DebugScenarioDelegate {
|
||||
|
@ -954,53 +1010,15 @@ impl PickerDelegate for DebugScenarioDelegate {
|
|||
cx: &mut Context<picker::Picker<Self>>,
|
||||
) -> gpui::Task<()> {
|
||||
let candidates = self.candidates.clone();
|
||||
let workspace = self.workspace.clone();
|
||||
let task_store = self.task_store.clone();
|
||||
|
||||
cx.spawn_in(window, async move |picker, cx| {
|
||||
let candidates: Vec<_> = match &candidates {
|
||||
Some(candidates) => candidates
|
||||
let candidates: Vec<_> = candidates
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(index, (_, candidate))| {
|
||||
StringMatchCandidate::new(index, candidate.label.as_ref())
|
||||
})
|
||||
.collect(),
|
||||
None => {
|
||||
let worktree_ids: Vec<_> = workspace
|
||||
.update(cx, |this, cx| {
|
||||
this.visible_worktrees(cx)
|
||||
.map(|tree| tree.read(cx).id())
|
||||
.collect()
|
||||
})
|
||||
.ok()
|
||||
.unwrap_or_default();
|
||||
|
||||
let scenarios: Vec<_> = task_store
|
||||
.update(cx, |task_store, cx| {
|
||||
task_store.task_inventory().map(|item| {
|
||||
item.read(cx).list_debug_scenarios(worktree_ids.into_iter())
|
||||
})
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
.unwrap_or_default();
|
||||
|
||||
picker
|
||||
.update(cx, |picker, _| {
|
||||
picker.delegate.candidates = Some(scenarios.clone());
|
||||
})
|
||||
.ok();
|
||||
|
||||
scenarios
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(index, (_, candidate))| {
|
||||
StringMatchCandidate::new(index, candidate.label.as_ref())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
};
|
||||
.collect();
|
||||
|
||||
let matches = fuzzy::match_strings(
|
||||
&candidates,
|
||||
|
@ -1019,6 +1037,13 @@ impl PickerDelegate for DebugScenarioDelegate {
|
|||
delegate.matches = matches;
|
||||
delegate.prompt = query;
|
||||
|
||||
delegate.divider_index = delegate.last_used_candidate_index.and_then(|index| {
|
||||
let index = delegate
|
||||
.matches
|
||||
.partition_point(|matching_task| matching_task.candidate_id <= index);
|
||||
Some(index).and_then(|index| (index != 0).then(|| index - 1))
|
||||
});
|
||||
|
||||
if delegate.matches.is_empty() {
|
||||
delegate.selected_index = 0;
|
||||
} else {
|
||||
|
@ -1030,33 +1055,33 @@ impl PickerDelegate for DebugScenarioDelegate {
|
|||
})
|
||||
}
|
||||
|
||||
fn separators_after_indices(&self) -> Vec<usize> {
|
||||
if let Some(i) = self.divider_index {
|
||||
vec![i]
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _: bool, window: &mut Window, cx: &mut Context<picker::Picker<Self>>) {
|
||||
let debug_scenario = self
|
||||
.matches
|
||||
.get(self.selected_index())
|
||||
.and_then(|match_candidate| {
|
||||
self.candidates
|
||||
.as_ref()
|
||||
.map(|candidates| candidates[match_candidate.candidate_id].clone())
|
||||
});
|
||||
.and_then(|match_candidate| self.candidates.get(match_candidate.candidate_id).cloned());
|
||||
|
||||
let Some((task_source_kind, debug_scenario)) = debug_scenario else {
|
||||
let Some((_, debug_scenario)) = debug_scenario else {
|
||||
return;
|
||||
};
|
||||
|
||||
let (task_context, worktree_id) = if let TaskSourceKind::Worktree {
|
||||
id: worktree_id,
|
||||
directory_in_worktree: _,
|
||||
id_base: _,
|
||||
} = task_source_kind
|
||||
{
|
||||
self.task_contexts
|
||||
.task_context_for_worktree_id(worktree_id)
|
||||
.cloned()
|
||||
.map(|context| (context, Some(worktree_id)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let (task_context, worktree_id) = self
|
||||
.task_contexts
|
||||
.as_ref()
|
||||
.and_then(|task_contexts| {
|
||||
Some((
|
||||
task_contexts.active_context().cloned()?,
|
||||
task_contexts.worktree(),
|
||||
))
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
self.debug_panel
|
||||
|
@ -1087,10 +1112,19 @@ impl PickerDelegate for DebugScenarioDelegate {
|
|||
char_count: hit.string.chars().count(),
|
||||
color: Color::Default,
|
||||
};
|
||||
let task_kind = &self.candidates[hit.candidate_id].0;
|
||||
|
||||
let icon = Icon::new(IconName::FileTree)
|
||||
.color(Color::Muted)
|
||||
.size(ui::IconSize::Small);
|
||||
let icon = match task_kind {
|
||||
Some(TaskSourceKind::Lsp(..)) => Some(Icon::new(IconName::Bolt)),
|
||||
Some(TaskSourceKind::UserInput) => Some(Icon::new(IconName::Terminal)),
|
||||
Some(TaskSourceKind::AbsPath { .. }) => Some(Icon::new(IconName::Settings)),
|
||||
Some(TaskSourceKind::Worktree { .. }) => Some(Icon::new(IconName::FileTree)),
|
||||
Some(TaskSourceKind::Language { name }) => file_icons::FileIcons::get(cx)
|
||||
.get_icon_for_type(&name.to_lowercase(), cx)
|
||||
.map(Icon::from_path),
|
||||
None => Some(Icon::new(IconName::HistoryRerun)),
|
||||
}
|
||||
.map(|icon| icon.color(Color::Muted).size(ui::IconSize::Small));
|
||||
|
||||
Some(
|
||||
ListItem::new(SharedString::from(format!("debug-scenario-selection-{ix}")))
|
||||
|
|
|
@ -1103,6 +1103,7 @@ impl CodeActionsMenu {
|
|||
this.child(
|
||||
h_flex()
|
||||
.overflow_hidden()
|
||||
.child("debug: ")
|
||||
.child(scenario.label.clone())
|
||||
.when(selected, |this| {
|
||||
this.text_color(colors.text_accent)
|
||||
|
@ -1138,7 +1139,9 @@ impl CodeActionsMenu {
|
|||
CodeActionsItem::CodeAction { action, .. } => {
|
||||
action.lsp_action.title().chars().count()
|
||||
}
|
||||
CodeActionsItem::DebugScenario(scenario) => scenario.label.chars().count(),
|
||||
CodeActionsItem::DebugScenario(scenario) => {
|
||||
format!("debug: {}", scenario.label).chars().count()
|
||||
}
|
||||
})
|
||||
.map(|(ix, _)| ix),
|
||||
)
|
||||
|
|
|
@ -5331,9 +5331,9 @@ impl Editor {
|
|||
.map(SharedString::from)
|
||||
})?;
|
||||
|
||||
dap_store.update(cx, |this, cx| {
|
||||
dap_store.update(cx, |dap_store, cx| {
|
||||
for (_, task) in &resolved_tasks.templates {
|
||||
if let Some(scenario) = this
|
||||
if let Some(scenario) = dap_store
|
||||
.debug_scenario_for_build_task(
|
||||
task.original_task().clone(),
|
||||
debug_adapter.clone().into(),
|
||||
|
|
|
@ -52,7 +52,7 @@ impl DapLocator for CargoLocator {
|
|||
}
|
||||
let mut task_template = build_config.clone();
|
||||
let cargo_action = task_template.args.first_mut()?;
|
||||
if cargo_action == "check" {
|
||||
if cargo_action == "check" || cargo_action == "clean" {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -75,10 +75,9 @@ impl DapLocator for CargoLocator {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
let label = format!("Debug `{resolved_label}`");
|
||||
Some(DebugScenario {
|
||||
adapter: adapter.0,
|
||||
label: SharedString::from(label),
|
||||
label: resolved_label.to_string().into(),
|
||||
build: Some(BuildTaskDefinition::Template {
|
||||
task_template,
|
||||
locator_name: Some(self.name()),
|
||||
|
|
|
@ -10,6 +10,7 @@ use std::{
|
|||
|
||||
use anyhow::Result;
|
||||
use collections::{HashMap, HashSet, VecDeque};
|
||||
use dap::DapRegistry;
|
||||
use gpui::{App, AppContext as _, Entity, SharedString, Task};
|
||||
use itertools::Itertools;
|
||||
use language::{
|
||||
|
@ -33,6 +34,7 @@ use crate::{task_store::TaskSettingsLocation, worktree_store::WorktreeStore};
|
|||
#[derive(Debug, Default)]
|
||||
pub struct Inventory {
|
||||
last_scheduled_tasks: VecDeque<(TaskSourceKind, ResolvedTask)>,
|
||||
last_scheduled_scenarios: VecDeque<DebugScenario>,
|
||||
templates_from_settings: InventoryFor<TaskTemplate>,
|
||||
scenarios_from_settings: InventoryFor<DebugScenario>,
|
||||
}
|
||||
|
@ -63,9 +65,8 @@ struct InventoryFor<T> {
|
|||
impl<T: InventoryContents> InventoryFor<T> {
|
||||
fn worktree_scenarios(
|
||||
&self,
|
||||
worktree: Option<WorktreeId>,
|
||||
worktree: WorktreeId,
|
||||
) -> impl '_ + Iterator<Item = (TaskSourceKind, T)> {
|
||||
worktree.into_iter().flat_map(|worktree| {
|
||||
self.worktree
|
||||
.get(&worktree)
|
||||
.into_iter()
|
||||
|
@ -86,7 +87,6 @@ impl<T: InventoryContents> InventoryFor<T> {
|
|||
template.clone(),
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn global_scenarios(&self) -> impl '_ + Iterator<Item = (TaskSourceKind, T)> {
|
||||
|
@ -168,6 +168,13 @@ impl TaskContexts {
|
|||
.and_then(|(_, location, _)| location.as_ref())
|
||||
}
|
||||
|
||||
pub fn file(&self, cx: &App) -> Option<Arc<dyn File>> {
|
||||
self.active_item_context
|
||||
.as_ref()
|
||||
.and_then(|(_, location, _)| location.as_ref())
|
||||
.and_then(|location| location.buffer.read(cx).file().cloned())
|
||||
}
|
||||
|
||||
pub fn worktree(&self) -> Option<WorktreeId> {
|
||||
self.active_item_context
|
||||
.as_ref()
|
||||
|
@ -214,16 +221,69 @@ impl Inventory {
|
|||
cx.new(|_| Self::default())
|
||||
}
|
||||
|
||||
pub fn scenario_scheduled(&mut self, scenario: DebugScenario) {
|
||||
self.last_scheduled_scenarios
|
||||
.retain(|s| s.label != scenario.label);
|
||||
self.last_scheduled_scenarios.push_back(scenario);
|
||||
if self.last_scheduled_scenarios.len() > 5_000 {
|
||||
self.last_scheduled_scenarios.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list_debug_scenarios(
|
||||
&self,
|
||||
worktrees: impl Iterator<Item = WorktreeId>,
|
||||
) -> Vec<(TaskSourceKind, DebugScenario)> {
|
||||
let global_scenarios = self.global_debug_scenarios_from_settings();
|
||||
task_contexts: &TaskContexts,
|
||||
cx: &mut App,
|
||||
) -> (Vec<DebugScenario>, Vec<(TaskSourceKind, DebugScenario)>) {
|
||||
let mut scenarios = Vec::new();
|
||||
|
||||
worktrees
|
||||
.flat_map(|tree_id| self.worktree_scenarios_from_settings(Some(tree_id)))
|
||||
.chain(global_scenarios)
|
||||
.collect()
|
||||
if let Some(worktree_id) = task_contexts
|
||||
.active_worktree_context
|
||||
.iter()
|
||||
.chain(task_contexts.other_worktree_contexts.iter())
|
||||
.map(|context| context.0)
|
||||
.next()
|
||||
{
|
||||
scenarios.extend(self.worktree_scenarios_from_settings(worktree_id));
|
||||
}
|
||||
scenarios.extend(self.global_debug_scenarios_from_settings());
|
||||
|
||||
let (_, new) = self.used_and_current_resolved_tasks(task_contexts, cx);
|
||||
if let Some(location) = task_contexts.location() {
|
||||
let file = location.buffer.read(cx).file();
|
||||
let language = location.buffer.read(cx).language();
|
||||
let language_name = language.as_ref().map(|l| l.name());
|
||||
let adapter = language_settings(language_name, file, cx)
|
||||
.debuggers
|
||||
.first()
|
||||
.map(SharedString::from)
|
||||
.or_else(|| {
|
||||
language.and_then(|l| l.config().debuggers.first().map(SharedString::from))
|
||||
});
|
||||
if let Some(adapter) = adapter {
|
||||
for (kind, task) in new {
|
||||
if let Some(scenario) =
|
||||
DapRegistry::global(cx)
|
||||
.locators()
|
||||
.values()
|
||||
.find_map(|locator| {
|
||||
locator.create_scenario(
|
||||
&task.original_task().clone(),
|
||||
&task.display_label(),
|
||||
adapter.clone().into(),
|
||||
)
|
||||
})
|
||||
{
|
||||
scenarios.push((kind, scenario));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
self.last_scheduled_scenarios.iter().cloned().collect(),
|
||||
scenarios,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn task_template_by_label(
|
||||
|
@ -262,7 +322,9 @@ impl Inventory {
|
|||
cx: &App,
|
||||
) -> Vec<(TaskSourceKind, TaskTemplate)> {
|
||||
let global_tasks = self.global_templates_from_settings();
|
||||
let worktree_tasks = self.worktree_templates_from_settings(worktree);
|
||||
let worktree_tasks = worktree
|
||||
.into_iter()
|
||||
.flat_map(|worktree| self.worktree_templates_from_settings(worktree));
|
||||
let task_source_kind = language.as_ref().map(|language| TaskSourceKind::Language {
|
||||
name: language.name().into(),
|
||||
});
|
||||
|
@ -354,8 +416,9 @@ impl Inventory {
|
|||
.into_iter()
|
||||
.flat_map(|tasks| tasks.0.into_iter())
|
||||
.flat_map(|task| Some((task_source_kind.clone()?, task)));
|
||||
let worktree_tasks = self
|
||||
.worktree_templates_from_settings(worktree)
|
||||
let worktree_tasks = worktree
|
||||
.into_iter()
|
||||
.flat_map(|worktree| self.worktree_templates_from_settings(worktree))
|
||||
.chain(language_tasks)
|
||||
.chain(global_tasks);
|
||||
|
||||
|
@ -471,14 +534,14 @@ impl Inventory {
|
|||
|
||||
fn worktree_scenarios_from_settings(
|
||||
&self,
|
||||
worktree: Option<WorktreeId>,
|
||||
worktree: WorktreeId,
|
||||
) -> impl '_ + Iterator<Item = (TaskSourceKind, DebugScenario)> {
|
||||
self.scenarios_from_settings.worktree_scenarios(worktree)
|
||||
}
|
||||
|
||||
fn worktree_templates_from_settings(
|
||||
&self,
|
||||
worktree: Option<WorktreeId>,
|
||||
worktree: WorktreeId,
|
||||
) -> impl '_ + Iterator<Item = (TaskSourceKind, TaskTemplate)> {
|
||||
self.templates_from_settings.worktree_scenarios(worktree)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue