@@ -84,10 +84,20 @@ impl<T: InventoryContents> InventoryFor<T> {
&self,
worktree: WorktreeId,
) -> impl '_ + Iterator<Item = (TaskSourceKind, T)> {
- self.worktree
- .get(&worktree)
+ let worktree_dirs = self.worktree.get(&worktree);
+ let has_zed_dir = worktree_dirs
+ .map(|dirs| {
+ dirs.keys()
+ .any(|dir| dir.file_name().is_some_and(|name| name == ".zed"))
+ })
+ .unwrap_or(false);
+
+ worktree_dirs
.into_iter()
.flatten()
+ .filter(move |(directory, _)| {
+ !(has_zed_dir && directory.file_name().is_some_and(|name| name == ".vscode"))
+ })
.flat_map(|(directory, templates)| {
templates.iter().map(move |template| (directory, template))
})
@@ -437,6 +447,17 @@ impl Inventory {
});
let file = location.and_then(|location| location.buffer.read(cx).file().cloned());
+ let worktrees_with_zed_tasks: HashSet<WorktreeId> = self
+ .templates_from_settings
+ .worktree
+ .iter()
+ .filter(|(_, dirs)| {
+ dirs.keys()
+ .any(|dir| dir.file_name().is_some_and(|name| name == ".zed"))
+ })
+ .map(|(id, _)| *id)
+ .collect();
+
let mut task_labels_to_ids = HashMap::<String, HashSet<TaskId>>::default();
let mut lru_score = 0_u32;
let previously_spawned_tasks = self
@@ -446,6 +467,14 @@ impl Inventory {
.filter(|(task_kind, _)| {
if matches!(task_kind, TaskSourceKind::Language { .. }) {
Some(task_kind) == task_source_kind.as_ref()
+ } else if let TaskSourceKind::Worktree {
+ id,
+ directory_in_worktree: dir,
+ ..
+ } = task_kind
+ {
+ !(worktrees_with_zed_tasks.contains(id)
+ && dir.file_name().is_some_and(|name| name == ".vscode"))
} else {
true
}
@@ -560,6 +560,54 @@ async fn test_inventory_static_task_filters(cx: &mut TestAppContext) {
);
}
+#[gpui::test]
+async fn test_zed_tasks_take_precedence_over_vscode(cx: &mut TestAppContext) {
+ init_test(cx);
+ let inventory = cx.update(|cx| Inventory::new(cx));
+ let worktree_id = WorktreeId::from_usize(0);
+
+ inventory.update(cx, |inventory, _| {
+ inventory
+ .update_file_based_tasks(
+ TaskSettingsLocation::Worktree(SettingsLocation {
+ worktree_id,
+ path: rel_path(".vscode"),
+ }),
+ Some(&mock_tasks_from_names(["vscode_task"])),
+ )
+ .unwrap();
+ });
+ assert_eq!(
+ task_template_names(&inventory, Some(worktree_id), cx).await,
+ vec!["vscode_task"],
+ "With only .vscode tasks, they should appear"
+ );
+
+ inventory.update(cx, |inventory, _| {
+ inventory
+ .update_file_based_tasks(
+ TaskSettingsLocation::Worktree(SettingsLocation {
+ worktree_id,
+ path: rel_path(".zed"),
+ }),
+ Some(&mock_tasks_from_names(["zed_task"])),
+ )
+ .unwrap();
+ });
+ assert_eq!(
+ task_template_names(&inventory, Some(worktree_id), cx).await,
+ vec!["zed_task"],
+ "With both .zed and .vscode tasks, only .zed tasks should appear"
+ );
+
+ register_worktree_task_used(&inventory, worktree_id, "zed_task", cx).await;
+ let resolved = resolved_task_names(&inventory, Some(worktree_id), cx).await;
+ assert!(
+ !resolved.iter().any(|name| name == "vscode_task"),
+ "Previously used .vscode tasks should not appear when .zed tasks exist, got: {resolved:?}"
+ );
+}
+
fn init_test(_cx: &mut TestAppContext) {
zlog::init_test();
TaskStore::init(None);
@@ -184,23 +184,11 @@ impl TasksModal {
};
let mut new_candidates = used_tasks;
new_candidates.extend(lsp_tasks);
- let hide_vscode = current_resolved_tasks.iter().any(|(kind, _)| match kind {
- TaskSourceKind::Worktree {
- id: _,
- directory_in_worktree: dir,
- id_base: _,
- } => dir.file_name().is_some_and(|name| name == ".zed"),
- _ => false,
- });
// todo(debugger): We're always adding lsp tasks here even if prefer_lsp is false
// We should move the filter to new_candidates instead of on current
// and add a test for this
new_candidates.extend(current_resolved_tasks.into_iter().filter(|(task_kind, _)| {
match task_kind {
- TaskSourceKind::Worktree {
- directory_in_worktree: dir,
- ..
- } => !(hide_vscode && dir.file_name().is_some_and(|name| name == ".vscode")),
TaskSourceKind::Language { .. } => add_current_language_tasks,
_ => true,
}