Cargo.lock 🔗
@@ -9134,6 +9134,7 @@ dependencies = [
"futures 0.3.31",
"gpui",
"http_client",
+ "indoc",
"language",
"log",
"lsp",
Conrad Irwin created
t
Cargo.lock | 1
crates/diagnostics/src/diagnostic_renderer.rs | 23 +++++++--
crates/diagnostics/src/diagnostics.rs | 10 ++++
crates/editor/src/editor.rs | 18 ++++++-
crates/editor/src/hover_popover.rs | 9 +++
crates/languages/Cargo.toml | 1
crates/languages/src/vtsls.rs | 45 ++++++++++++++++++--
crates/markdown/src/markdown.rs | 18 +++++++
8 files changed, 106 insertions(+), 19 deletions(-)
@@ -9134,6 +9134,7 @@ dependencies = [
"futures 0.3.31",
"gpui",
"http_client",
+ "indoc",
"language",
"log",
"lsp",
@@ -6,7 +6,7 @@ use editor::{
hover_popover::diagnostics_markdown_style,
};
use gpui::{AppContext, Entity, Focusable, WeakEntity};
-use language::{BufferId, Diagnostic, DiagnosticEntry};
+use language::{BufferId, Diagnostic, DiagnosticEntry, LanguageRegistry};
use lsp::DiagnosticSeverity;
use markdown::{Markdown, MarkdownElement};
use settings::Settings;
@@ -27,6 +27,7 @@ impl DiagnosticRenderer {
diagnostic_group: Vec<DiagnosticEntry<Point>>,
buffer_id: BufferId,
diagnostics_editor: Option<WeakEntity<ProjectDiagnosticsEditor>>,
+ languages: Arc<LanguageRegistry>,
cx: &mut App,
) -> Vec<DiagnosticBlock> {
let Some(primary_ix) = diagnostic_group
@@ -79,7 +80,9 @@ impl DiagnosticRenderer {
initial_range: primary.range.clone(),
severity: primary.diagnostic.severity,
diagnostics_editor: diagnostics_editor.clone(),
- markdown: cx.new(|cx| Markdown::new(markdown.into(), None, None, cx)),
+ markdown: cx.new(|cx| {
+ Markdown::new(markdown.into(), Some(languages.clone()), None, cx)
+ }),
});
} else if entry.range.start.row.abs_diff(primary.range.start.row) < 5 {
let markdown = Self::markdown(&entry.diagnostic);
@@ -88,7 +91,9 @@ impl DiagnosticRenderer {
initial_range: entry.range.clone(),
severity: entry.diagnostic.severity,
diagnostics_editor: diagnostics_editor.clone(),
- markdown: cx.new(|cx| Markdown::new(markdown.into(), None, None, cx)),
+ markdown: cx.new(|cx| {
+ Markdown::new(markdown.into(), Some(languages.clone()), None, cx)
+ }),
});
} else {
let mut markdown = Self::markdown(&entry.diagnostic);
@@ -100,7 +105,9 @@ impl DiagnosticRenderer {
initial_range: entry.range.clone(),
severity: entry.diagnostic.severity,
diagnostics_editor: diagnostics_editor.clone(),
- markdown: cx.new(|cx| Markdown::new(markdown.into(), None, None, cx)),
+ markdown: cx.new(|cx| {
+ Markdown::new(markdown.into(), Some(languages.clone()), None, cx)
+ }),
});
}
}
@@ -127,9 +134,11 @@ impl editor::DiagnosticRenderer for DiagnosticRenderer {
buffer_id: BufferId,
snapshot: EditorSnapshot,
editor: WeakEntity<Editor>,
+ languages: Arc<LanguageRegistry>,
cx: &mut App,
) -> Vec<BlockProperties<Anchor>> {
- let blocks = Self::diagnostic_blocks_for_group(diagnostic_group, buffer_id, None, cx);
+ let blocks =
+ Self::diagnostic_blocks_for_group(diagnostic_group, buffer_id, None, languages, cx);
blocks
.into_iter()
.map(|block| {
@@ -155,9 +164,11 @@ impl editor::DiagnosticRenderer for DiagnosticRenderer {
diagnostic_group: Vec<DiagnosticEntry<Point>>,
range: Range<Point>,
buffer_id: BufferId,
+ languages: Arc<LanguageRegistry>,
cx: &mut App,
) -> Option<Entity<Markdown>> {
- let blocks = Self::diagnostic_blocks_for_group(diagnostic_group, buffer_id, None, cx);
+ let blocks =
+ Self::diagnostic_blocks_for_group(diagnostic_group, buffer_id, None, languages, cx);
blocks.into_iter().find_map(|block| {
if block.initial_range == range {
Some(block.markdown)
@@ -508,6 +508,15 @@ impl ProjectDiagnosticsEditor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Task<Result<()>> {
+ let languages = self
+ .editor
+ .read(cx)
+ .project
+ .as_ref()
+ .unwrap()
+ .read(cx)
+ .languages()
+ .clone();
let was_empty = self.multibuffer.read(cx).is_empty();
let buffer_snapshot = buffer.read(cx).snapshot();
let buffer_id = buffer_snapshot.remote_id();
@@ -559,6 +568,7 @@ impl ProjectDiagnosticsEditor {
group,
buffer_snapshot.remote_id(),
Some(this.clone()),
+ languages.clone(),
cx,
)
})?;
@@ -111,8 +111,9 @@ use itertools::Itertools;
use language::{
AutoindentMode, BracketMatch, BracketPair, Buffer, Capability, CharKind, CodeLabel,
CursorShape, DiagnosticEntry, DiffOptions, DocumentationConfig, EditPredictionsMode,
- EditPreview, HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point,
- Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions, WordsQuery,
+ EditPreview, HighlightedText, IndentKind, IndentSize, Language, LanguageRegistry,
+ OffsetRangeExt, Point, Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions,
+ WordsQuery,
language_settings::{
self, InlayHintSettings, LspInsertMode, RewrapBehavior, WordsCompletionMode,
all_language_settings, language_settings,
@@ -402,6 +403,7 @@ pub trait DiagnosticRenderer {
buffer_id: BufferId,
snapshot: EditorSnapshot,
editor: WeakEntity<Editor>,
+ languages: Arc<LanguageRegistry>,
cx: &mut App,
) -> Vec<BlockProperties<Anchor>>;
@@ -410,6 +412,7 @@ pub trait DiagnosticRenderer {
diagnostic_group: Vec<DiagnosticEntry<Point>>,
range: Range<Point>,
buffer_id: BufferId,
+ languages: Arc<LanguageRegistry>,
cx: &mut App,
) -> Option<Entity<markdown::Markdown>>;
@@ -16574,13 +16577,20 @@ impl Editor {
let Some(renderer) = GlobalDiagnosticRenderer::global(cx) else {
return;
};
+ let languages = self.project.as_ref().unwrap().read(cx).languages().clone();
let diagnostic_group = buffer
.diagnostic_group(buffer_id, diagnostic.diagnostic.group_id)
.collect::<Vec<_>>();
- let blocks =
- renderer.render_group(diagnostic_group, buffer_id, snapshot, cx.weak_entity(), cx);
+ let blocks = renderer.render_group(
+ diagnostic_group,
+ buffer_id,
+ snapshot,
+ cx.weak_entity(),
+ languages,
+ cx,
+ );
let blocks = self.display_map.update(cx, |display_map, cx| {
display_map.insert_blocks(blocks, cx).into_iter().collect()
@@ -275,6 +275,13 @@ fn show_hover(
return None;
}
}
+ let languages = editor
+ .project
+ .as_ref()
+ .unwrap()
+ .read(cx)
+ .languages()
+ .clone();
let hover_popover_delay = EditorSettings::get_global(cx).hover_popover_delay;
let all_diagnostics_active = editor.active_diagnostics == ActiveDiagnostic::All;
@@ -340,7 +347,7 @@ fn show_hover(
renderer
.as_ref()
.and_then(|renderer| {
- renderer.render_hover(group, point_range, buffer_id, cx)
+ renderer.render_hover(group, point_range, buffer_id, languages, cx)
})
.context("no rendered diagnostic")
})??;
@@ -44,6 +44,7 @@ dap.workspace = true
futures.workspace = true
gpui.workspace = true
http_client.workspace = true
+indoc.workspace = true
language.workspace = true
log.workspace = true
lsp.workspace = true
@@ -283,26 +283,35 @@ impl LspAdapter for VtslsLspAdapter {
fn diagnostic_message_to_markdown(&self, message: &str) -> Option<String> {
use regex::{Captures, Regex};
+ dbg!(&message);
// Helper functions for formatting
let format_type_block = |prefix: &str, content: &str| -> String {
if prefix.is_empty() {
if content.len() > 50 || content.contains('\n') || content.contains('`') {
- format!("\n```typescript\n{}\n```\n", content)
+ format!("\n```typescript\ntype a ={}\n```\n", dbg!(content))
} else {
- format!("`{}`", content)
+ format!("`{}`", dbg!(content))
}
} else {
- format!("{} `{}`", prefix, content)
+ if content.len() > 50 || content.contains('\n') || content.contains('`') {
+ format!(
+ "{}\n```typescript\ntype a ={}\n```\n",
+ prefix,
+ dbg!(content)
+ )
+ } else {
+ format!("{} `{}`", prefix, dbg!(content))
+ }
}
};
let format_typescript_block =
- |content: &str| -> String { format!("\n\n```typescript\n{}\n```\n", content) };
+ |content: &str| -> String { format!("\n\n```typescript\n{}\n```\n", dbg!(content)) };
- let format_simple_type_block = |content: &str| -> String { format!("`{}`", content) };
+ let format_simple_type_block = |content: &str| -> String { format!("`{}`", dbg!(content)) };
- let unstyle_code_block = |content: &str| -> String { format!("`{}`", content) };
+ let unstyle_code_block = |content: &str| -> String { format!("`{}`", dbg!(content)) };
let mut result = message.to_string();
@@ -396,9 +405,11 @@ impl LspAdapter for VtslsLspAdapter {
.to_string();
// Format types
+ dbg!(&result);
let re = Regex::new(r#"(?i)(type|type alias|interface|module|file|file name|class|method's|subtype of constraint) ['"](.*?)['"]"#).unwrap();
result = re
.replace_all(&result, |caps: &Captures| {
+ dbg!(&caps);
format_type_block(&caps[1], &caps[2])
})
.to_string();
@@ -469,3 +480,25 @@ async fn get_cached_ts_server_binary(
.await
.log_err()
}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use indoc::indoc;
+
+ #[test]
+ fn test_diagnostic_message_to_markdown() {
+ let message = "Property 'user' is missing in type '{ person: { username: string; email: string; }; }' but required in type '{ user: { name: string; email: `${string}@${string}.${string}`; age: number; }; }'.";
+ let expected = indoc! { "
+ Property `user` is missing in type `{ person: { username: string; email: string; }; }` but required in type
+
+ ```typescript
+ { user: { name: string; email: `${string}@${string}.${string}`; age: number; }; }
+ ```
+ "};
+ let result = VtslsLspAdapter::new(NodeRuntime::unavailable())
+ .diagnostic_message_to_markdown(message)
+ .unwrap();
+ pretty_assertions::assert_eq!(result, expected.to_string());
+ }
+}
@@ -1534,12 +1534,26 @@ impl MarkdownElementBuilder {
rendered_index: self.pending_line.text.len(),
source_index: source_range.start,
});
- self.pending_line.text.push_str(text);
+ if text.starts_with("type a =") {
+ self.pending_line.text.push_str(&text["type a =".len()..]);
+ } else {
+ self.pending_line.text.push_str(text);
+ }
self.current_source_index = source_range.end;
if let Some(Some(language)) = self.code_block_stack.last() {
+ dbg!(&language);
let mut offset = 0;
- for (range, highlight_id) in language.highlight_text(&Rope::from(text), 0..text.len()) {
+ for (mut range, highlight_id) in
+ language.highlight_text(&Rope::from(text), 0..text.len())
+ {
+ if text.starts_with("type a =") {
+ if range.start < "type a =".len() || range.end < "type a =".len() {
+ continue;
+ }
+ range.start -= "type a =".len();
+ range.end -= "type a =".len();
+ };
if range.start > offset {
self.pending_line
.runs