ts_bridge/protocol/
mod.rs

1//! =============================================================================
2//! Protocol Handlers
3//! =============================================================================
4//!
5//! Every LSP method will map to a Rust module inside this tree.  The Lua
6//! implementation dynamically transformed method names into module paths; in
7//! Rust we will keep a static registry for clarity and compile-time checking.
8
9use lsp_types::{GotoDefinitionParams, TextDocumentPositionParams, request::Request};
10use serde_json::Value;
11
12use crate::rpc::{Priority, Route};
13
14pub mod diagnostics;
15pub mod text_document;
16pub mod workspace;
17
18pub enum AdapterResult {
19    Ready(Value),
20    Continue(RequestSpec),
21}
22
23impl AdapterResult {
24    pub fn ready(value: Value) -> Self {
25        Self::Ready(value)
26    }
27}
28
29pub type ResponseAdapter = fn(&Value, Option<&Value>) -> anyhow::Result<AdapterResult>;
30
31#[derive(Debug)]
32pub struct RequestSpec {
33    pub route: Route,
34    pub payload: Value,
35    pub priority: Priority,
36    pub on_response: Option<ResponseAdapter>,
37    pub response_context: Option<Value>,
38}
39
40#[derive(Debug)]
41pub struct NotificationSpec {
42    pub route: Route,
43    pub payload: Value,
44    pub priority: Priority,
45}
46
47pub fn route_request(method: &str, params: Value) -> Option<RequestSpec> {
48    match method {
49        lsp_types::request::HoverRequest::METHOD => {
50            let params: lsp_types::HoverParams = serde_json::from_value(params).ok()?;
51            Some(text_document::hover::handle(params))
52        }
53        lsp_types::request::Completion::METHOD => {
54            let params: lsp_types::CompletionParams = serde_json::from_value(params).ok()?;
55            Some(text_document::completion::handle(params))
56        }
57        lsp_types::request::ResolveCompletionItem::METHOD => {
58            let item: lsp_types::CompletionItem = serde_json::from_value(params).ok()?;
59            text_document::completion_resolve::handle(item)
60        }
61        lsp_types::request::GotoDefinition::METHOD => {
62            let params: text_document::definition::DefinitionParams =
63                serde_json::from_value(params).ok()?;
64            Some(text_document::definition::handle(params))
65        }
66        lsp_types::request::SignatureHelpRequest::METHOD => {
67            let params: lsp_types::SignatureHelpParams = serde_json::from_value(params).ok()?;
68            Some(text_document::signature_help::handle(params))
69        }
70        lsp_types::request::References::METHOD => {
71            let params: lsp_types::ReferenceParams = serde_json::from_value(params).ok()?;
72            Some(text_document::references::handle(params))
73        }
74        lsp_types::request::GotoTypeDefinition::METHOD => {
75            let params: GotoDefinitionParams = serde_json::from_value(params).ok()?;
76            Some(text_document::type_definition::handle(params))
77        }
78        lsp_types::request::GotoImplementation::METHOD => {
79            let params: GotoDefinitionParams = serde_json::from_value(params).ok()?;
80            Some(text_document::implementation::handle(params))
81        }
82        lsp_types::request::DocumentSymbolRequest::METHOD => {
83            let params: lsp_types::DocumentSymbolParams = serde_json::from_value(params).ok()?;
84            Some(text_document::document_symbol::handle(params))
85        }
86        lsp_types::request::PrepareRenameRequest::METHOD => {
87            let params: TextDocumentPositionParams = serde_json::from_value(params).ok()?;
88            Some(text_document::rename::handle_prepare(params))
89        }
90        lsp_types::request::Rename::METHOD => {
91            let params: lsp_types::RenameParams = serde_json::from_value(params).ok()?;
92            Some(text_document::rename::handle(params))
93        }
94        lsp_types::request::CodeActionRequest::METHOD => {
95            let params: lsp_types::CodeActionParams = serde_json::from_value(params).ok()?;
96            Some(text_document::code_action::handle(params))
97        }
98        lsp_types::request::CodeActionResolveRequest::METHOD => {
99            let action: lsp_types::CodeAction = serde_json::from_value(params).ok()?;
100            text_document::code_action_resolve::handle(action)
101        }
102        lsp_types::request::Formatting::METHOD => {
103            let params: lsp_types::DocumentFormattingParams =
104                serde_json::from_value(params).ok()?;
105            Some(text_document::formatting::handle(params))
106        }
107        lsp_types::request::SemanticTokensFullRequest::METHOD => {
108            let params: lsp_types::SemanticTokensParams = serde_json::from_value(params).ok()?;
109            Some(text_document::semantic_tokens::handle_full(params))
110        }
111        lsp_types::request::SemanticTokensRangeRequest::METHOD => {
112            let params: lsp_types::SemanticTokensRangeParams =
113                serde_json::from_value(params).ok()?;
114            Some(text_document::semantic_tokens::handle_range(params))
115        }
116        lsp_types::request::WorkspaceSymbolRequest::METHOD => {
117            let params: lsp_types::WorkspaceSymbolParams = serde_json::from_value(params).ok()?;
118            Some(workspace::symbol::handle(params))
119        }
120        lsp_types::request::WillRenameFiles::METHOD => {
121            let params: lsp_types::RenameFilesParams = serde_json::from_value(params).ok()?;
122            workspace::rename::handle(params)
123        }
124        lsp_types::request::ExecuteCommand::METHOD => {
125            let params: lsp_types::ExecuteCommandParams = serde_json::from_value(params).ok()?;
126            workspace::execute_command::handle(params)
127        }
128        _ => None,
129    }
130}
131
132pub fn route_notification(_method: &str, _params: Value) -> Option<NotificationSpec> {
133    None
134}