1use dashmap::DashMap;
2use lsp_max_ast_core::document::Document;
3use lsp_types_max::{
4 Diagnostic, DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams,
5 DocumentUri,
6};
7use parking_lot::Mutex;
8use tree_sitter::Parser;
9
10pub struct AutoLspAdapter {
17 documents: DashMap<DocumentUri, Mutex<Document>>,
19}
20
21impl Default for AutoLspAdapter {
22 fn default() -> Self {
23 Self::new_default()
24 }
25}
26
27impl AutoLspAdapter {
28 pub fn new_default() -> Self {
30 Self {
31 documents: DashMap::new(),
32 }
33 }
34
35 pub fn handle_did_open(
37 &self,
38 params: DidOpenTextDocumentParams,
39 language: tree_sitter::Language,
40 ) {
41 let uri = params.text_document.uri;
42 let text = params.text_document.text;
43
44 let mut parser = Parser::new();
45 parser
46 .set_language(&language)
47 .expect("Error loading grammar");
48
49 if let Some(tree) = parser.parse(&text, None) {
50 let doc = Document::new(text, tree, None);
51 self.documents.insert(uri, Mutex::new(doc));
52 }
53 }
54
55 pub fn handle_did_change(
57 &self,
58 params: DidChangeTextDocumentParams,
59 language: tree_sitter::Language,
60 ) {
61 let uri = params.text_document.uri;
62 if let Some(doc_ref) = self.documents.get(&uri) {
63 let mut doc = doc_ref.lock();
64 let mut parser = Parser::new();
65 parser
66 .set_language(&language)
67 .expect("Error loading grammar");
68
69 let _ = doc.update(&mut parser, ¶ms.content_changes);
70 }
71 }
72
73 pub fn handle_did_close(&self, params: DidCloseTextDocumentParams) {
75 self.documents.remove(¶ms.text_document.uri);
76 }
77
78 pub fn pull_diagnostics(&self, uri: &DocumentUri) -> Vec<Diagnostic> {
80 let mut diags = Vec::new();
81 if let Some(doc_ref) = self.documents.get(uri) {
82 let doc = doc_ref.lock();
83
84 let mut queue = vec![doc.tree.root_node()];
87 while let Some(node) = queue.pop() {
88 if node.is_error() || node.is_missing() {
89 let range = doc.denormalize_range(&node.range()).unwrap_or_default();
90 diags.push(Diagnostic {
91 range,
92 severity: Some(lsp_types_max::DiagnosticSeverity::ERROR),
93 code: Some(lsp_types_max::NumberOrString::String(
94 "AST_ERROR".to_string(),
95 )),
96 source: Some("lsp-max-ast".to_string()),
97 message: "Syntax error detected by formal parser.".to_string(),
98 ..Default::default()
99 });
100 }
101
102 for i in 0..node.child_count() as u32 {
104 if let Some(child) = node.child(i) {
105 queue.push(child);
106 }
107 }
108 }
109 }
110 diags
111 }
112
113 pub fn get_document<F, R>(&self, uri: &DocumentUri, f: F) -> Option<R>
115 where
116 F: FnOnce(&Document) -> R,
117 {
118 self.documents.get(uri).map(|doc_ref| f(&doc_ref.lock()))
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_adapter_initialization() {
128 let adapter = AutoLspAdapter::new_default();
129 assert!(adapter.documents.is_empty());
130 }
131}