Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions crates/ui/src/input/lsp/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl InputState {
pub(crate) fn on_action_go_to_definition(
&mut self,
_: &GoToDefinition,
_: &mut Window,
window: &mut Window,
cx: &mut Context<Self>,
) {
let offset = self.cursor();
Expand All @@ -121,7 +121,7 @@ impl InputState {
}

if let Some(location) = locations.first().cloned() {
self.go_to_definition(&location, cx);
self.go_to_definition(&location, window, cx);
}
}
}
Expand All @@ -131,7 +131,7 @@ impl InputState {
&mut self,
event: &MouseDownEvent,
offset: usize,
_: &mut Window,
window: &mut Window,
cx: &mut Context<InputState>,
) -> bool {
if !event.modifiers.secondary() {
Expand All @@ -149,26 +149,42 @@ impl InputState {
return false;
};

self.go_to_definition(&location, cx);
self.go_to_definition(&location, window, cx);

true
}

pub(crate) fn go_to_definition(
&mut self,
location: &lsp_types::LocationLink,
window: &mut Window,
cx: &mut Context<Self>,
) {
if location
let external = location
.target_uri
.scheme()
.map(|s| s.as_str() == "https" || s.as_str() == "http")
== Some(true)
{
== Some(true);

// Give the host a chance to show the document first (window/showDocument),
// e.g. to open virtual/external documents (stdlib docs) in an app window.
if let Some(handler) = self.lsp.show_document.clone() {
let params = lsp_types::ShowDocumentParams {
uri: location.target_uri.clone(),
external: Some(external),
take_focus: Some(true),
selection: Some(location.target_selection_range),
};
if handler(&params, window, cx) {
return;
}
}

if external {
cx.open_url(&location.target_uri.to_string());
} else {
// Move to the location.
let target_range = location.target_range;
let target_range = location.target_selection_range;
let start = self.text.position_to_offset(&target_range.start);
let end = self.text.position_to_offset(&target_range.end);

Expand Down
18 changes: 18 additions & 0 deletions crates/ui/src/input/lsp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ pub use document_colors::*;
pub use hover::*;
pub use semantic_tokens::*;

/// Host hook to show a document when following an LSP location
/// (Go to Definition), modeled after the `window/showDocument` request.
///
/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#window_showDocument
///
/// Called before the built-in behavior. Return `true` if the host has shown
/// the document (e.g. opened a docs window for a virtual/external URI);
/// return `false` to fall through to the default handling (`external` URIs
/// open in the browser, anything else jumps within the current document).
pub type ShowDocumentHandler =
Rc<dyn Fn(&lsp_types::ShowDocumentParams, &mut Window, &mut App) -> bool>;

/// LSP ServerCapabilities
///
/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#serverCapabilities
Expand All @@ -35,6 +47,11 @@ pub struct Lsp {
pub document_color_provider: Option<Rc<dyn DocumentColorProvider>>,
/// The range semantic tokens provider.
pub semantic_tokens_provider: Option<Rc<dyn DocumentRangeSemanticTokensProvider>>,
/// Optional host hook to show documents for Go to Definition locations,
/// following the `window/showDocument` request (see [`ShowDocumentHandler`]).
///
/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#window_showDocument
pub show_document: Option<ShowDocumentHandler>,

document_colors: Vec<(lsp_types::Range, Hsla)>,
/// Cached semantic tokens as absolute position ranges + theme token-type
Expand All @@ -55,6 +72,7 @@ impl Default for Lsp {
definition_provider: None,
document_color_provider: None,
semantic_tokens_provider: None,
show_document: None,
document_colors: vec![],
semantic_tokens: vec![],
_hover_task: Task::ready(Ok(())),
Expand Down
Loading