diff options
Diffstat (limited to 'support/texlab/src/server.rs')
-rw-r--r-- | support/texlab/src/server.rs | 114 |
1 files changed, 82 insertions, 32 deletions
diff --git a/support/texlab/src/server.rs b/support/texlab/src/server.rs index 5a78d5e2e2..6806e5f8e5 100644 --- a/support/texlab/src/server.rs +++ b/support/texlab/src/server.rs @@ -1,18 +1,17 @@ use std::{ path::PathBuf, sync::{Arc, Mutex}, - thread, }; use anyhow::Result; use cancellation::{CancellationToken, CancellationTokenSource}; use crossbeam_channel::Sender; -use log::{info, warn}; +use log::{error, info, warn}; use lsp_server::{Connection, ErrorCode, Message, RequestId}; use lsp_types::{ notification::{ Cancel, DidChangeConfiguration, DidChangeTextDocument, DidOpenTextDocument, - DidSaveTextDocument, LogMessage, PublishDiagnostics, + DidSaveTextDocument, PublishDiagnostics, }, request::{ DocumentLinkRequest, FoldingRangeRequest, Formatting, GotoDefinition, PrepareRenameRequest, @@ -37,10 +36,10 @@ use crate::{ dispatch::{NotificationDispatcher, RequestDispatcher}, distro::Distribution, features::{ - build_document, find_all_references, find_document_highlights, find_document_links, - find_document_symbols, find_foldings, find_hover, find_workspace_symbols, - format_source_code, goto_definition, prepare_rename_all, rename_all, BuildParams, - BuildResult, FeatureRequest, ForwardSearchResult, + find_all_references, find_document_highlights, find_document_links, find_document_symbols, + find_foldings, find_hover, find_workspace_symbols, format_source_code, goto_definition, + prepare_rename_all, rename_all, BuildEngine, BuildParams, BuildResult, BuildStatus, + FeatureRequest, ForwardSearchResult, }, req_queue::{IncomingData, ReqQueue}, DocumentLanguage, ServerContext, Uri, Workspace, WorkspaceSource, @@ -55,6 +54,7 @@ pub struct Server { chktex_debouncer: DiagnosticsDebouncer, pool: ThreadPool, load_resolver: bool, + build_engine: Arc<BuildEngine>, } impl Server { @@ -83,6 +83,7 @@ impl Server { chktex_debouncer, pool: threadpool::Builder::new().build(), load_resolver, + build_engine: Arc::default(), }) } @@ -257,7 +258,24 @@ impl Server { fn did_change(&self, mut params: DidChangeTextDocumentParams) -> Result<()> { let uri = params.text_document.uri.into(); assert_eq!(params.content_changes.len(), 1); - let text = params.content_changes.pop().unwrap().text; + let old_document = self.workspace.get(&uri); + let old_text = old_document.as_ref().map(|document| document.text.as_str()); + let new_text = params.content_changes.pop().unwrap().text; + + let uri = Arc::new(uri); + + let line = match old_text { + Some(old_text) => old_text + .lines() + .zip(new_text.lines()) + .position(|(a, b)| a != b) + .unwrap_or_default() as u32, + None => 0, + }; + self.build_engine + .positions_by_uri + .insert(Arc::clone(&uri), Position::new(line, 0)); + let language = self .workspace .get(&uri) @@ -266,7 +284,7 @@ impl Server { let document = self .workspace - .open(Arc::new(uri), text, language, WorkspaceSource::Client); + .open(uri, new_text, language, WorkspaceSource::Client); let should_lint = { self.context.options.read().unwrap().chktex.on_edit }; if let Some(document) = self @@ -287,6 +305,36 @@ impl Server { fn did_save(&self, params: DidSaveTextDocumentParams) -> Result<()> { let uri = params.text_document.uri.into(); + + let should_build = { self.context.options.read().unwrap().build.on_save }; + if let Some(request) = + self.workspace + .get(&uri) + .filter(|_| should_build) + .and_then(|document| { + self.feature_request( + Arc::clone(&document.uri), + BuildParams { + text_document: TextDocumentIdentifier::new(uri.clone().into()), + }, + ) + }) + { + let lsp_sender = self.connection.sender.clone(); + let req_queue = Arc::clone(&self.req_queue); + let build_engine = Arc::clone(&self.build_engine); + self.pool.execute(move || { + build_engine + .build(request, CancellationToken::none(), &req_queue, &lsp_sender) + .unwrap_or_else(|why| { + error!("Build failed: {}", why); + BuildResult { + status: BuildStatus::FAILURE, + } + }); + }); + } + let should_lint = { self.context.options.read().unwrap().chktex.on_open_and_save }; if let Some(document) = self.workspace.get(&uri).filter(|_| should_lint) { self.chktex_debouncer @@ -430,6 +478,11 @@ impl Server { .clone() .into(), ); + + self.build_engine + .positions_by_uri + .insert(Arc::clone(&uri), params.text_document_position.position); + self.handle_feature_request(id, params, uri, token, crate::features::complete)?; Ok(()) } @@ -452,7 +505,7 @@ impl Server { .documentation(&item.label) .map(Documentation::MarkupContent); } - #[cfg(feature = "citeproc")] + #[cfg(feature = "citation")] crate::features::CompletionItemData::Citation { uri, key } => { if let Some(document) = workspace.get(&uri) { if let Some(data) = document.data.as_bibtex() { @@ -519,6 +572,11 @@ impl Server { .clone() .into(), ); + self.build_engine.positions_by_uri.insert( + Arc::clone(&uri), + params.text_document_position_params.position, + ); + self.handle_feature_request(id, params, uri, token, find_hover)?; Ok(()) } @@ -635,23 +693,17 @@ impl Server { ) -> Result<()> { let uri = Arc::new(params.text_document.uri.clone().into()); let lsp_sender = self.connection.sender.clone(); - self.handle_feature_request(id, params, uri, token, |request, token| { - let (log_sender, log_receiver) = crossbeam_channel::unbounded(); - - thread::spawn(move || { - for message in &log_receiver { - send_notification::<LogMessage>( - &lsp_sender, - LogMessageParams { - message, - typ: MessageType::Log, - }, - ) - .unwrap(); - } - }); - - build_document(request, token, log_sender) + let req_queue = Arc::clone(&self.req_queue); + let build_engine = Arc::clone(&self.build_engine); + self.handle_feature_request(id, params, uri, token, move |request, token| { + build_engine + .build(request, token, &req_queue, &lsp_sender) + .unwrap_or_else(|why| { + error!("Build failed: {}", why); + BuildResult { + status: BuildStatus::FAILURE, + } + }) })?; Ok(()) } @@ -745,11 +797,9 @@ impl Server { Message::Response(response) => { let mut req_queue = self.req_queue.lock().unwrap(); let data = req_queue.outgoing.complete(response.id); - let result = match response.result { - Some(result) => Ok(result), - None => Err(response - .error - .expect("response without result or error received")), + let result = match response.error { + Some(error) => Err(error), + None => Ok(response.result.unwrap_or_default()), }; data.sender.send(result)?; } |