1
use tower_lsp::{
2
    Client,
3
    LanguageServer,
4
    LspService,
5
    Server,
6
    jsonrpc::Result, //add error in future if needed
7
    lsp_types::*,
8
};
9

            
10
use crate::handlers::cache::{CacheCont, create_cache};
11

            
12
use moka::future::Cache;
13

            
14
#[derive(Debug)]
15
pub struct Backend {
16
    pub client: Client,
17
    //cache is a member of backend and therefore can be accessed from within backend
18
    pub lsp_cache: Cache<Url, CacheCont>,
19
}
20

            
21
impl Backend {
22
    pub fn new(client: Client, lsp_cache: Cache<Url, CacheCont>) -> Self {
23
        Backend { client, lsp_cache } //add cache here
24
    }
25
}
26

            
27
#[tower_lsp::async_trait]
28
impl LanguageServer for Backend {
29
    //this is the server implementation and manages the server response to client requests
30
    async fn initialize(&self, _: InitializeParams) -> Result<InitializeResult> {
31
        //first request of client to server
32
        Ok(InitializeResult {
33
            server_info: None,
34
            capabilities: ServerCapabilities {
35
                //
36
                execute_command_provider: Some(ExecuteCommandOptions {
37
                    commands: vec![String::from("custom.notification")],
38
                    work_done_progress_options: Default::default(),
39
                }),
40
                text_document_sync: Some(TextDocumentSyncCapability::Options(
41
                    TextDocumentSyncOptions {
42
                        open_close: Some(true),
43
                        // sends only the change and the range of the change
44
                        change: Some(TextDocumentSyncKind::INCREMENTAL),
45
                        save: Some(TextDocumentSyncSaveOptions::SaveOptions(SaveOptions {
46
                            include_text: Some(true),
47
                        })),
48
                        ..Default::default()
49
                    },
50
                )),
51
                //provides some simple hovering
52
                hover_provider: Some(HoverProviderCapability::Simple(true)),
53
                ..ServerCapabilities::default()
54
            },
55
        })
56
    }
57
    async fn initialized(&self, _: InitializedParams) {
58
        //request after recieving result of initialise() and before anything else
59
        self.client
60
            .log_message(MessageType::INFO, "server initialised!") //client logs message of initialised
61
            .await;
62
    }
63
    async fn shutdown(&self) -> Result<()> {
64
        Ok(())
65
    }
66
    //set up synchronising handlers
67
    async fn did_open(&self, params: DidOpenTextDocumentParams) {
68
        self.client.log_message(MessageType::INFO, "opened").await;
69
        self.handle_did_open(params).await;
70
    }
71
    async fn did_save(&self, params: DidSaveTextDocumentParams) {
72
        self.client.log_message(MessageType::INFO, "saved").await;
73

            
74
        self.handle_did_save(params).await;
75
    }
76
    async fn did_change(&self, params: DidChangeTextDocumentParams) {
77
        self.client.log_message(MessageType::INFO, "changed").await;
78

            
79
        self.handle_did_change(params).await;
80
    }
81
    //set up hover handler
82
    async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
83
        self.client.log_message(MessageType::INFO, "hovering").await;
84
        self.handle_hovering(params).await
85
    }
86
}
87

            
88
#[tokio::main]
89
pub async fn main() {
90
    let stdin = tokio::io::stdin();
91
    let stdout = tokio::io::stdout();
92

            
93
    //make a new cache
94
    let lsp_cache = create_cache().await;
95

            
96
    //set cache into service when built
97
    let (service, socket) = LspService::build(|client| Backend::new(client, lsp_cache)).finish();
98

            
99
    Server::new(stdin, stdout, socket).serve(service).await;
100
}