diff options
author | Hirochika Matsumoto <matsujika@gmail.com> | 2021-01-13 06:53:27 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-13 08:53:27 +1100 |
commit | 8d5af6ca5264201be1cb04b0bb1a0b88ce5166da (patch) | |
tree | b466958b75a1eb4f7f71626ea59e272dac8ecd0a /cli/lsp/language_server.rs | |
parent | 46a072c79267ee937b6fd14ad22b2aff2ff3d739 (diff) |
feat(lsp): Add textDocument/implementation (#9071)
Ref #8643
Diffstat (limited to 'cli/lsp/language_server.rs')
-rw-r--r-- | cli/lsp/language_server.rs | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 70036df3e..1b22cea2c 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -11,6 +11,7 @@ use deno_core::ModuleSpecifier; use dprint_plugin_typescript as dprint; use lspower::jsonrpc::Error as LspError; use lspower::jsonrpc::Result as LspResult; +use lspower::lsp_types::request::*; use lspower::lsp_types::*; use lspower::Client; use std::collections::HashMap; @@ -893,6 +894,69 @@ impl lspower::LanguageServer for LanguageServer { } } + async fn goto_implementation( + &self, + params: GotoImplementationParams, + ) -> LspResult<Option<GotoImplementationResponse>> { + if !self.enabled() { + return Ok(None); + } + let specifier = utils::normalize_url( + params.text_document_position_params.text_document.uri, + ); + let line_index = + self + .get_line_index(specifier.clone()) + .await + .map_err(|err| { + error!("Failed to get line_index {:#?}", err); + LspError::internal_error() + })?; + + let req = tsc::RequestMethod::GetImplementation(( + specifier, + text::to_char_pos( + &line_index, + params.text_document_position_params.position, + ), + )); + let res = + self + .ts_server + .request(self.snapshot(), req) + .await + .map_err(|err| { + error!("Failed to request to tsserver {:#?}", err); + LspError::invalid_request() + })?; + + let maybe_implementations = serde_json::from_value::<Option<Vec<tsc::ImplementationLocation>>>(res) + .map_err(|err| { + error!("Failed to deserialized tsserver response to Vec<ImplementationLocation> {:#?}", err); + LspError::internal_error() + })?; + + if let Some(implementations) = maybe_implementations { + let mut results = Vec::new(); + for impl_ in implementations { + let document_span = impl_.document_span; + let impl_specifier = + ModuleSpecifier::resolve_url(&document_span.file_name).unwrap(); + let impl_line_index = + &self.get_line_index(impl_specifier).await.unwrap(); + if let Some(link) = document_span + .to_link(impl_line_index, |s| self.get_line_index(s)) + .await + { + results.push(link); + } + } + Ok(Some(GotoDefinitionResponse::Link(results))) + } else { + Ok(None) + } + } + async fn rename( &self, params: RenameParams, |