diff --git a/server/Cargo.lock b/server/Cargo.lock index d46cf22..297f645 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -8,6 +8,11 @@ dependencies = [ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "anyhow" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "autocfg" version = "1.0.0" @@ -373,6 +378,7 @@ dependencies = [ name = "vscode-mc-shader" version = "0.1.0" dependencies = [ + "anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "chan 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -426,6 +432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +"checksum anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" diff --git a/server/Cargo.toml b/server/Cargo.toml index 640ba9f..f3fa6e2 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -15,6 +15,7 @@ regex = "1.3.9" chan = "0.1.23" url = "2.1.1" percent-encoding = "2.1.0" +anyhow = "1.0.31" [dev-dependencies] tempdir = "0.3.7" diff --git a/server/src/main.rs b/server/src/main.rs index 46ddab3..25a75ad 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,23 +1,20 @@ -use rust_lsp::jsonrpc::method_types::*; -use rust_lsp::jsonrpc::*; +use rust_lsp::jsonrpc::{*, method_types::*}; use rust_lsp::lsp::*; -use rust_lsp::lsp_types::*; -use rust_lsp::lsp_types::notification::*; +use rust_lsp::lsp_types::{*, notification::*}; use walkdir; use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryFrom; -use std::fmt::Display; -use std::fmt::Formatter; -use std::io; -use std::io::Write; -use std::io::{BufRead, BufReader}; +use std::fmt::{Display, Formatter}; +use std::io::{stdin, stdout, BufRead, BufReader, Write}; use std::ops::Add; use std::process; use std::rc::Rc; +use anyhow::Result; + use chan::WaitGroup; use percent_encoding::percent_decode_str; @@ -45,9 +42,9 @@ static INCLUDE_STR: &'static str = "#extension GL_GOOGLE_include_directive : req static SOURCE: &'static str = "mc-glsl"; fn main() { - let stdin = std::io::stdin(); + let stdin = stdin(); - let endpoint_output = LSPEndpoint::create_lsp_output_with_output_stream(|| io::stdout()); + let endpoint_output = LSPEndpoint::create_lsp_output_with_output_stream(|| stdout()); let cache_graph = graph::CachedStableGraph::new(); @@ -238,21 +235,11 @@ impl MinecraftShaderLanguageServer { return includes; } - pub fn lint(&self, source: impl Into) -> Vec { - let source: String = source.into(); - eprintln!("validator bin path: {}", self.config.glslang_validator_path); - let cmd = process::Command::new(&self.config.glslang_validator_path) - .args(&["--stdin", "-S", "frag"]) - .stdin(process::Stdio::piped()) - .stdout(process::Stdio::piped()) - .spawn(); + pub fn lint(&self, source: impl Into) -> Result> { + let source: Rc = Rc::new(source.into()); + + let stdout = self.invoke_validator(source.as_ref())?; - let mut child = cmd.expect("glslangValidator failed to spawn"); - let stdin = child.stdin.as_mut().expect("no stdin handle found"); - stdin.write(source.as_bytes()).expect("failed to write to stdin"); - - let output = child.wait_with_output().expect("expected output"); - let stdout = String::from_utf8(output.stdout).unwrap(); eprintln!("glslangValidator output: {}\n", stdout); let mut diagnostics: Vec = vec![]; @@ -273,22 +260,23 @@ impl MinecraftShaderLanguageServer { return } - let line = match diagnostic_capture - .get(3) - .expect("third capture group was None") - .as_str() - .parse::() { - Ok(line) => line, - Err(_) => return, + let line = match diagnostic_capture.get(3) { + Some(c) => match c.as_str().parse::() { + Ok(i) => i, + Err(_) => 0, + }, + None => 0, } - 1; - let line_text = source_lines[line as usize]; let leading_whitespace = line_text.len() - line_text.trim_start().len(); - let severity = match diagnostic_capture.get(0).unwrap().as_str() { - "ERROR" => DiagnosticSeverity::Error, - "WARNING" => DiagnosticSeverity::Warning, + let severity = match diagnostic_capture.get(1) { + Some(c) => match c.as_str() { + "ERROR" => DiagnosticSeverity::Error, + "WARNING" => DiagnosticSeverity::Warning, + _ => DiagnosticSeverity::Information, + } _ => DiagnosticSeverity::Information, }; @@ -308,7 +296,25 @@ impl MinecraftShaderLanguageServer { diagnostics.push(diagnostic); }); - diagnostics + Ok(diagnostics) + } + + fn invoke_validator(&self, source: impl Into) -> Result { + let source: String = source.into(); + eprintln!("validator bin path: {}", self.config.glslang_validator_path); + let cmd = process::Command::new(&self.config.glslang_validator_path) + .args(&["--stdin", "-S", "frag"]) + .stdin(process::Stdio::piped()) + .stdout(process::Stdio::piped()) + .spawn(); + + let mut child = cmd?;//.expect("glslangValidator failed to spawn"); + let stdin = child.stdin.as_mut().expect("no stdin handle found"); + stdin.write(source.as_bytes())?;//.expect("failed to write to stdin"); + + let output = child.wait_with_output()?;//.expect("expected output"); + let stdout = String::from_utf8(output.stdout).unwrap(); + Ok(stdout) } pub fn publish_diagnostic(&self, diagnostics: Vec, uri: impl Into, document_version: Option) { @@ -427,8 +433,10 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer { fn did_open_text_document(&mut self, params: DidOpenTextDocumentParams) { eprintln!("opened doc {}", params.text_document.uri); - let diagnostics = self.lint(params.text_document.text); - self.publish_diagnostic(diagnostics, params.text_document.uri, Some(params.text_document.version)); + match self.lint(params.text_document.text) { + Ok(diagnostics) => self.publish_diagnostic(diagnostics, params.text_document.uri, Some(params.text_document.version)), + _ => return + } } fn did_change_text_document(&mut self, params: DidChangeTextDocumentParams) { @@ -447,8 +455,10 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer { let path: String = percent_encoding::percent_decode_str(params.text_document.uri.path()).decode_utf8().unwrap().into(); let file_content = std::fs::read(path).unwrap(); - let diagnostics = self.lint(String::from_utf8(file_content).unwrap()); - self.publish_diagnostic(diagnostics, params.text_document.uri, None); + match self.lint(String::from_utf8(file_content).unwrap()) { + Ok(diagnostics) => self.publish_diagnostic(diagnostics, params.text_document.uri, None), + _ => return + } } fn did_change_watched_files(&mut self, _: DidChangeWatchedFilesParams) {}