diff options
Diffstat (limited to 'support/texlab/src/diagnostics/latex.rs')
-rw-r--r-- | support/texlab/src/diagnostics/latex.rs | 86 |
1 files changed, 47 insertions, 39 deletions
diff --git a/support/texlab/src/diagnostics/latex.rs b/support/texlab/src/diagnostics/latex.rs index 8b15f67dfc..95fcaeeacf 100644 --- a/support/texlab/src/diagnostics/latex.rs +++ b/support/texlab/src/diagnostics/latex.rs @@ -1,33 +1,22 @@ -use crate::range::RangeExt; -use crate::workspace::{Document, Uri}; -use lsp_types::*; +use crate::{ + protocol::{Diagnostic, DiagnosticSeverity, NumberOrString, Range, RangeExt, Uri}, + workspace::Document, +}; +use chashmap::CHashMap; +use futures::{ + future::{AbortHandle, Abortable, Aborted}, + lock::Mutex, +}; +use log::trace; use once_cell::sync::Lazy; use regex::Regex; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; -use std::io::{Read, Write}; -use std::process::{Command, Stdio}; +use std::process::Stdio; +use tokio::{prelude::*, process::Command}; -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct LatexLintOptions { - pub on_change: Option<bool>, - pub on_save: Option<bool>, -} - -impl LatexLintOptions { - pub fn on_change(&self) -> bool { - self.on_change.unwrap_or(false) - } - - pub fn on_save(&self) -> bool { - self.on_save.unwrap_or(false) - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Default)] +#[derive(Debug, Default)] pub struct LatexDiagnosticsProvider { - diagnostics_by_uri: HashMap<Uri, Vec<Diagnostic>>, + diagnostics_by_uri: CHashMap<Uri, Vec<Diagnostic>>, + handle: Mutex<Option<AbortHandle>>, } impl LatexDiagnosticsProvider { @@ -38,34 +27,52 @@ impl LatexDiagnosticsProvider { } } - pub fn update(&mut self, uri: &Uri, text: &str) { + pub async fn update(&self, uri: &Uri, text: &str) { if uri.scheme() != "file" { return; } - self.diagnostics_by_uri - .insert(uri.clone(), lint(text).unwrap_or_default()); + let mut handle_guard = self.handle.lock().await; + if let Some(handle) = &*handle_guard { + handle.abort(); + } + + let (handle, registration) = AbortHandle::new_pair(); + *handle_guard = Some(handle); + drop(handle_guard); + + let future = Abortable::new( + async move { + self.diagnostics_by_uri + .insert(uri.clone(), lint(text.into()).await.unwrap_or_default()); + }, + registration, + ); + + if let Err(Aborted) = future.await { + trace!("Killed ChkTeX because it took too long to execute") + } } } pub static LINE_REGEX: Lazy<Regex> = - Lazy::new(|| Regex::new("(\\d+):(\\d+):(\\d+):(\\w+):(\\w)+:(.*)").unwrap()); + Lazy::new(|| Regex::new("(\\d+):(\\d+):(\\d+):(\\w+):(\\w+):(.*)").unwrap()); -fn lint(text: &str) -> Option<Vec<Diagnostic>> { - let mut process = Command::new("chktex") +async fn lint(text: String) -> io::Result<Vec<Diagnostic>> { + let mut process: tokio::process::Child = Command::new("chktex") .args(&["-I0", "-f%l:%c:%d:%k:%n:%m\n"]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::null()) - .spawn() - .ok()?; + .kill_on_drop(true) + .spawn()?; process .stdin .take() .unwrap() .write_all(text.as_bytes()) - .ok()?; + .await?; let mut stdout = String::new(); process @@ -73,7 +80,7 @@ fn lint(text: &str) -> Option<Vec<Diagnostic>> { .take() .unwrap() .read_to_string(&mut stdout) - .ok()?; + .await?; let mut diagnostics = Vec::new(); for line in stdout.lines() { @@ -83,7 +90,7 @@ fn lint(text: &str) -> Option<Vec<Diagnostic>> { let digit = captures[3].parse::<u64>().unwrap(); let kind = &captures[4]; let code = &captures[5]; - let message = captures[6].to_owned(); + let message = captures[6].into(); let range = Range::new_simple(line, character, line, character + digit); let severity = match kind { "Message" => DiagnosticSeverity::Information, @@ -93,13 +100,14 @@ fn lint(text: &str) -> Option<Vec<Diagnostic>> { diagnostics.push(Diagnostic { source: Some("chktex".into()), - code: Some(NumberOrString::String(code.to_owned())), + code: Some(NumberOrString::String(code.into())), message, severity: Some(severity), range, related_information: None, + tags: None, }) } } - Some(diagnostics) + Ok(diagnostics) } |