ts_bridge/protocol/text_document/
implementation.rs1use anyhow::{Context, Result};
10use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse};
11use serde_json::{Value, json};
12
13use crate::protocol::{AdapterResult, RequestSpec};
14use crate::rpc::{Priority, Route};
15use crate::utils::{tsserver_span_to_location_link, uri_to_file_path};
16
17const CMD_IMPLEMENTATION: &str = "implementation";
18
19pub fn handle(params: GotoDefinitionParams) -> RequestSpec {
20 let text_document = params.text_document_position_params.text_document;
21 let uri_string = text_document.uri.to_string();
22 let file_name = uri_to_file_path(text_document.uri.as_str()).unwrap_or(uri_string);
23 let position = params.text_document_position_params.position;
24
25 let request = json!({
26 "command": CMD_IMPLEMENTATION,
27 "arguments": {
28 "file": file_name,
29 "line": position.line + 1,
30 "offset": position.character + 1,
31 }
32 });
33
34 RequestSpec {
35 route: Route::Syntax,
36 payload: request,
37 priority: Priority::Normal,
38 on_response: Some(adapt_implementation),
39 response_context: None,
40 }
41}
42
43fn adapt_implementation(payload: &Value, _context: Option<&Value>) -> Result<AdapterResult> {
44 let body = payload
45 .get("body")
46 .context("tsserver implementation missing body")?;
47 let locations = body
48 .as_array()
49 .context("tsserver implementation body must be array")?;
50
51 let mut links = Vec::new();
52 for span in locations {
53 if let Some(link) = tsserver_span_to_location_link(span, None) {
54 links.push(link);
55 }
56 }
57
58 let response = GotoDefinitionResponse::Link(links);
59 Ok(AdapterResult::ready(serde_json::to_value(response)?))
60}