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

            
10
use std::collections::HashMap;
11
use std::sync::Arc;
12
use tokio::sync::RwLock;
13

            
14
#[derive(Debug)]
15
pub struct Backend {
16
    pub client: Client,
17
    pub documents: Arc<RwLock<HashMap<String, String>>>, //caching document
18
}
19

            
20
impl Backend {
21
    pub fn new(client: Client, documents: Arc<RwLock<HashMap<String, String>>>) -> Self {
22
        Backend { client, documents }
23
    }
24
}
25

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

            
75
#[tokio::main]
76
pub async fn main() {
77
    let stdin = tokio::io::stdin();
78
    let stdout = tokio::io::stdout();
79
    let documents = Arc::new(RwLock::new(HashMap::new()));
80

            
81
    let (service, socket) =
82
        LspService::build(|client| Backend::new(client, Arc::clone(&documents))).finish();
83

            
84
    Server::new(stdin, stdout, socket).serve(service).await;
85
}