From 29f473f00492cda1d00f37cc84b1fd150c8551ef Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Thu, 29 Oct 2026 03:37:40 +0800 Subject: [PATCH] feat(project): Jump to Source in the project view menu; hide deleted files from Recent Files The project view context menu gains Jump to Source (F4) for files. Recent Files no longer lists files deleted since they were opened, including files removed while the IDE was closed; virtual documents stay listed. --- crates/ide-index/src/lib.rs | 6 ++++-- crates/ide-index/src/tests.rs | 13 +++++++++++++ src/features/project-tree/contextMenu.test.ts | 1 + src/features/project-tree/contextMenu.ts | 10 +++++++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/crates/ide-index/src/lib.rs b/crates/ide-index/src/lib.rs index 4e4794538..d0b08799b 100644 --- a/crates/ide-index/src/lib.rs +++ b/crates/ide-index/src/lib.rs @@ -218,9 +218,11 @@ impl ProjectIndex { self.shared.enqueue(Job::SaveRecent); } - /// Recently opened files, most recent first. + /// Recently opened files, most recent first; files deleted since (also while + /// the IDE was closed) are left out. Virtual documents are always listed. pub fn recent_files(&self) -> Vec { - self.shared.recent.lock().clone() + let recent = self.shared.recent.lock().clone(); + recent.into_iter().filter(|p| p.to_str().is_some_and(ide_core::text::is_virtual_uri) || p.exists()).collect() } /// Blocks until the initial scan and every queued update has been applied diff --git a/crates/ide-index/src/tests.rs b/crates/ide-index/src/tests.rs index 8094cdc81..3e45fc50a 100644 --- a/crates/ide-index/src/tests.rs +++ b/crates/ide-index/src/tests.rs @@ -178,6 +178,19 @@ fn symbol_ranking_is_idea_like() { assert!(idx.find_symbols("", SymbolFilter::All, 5).is_empty()); } +#[test] +fn recent_files_skip_deleted_files_but_keep_virtual_documents() { + let fx = sample(); + let idx = fx.open(); + let app = fx.root.join("web/app.py"); + let virt = PathBuf::from("jdt://contents/rt.jar/java.lang/String.class"); + idx.mark_recent(&app); + idx.mark_recent(&virt); + assert_eq!(idx.recent_files(), vec![virt.clone(), app.clone()]); + std::fs::remove_file(&app).unwrap(); + assert_eq!(idx.recent_files(), vec![virt]); +} + #[test] fn persistence_skips_unchanged_files_on_reopen() { let fx = sample(); diff --git a/src/features/project-tree/contextMenu.test.ts b/src/features/project-tree/contextMenu.test.ts index d269d7905..fcb76d43e 100644 --- a/src/features/project-tree/contextMenu.test.ts +++ b/src/features/project-tree/contextMenu.test.ts @@ -84,6 +84,7 @@ describe("project view context menu", () => { "Copy Path/Reference…", "Paste", "-", + "Jump to Source", "Find Usages", "Find in Files…", "Replace in Files…", diff --git a/src/features/project-tree/contextMenu.ts b/src/features/project-tree/contextMenu.ts index 7ce9108bc..635e417b9 100644 --- a/src/features/project-tree/contextMenu.ts +++ b/src/features/project-tree/contextMenu.ts @@ -20,6 +20,7 @@ import { findFileUsages, folderOf, openCopyDialog, + openFile, openMoveDialog, openRenameDialog, paste, @@ -196,8 +197,15 @@ export function contextMenuItems(nodes: ProjectNode[]): MenuItem[] { { kind: "separator" }, ); - // Find Usages / Find in Files… / Replace in Files… + // Jump to Source / Find Usages / Find in Files… / Replace in Files… push( + files.length > 0 && { + id: "jumpToSource", + label: "Jump to Source", + icon: "edit", + shortcut: keyLabel("project.open"), + run: () => files.forEach((f) => void openFile(f.path)), + }, inProject && singleFile && { id: "findUsages",