From fe4907c22f67e899e2bb5e8ae3da40b3a03c9f52 Mon Sep 17 00:00:00 2001 From: DavidLee18 Date: Thu, 31 Oct 2024 13:09:56 +0900 Subject: [PATCH] update server capabilities + react! to different arguments --- src/main.rs | 99 +++++++++++++++++++++++++------------------ src/norminette_msg.rs | 21 +++++---- 2 files changed, 68 insertions(+), 52 deletions(-) diff --git a/src/main.rs b/src/main.rs index e1b6c1c..9af28eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,12 +2,13 @@ pub mod norminette_msg; pub mod parser; use lsp_server::{Connection, ExtractError, Message, Notification, Request, RequestId, Response}; -use lsp_types::notification::{DidChangeTextDocument, DidOpenTextDocument, DidSaveTextDocument}; +use lsp_types::notification::{DidOpenTextDocument, DidSaveTextDocument}; use lsp_types::request::DocumentDiagnosticRequest; use lsp_types::{ - Diagnostic, DiagnosticOptions, DiagnosticServerCapabilities, - InitializeParams, LogMessageParams, MessageType, PublishDiagnosticsParams, ServerCapabilities, - WorkDoneProgressOptions, + Diagnostic, DiagnosticOptions, DiagnosticServerCapabilities, DidOpenTextDocumentParams, + DidSaveTextDocumentParams, InitializeParams, PublishDiagnosticsParams, SaveOptions, + ServerCapabilities, TextDocumentSyncCapability, TextDocumentSyncOptions, + TextDocumentSyncSaveOptions, WorkDoneProgressOptions, }; use parser::parse_norminette; use std::error::Error; @@ -15,11 +16,11 @@ use std::io; use std::path::Path; macro_rules! diag_on_event { - ($conn: expr, $noti: expr, $t: ident) => { + ($conn: expr, $noti: expr, $t: ident, $f: expr) => { match cast_noti::<$t>($noti) { Ok(params) => { eprintln!("got doc document open notification: {params:?}"); - notify_diagnostics!($conn, params); + notify_diagnostics!($conn, ¶ms, $f); } Err(_) => {} } @@ -27,30 +28,25 @@ macro_rules! diag_on_event { } macro_rules! notify_diagnostics { - ($conn: expr, $params: expr) => { - match read_norminette(&Path::new($params.text_document.uri.path().as_str())) { + ($conn: expr, $params: expr, $f: expr) => { + let text = $f.map(|f_| f_($params)); + match read_norminette(&Path::new($params.text_document.uri.path().as_str()), text) { Ok(diags) => { $conn.sender.send(Message::Notification(Notification { method: String::from("textDocument/publishDiagnostics"), params: serde_json::to_value(&PublishDiagnosticsParams { - uri: $params.text_document.uri, + uri: $params.text_document.uri.clone(), diagnostics: diags, version: None, })?, }))?; } Err(e) => { - $conn.sender.send(Message::Notification(Notification { - method: String::from("window/logMessage"), - params: serde_json::to_value(&LogMessageParams { - typ: MessageType::ERROR, - message: format!( - "norminette read of {} failed: {}", - $params.text_document.uri.path(), - e - ), - })?, - }))?; + eprintln!( + "norminette read of {} failed: {}", + $params.text_document.uri.path(), + e + ); } } }; @@ -58,7 +54,7 @@ macro_rules! notify_diagnostics { macro_rules! send_diagnostics { ($conn: expr, $id: expr, $params: expr) => { - match read_norminette(&Path::new($params.text_document.uri.path().as_str())) { + match read_norminette(&Path::new($params.text_document.uri.path().as_str()), None) { Ok(diags) => { $conn.sender.send(Message::Response(Response { id: $id, @@ -71,29 +67,28 @@ macro_rules! send_diagnostics { }))?; } Err(e) => { - $conn.sender.send(Message::Response(Response { - id: $id, - result: Some(serde_json::to_value(&LogMessageParams { - typ: MessageType::ERROR, - message: format!( - "norminette read of {} failed: {}", - $params.text_document.uri.path(), - e - ), - })?), - error: None, - }))?; + eprintln!( + "norminette read of {} failed: {}", + $params.text_document.uri.path(), + e + ); } } }; } -fn read_norminette(path: &Path) -> io::Result> { - let output = std::process::Command::new("norminette") - .arg(path) - .output()?; +fn read_norminette(path: &Path, text: Option) -> io::Result> { + let mut cmd = std::process::Command::new("norminette"); + match text { + Some(text) => { + cmd.args(["--cfile", &text, "--filename", path.to_str().unwrap()]); + } + None => { + cmd.arg(path); + } + } let (_, diags) = parse_norminette( - &String::from_utf8(output.stdout) + &String::from_utf8(cmd.output()?.stdout) .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?, ) .map_err(|err| { @@ -123,6 +118,16 @@ fn main() -> Result<(), Box> { workspace_diagnostics: false, work_done_progress_options: WorkDoneProgressOptions::default(), })), + text_document_sync: Some(TextDocumentSyncCapability::Options( + TextDocumentSyncOptions { + open_close: Some(true), + change: None, + save: Some(TextDocumentSyncSaveOptions::SaveOptions(SaveOptions { + include_text: Some(true), + })), + ..Default::default() + }, + )), ..Default::default() })?; let initialization_params = match connection.initialize(server_capabilities) { @@ -171,9 +176,21 @@ fn main_loop( } Message::Notification(not) => { eprintln!("got notification: {not:?}"); - diag_on_event!(connection, not.clone(), DidOpenTextDocument); - diag_on_event!(connection, not.clone(), DidChangeTextDocument); - diag_on_event!(connection, not, DidSaveTextDocument); + diag_on_event!( + connection, + not.clone(), + DidOpenTextDocument, + Some(|p: &DidOpenTextDocumentParams| p.text_document.text.clone()) + ); + diag_on_event!( + connection, + not, + DidSaveTextDocument, + Some(|p: &DidSaveTextDocumentParams| p + .text + .clone() + .expect("includeText set to true yet text was None")) + ); } } } diff --git a/src/norminette_msg.rs b/src/norminette_msg.rs index 78f1076..20a93ef 100644 --- a/src/norminette_msg.rs +++ b/src/norminette_msg.rs @@ -10,29 +10,28 @@ pub enum NorminetteMsg { column: i32, message: String, }, - Ok + Ok, } impl NorminetteMsg { pub fn find_range(&self) -> Option { match self { - NorminetteMsg::Error { - error_type: _, - line, - column, - message: _, - } => Some(Range { + NorminetteMsg::Error { line, column, .. } => Some(Range { start: Position::new((line - 1) as u32, *column as u32), - end: Position::new(*line as u32, u32::MAX), + end: Position::new(*line as u32, (column + 1) as u32), }), - NorminetteMsg::Ok => None + NorminetteMsg::Ok => None, } } pub fn to_diagnostic(self) -> Option { let range = self.find_range()?; match self { - NorminetteMsg::Error { error_type, message, .. } => Some(Diagnostic { + NorminetteMsg::Error { + error_type, + message, + .. + } => Some(Diagnostic { range, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String(error_type)), @@ -43,7 +42,7 @@ impl NorminetteMsg { tags: None, data: None, }), - NorminetteMsg::Ok => None + NorminetteMsg::Ok => None, } } }