From 3f7533a0b482eb19682cc4049b3b897073c02c01 Mon Sep 17 00:00:00 2001 From: Julia Date: Wed, 26 Apr 2023 15:46:20 -0400 Subject: [PATCH 1/4] Show source of diagnostic hovers --- crates/editor/src/hover_popover.rs | 18 +++++++++++++++--- crates/language/src/buffer.rs | 2 ++ crates/language/src/proto.rs | 2 ++ crates/project/src/project.rs | 2 ++ crates/rpc/proto/zed.proto | 17 +++++++++-------- crates/rpc/src/rpc.rs | 2 +- crates/theme/src/theme.rs | 1 + crates/zed/src/languages.rs | 23 +++++++++++++---------- styles/src/styleTree/hoverPopover.ts | 5 +++-- 9 files changed, 48 insertions(+), 24 deletions(-) diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 43c93cf33bd6119dfc3addf01160e719c4ae0eb2..df2570a8ef4daad1ce2a2ef624553d20c03257a6 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -1,7 +1,7 @@ use futures::FutureExt; use gpui::{ actions, - elements::{Flex, MouseEventHandler, Padding, Text}, + elements::{Flex, MouseEventHandler, Padding, ParentElement, Text}, impl_internal_actions, platform::{CursorStyle, MouseButton}, AnyElement, AppContext, Axis, Element, ModelHandle, Task, ViewContext, @@ -378,6 +378,8 @@ impl DiagnosticPopover { let mut text_style = style.hover_popover.prose.clone(); text_style.font_size = style.text.font_size; + let mut diagnostic_source_style = style.hover_popover.diagnostic_source.clone(); + diagnostic_source_style.font_size = style.text.font_size; let container_style = match self.local_diagnostic.diagnostic.severity { DiagnosticSeverity::HINT => style.hover_popover.info_container, @@ -390,8 +392,18 @@ impl DiagnosticPopover { let tooltip_style = cx.global::().theme.tooltip.clone(); MouseEventHandler::::new(0, cx, |_, _| { - Text::new(self.local_diagnostic.diagnostic.message.clone(), text_style) - .with_soft_wrap(true) + Flex::row() + .with_children( + self.local_diagnostic + .diagnostic + .source + .as_ref() + .map(|source| Text::new(format!("{source}: "), diagnostic_source_style)), + ) + .with_child( + Text::new(self.local_diagnostic.diagnostic.message.clone(), text_style) + .with_soft_wrap(true), + ) .contained() .with_style(container_style) }) diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 65e4d3b8b6f0cc286a8d0f858351e63d7a94b8a2..32cbc260ec126d29e878d526d0db81aeec9b2f98 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -138,6 +138,7 @@ pub struct GroupId { #[derive(Clone, Debug, PartialEq, Eq)] pub struct Diagnostic { + pub source: Option, pub code: Option, pub severity: DiagnosticSeverity, pub message: String, @@ -2881,6 +2882,7 @@ impl operation_queue::Operation for Operation { impl Default for Diagnostic { fn default() -> Self { Self { + source: Default::default(), code: None, severity: DiagnosticSeverity::ERROR, message: Default::default(), diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index bf1d1dd2733e473211945d0683c526142d1eb05d..0de3f704c7f29e4d1cff8f3fe371d0fad36d1f42 100644 --- a/crates/language/src/proto.rs +++ b/crates/language/src/proto.rs @@ -173,6 +173,7 @@ pub fn serialize_diagnostics<'a>( diagnostics .into_iter() .map(|entry| proto::Diagnostic { + source: entry.diagnostic.source.clone(), start: Some(serialize_anchor(&entry.range.start)), end: Some(serialize_anchor(&entry.range.end)), message: entry.diagnostic.message.clone(), @@ -359,6 +360,7 @@ pub fn deserialize_diagnostics( Some(DiagnosticEntry { range: deserialize_anchor(diagnostic.start?)?..deserialize_anchor(diagnostic.end?)?, diagnostic: Diagnostic { + source: diagnostic.source, severity: match proto::diagnostic::Severity::from_i32(diagnostic.severity)? { proto::diagnostic::Severity::Error => DiagnosticSeverity::ERROR, proto::diagnostic::Severity::Warning => DiagnosticSeverity::WARNING, diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index d543f225b20fa2d87488ec832bc335907bef7ac7..3aa332696bc9d51f7ab6256b99558979c265e857 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2954,6 +2954,7 @@ impl Project { diagnostics.push(DiagnosticEntry { range, diagnostic: Diagnostic { + source: diagnostic.source.clone(), code: code.clone(), severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR), message: diagnostic.message.clone(), @@ -2971,6 +2972,7 @@ impl Project { diagnostics.push(DiagnosticEntry { range, diagnostic: Diagnostic { + source: diagnostic.source.clone(), code: code.clone(), severity: DiagnosticSeverity::INFORMATION, message: info.message.clone(), diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 599d80e2bab87c3b923f028d4c6f73005226a2d9..ffd770901508b404023e8f2b31f952cf102a13bb 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -1049,14 +1049,15 @@ enum Bias { message Diagnostic { Anchor start = 1; Anchor end = 2; - Severity severity = 3; - string message = 4; - optional string code = 5; - uint64 group_id = 6; - bool is_primary = 7; - bool is_valid = 8; - bool is_disk_based = 9; - bool is_unnecessary = 10; + optional string source = 3; + Severity severity = 4; + string message = 5; + optional string code = 6; + uint64 group_id = 7; + bool is_primary = 8; + bool is_valid = 9; + bool is_disk_based = 10; + bool is_unnecessary = 11; enum Severity { None = 0; diff --git a/crates/rpc/src/rpc.rs b/crates/rpc/src/rpc.rs index f64e6bea4c0176c73464e791ee2c1096678d792a..b7cb59266c73ccf16a69ca0dce8051c4218e0c8d 100644 --- a/crates/rpc/src/rpc.rs +++ b/crates/rpc/src/rpc.rs @@ -6,4 +6,4 @@ pub use conn::Connection; pub use peer::*; mod macros; -pub const PROTOCOL_VERSION: u32 = 52; +pub const PROTOCOL_VERSION: u32 = 53; diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index b98dd5483e7234fb41753c31fc0a127e4942963c..6edf69d0541393681f61e786a6fdbbd49293422a 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -887,6 +887,7 @@ pub struct HoverPopover { pub error_container: ContainerStyle, pub block_style: ContainerStyle, pub prose: TextStyle, + pub diagnostic_source: TextStyle, pub highlight: Color, } diff --git a/crates/zed/src/languages.rs b/crates/zed/src/languages.rs index 9ab6e1d77805393aa3fbd41e43a0deba06d592a9..91b58f634b855743e8dd0421b317cbc5efe6b725 100644 --- a/crates/zed/src/languages.rs +++ b/crates/zed/src/languages.rs @@ -89,23 +89,26 @@ pub fn init( ( "tsx", tree_sitter_typescript::language_tsx(), - vec![adapter_arc(typescript::TypeScriptLspAdapter::new( - node_runtime.clone(), - ))], + vec![ + adapter_arc(typescript::TypeScriptLspAdapter::new(node_runtime.clone())), + adapter_arc(typescript::EsLintLspAdapter::new(node_runtime.clone())), + ], ), ( "typescript", tree_sitter_typescript::language_typescript(), - vec![adapter_arc(typescript::TypeScriptLspAdapter::new( - node_runtime.clone(), - ))], + vec![ + adapter_arc(typescript::TypeScriptLspAdapter::new(node_runtime.clone())), + adapter_arc(typescript::EsLintLspAdapter::new(node_runtime.clone())), + ], ), ( "javascript", tree_sitter_typescript::language_tsx(), - vec![adapter_arc(typescript::TypeScriptLspAdapter::new( - node_runtime.clone(), - ))], + vec![ + adapter_arc(typescript::TypeScriptLspAdapter::new(node_runtime.clone())), + adapter_arc(typescript::EsLintLspAdapter::new(node_runtime.clone())), + ], ), ( "html", @@ -132,7 +135,7 @@ pub fn init( ( "yaml", tree_sitter_yaml::language(), - vec![adapter_arc(yaml::YamlLspAdapter::new(node_runtime.clone()))], + vec![adapter_arc(yaml::YamlLspAdapter::new(node_runtime))], ), ]; diff --git a/styles/src/styleTree/hoverPopover.ts b/styles/src/styleTree/hoverPopover.ts index 032c53112b27f9f6f47f378a23ef59a9ea40ac53..31e1d807788e0d30ed03a498be27f73c86c08e90 100644 --- a/styles/src/styleTree/hoverPopover.ts +++ b/styles/src/styleTree/hoverPopover.ts @@ -1,5 +1,5 @@ import { ColorScheme } from "../themes/common/colorScheme" -import { background, border, text } from "./components" +import { background, border, foreground, text } from "./components" export default function HoverPopover(colorScheme: ColorScheme) { let layer = colorScheme.middle @@ -36,10 +36,11 @@ export default function HoverPopover(colorScheme: ColorScheme) { background: background(layer, "negative"), border: border(layer, "negative"), }, - block_style: { + blockStyle: { padding: { top: 4 }, }, prose: text(layer, "sans", { size: "sm" }), + diagnosticSource: text(layer, "sans", { size: "sm", underline: true, color: foreground(layer, "accent") }), highlight: colorScheme.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better } } From 678c188de0e3572e7d9f0e7ed388455ed057a1c4 Mon Sep 17 00:00:00 2001 From: Julia Date: Wed, 26 Apr 2023 13:21:19 -0400 Subject: [PATCH 2/4] Re-allow diagnostics hovers to soft wrap Co-Authored-By: Max Brunsfeld --- crates/editor/src/hover_popover.rs | 28 +++++++++++++--------------- crates/theme/src/theme.rs | 2 +- styles/src/styleTree/hoverPopover.ts | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index df2570a8ef4daad1ce2a2ef624553d20c03257a6..b45cdb6b017a7b87ae02f6ab903458861ed94057 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -1,7 +1,7 @@ use futures::FutureExt; use gpui::{ actions, - elements::{Flex, MouseEventHandler, Padding, ParentElement, Text}, + elements::{Flex, MouseEventHandler, Padding, Text}, impl_internal_actions, platform::{CursorStyle, MouseButton}, AnyElement, AppContext, Axis, Element, ModelHandle, Task, ViewContext, @@ -378,8 +378,17 @@ impl DiagnosticPopover { let mut text_style = style.hover_popover.prose.clone(); text_style.font_size = style.text.font_size; - let mut diagnostic_source_style = style.hover_popover.diagnostic_source.clone(); - diagnostic_source_style.font_size = style.text.font_size; + let diagnostic_source_style = style.hover_popover.diagnostic_source_highlight.clone(); + + let text = match &self.local_diagnostic.diagnostic.source { + Some(source) => Text::new( + format!("{source}: {}", self.local_diagnostic.diagnostic.message), + text_style, + ) + .with_highlights(vec![(0..source.len(), diagnostic_source_style)]), + + None => Text::new(self.local_diagnostic.diagnostic.message.clone(), text_style), + }; let container_style = match self.local_diagnostic.diagnostic.severity { DiagnosticSeverity::HINT => style.hover_popover.info_container, @@ -392,18 +401,7 @@ impl DiagnosticPopover { let tooltip_style = cx.global::().theme.tooltip.clone(); MouseEventHandler::::new(0, cx, |_, _| { - Flex::row() - .with_children( - self.local_diagnostic - .diagnostic - .source - .as_ref() - .map(|source| Text::new(format!("{source}: "), diagnostic_source_style)), - ) - .with_child( - Text::new(self.local_diagnostic.diagnostic.message.clone(), text_style) - .with_soft_wrap(true), - ) + text.with_soft_wrap(true) .contained() .with_style(container_style) }) diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 6edf69d0541393681f61e786a6fdbbd49293422a..5f0e89b5bf9d26cd51209ad38da9f3e31676eb1f 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -887,7 +887,7 @@ pub struct HoverPopover { pub error_container: ContainerStyle, pub block_style: ContainerStyle, pub prose: TextStyle, - pub diagnostic_source: TextStyle, + pub diagnostic_source_highlight: HighlightStyle, pub highlight: Color, } diff --git a/styles/src/styleTree/hoverPopover.ts b/styles/src/styleTree/hoverPopover.ts index 31e1d807788e0d30ed03a498be27f73c86c08e90..fadd62db1d4cc1732a14b4459f2c3eea28891e71 100644 --- a/styles/src/styleTree/hoverPopover.ts +++ b/styles/src/styleTree/hoverPopover.ts @@ -40,7 +40,7 @@ export default function HoverPopover(colorScheme: ColorScheme) { padding: { top: 4 }, }, prose: text(layer, "sans", { size: "sm" }), - diagnosticSource: text(layer, "sans", { size: "sm", underline: true, color: foreground(layer, "accent") }), + diagnosticSourceHighlight: { underline: true, color: foreground(layer, "accent") }, highlight: colorScheme.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better } } From a284fae515519d5d200dbe106c77713dff50f5e7 Mon Sep 17 00:00:00 2001 From: Julia Date: Wed, 26 Apr 2023 13:23:38 -0400 Subject: [PATCH 3/4] Don't hardcode `workspaceFolder` for ESLint adapter --- crates/zed/src/languages/typescript.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/zed/src/languages/typescript.rs b/crates/zed/src/languages/typescript.rs index bfd6c11a27136e914331aa9b7b2a63573aa688b1..e4a540dcd8efc1fcc315852aa3bed47a87f1965e 100644 --- a/crates/zed/src/languages/typescript.rs +++ b/crates/zed/src/languages/typescript.rs @@ -206,10 +206,6 @@ impl LspAdapter for EsLintLspAdapter { "shortenToSingleLine": false }, "nodePath": null, - "workspaceFolder": { - "name": "testing_ts", - "uri": "file:///Users/julia/Stuff/testing_ts" - }, "codeAction": { "disableRuleComment": { "enable": true, From 87539e7b82da7dbabdfb2a48df88fc3a09095f00 Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 27 Apr 2023 15:04:48 -0400 Subject: [PATCH 4/4] Update test to not fail due to absence of diagnostic source --- crates/project/src/project_tests.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 5d062d42cee6a7129a7aa60f7a3db7c085840f08..fc530b51224eaffa8e069aa20dd5f7946aec35c2 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -1190,6 +1190,7 @@ async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) { DiagnosticEntry { range: Point::new(3, 9)..Point::new(3, 11), diagnostic: Diagnostic { + source: Some("disk".into()), severity: DiagnosticSeverity::ERROR, message: "undefined variable 'BB'".to_string(), is_disk_based: true, @@ -1201,6 +1202,7 @@ async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) { DiagnosticEntry { range: Point::new(4, 9)..Point::new(4, 12), diagnostic: Diagnostic { + source: Some("disk".into()), severity: DiagnosticSeverity::ERROR, message: "undefined variable 'CCC'".to_string(), is_disk_based: true, @@ -1266,6 +1268,7 @@ async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) { DiagnosticEntry { range: Point::new(2, 9)..Point::new(2, 12), diagnostic: Diagnostic { + source: Some("disk".into()), severity: DiagnosticSeverity::WARNING, message: "unreachable statement".to_string(), is_disk_based: true, @@ -1277,6 +1280,7 @@ async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) { DiagnosticEntry { range: Point::new(2, 9)..Point::new(2, 10), diagnostic: Diagnostic { + source: Some("disk".into()), severity: DiagnosticSeverity::ERROR, message: "undefined variable 'A'".to_string(), is_disk_based: true, @@ -1356,6 +1360,7 @@ async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) { DiagnosticEntry { range: Point::new(2, 21)..Point::new(2, 22), diagnostic: Diagnostic { + source: Some("disk".into()), severity: DiagnosticSeverity::WARNING, message: "undefined variable 'A'".to_string(), is_disk_based: true, @@ -1367,6 +1372,7 @@ async fn test_transforming_diagnostics(cx: &mut gpui::TestAppContext) { DiagnosticEntry { range: Point::new(3, 9)..Point::new(3, 14), diagnostic: Diagnostic { + source: Some("disk".into()), severity: DiagnosticSeverity::ERROR, message: "undefined variable 'BB'".to_string(), is_disk_based: true,