diff --git a/crates/project/src/task_inventory.rs b/crates/project/src/task_inventory.rs index cbe4a73a654472550673fe54b60974c57e08991d..2cd62a9fa83f78b4f2f64cd8cd6503fcf0fb5f29 100644 --- a/crates/project/src/task_inventory.rs +++ b/crates/project/src/task_inventory.rs @@ -84,10 +84,20 @@ impl InventoryFor { &self, worktree: WorktreeId, ) -> impl '_ + Iterator { - 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 = 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::>::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 } diff --git a/crates/project/tests/integration/task_inventory.rs b/crates/project/tests/integration/task_inventory.rs index fe42a0dea28645fcbf636f9e62608b549249fb93..6c51fa93571c4ca5d5f55631c67b29c1bc1c9963 100644 --- a/crates/project/tests/integration/task_inventory.rs +++ b/crates/project/tests/integration/task_inventory.rs @@ -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); diff --git a/crates/tasks_ui/src/modal.rs b/crates/tasks_ui/src/modal.rs index 6b4fc21ef3ede0482c9eb3ac6b8dd9c000b7f7d4..34f0cd809692d649bcfbabb7952f3075618ead04 100644 --- a/crates/tasks_ui/src/modal.rs +++ b/crates/tasks_ui/src/modal.rs @@ -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, }