From d00ad02b05981c79942b3bdff957e2384e68b89f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Kondzior?= Date: Tue, 28 Oct 2025 16:43:48 +0100 Subject: [PATCH] agent_ui: Add file name and line number to symbol completions (#40508) Symbol completions in the context picker now show "SymbolName filename.txt L123" instead of just "SymbolName". This helps distinguish between symbols with the same name in different files. ## Motivation I noticed that the message prompt editor only showed symbol names without any context, making it hard to use in large projects with many symbols sharing the same name. The inline prompt editor already includes file context for symbol completions, so I brought that same UX improvement to the message prompt editor. I've decided to match the highlighting style with directory completion entries from the message editor. ## Changes - Extract file name from both InProject and OutsideProject symbol locations - Add `build_symbol_label` helper to format labels with file context - Update test expectation for new label format ## Screenshots Inline Prompt Editor Screenshot 2025-10-17 at 17 47 52 Old Message Editor: Screenshot 2025-10-17 at 17 31 44 New Message Editor: Screenshot 2025-10-17 at 17 31 23 Release Notes: - Added file names and line numbers to symbol completions in the agent panel --- .../agent_ui/src/acp/completion_provider.rs | 30 ++++++++++++++----- crates/agent_ui/src/acp/message_editor.rs | 2 +- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/crates/agent_ui/src/acp/completion_provider.rs b/crates/agent_ui/src/acp/completion_provider.rs index c5ab47fe18970791c047ef157f6664188c95e346..2dac9fc563e41ea1985754ea80b6b31e2a7e3add 100644 --- a/crates/agent_ui/src/acp/completion_provider.rs +++ b/crates/agent_ui/src/acp/completion_provider.rs @@ -253,17 +253,22 @@ impl ContextPickerCompletionProvider { ) -> Option { let project = workspace.read(cx).project().clone(); - let label = CodeLabel::plain(symbol.name.clone(), None); - - let abs_path = match &symbol.path { - SymbolLocation::InProject(project_path) => { - project.read(cx).absolute_path(&project_path, cx)? - } + let (abs_path, file_name) = match &symbol.path { + SymbolLocation::InProject(project_path) => ( + project.read(cx).absolute_path(&project_path, cx)?, + project_path.path.file_name()?.to_string().into(), + ), SymbolLocation::OutsideProject { abs_path, signature: _, - } => PathBuf::from(abs_path.as_ref()), + } => ( + PathBuf::from(abs_path.as_ref()), + abs_path.file_name().map(|f| f.to_string_lossy())?, + ), }; + + let label = build_symbol_label(&symbol.name, &file_name, symbol.range.start.0.row + 1, cx); + let uri = MentionUri::Symbol { abs_path, name: symbol.name.clone(), @@ -674,6 +679,17 @@ impl ContextPickerCompletionProvider { } } +fn build_symbol_label(symbol_name: &str, file_name: &str, line: u32, cx: &App) -> CodeLabel { + let comment_id = cx.theme().syntax().highlight_id("comment").map(HighlightId); + let mut label = CodeLabelBuilder::default(); + + label.push_str(symbol_name, None); + label.push_str(" ", None); + label.push_str(&format!("{} L{}", file_name, line), comment_id); + + label.build() +} + fn build_code_label_for_full_path(file_name: &str, directory: Option<&str>, cx: &App) -> CodeLabel { let comment_id = cx.theme().syntax().highlight_id("comment").map(HighlightId); let mut label = CodeLabelBuilder::default(); diff --git a/crates/agent_ui/src/acp/message_editor.rs b/crates/agent_ui/src/acp/message_editor.rs index 91e9850b082f0d8432984b49aa4cd82f9794e898..6bedb61171b69abcc5bf70e8b171be5c93846dbe 100644 --- a/crates/agent_ui/src/acp/message_editor.rs +++ b/crates/agent_ui/src/acp/message_editor.rs @@ -2473,7 +2473,7 @@ mod tests { format!("Lorem [@one.txt]({url_one}) Ipsum [@eight.txt]({url_eight}) @symbol ") ); assert!(editor.has_visible_completions_menu()); - assert_eq!(current_completion_labels(editor), &["MySymbol"]); + assert_eq!(current_completion_labels(editor), &["MySymbol one.txt L1"]); }); editor.update_in(&mut cx, |editor, window, cx| {