summaryrefslogtreecommitdiff
path: root/support/texlab/src/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/server.rs')
-rw-r--r--support/texlab/src/server.rs114
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)?;
}