diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs index e0005c097..cd07699de 100644 --- a/helix-lsp/src/client.rs +++ b/helix-lsp/src/client.rs @@ -583,6 +583,30 @@ impl Client { Ok(response.unwrap_or_default()) } + pub async fn goto_generic( + &self, + response: Option, + ) -> anyhow::Result> { + let items = match response { + Some(lsp::GotoDefinitionResponse::Scalar(location)) => vec![location], + Some(lsp::GotoDefinitionResponse::Array(location_vec)) => location_vec, + Some(lsp::GotoDefinitionResponse::Link(location_link_vec)) => { + let mut location_vec: Vec = Vec::new(); + location_link_vec.into_iter().for_each(|location_link| { + let link = lsp::Location { + uri: location_link.target_uri, + range: location_link.target_range, + }; + location_vec.push(link) + }); + location_vec + } + None => Vec::new(), + }; + + Ok(items) + } + pub async fn goto_definition( &self, text_document: lsp::TextDocumentIdentifier, @@ -603,23 +627,83 @@ impl Client { let response = self.request::(params).await?; - let items = match response { - Some(lsp::GotoDefinitionResponse::Scalar(location)) => vec![location], - Some(lsp::GotoDefinitionResponse::Array(location_vec)) => location_vec, - Some(lsp::GotoDefinitionResponse::Link(location_link_vec)) => { - let mut location_vec: Vec = Vec::new(); - location_link_vec.into_iter().for_each(|location_link| { - let link = lsp::Location { - uri: location_link.target_uri, - range: location_link.target_range, - }; - location_vec.push(link) - }); - location_vec - } - None => Vec::new(), + self.goto_generic(response).await + } + + pub async fn goto_type_definition( + &self, + text_document: lsp::TextDocumentIdentifier, + position: lsp::Position, + ) -> anyhow::Result> { + let params = lsp::GotoDefinitionParams { + text_document_position_params: lsp::TextDocumentPositionParams { + text_document, + position, + }, + work_done_progress_params: lsp::WorkDoneProgressParams { + work_done_token: None, + }, + partial_result_params: lsp::PartialResultParams { + partial_result_token: None, + }, }; - Ok(items) + let response = self + .request::(params) + .await?; + + self.goto_generic(response).await + } + + pub async fn goto_implementation( + &self, + text_document: lsp::TextDocumentIdentifier, + position: lsp::Position, + ) -> anyhow::Result> { + let params = lsp::GotoDefinitionParams { + text_document_position_params: lsp::TextDocumentPositionParams { + text_document, + position, + }, + work_done_progress_params: lsp::WorkDoneProgressParams { + work_done_token: None, + }, + partial_result_params: lsp::PartialResultParams { + partial_result_token: None, + }, + }; + + let response = self + .request::(params) + .await?; + + self.goto_generic(response).await + } + + pub async fn goto_reference( + &self, + text_document: lsp::TextDocumentIdentifier, + position: lsp::Position, + ) -> anyhow::Result> { + let params = lsp::ReferenceParams { + text_document_position: lsp::TextDocumentPositionParams { + text_document, + position, + }, + context: lsp::ReferenceContext { + include_declaration: true, + }, + work_done_progress_params: lsp::WorkDoneProgressParams { + work_done_token: None, + }, + partial_result_params: lsp::PartialResultParams { + partial_result_token: None, + }, + }; + + let response = self.request::(params).await?; + + self.goto_generic(response.map(lsp::GotoDefinitionResponse::Array)) + .await } } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index f07a39330..9b48e8034 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -872,11 +872,19 @@ pub fn goto_definition(cx: &mut Context) { doc.mode = Mode::Normal; + log::info!("{:?}", res); + let filepath = doc.path.clone().unwrap(); + log::info!("{:?}", filepath); + match &res.as_slice() { [location] => { - let definition_pos = location.range.start; - let new_pos = helix_lsp::util::lsp_pos_to_pos(doc.text().slice(..), definition_pos); - doc.set_selection(Selection::point(new_pos)); + if filepath.to_str().unwrap() == location.uri.path() { + let definition_pos = location.range.start; + let new_pos = helix_lsp::util::lsp_pos_to_pos(doc.text().slice(..), definition_pos); + doc.set_selection(Selection::point(new_pos)); + } else { + // open new file + } } [] => (), // maybe show user message that no definition was found? _ => { diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 82258bde9..9ec70023b 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -19,7 +19,7 @@ pub enum Mode { pub struct Document { pub state: State, // rope + selection /// File path on disk. - path: Option, + pub path: Option, // pub for testing /// Current editing mode. pub mode: Mode,