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 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()
}