Minimize diff some more

Co-authored-by: David Kleingeld <davidsk@zed.dev>
This commit is contained in:
Richard Feldman 2025-08-25 11:30:45 -04:00
parent c70178b7ea
commit 78ca73e0b9
No known key found for this signature in database

View file

@ -391,27 +391,25 @@ pub fn update_inlay_link_and_hover_points(
} }
} }
project::InlayHintLabel::LabelParts(label_parts) => { project::InlayHintLabel::LabelParts(label_parts) => {
// Find the first part with actual hover information (tooltip or location) let hint_start =
let _hint_start =
snapshot.anchor_to_inlay_offset(hovered_hint.position); snapshot.anchor_to_inlay_offset(hovered_hint.position);
let mut part_offset = 0; if let Some((hovered_hint_part, part_range)) =
hover_popover::find_hovered_hint_part(
for part in label_parts { label_parts,
let part_len = part.value.chars().count(); hint_start,
hovered_offset,
if part.tooltip.is_some() || part.location.is_some() { )
// Found the meaningful part - show hover for it {
let highlight_start = part_offset + extra_shift_left; let highlight_start =
(part_range.start - hint_start).0 + extra_shift_left;
let highlight_end = let highlight_end =
part_offset + part_len + extra_shift_right; (part_range.end - hint_start).0 + extra_shift_right;
let highlight = InlayHighlight { let highlight = InlayHighlight {
inlay: hovered_hint.id, inlay: hovered_hint.id,
inlay_position: hovered_hint.position, inlay_position: hovered_hint.position,
range: highlight_start..highlight_end, range: highlight_start..highlight_end,
}; };
if let Some(tooltip) = hovered_hint_part.tooltip {
if let Some(tooltip) = part.tooltip {
hover_popover::hover_at_inlay( hover_popover::hover_at_inlay(
editor, editor,
InlayHover { InlayHover {
@ -436,38 +434,15 @@ pub fn update_inlay_link_and_hover_points(
); );
hover_updated = true; hover_updated = true;
} }
if let Some((language_server_id, location)) = if let Some((language_server_id, location)) =
part.location.clone() hovered_hint_part.location
{ {
// When there's no tooltip but we have a location, perform a "Go to Definition" style operation
let filename = location
.uri
.path()
.split('/')
.next_back()
.unwrap_or("unknown")
.to_string();
hover_popover::hover_at_inlay(
editor,
InlayHover {
tooltip: HoverBlock {
text: "Loading documentation..."
.to_string(),
kind: HoverBlockKind::PlainText,
},
range: highlight.clone(),
},
window,
cx,
);
hover_updated = true;
// Now perform the "Go to Definition" flow to get hover documentation // Now perform the "Go to Definition" flow to get hover documentation
if let Some(project) = editor.project.clone() { if let Some(project) = editor.project.clone() {
let highlight = highlight.clone(); let highlight = highlight.clone();
let hint_value = part.value.clone(); let hint_value = hovered_hint_part.value.clone();
let location_uri = location.uri.clone(); let location = location.clone();
cx.spawn_in(window, async move |editor, cx| { cx.spawn_in(window, async move |editor, cx| {
async move { async move {
@ -477,8 +452,10 @@ pub fn update_inlay_link_and_hover_points(
.await; .await;
// Convert LSP URL to file path // Convert LSP URL to file path
let file_path = location.uri.to_file_path() let file_path =
.map_err(|_| anyhow::anyhow!("Invalid file URL"))?; location.uri.to_file_path().map_err(
|_| anyhow::anyhow!("Invalid file URL"),
)?;
// Open the definition file // Open the definition file
let definition_buffer = project let definition_buffer = project
@ -488,49 +465,78 @@ pub fn update_inlay_link_and_hover_points(
.await?; .await?;
// Extract documentation directly from the source // Extract documentation directly from the source
let documentation = definition_buffer.update(cx, |buffer, _| { let documentation = definition_buffer.update(
let line_number = location.range.start.line as usize; cx,
|buffer, _| {
let line_number =
location.range.start.line as usize;
// Get the text of the buffer // Get the text of the buffer
let text = buffer.text(); let text = buffer.text();
let lines: Vec<&str> = text.lines().collect(); let lines: Vec<&str> =
text.lines().collect();
// Look backwards from the definition line to find doc comments // Look backwards from the definition line to find doc comments
let mut doc_lines = Vec::new(); let mut doc_lines = Vec::new();
let mut current_line = line_number.saturating_sub(1); let mut current_line =
line_number.saturating_sub(1);
// Skip any attributes like #[derive(...)] // Skip any attributes like #[derive(...)]
while current_line > 0 && lines.get(current_line).map_or(false, |line| { while current_line > 0
&& lines.get(current_line).map_or(
false,
|line| {
let trimmed = line.trim(); let trimmed = line.trim();
trimmed.starts_with("#[") || trimmed.is_empty() trimmed.starts_with("#[")
}) { || trimmed.is_empty()
current_line = current_line.saturating_sub(1); },
)
{
current_line =
current_line.saturating_sub(1);
} }
// Collect doc comments // Collect doc comments
while current_line > 0 { while current_line > 0 {
if let Some(line) = lines.get(current_line) { if let Some(line) =
lines.get(current_line)
{
let trimmed = line.trim(); let trimmed = line.trim();
if trimmed.starts_with("///") { if trimmed.starts_with("///") {
// Remove the /// and any leading space // Remove the /// and any leading space
let doc_text = trimmed.strip_prefix("///").unwrap_or("") let doc_text = trimmed
.strip_prefix(" ").unwrap_or_else(|| trimmed.strip_prefix("///").unwrap_or("")); .strip_prefix("///")
doc_lines.push(doc_text.to_string()); .unwrap_or("")
.strip_prefix(" ")
.unwrap_or_else(|| {
trimmed
.strip_prefix(
"///",
)
.unwrap_or("")
});
doc_lines.push(
doc_text.to_string(),
);
} else if !trimmed.is_empty() { } else if !trimmed.is_empty() {
// Stop at the first non-doc, non-empty line // Stop at the first non-doc, non-empty line
break; break;
} }
} }
current_line = current_line.saturating_sub(1); current_line =
current_line.saturating_sub(1);
} }
// Reverse to get correct order // Reverse to get correct order
doc_lines.reverse(); doc_lines.reverse();
// Also get the actual definition line // Also get the actual definition line
let definition = lines.get(line_number) let definition = lines
.get(line_number)
.map(|s| s.trim().to_string()) .map(|s| s.trim().to_string())
.unwrap_or_else(|| hint_value.clone()); .unwrap_or_else(|| {
hint_value.clone()
});
if doc_lines.is_empty() { if doc_lines.is_empty() {
None None
@ -538,13 +544,19 @@ pub fn update_inlay_link_and_hover_points(
let docs = doc_lines.join("\n"); let docs = doc_lines.join("\n");
Some((definition, docs)) Some((definition, docs))
} }
})?; },
)?;
if let Some((definition, docs)) = documentation { if let Some((definition, docs)) = documentation
{
// Format as markdown with the definition as a code block // Format as markdown with the definition as a code block
let formatted_docs = format!("```rust\n{}\n```\n\n{}", definition, docs); let formatted_docs = format!(
"```rust\n{}\n```\n\n{}",
definition, docs
);
editor.update_in(cx, |editor, window, cx| { editor
.update_in(cx, |editor, window, cx| {
hover_popover::hover_at_inlay( hover_popover::hover_at_inlay(
editor, editor,
InlayHover { InlayHover {
@ -557,16 +569,18 @@ pub fn update_inlay_link_and_hover_points(
window, window,
cx, cx,
); );
}).log_err(); })
.log_err();
} else { } else {
// Fallback to showing just the location info // Fallback to showing just the location info
let fallback_text = format!( let fallback_text = format!(
"{}\n\nDefined in {} at line {}", "{}\n\nDefined in at line {}",
hint_value.trim(), hint_value.trim(),
filename, // filename, // TODO
location.range.start.line + 1 location.range.start.line + 1
); );
editor.update_in(cx, |editor, window, cx| { editor
.update_in(cx, |editor, window, cx| {
hover_popover::hover_at_inlay( hover_popover::hover_at_inlay(
editor, editor,
InlayHover { InlayHover {
@ -579,19 +593,18 @@ pub fn update_inlay_link_and_hover_points(
window, window,
cx, cx,
); );
}).log_err(); })
.log_err();
} }
anyhow::Ok(()) anyhow::Ok(())
} }
.log_err() .log_err()
.await .await
}).detach(); })
} .detach();
} }
if let Some((language_server_id, location)) = &part.location
{
if secondary_held if secondary_held
&& !editor.has_pending_nonempty_selection() && !editor.has_pending_nonempty_selection()
{ {
@ -601,8 +614,8 @@ pub fn update_inlay_link_and_hover_points(
editor, editor,
TriggerPoint::InlayHint( TriggerPoint::InlayHint(
highlight, highlight,
location.clone(), location,
*language_server_id, language_server_id,
), ),
snapshot, snapshot,
window, window,
@ -610,14 +623,9 @@ pub fn update_inlay_link_and_hover_points(
); );
} }
} }
break;
}
part_offset += part_len;
} }
} }
}; }
} }
ResolveState::Resolving => {} ResolveState::Resolving => {}
}; };