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 tower_lsp::lsp_types::{
11
    SemanticTokenModifier, SemanticTokenType, SemanticTokensLegend, SemanticTokensOptions,
12
    SemanticTokensServerCapabilities, ServerCapabilities,
13
};
14

            
15
use crate::handlers::cache::{CacheCont, create_cache};
16

            
17
use moka::future::Cache;
18

            
19
#[derive(Debug)]
20
pub struct Backend {
21
    pub client: Client,
22
    //cache is a member of backend and therefore can be accessed from within backend
23
    pub lsp_cache: Cache<Url, CacheCont>,
24
}
25

            
26
impl Backend {
27
    pub fn new(client: Client, lsp_cache: Cache<Url, CacheCont>) -> Self {
28
        Backend { client, lsp_cache } //add cache here
29
    }
30
}
31

            
32
#[tower_lsp::async_trait]
33
impl LanguageServer for Backend {
34
    //this is the server implementation and manages the server response to client requests
35
    async fn initialize(&self, _: InitializeParams) -> Result<InitializeResult> {
36
        //first request of client to server
37
        Ok(InitializeResult {
38
            server_info: None,
39
            capabilities: ServerCapabilities {
40
                //
41
                execute_command_provider: Some(ExecuteCommandOptions {
42
                    commands: vec![String::from("custom.notification")],
43
                    work_done_progress_options: Default::default(),
44
                }),
45
                text_document_sync: Some(TextDocumentSyncCapability::Options(
46
                    TextDocumentSyncOptions {
47
                        open_close: Some(true),
48
                        // sends only the change and the range of the change
49
                        change: Some(TextDocumentSyncKind::INCREMENTAL),
50
                        save: Some(TextDocumentSyncSaveOptions::SaveOptions(SaveOptions {
51
                            include_text: Some(true),
52
                        })),
53
                        ..Default::default()
54
                    },
55
                )),
56
                // provides semantic highlighting
57
                semantic_tokens_provider: Some(
58
                    SemanticTokensServerCapabilities::SemanticTokensOptions(
59
                        SemanticTokensOptions {
60
                            legend: SemanticTokensLegend {
61
                                token_types: vec![
62
                                    SemanticTokenType::NUMBER,
63
                                    SemanticTokenType::FUNCTION,
64
                                    SemanticTokenType::VARIABLE,
65
                                    SemanticTokenType::new("letting"),
66
                                    SemanticTokenType::new("find"),
67
                                    SemanticTokenType::new("domain"),
68
                                    SemanticTokenType::new("lettingVar"),
69
                                    SemanticTokenType::new("findVar"),
70
                                    SemanticTokenType::new("given"),
71
                                    SemanticTokenType::new("givenVar"),
72
                                ],
73
                                token_modifiers: vec![
74
                                    SemanticTokenModifier::DECLARATION,
75
                                    SemanticTokenModifier::READONLY,
76
                                ],
77
                            },
78
                            full: Some(SemanticTokensFullOptions::Bool(true)),
79
                            range: None,
80
                            work_done_progress_options: Default::default(),
81
                        },
82
                    ),
83
                ),
84
                //provides some simple hovering
85
                hover_provider: Some(HoverProviderCapability::Simple(true)),
86
                ..ServerCapabilities::default()
87
            },
88
        })
89
    }
90
    async fn initialized(&self, _: InitializedParams) {
91
        //request after recieving result of initialise() and before anything else
92
        self.client
93
            .log_message(MessageType::INFO, "server initialised!") //client logs message of initialised
94
            .await;
95
    }
96
    async fn shutdown(&self) -> Result<()> {
97
        Ok(())
98
    }
99
    //set up synchronising handlers
100
    async fn did_open(&self, params: DidOpenTextDocumentParams) {
101
        self.client.log_message(MessageType::INFO, "opened").await;
102
        self.handle_did_open(params).await;
103
    }
104
    async fn did_save(&self, params: DidSaveTextDocumentParams) {
105
        self.client.log_message(MessageType::INFO, "saved").await;
106

            
107
        self.handle_did_save(params).await;
108
    }
109
    async fn did_change(&self, params: DidChangeTextDocumentParams) {
110
        self.client.log_message(MessageType::INFO, "changed").await;
111

            
112
        self.handle_did_change(params).await;
113
    }
114
    //set up hover handler
115
    async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
116
        self.client.log_message(MessageType::INFO, "hovering").await;
117
        self.handle_hovering(params).await
118
    }
119

            
120
    // set up semantic highlighting
121
    async fn semantic_tokens_full(
122
        &self,
123
        params: SemanticTokensParams,
124
    ) -> Result<Option<SemanticTokensResult>> {
125
        self.client
126
            .log_message(MessageType::INFO, "semantic highlighting")
127
            .await;
128
        self.handle_semantic_highlighting(params).await
129
    }
130
}
131

            
132
#[tokio::main]
133
pub async fn main() {
134
    let stdin = tokio::io::stdin();
135
    let stdout = tokio::io::stdout();
136

            
137
    //make a new cache
138
    let lsp_cache = create_cache().await;
139

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

            
143
    Server::new(stdin, stdout, socket).serve(service).await;
144
}