From fd32e31d5657e88c2973e7c6b2a48e32d61311fd Mon Sep 17 00:00:00 2001 From: ozacod <47009516+ozacod@users.noreply.github.com> Date: Fri, 20 Feb 2026 18:30:55 +0300 Subject: [PATCH] editor: Add copy button for project diagnostics messages (#49671) | Before | After | |---|---| | before | after | Before you mark this PR as ready for review, make sure that you have: - [x] Added a solid test coverage and/or screenshots from doing manual testing - [x] Done a self-review taking into account security and performance aspects - [x] Aligned any UI changes with the [UI checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) Release Notes: - Added copy button for project diagnostics messages --------- Co-authored-by: ozacod Co-authored-by: Danilo Leal --- crates/diagnostics/src/diagnostic_renderer.rs | 67 ++++++++++++------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/crates/diagnostics/src/diagnostic_renderer.rs b/crates/diagnostics/src/diagnostic_renderer.rs index 521752ff1959fccc12b74857e342ff33a0444f3f..920bf4bc880c347c640d3dbf7106f3545bba3444 100644 --- a/crates/diagnostics/src/diagnostic_renderer.rs +++ b/crates/diagnostics/src/diagnostic_renderer.rs @@ -12,10 +12,7 @@ use markdown::{Markdown, MarkdownElement}; use settings::Settings; use text::{AnchorRangeExt, Point}; use theme::ThemeSettings; -use ui::{ - ActiveTheme, AnyElement, App, Context, IntoElement, ParentElement, SharedString, Styled, - Window, div, -}; +use ui::{CopyButton, prelude::*}; use util::maybe; use crate::toolbar_controls::DiagnosticsToolbarEditor; @@ -81,6 +78,7 @@ impl DiagnosticRenderer { initial_range: primary.range.clone(), severity: primary.diagnostic.severity, diagnostics_editor: diagnostics_editor.clone(), + copy_message: primary.diagnostic.message.clone().into(), markdown: cx.new(|cx| { Markdown::new(markdown.into(), language_registry.clone(), None, cx) }), @@ -95,6 +93,7 @@ impl DiagnosticRenderer { initial_range: entry.range.clone(), severity: entry.diagnostic.severity, diagnostics_editor: diagnostics_editor.clone(), + copy_message: entry.diagnostic.message.clone().into(), markdown: cx.new(|cx| { Markdown::new(markdown.into(), language_registry.clone(), None, cx) }), @@ -191,6 +190,7 @@ pub(crate) struct DiagnosticBlock { pub(crate) severity: DiagnosticSeverity, pub(crate) markdown: Entity, pub(crate) diagnostics_editor: Option>, + pub(crate) copy_message: SharedString, } impl DiagnosticBlock { @@ -214,32 +214,49 @@ impl DiagnosticBlock { let line_height = editor_line_height; let diagnostics_editor = self.diagnostics_editor.clone(); - div() + let copy_button_id = format!( + "copy-diagnostic-{}-{}-{}-{}", + self.initial_range.start.row, + self.initial_range.start.column, + self.initial_range.end.row, + self.initial_range.end.column + ); + + h_flex() + .max_w(max_width) + .pl_1p5() + .pr_0p5() + .items_start() + .gap_1() .border_l_2() - .px_2() .line_height(line_height) .bg(background_color) .border_color(border_color) - .max_w(max_width) .child( - MarkdownElement::new( - self.markdown.clone(), - diagnostics_markdown_style(bcx.window, cx), - ) - .code_block_renderer(markdown::CodeBlockRenderer::Default { - copy_button: false, - copy_button_on_hover: false, - border: false, - }) - .on_url_click({ - move |link, window, cx| { - editor - .update(cx, |editor, cx| { - Self::open_link(editor, &diagnostics_editor, link, window, cx) - }) - .ok(); - } - }), + div().flex_1().min_w_0().child( + MarkdownElement::new( + self.markdown.clone(), + diagnostics_markdown_style(bcx.window, cx), + ) + .code_block_renderer(markdown::CodeBlockRenderer::Default { + copy_button: false, + copy_button_on_hover: false, + border: false, + }) + .on_url_click({ + move |link, window, cx| { + editor + .update(cx, |editor, cx| { + Self::open_link(editor, &diagnostics_editor, link, window, cx) + }) + .ok(); + } + }), + ), + ) + .child( + CopyButton::new(copy_button_id, self.copy_message.clone()) + .tooltip_label("Copy Diagnostic"), ) .into_any_element() }