lsp_proxy/
hooks.rs

1use async_trait::async_trait;
2use std::fmt::Display;
3
4use crate::{
5    Message, Notification, Request, Response, message::Direction,
6    processed_message::ProcessedMessage,
7};
8
9#[derive(Debug)]
10pub enum HookError {
11    ProcessingFailed(String),
12}
13
14impl Display for HookError {
15    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16        match self {
17            HookError::ProcessingFailed(msg) => write!(f, "Hook processing failed: {}", msg),
18        }
19    }
20}
21
22impl std::error::Error for HookError {}
23
24#[derive(Debug)]
25pub struct HookOutput {
26    pub message: Option<Message>,
27    pub generated_messages: Vec<(Direction, Message)>,
28}
29
30impl HookOutput {
31    pub fn new(message: Message) -> Self {
32        Self {
33            message: Some(message),
34            generated_messages: Vec::new(),
35        }
36    }
37
38    pub fn empty() -> Self {
39        Self {
40            message: None,
41            generated_messages: Vec::new(),
42        }
43    }
44
45    pub fn with_message(mut self, direction: Direction, message: Message) -> Self {
46        self.generated_messages.push((direction, message));
47        self
48    }
49
50    pub fn with_messages(mut self, messages: Vec<(Direction, Message)>) -> Self {
51        self.generated_messages.extend(messages);
52        self
53    }
54
55    pub fn as_processed(self) -> ProcessedMessage {
56        match self.message {
57            Some(message) => {
58                if self.generated_messages.is_empty() {
59                    return ProcessedMessage::Forward(message);
60                }
61
62                ProcessedMessage::WithMessages {
63                    message,
64                    generated_messages: self.generated_messages,
65                }
66            }
67            None => ProcessedMessage::Ignore {
68                generated_messages: self.generated_messages,
69            },
70        }
71    }
72}
73
74pub type HookResult = Result<HookOutput, HookError>;
75
76#[async_trait]
77pub trait Hook: Send + Sync {
78    async fn on_request(&self, request: Request) -> HookResult {
79        Ok(HookOutput::new(Message::Request(request)))
80    }
81
82    async fn on_response(&self, response: Response) -> HookResult {
83        Ok(HookOutput::new(Message::Response(response)))
84    }
85
86    async fn on_notification(&self, notification: Notification) -> HookResult {
87        Ok(HookOutput::new(Message::Notification(notification)))
88    }
89}