brack_language_server/
server.rs1use std::str::from_utf8;
2
3use anyhow::{anyhow, Result};
4use lsp_types::{ClientCapabilities, Diagnostic, Position, Range};
5use serde_json::{from_str, json, Value};
6use tokio::io::{stdin, stdout, AsyncReadExt, AsyncWriteExt};
7
8pub struct LanguageServer {
9 client_capabilities: ClientCapabilities,
10}
11
12impl LanguageServer {
13 pub fn new() -> Self {
14 Self {
15 client_capabilities: ClientCapabilities::default(),
16 }
17 }
18
19 async fn send_message(&self, msg: &str) -> Result<()> {
20 let mut output = stdout();
21 output
22 .write_all(format!("Content-Length: {}\r\n\r\n{}", msg.len(), msg).as_bytes())
23 .await?;
24 output.flush().await?;
25 Ok(())
26 }
27
28 async fn log_message(&self, message: &str) -> Result<()> {
29 let response = json!({
30 "jsonrpc": "2.0",
31 "method": "window/logMessage",
32 "params": {
33 "type": 3,
34 "message": message
35 }
36 })
37 .to_string();
38 self.send_message(&response).await
39 }
40
41 async fn send_error_response(&self, id: Option<i64>, code: i32, message: &str) -> Result<()> {
42 let response = json!({
43 "jsonrpc": "2.0",
44 "id": id,
45 "error": {
46 "code": code,
47 "message": message,
48 }
49 })
50 .to_string();
51 self.send_message(&response).await
52 }
53
54 async fn send_invalid_request_response(&self) -> Result<()> {
55 self.send_error_response(None, -32600, "received an invalid request")
56 .await
57 }
58
59 async fn send_method_not_found_response(&self, id: i64, method: &str) -> Result<()> {
60 self.send_error_response(Some(id), -32601, &format!("{} is not supported", method))
61 .await
62 }
63
64 #[allow(dead_code)]
65 async fn send_parse_error_response(&self) -> Result<()> {
66 self.send_error_response(None, -32700, "received an invalid JSON")
67 .await
68 }
69
70 async fn send_publish_diagnostics(
71 &self,
72 uri: &str,
73 diagnostics: &Vec<Diagnostic>,
74 ) -> Result<()> {
75 if self
77 .client_capabilities
78 .text_document
79 .as_ref()
80 .and_then(|td| td.publish_diagnostics.as_ref())
81 .is_none()
82 {
83 return Ok(());
84 }
85
86 let response = json!({
87 "jsonrpc": "2.0",
88 "method": "textDocument/publishDiagnostics",
89 "params": {
90 "uri": uri,
91 "diagnostics": json!(diagnostics),
92 }
93 })
94 .to_string();
95 self.send_message(&response).await
96 }
97
98 async fn handle_request(&mut self, msg: &Value, id: i64, method: &str) -> Result<()> {
99 match method {
100 "initialize" => {
101 self.log_message("Brack Language Server is initializing...")
102 .await?;
103 self.client_capabilities = serde_json::from_value(
104 msg.get("params")
105 .ok_or_else(|| anyhow!("No params"))?
106 .get("capabilities")
107 .ok_or_else(|| anyhow!("No capabilities"))?
108 .clone(),
109 )?;
110
111 let response = json!({
119 "jsonrpc": "2.0",
120 "id": id,
121 "result": { "capabilities": {
122 "textDocumentSync": 1,
123 } }
124 })
125 .to_string();
126 self.send_message(&response).await
127 }
128 _ => self.send_method_not_found_response(id, method).await,
129 }
130 }
131
132 async fn handle_response(&self, _: &Value, _: i64) -> Result<()> {
133 Ok(())
134 }
135
136 async fn handle_notification_text_document_did_open(&self, msg: &Value) -> Result<()> {
137 let text_document = msg
138 .get("params")
139 .ok_or_else(|| anyhow!("No params"))?
140 .get("textDocument")
141 .ok_or_else(|| anyhow!("No textDocument"))?;
142 let uri = text_document
143 .get("uri")
144 .and_then(|uri| uri.as_str())
145 .ok_or_else(|| anyhow!("No uri"))?;
146 let _ = text_document
147 .get("text")
148 .and_then(|text| text.as_str())
149 .ok_or_else(|| anyhow!("No text"))?;
150 self.log_message(&format!("Did open {}", uri)).await?;
151
152 Ok(())
153 }
154
155 async fn handle_notification_text_document_did_change(&self, msg: &Value) -> Result<()> {
156 let uri = msg
157 .get("params")
158 .ok_or_else(|| anyhow!("No params"))?
159 .get("textDocument")
160 .ok_or_else(|| anyhow!("No textDocument"))?
161 .get("uri")
162 .and_then(|uri| uri.as_str())
163 .ok_or_else(|| anyhow!("No uri"))?;
164 let index = msg
165 .get("params")
166 .ok_or_else(|| anyhow!("No params"))?
167 .get("contentChanges")
168 .and_then(|content_changes| content_changes.as_array())
169 .and_then(|content_changes| content_changes.len().checked_sub(1))
170 .ok_or_else(|| anyhow!("No contentChanges"))?;
171 let _ = msg
172 .get("params")
173 .ok_or_else(|| anyhow!("No params"))?
174 .get("contentChanges")
175 .and_then(|content_changes| content_changes.get(index))
176 .and_then(|content_change| content_change.get("text"))
177 .and_then(|text| text.as_str())
178 .ok_or_else(|| anyhow!("No text"))?;
179 self.log_message(&format!("Did change {}", uri)).await?;
180
181 let diagnostics = vec![Diagnostic {
182 range: Range {
183 start: Position {
184 line: 0,
185 character: 0,
186 },
187 end: Position {
188 line: 0,
189 character: 3,
190 },
191 },
192 message: "This is a test diagnostic message 2!".to_string(),
193 ..Default::default()
194 }];
195 self.log_message(&format!("{:?}", diagnostics)).await?;
196 self.send_publish_diagnostics(uri, &diagnostics).await
197 }
198
199 async fn handle_notification(&mut self, msg: &Value, method: &str) -> Result<()> {
200 match method {
201 "initialized" => {
202 self.log_message("Brack Language Server has been initialized!")
203 .await?;
204 Ok(())
205 }
206 "textDocument/didOpen" => self.handle_notification_text_document_did_open(msg).await,
207 "textDocument/didChange" => {
208 self.handle_notification_text_document_did_change(msg).await
209 }
210 _ => Ok(()),
211 }
212 }
213
214 async fn dispatch(&mut self, msg: Value) -> Result<()> {
215 match (
216 msg.get("id").and_then(|i| i.as_i64()),
217 msg.get("method").and_then(|m| m.as_str()),
218 ) {
219 (Some(id), Some(method)) => self.handle_request(&msg, id, method).await,
220 (Some(id), None) => self.handle_response(&msg, id).await,
221 (None, Some(method)) => self.handle_notification(&msg, method).await,
222 _ => self.send_invalid_request_response().await,
223 }
224 }
225
226 pub async fn run(&mut self) -> Result<()> {
227 let mut stdin = stdin();
228 let mut buffer = Vec::new();
229
230 loop {
231 let mut tmp_buffer = [0; 1024];
232
233 let chunk = stdin.read(&mut tmp_buffer).await?;
234
235 if chunk == 0 {
236 break;
237 }
238 buffer.extend_from_slice(&tmp_buffer[..chunk]);
239
240 let buffer_string = from_utf8(&buffer)?;
241 if !buffer_string.contains("\r\n\r\n") {
242 continue;
243 }
244
245 let splitted_buffer = buffer_string.split("\r\n\r\n").collect::<Vec<&str>>();
246 let header_string = splitted_buffer[0];
247
248 let mut content_length = -1;
249 let header_length = header_string.len() + 4;
250 for line in header_string.split("\r\n") {
251 let splitted_line = line.split(": ").collect::<Vec<&str>>();
252 let key = splitted_line[0];
253 let value = splitted_line[1];
254 if key == "Content-Length" {
255 content_length = value.parse::<i32>()?;
256 }
257 }
258
259 if content_length == -1 {
260 continue;
261 }
262 let total_length = header_length + content_length as usize;
263
264 if buffer.len() < total_length {
265 continue;
266 }
267
268 let msg: Value = from_str(&buffer_string[header_length..total_length])?;
269 self.dispatch(msg).await?;
270 buffer.drain(0..total_length);
271 }
272
273 Ok(())
274 }
275}