1
use tower_lsp::{lsp_types::Diagnostic as LspDiagnostic, lsp_types::*};
2

            
3
use conjure_cp_essence_parser::diagnostics::diagnostics_api::Diagnostic as ParserDiagnostic;
4
use conjure_cp_essence_parser::diagnostics::diagnostics_api::Position as ParserPosition;
5
use conjure_cp_essence_parser::diagnostics::diagnostics_api::Range as ParserRange;
6
use conjure_cp_essence_parser::diagnostics::diagnostics_api::Severity as ParserSeverity;
7
use conjure_cp_essence_parser::diagnostics::diagnostics_api::get_diagnostics;
8
use tower_lsp::lsp_types::Position as LspPosition;
9
use tower_lsp::lsp_types::Range as LspRange;
10

            
11
use crate::server::Backend;
12

            
13
// use tokio::fs;
14

            
15
impl Backend {
16
    pub async fn handle_did_open(&self, params: DidOpenTextDocumentParams) {
17
        let uri = params.text_document.uri;
18
        let text = params.text_document.text.clone();
19
        self.documents
20
            .write()
21
            .await
22
            .insert(uri.to_string().clone(), text.clone());
23

            
24
        self.client
25
            .log_message(MessageType::INFO, "Did open document")
26
            .await;
27

            
28
        //diagnostic stuff here
29
        self.handle_diagnostics(&uri.clone(), text.clone()).await;
30
    }
31
    pub async fn handle_did_save(&self, params: DidSaveTextDocumentParams) {
32
        let uri = params.text_document.uri;
33
        if let Some(text) = params.text {
34
            self.documents
35
                .write()
36
                .await
37
                .insert(uri.to_string().clone(), text.clone());
38

            
39
            self.client
40
                .log_message(MessageType::INFO, "Did save document")
41
                .await;
42

            
43
            self.handle_diagnostics(&uri.clone(), text.clone()).await;
44
        }
45
    }
46
    pub async fn handle_did_change(&self, params: DidChangeTextDocumentParams) {
47
        let uri = params.text_document.uri;
48

            
49
        if let Some(change) = params.content_changes.first() {
50
            let text = change.text.clone();
51

            
52
            self.client
53
                .log_message(MessageType::INFO, format!("New text: {}", text))
54
                .await;
55

            
56
            self.documents
57
                .write()
58
                .await
59
                .insert(uri.to_string().clone(), text.clone());
60

            
61
            //diagnostic stuff here
62
            self.handle_diagnostics(&uri.clone(), text.clone()).await;
63
        }
64
    }
65

            
66
    pub async fn handle_diagnostics(&self, uri: &Url, code: String) {
67
        let diagnostics = get_diagnostics(&code);
68
        let lsp_diagnostics = convert_diagnostics(diagnostics);
69

            
70
        // Publish diagnostics back to the client
71
        self.client
72
            .publish_diagnostics(uri.clone(), lsp_diagnostics, None)
73
            .await;
74
    }
75
}
76

            
77
// convert diagnostics from cp-essence-parser to LSP diagnostics
78
pub fn convert_diagnostics(diagnostics: Vec<ParserDiagnostic>) -> Vec<LspDiagnostic> {
79
    // map each ParserDiagnostic to LspDiagnostic
80
    diagnostics
81
        .into_iter()
82
        .map(|diag| {
83
            LspDiagnostic {
84
                range: parser_to_lsp_range(diag.range),
85
                severity: match diag.severity {
86
                    ParserSeverity::Error => Some(tower_lsp::lsp_types::DiagnosticSeverity::ERROR),
87
                    ParserSeverity::Warn => Some(tower_lsp::lsp_types::DiagnosticSeverity::WARNING),
88
                    ParserSeverity::Info => {
89
                        Some(tower_lsp::lsp_types::DiagnosticSeverity::INFORMATION)
90
                    }
91
                    ParserSeverity::Hint => Some(tower_lsp::lsp_types::DiagnosticSeverity::HINT),
92
                },
93
                code: None,             // for now
94
                code_description: None, // also for now
95
                source: Some(diag.source.to_string()),
96
                message: diag.message,
97
                related_information: None,
98
                tags: None,
99
                data: None,
100
            }
101
        })
102
        .collect()
103
}
104

            
105
// playing that position converts properly
106
pub fn parser_to_lsp_range(range: ParserRange) -> LspRange {
107
    LspRange {
108
        start: parser_to_lsp_position(range.start),
109
        end: parser_to_lsp_position(range.end),
110
    }
111
}
112

            
113
pub fn parser_to_lsp_position(position: ParserPosition) -> LspPosition {
114
    LspPosition {
115
        line: position.line,
116
        character: position.character,
117
    }
118
}