summaryrefslogtreecommitdiff
path: root/support/texlab/src
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-02-27 03:01:13 +0000
committerNorbert Preining <norbert@preining.info>2022-02-27 03:01:13 +0000
commita911d39178540078c8ff5bc880418478d7433c40 (patch)
treef23b6a0f6bf9f548e7e43cf2405e864eba99b21e /support/texlab/src
parent740a11f29a3551babe3d7edbb57ac3baa2280a3f (diff)
CTAN sync 202202270301
Diffstat (limited to 'support/texlab/src')
-rw-r--r--support/texlab/src/citation.rs4
-rw-r--r--support/texlab/src/config.rs4
-rw-r--r--support/texlab/src/diagnostics/bibtex.rs10
-rw-r--r--support/texlab/src/diagnostics/build_log.rs4
-rw-r--r--support/texlab/src/diagnostics/chktex.rs6
-rw-r--r--support/texlab/src/diagnostics/debouncer.rs4
-rw-r--r--support/texlab/src/diagnostics/latex.rs6
-rw-r--r--support/texlab/src/features/build.rs6
-rw-r--r--support/texlab/src/features/completion.rs5
-rw-r--r--support/texlab/src/features/completion/util.rs2
-rw-r--r--support/texlab/src/features/cursor.rs4
-rw-r--r--support/texlab/src/features/highlight/label.rs12
-rw-r--r--support/texlab/src/features/lsp_kinds.rs100
-rw-r--r--support/texlab/src/server.rs97
-rw-r--r--support/texlab/src/syntax/latex/analysis.rs3
-rw-r--r--support/texlab/src/syntax/latex/analysis/command.rs12
-rw-r--r--support/texlab/src/syntax/latex/analysis/explicit_link.rs8
-rw-r--r--support/texlab/src/syntax/latex/cst.rs2
-rw-r--r--support/texlab/src/syntax/latex/kind.rs1
-rw-r--r--support/texlab/src/syntax/latex/lexer.rs14
-rw-r--r--support/texlab/src/syntax/latex/parser.rs31
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__comment.snap3
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__line_break.snap20
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_optional.snap30
-rw-r--r--support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_line_break.snap21
-rw-r--r--support/texlab/src/workspace/api.rs7
-rw-r--r--support/texlab/src/workspace/children_expand.rs8
-rw-r--r--support/texlab/src/workspace/parent_expand.rs8
-rw-r--r--support/texlab/src/workspace/storage.rs11
-rw-r--r--support/texlab/src/workspace/watch.rs31
30 files changed, 320 insertions, 154 deletions
diff --git a/support/texlab/src/citation.rs b/support/texlab/src/citation.rs
index 96a5a2eccf..5be86561c9 100644
--- a/support/texlab/src/citation.rs
+++ b/support/texlab/src/citation.rs
@@ -97,12 +97,12 @@ fn generate_bibliography(reference: Reference) -> Option<String> {
})
.ok()?;
let cite = Cite::basic(&reference.id);
- let cluster_id = processor.new_cluster("texlab");
+ let cluster_id = processor.cluster_id("texlab");
processor.insert_reference(reference);
processor.insert_cites(cluster_id, &[cite]);
processor
.set_cluster_order(&[ClusterPosition {
- id: cluster_id,
+ id: Some(cluster_id),
note: Some(1),
}])
.unwrap();
diff --git a/support/texlab/src/config.rs b/support/texlab/src/config.rs
index 5690bee091..5e9703ef3a 100644
--- a/support/texlab/src/config.rs
+++ b/support/texlab/src/config.rs
@@ -17,9 +17,7 @@ pub fn register_config_capability(
client_capabilities: &Mutex<ClientCapabilities>,
) {
let client_capabilities = client_capabilities.lock().unwrap();
- if !client_capabilities.has_pull_configuration_support()
- && client_capabilities.has_push_configuration_support()
- {
+ if client_capabilities.has_push_configuration_support() {
drop(client_capabilities);
let reg = Registration {
id: "pull-config".to_string(),
diff --git a/support/texlab/src/diagnostics/bibtex.rs b/support/texlab/src/diagnostics/bibtex.rs
index d90bde0c8d..8c93c6f925 100644
--- a/support/texlab/src/diagnostics/bibtex.rs
+++ b/support/texlab/src/diagnostics/bibtex.rs
@@ -41,7 +41,7 @@ fn analyze_entry(
range: document
.line_index
.line_col_lsp_range(entry.ty()?.text_range()),
- severity: Some(DiagnosticSeverity::Error),
+ severity: Some(DiagnosticSeverity::ERROR),
code: Some(NumberOrString::Number(4)),
code_description: None,
source: Some("texlab".to_string()),
@@ -61,7 +61,7 @@ fn analyze_entry(
range: document
.line_index
.line_col_lsp_range(entry.left_delimiter()?.text_range()),
- severity: Some(DiagnosticSeverity::Error),
+ severity: Some(DiagnosticSeverity::ERROR),
code: Some(NumberOrString::Number(5)),
code_description: None,
source: Some("texlab".to_string()),
@@ -81,7 +81,7 @@ fn analyze_entry(
range: document
.line_index
.line_col_lsp_range(entry.right_delimiter()?.text_range()),
- severity: Some(DiagnosticSeverity::Error),
+ severity: Some(DiagnosticSeverity::ERROR),
code: Some(NumberOrString::Number(6)),
code_description: None,
source: Some("texlab".to_string()),
@@ -110,7 +110,7 @@ fn analyze_field(
range: document
.line_index
.line_col_lsp_range(TextRange::empty(field.name()?.text_range().end())),
- severity: Some(DiagnosticSeverity::Error),
+ severity: Some(DiagnosticSeverity::ERROR),
code: Some(NumberOrString::Number(7)),
code_description: None,
source: Some("texlab".to_string()),
@@ -130,7 +130,7 @@ fn analyze_field(
range: document.line_index.line_col_lsp_range(TextRange::empty(
field.equality_sign()?.text_range().end(),
)),
- severity: Some(DiagnosticSeverity::Error),
+ severity: Some(DiagnosticSeverity::ERROR),
code: Some(NumberOrString::Number(8)),
code_description: None,
source: Some("texlab".to_string()),
diff --git a/support/texlab/src/diagnostics/build_log.rs b/support/texlab/src/diagnostics/build_log.rs
index ede3a873a8..01579cbd0b 100644
--- a/support/texlab/src/diagnostics/build_log.rs
+++ b/support/texlab/src/diagnostics/build_log.rs
@@ -32,8 +32,8 @@ pub fn analyze_build_log_static(
for error in &parse.errors {
let pos = Position::new(error.line.unwrap_or(0), 0);
let severity = match error.level {
- BuildErrorLevel::Error => DiagnosticSeverity::Error,
- BuildErrorLevel::Warning => DiagnosticSeverity::Warning,
+ BuildErrorLevel::Error => DiagnosticSeverity::ERROR,
+ BuildErrorLevel::Warning => DiagnosticSeverity::WARNING,
};
let range = Range::new(pos, pos);
let diagnostic = Diagnostic {
diff --git a/support/texlab/src/diagnostics/chktex.rs b/support/texlab/src/diagnostics/chktex.rs
index 897887c473..1786644d97 100644
--- a/support/texlab/src/diagnostics/chktex.rs
+++ b/support/texlab/src/diagnostics/chktex.rs
@@ -83,9 +83,9 @@ fn lint(text: &str, current_dir: &Path) -> io::Result<Vec<Diagnostic>> {
let message = captures[6].into();
let range = Range::new_simple(line, character, line, character + digit);
let severity = match kind {
- "Message" => DiagnosticSeverity::Information,
- "Warning" => DiagnosticSeverity::Warning,
- _ => DiagnosticSeverity::Error,
+ "Message" => DiagnosticSeverity::INFORMATION,
+ "Warning" => DiagnosticSeverity::WARNING,
+ _ => DiagnosticSeverity::ERROR,
};
diagnostics.push(Diagnostic {
diff --git a/support/texlab/src/diagnostics/debouncer.rs b/support/texlab/src/diagnostics/debouncer.rs
index 46bea80176..8c1cb63253 100644
--- a/support/texlab/src/diagnostics/debouncer.rs
+++ b/support/texlab/src/diagnostics/debouncer.rs
@@ -4,8 +4,8 @@ use std::{
time::{Duration, Instant},
};
-use chashmap::CHashMap;
use crossbeam_channel::Sender;
+use dashmap::DashMap;
use crate::{Document, ServerContext, Uri, Workspace};
@@ -31,7 +31,7 @@ impl DiagnosticsDebouncer {
let handle = thread::spawn(move || {
let pool = threadpool::Builder::new().build();
- let last_task_time_by_uri: Arc<CHashMap<Arc<Uri>, Instant>> = Arc::default();
+ let last_task_time_by_uri: Arc<DashMap<Arc<Uri>, Instant>> = Arc::default();
while let Ok(DiagnosticsMessage::Analyze {
workspace,
document,
diff --git a/support/texlab/src/diagnostics/latex.rs b/support/texlab/src/diagnostics/latex.rs
index 012e9b399f..72048da93d 100644
--- a/support/texlab/src/diagnostics/latex.rs
+++ b/support/texlab/src/diagnostics/latex.rs
@@ -30,7 +30,7 @@ pub fn analyze_latex_static(
Arc::clone(&document.uri),
Diagnostic {
range: document.line_index.line_col_lsp_range(node.text_range()),
- severity: Some(DiagnosticSeverity::Error),
+ severity: Some(DiagnosticSeverity::ERROR),
code: Some(NumberOrString::Number(1)),
code_description: None,
source: Some("texlab".to_string()),
@@ -63,7 +63,7 @@ fn analyze_environment(
Arc::clone(&document.uri),
Diagnostic {
range: document.line_index.line_col_lsp_range(name1.small_range()),
- severity: Some(DiagnosticSeverity::Error),
+ severity: Some(DiagnosticSeverity::ERROR),
code: Some(NumberOrString::Number(3)),
code_description: None,
source: Some("texlab".to_string()),
@@ -115,7 +115,7 @@ fn analyze_curly_group(
range: document
.line_index
.line_col_lsp_range(TextRange::empty(node.text_range().end())),
- severity: Some(DiagnosticSeverity::Error),
+ severity: Some(DiagnosticSeverity::ERROR),
code: Some(NumberOrString::Number(2)),
code_description: None,
source: Some("texlab".to_string()),
diff --git a/support/texlab/src/features/build.rs b/support/texlab/src/features/build.rs
index 6953698a29..5505b9fb70 100644
--- a/support/texlab/src/features/build.rs
+++ b/support/texlab/src/features/build.rs
@@ -8,8 +8,8 @@ use std::{
use anyhow::Result;
use cancellation::CancellationToken;
-use chashmap::CHashMap;
use crossbeam_channel::Sender;
+use dashmap::DashMap;
use encoding_rs_io::DecodeReaderBytesBuilder;
use lsp_types::{
notification::{LogMessage, Progress},
@@ -101,7 +101,7 @@ impl<'a> Drop for ProgressReporter<'a> {
#[derive(Default)]
pub struct BuildEngine {
lock: Mutex<()>,
- pub positions_by_uri: CHashMap<Arc<Uri>, Position>,
+ pub positions_by_uri: DashMap<Arc<Uri>, Position>,
}
impl BuildEngine {
@@ -233,7 +233,7 @@ fn capture_output(
&lsp_sender,
LogMessageParams {
message,
- typ: lsp_types::MessageType::Log,
+ typ: lsp_types::MessageType::LOG,
},
)
.unwrap();
diff --git a/support/texlab/src/features/completion.rs b/support/texlab/src/features/completion.rs
index cb6a66f3cd..2a3f4ea9af 100644
--- a/support/texlab/src/features/completion.rs
+++ b/support/texlab/src/features/completion.rs
@@ -326,14 +326,15 @@ fn convert_internal_items(
.and_then(|cap| cap.snippet_support)
== Some(true)
{
+ let text_edit = TextEdit::new(range, "begin{$1}\n\t$0\n\\end{$1}".into());
CompletionItem {
kind: Some(adjust_kind(
&context.request,
Structure::Snippet.completion_kind(),
)),
data: Some(serde_json::to_value(CompletionItemData::CommandSnippet).unwrap()),
- insert_text: Some("begin{$1}\n\t$0\n\\end{$1}".into()),
- insert_text_format: Some(InsertTextFormat::Snippet),
+ text_edit: Some(CompletionTextEdit::Edit(text_edit)),
+ insert_text_format: Some(InsertTextFormat::SNIPPET),
..CompletionItem::new_simple("begin".into(), component_detail(&[]))
}
} else {
diff --git a/support/texlab/src/features/completion/util.rs b/support/texlab/src/features/completion/util.rs
index 296d6d25d9..5c4d83e4e9 100644
--- a/support/texlab/src/features/completion/util.rs
+++ b/support/texlab/src/features/completion/util.rs
@@ -62,5 +62,5 @@ pub fn adjust_kind(
return kind;
}
}
- CompletionItemKind::Text
+ CompletionItemKind::TEXT
}
diff --git a/support/texlab/src/features/cursor.rs b/support/texlab/src/features/cursor.rs
index d8db0f2aa8..d1de067091 100644
--- a/support/texlab/src/features/cursor.rs
+++ b/support/texlab/src/features/cursor.rs
@@ -46,7 +46,9 @@ impl Cursor {
return Some(Self::Latex(left));
}
- if right.kind() == latex::WHITESPACE && right.parent().kind() == latex::KEY {
+ if matches!(right.kind(), latex::WHITESPACE | latex::LINE_BREAK)
+ && right.parent().kind() == latex::KEY
+ {
return Some(Self::Latex(right));
}
diff --git a/support/texlab/src/features/highlight/label.rs b/support/texlab/src/features/highlight/label.rs
index 9694993033..9394378c09 100644
--- a/support/texlab/src/features/highlight/label.rs
+++ b/support/texlab/src/features/highlight/label.rs
@@ -31,7 +31,7 @@ pub fn find_label_highlights(
highlights.push(DocumentHighlight {
range,
- kind: Some(DocumentHighlightKind::Write),
+ kind: Some(DocumentHighlightKind::WRITE),
});
} else if let Some(label) = latex::LabelReference::cast(node) {
for label_name in label
@@ -46,7 +46,7 @@ pub fn find_label_highlights(
highlights.push(DocumentHighlight {
range,
- kind: Some(DocumentHighlightKind::Read),
+ kind: Some(DocumentHighlightKind::READ),
});
}
} else if let Some(label) = latex::LabelReferenceRange::cast(node) {
@@ -61,7 +61,7 @@ pub fn find_label_highlights(
highlights.push(DocumentHighlight {
range,
- kind: Some(DocumentHighlightKind::Read),
+ kind: Some(DocumentHighlightKind::READ),
});
}
@@ -76,7 +76,7 @@ pub fn find_label_highlights(
highlights.push(DocumentHighlight {
range,
- kind: Some(DocumentHighlightKind::Read),
+ kind: Some(DocumentHighlightKind::READ),
});
}
}
@@ -141,11 +141,11 @@ mod tests {
let expected_highlights = vec![
DocumentHighlight {
range: Range::new_simple(0, 7, 0, 10),
- kind: Some(DocumentHighlightKind::Write),
+ kind: Some(DocumentHighlightKind::WRITE),
},
DocumentHighlight {
range: Range::new_simple(1, 5, 1, 8),
- kind: Some(DocumentHighlightKind::Read),
+ kind: Some(DocumentHighlightKind::READ),
},
];
diff --git a/support/texlab/src/features/lsp_kinds.rs b/support/texlab/src/features/lsp_kinds.rs
index fbfc50cace..82706b5aee 100644
--- a/support/texlab/src/features/lsp_kinds.rs
+++ b/support/texlab/src/features/lsp_kinds.rs
@@ -30,64 +30,64 @@ pub enum Structure {
impl Structure {
pub fn completion_kind(self) -> CompletionItemKind {
match self {
- Self::Command => CompletionItemKind::Function,
- Self::Snippet => CompletionItemKind::Snippet,
- Self::Environment => CompletionItemKind::Enum,
- Self::Section => CompletionItemKind::Module,
- Self::Float => CompletionItemKind::Method,
- Self::Theorem => CompletionItemKind::Variable,
- Self::Equation => CompletionItemKind::Constant,
- Self::Item => CompletionItemKind::EnumMember,
- Self::Label => CompletionItemKind::Constructor,
- Self::Folder => CompletionItemKind::Folder,
- Self::File => CompletionItemKind::File,
- Self::PgfLibrary => CompletionItemKind::Property,
- Self::TikzLibrary => CompletionItemKind::Property,
- Self::Color => CompletionItemKind::Color,
- Self::ColorModel => CompletionItemKind::Color,
- Self::Package => CompletionItemKind::Class,
- Self::Class => CompletionItemKind::Class,
- Self::Entry(BibtexEntryTypeCategory::Misc) => CompletionItemKind::Interface,
- Self::Entry(BibtexEntryTypeCategory::String) => CompletionItemKind::Text,
- Self::Entry(BibtexEntryTypeCategory::Article) => CompletionItemKind::Event,
- Self::Entry(BibtexEntryTypeCategory::Book) => CompletionItemKind::Struct,
- Self::Entry(BibtexEntryTypeCategory::Collection) => CompletionItemKind::TypeParameter,
- Self::Entry(BibtexEntryTypeCategory::Part) => CompletionItemKind::Operator,
- Self::Entry(BibtexEntryTypeCategory::Thesis) => CompletionItemKind::Unit,
- Self::Field => CompletionItemKind::Field,
- Self::Argument => CompletionItemKind::Value,
- Self::GlossaryEntry => CompletionItemKind::Keyword,
+ Self::Command => CompletionItemKind::FUNCTION,
+ Self::Snippet => CompletionItemKind::SNIPPET,
+ Self::Environment => CompletionItemKind::ENUM,
+ Self::Section => CompletionItemKind::MODULE,
+ Self::Float => CompletionItemKind::METHOD,
+ Self::Theorem => CompletionItemKind::VARIABLE,
+ Self::Equation => CompletionItemKind::CONSTANT,
+ Self::Item => CompletionItemKind::ENUM_MEMBER,
+ Self::Label => CompletionItemKind::CONSTRUCTOR,
+ Self::Folder => CompletionItemKind::FOLDER,
+ Self::File => CompletionItemKind::FILE,
+ Self::PgfLibrary => CompletionItemKind::PROPERTY,
+ Self::TikzLibrary => CompletionItemKind::PROPERTY,
+ Self::Color => CompletionItemKind::COLOR,
+ Self::ColorModel => CompletionItemKind::COLOR,
+ Self::Package => CompletionItemKind::CLASS,
+ Self::Class => CompletionItemKind::CLASS,
+ Self::Entry(BibtexEntryTypeCategory::Misc) => CompletionItemKind::INTERFACE,
+ Self::Entry(BibtexEntryTypeCategory::String) => CompletionItemKind::TEXT,
+ Self::Entry(BibtexEntryTypeCategory::Article) => CompletionItemKind::EVENT,
+ Self::Entry(BibtexEntryTypeCategory::Book) => CompletionItemKind::STRUCT,
+ Self::Entry(BibtexEntryTypeCategory::Collection) => CompletionItemKind::TYPE_PARAMETER,
+ Self::Entry(BibtexEntryTypeCategory::Part) => CompletionItemKind::OPERATOR,
+ Self::Entry(BibtexEntryTypeCategory::Thesis) => CompletionItemKind::UNIT,
+ Self::Field => CompletionItemKind::FIELD,
+ Self::Argument => CompletionItemKind::VALUE,
+ Self::GlossaryEntry => CompletionItemKind::KEYWORD,
}
}
pub fn symbol_kind(self) -> SymbolKind {
match self {
- Self::Command => SymbolKind::Function,
+ Self::Command => SymbolKind::FUNCTION,
Self::Snippet => unimplemented!(),
- Self::Environment => SymbolKind::Enum,
- Self::Section => SymbolKind::Module,
- Self::Float => SymbolKind::Method,
- Self::Theorem => SymbolKind::Variable,
- Self::Equation => SymbolKind::Constant,
- Self::Item => SymbolKind::EnumMember,
- Self::Label => SymbolKind::Constructor,
- Self::Folder => SymbolKind::Namespace,
- Self::File => SymbolKind::File,
- Self::PgfLibrary => SymbolKind::Property,
- Self::TikzLibrary => SymbolKind::Property,
+ Self::Environment => SymbolKind::ENUM,
+ Self::Section => SymbolKind::MODULE,
+ Self::Float => SymbolKind::METHOD,
+ Self::Theorem => SymbolKind::VARIABLE,
+ Self::Equation => SymbolKind::CONSTANT,
+ Self::Item => SymbolKind::ENUM_MEMBER,
+ Self::Label => SymbolKind::CONSTRUCTOR,
+ Self::Folder => SymbolKind::NAMESPACE,
+ Self::File => SymbolKind::FILE,
+ Self::PgfLibrary => SymbolKind::PROPERTY,
+ Self::TikzLibrary => SymbolKind::PROPERTY,
Self::Color => unimplemented!(),
Self::ColorModel => unimplemented!(),
- Self::Package => SymbolKind::Class,
- Self::Class => SymbolKind::Class,
- Self::Entry(BibtexEntryTypeCategory::Misc) => SymbolKind::Interface,
- Self::Entry(BibtexEntryTypeCategory::String) => SymbolKind::String,
- Self::Entry(BibtexEntryTypeCategory::Article) => SymbolKind::Event,
- Self::Entry(BibtexEntryTypeCategory::Book) => SymbolKind::Struct,
- Self::Entry(BibtexEntryTypeCategory::Collection) => SymbolKind::TypeParameter,
- Self::Entry(BibtexEntryTypeCategory::Part) => SymbolKind::Operator,
- Self::Entry(BibtexEntryTypeCategory::Thesis) => SymbolKind::Object,
- Self::Field => SymbolKind::Field,
- Self::Argument => SymbolKind::Number,
+ Self::Package => SymbolKind::CLASS,
+ Self::Class => SymbolKind::CLASS,
+ Self::Entry(BibtexEntryTypeCategory::Misc) => SymbolKind::INTERFACE,
+ Self::Entry(BibtexEntryTypeCategory::String) => SymbolKind::STRING,
+ Self::Entry(BibtexEntryTypeCategory::Article) => SymbolKind::EVENT,
+ Self::Entry(BibtexEntryTypeCategory::Book) => SymbolKind::STRUCT,
+ Self::Entry(BibtexEntryTypeCategory::Collection) => SymbolKind::TYPE_PARAMETER,
+ Self::Entry(BibtexEntryTypeCategory::Part) => SymbolKind::OPERATOR,
+ Self::Entry(BibtexEntryTypeCategory::Thesis) => SymbolKind::OBJECT,
+ Self::Field => SymbolKind::FIELD,
+ Self::Argument => SymbolKind::NUMBER,
Self::GlossaryEntry => unimplemented!(),
}
}
diff --git a/support/texlab/src/server.rs b/support/texlab/src/server.rs
index 000118a9a2..2521faba09 100644
--- a/support/texlab/src/server.rs
+++ b/support/texlab/src/server.rs
@@ -20,6 +20,7 @@ use lsp_types::{
*,
};
use notification::DidCloseTextDocument;
+use notify::RecursiveMode;
use request::{
Completion, DocumentHighlightRequest, DocumentSymbolRequest, HoverRequest,
ResolveCompletionItem, WorkspaceSymbol,
@@ -39,10 +40,11 @@ use crate::{
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,
+ FeatureRequest, ForwardSearchResult, ForwardSearchStatus,
},
- req_queue::{IncomingData, ReqQueue},
- Document, DocumentLanguage, LineIndexExt, ServerContext, Uri, Workspace, WorkspaceSource,
+ req_queue::{self, IncomingData, ReqQueue},
+ ClientCapabilitiesExt, Document, DocumentLanguage, LineIndexExt, ServerContext, Uri, Workspace,
+ WorkspaceSource,
};
pub struct Server {
@@ -92,7 +94,7 @@ impl Server {
text_document_sync: Some(TextDocumentSyncCapability::Options(
TextDocumentSyncOptions {
open_close: Some(true),
- change: Some(TextDocumentSyncKind::Incremental),
+ change: Some(TextDocumentSyncKind::INCREMENTAL),
will_save: None,
will_save_wait_until: None,
save: Some(TextDocumentSyncSaveOptions::SaveOptions(SaveOptions {
@@ -179,22 +181,9 @@ impl Server {
let workspace = Arc::clone(&self.workspace);
self.pool.execute(move || {
register_config_capability(&req_queue, &sender, &context.client_capabilities);
- pull_config(
- &req_queue,
- &sender,
- &context.options,
- &context.client_capabilities.lock().unwrap(),
- );
-
- for document in workspace.documents() {
- workspace.open(
- Arc::clone(&document.uri),
- document.text.clone(),
- document.language(),
- WorkspaceSource::Client,
- );
- }
+ pull_and_reparse_all(req_queue, sender, context, workspace);
});
+
Ok(())
}
@@ -235,7 +224,27 @@ impl Server {
}
fn did_change_configuration(&self, params: DidChangeConfigurationParams) -> Result<()> {
- push_config(&self.context.options, params.settings);
+ let client_capabilities = { self.context.client_capabilities.lock().unwrap().clone() };
+ if client_capabilities.has_pull_configuration_support() {
+ let req_queue = Arc::clone(&self.req_queue);
+ let sender = self.connection.sender.clone();
+ let context = Arc::clone(&self.context);
+ let workspace = Arc::clone(&self.workspace);
+ self.pool.execute(move || {
+ pull_and_reparse_all(req_queue, sender, context, workspace);
+ });
+ } else {
+ push_config(&self.context.options, params.settings);
+ if let Some(path) = { self.context.options.read().unwrap().aux_directory.clone() } {
+ let _ = self.workspace.watch(path, RecursiveMode::NonRecursive);
+ }
+
+ let workspace = Arc::clone(&self.workspace);
+ self.pool.execute(move || {
+ reparse_all(workspace.as_ref());
+ });
+ }
+
Ok(())
}
@@ -394,14 +403,6 @@ impl Server {
}
fn feature_request<P>(&self, uri: Arc<Uri>, params: P) -> Option<FeatureRequest<P>> {
- let req_queue = Arc::clone(&self.req_queue);
- let sender = self.connection.sender.clone();
- let cx = Arc::clone(&self.context);
- self.pool.execute(move || {
- let client_capabilities = &cx.client_capabilities.lock().unwrap().clone();
- pull_config(&req_queue, &sender, &cx.options, &client_capabilities);
- });
-
Some(FeatureRequest {
context: Arc::clone(&self.context),
params,
@@ -751,13 +752,13 @@ impl Server {
token: &Arc<CancellationToken>,
) -> Result<()> {
let uri = Arc::new(params.text_document.uri.clone().into());
- self.handle_feature_request(
- id,
- params,
- uri,
- token,
- crate::features::execute_forward_search,
- )?;
+ self.handle_feature_request(id, params, uri, token, |req, token| {
+ crate::features::execute_forward_search(req, token).unwrap_or_else(|| {
+ ForwardSearchResult {
+ status: ForwardSearchStatus::ERROR,
+ }
+ })
+ })?;
Ok(())
}
@@ -854,6 +855,32 @@ impl Server {
}
}
+fn pull_and_reparse_all(
+ req_queue: Arc<Mutex<lsp_server::ReqQueue<IncomingData, req_queue::OutgoingData>>>,
+ sender: Sender<Message>,
+ context: Arc<ServerContext>,
+ workspace: Arc<dyn Workspace>,
+) {
+ let client_capabilities = { context.client_capabilities.lock().unwrap().clone() };
+ pull_config(&req_queue, &sender, &context.options, &client_capabilities);
+ if let Some(path) = { context.options.read().unwrap().aux_directory.clone() } {
+ let _ = workspace.watch(path, RecursiveMode::NonRecursive);
+ }
+
+ reparse_all(workspace.as_ref());
+}
+
+fn reparse_all(workspace: &dyn Workspace) {
+ for document in workspace.documents() {
+ workspace.open(
+ Arc::clone(&document.uri),
+ document.text.clone(),
+ document.language(),
+ WorkspaceSource::Client,
+ );
+ }
+}
+
fn create_static_debouncer(
manager: Arc<Mutex<DiagnosticsManager>>,
conn: &Connection,
diff --git a/support/texlab/src/syntax/latex/analysis.rs b/support/texlab/src/syntax/latex/analysis.rs
index 063d8e95f3..2849ade1be 100644
--- a/support/texlab/src/syntax/latex/analysis.rs
+++ b/support/texlab/src/syntax/latex/analysis.rs
@@ -12,7 +12,7 @@ use crate::syntax::latex;
pub use self::types::*;
use self::{
- command::analyze_command,
+ command::{analyze_command, analyze_command_definition},
environment::analyze_begin,
explicit_link::{analyze_import, analyze_include},
implicit_link::analyze_implicit_links,
@@ -25,6 +25,7 @@ pub fn analyze(context: &mut LatexAnalyzerContext, root: &latex::SyntaxNode) {
analyze_implicit_links(context);
for node in root.descendants() {
analyze_command(context, node)
+ .or_else(|| analyze_command_definition(context, node))
.or_else(|| analyze_begin(context, node))
.or_else(|| analyze_include(context, node))
.or_else(|| analyze_import(context, node))
diff --git a/support/texlab/src/syntax/latex/analysis/command.rs b/support/texlab/src/syntax/latex/analysis/command.rs
index 9dea4d84ee..b8b3f0ef9a 100644
--- a/support/texlab/src/syntax/latex/analysis/command.rs
+++ b/support/texlab/src/syntax/latex/analysis/command.rs
@@ -10,3 +10,15 @@ pub fn analyze_command(context: &mut LatexAnalyzerContext, node: &latex::SyntaxN
.insert(command.name()?.text().into());
Some(())
}
+
+pub fn analyze_command_definition(
+ context: &mut LatexAnalyzerContext,
+ node: &latex::SyntaxNode,
+) -> Option<()> {
+ let definition = latex::CommandDefinition::cast(node)?;
+ context
+ .extras
+ .command_names
+ .insert(definition.name()?.command()?.text().into());
+ Some(())
+}
diff --git a/support/texlab/src/syntax/latex/analysis/explicit_link.rs b/support/texlab/src/syntax/latex/analysis/explicit_link.rs
index f177354ac7..48f8d6b5ee 100644
--- a/support/texlab/src/syntax/latex/analysis/explicit_link.rs
+++ b/support/texlab/src/syntax/latex/analysis/explicit_link.rs
@@ -50,10 +50,10 @@ pub fn analyze_import(context: &mut LatexAnalyzerContext, node: &latex::SyntaxNo
let import = latex::Import::cast(node)?;
let mut targets = Vec::new();
- let directory = context
- .base_uri
- .join(&import.directory()?.key()?.to_string())
- .ok()?;
+ let directory = match import.directory().and_then(|dir| dir.key()) {
+ Some(dir) => Arc::new(context.base_uri.join(&dir.to_string()).ok()?.into()),
+ None => Arc::clone(&context.base_uri),
+ };
let file = import.file()?.key()?;
let stem = file.to_string();
diff --git a/support/texlab/src/syntax/latex/cst.rs b/support/texlab/src/syntax/latex/cst.rs
index a800236ebf..80c3375304 100644
--- a/support/texlab/src/syntax/latex/cst.rs
+++ b/support/texlab/src/syntax/latex/cst.rs
@@ -33,7 +33,7 @@ macro_rules! cst_node {
let start = full_range.start();
let mut token = self.syntax().last_token();
while let Some(current) = token {
- if !matches!(current.kind(), WHITESPACE | COMMENT) {
+ if !matches!(current.kind(), LINE_BREAK | WHITESPACE | COMMENT) {
return TextRange::new(start, current.text_range().end());
}
token = current.prev_token();
diff --git a/support/texlab/src/syntax/latex/kind.rs b/support/texlab/src/syntax/latex/kind.rs
index 90b68145a7..410cd4fef7 100644
--- a/support/texlab/src/syntax/latex/kind.rs
+++ b/support/texlab/src/syntax/latex/kind.rs
@@ -5,6 +5,7 @@ pub enum SyntaxKind {
ERROR = 0,
MISSING,
+ LINE_BREAK,
WHITESPACE,
COMMENT,
L_CURLY,
diff --git a/support/texlab/src/syntax/latex/lexer.rs b/support/texlab/src/syntax/latex/lexer.rs
index f697403577..4ea11bf377 100644
--- a/support/texlab/src/syntax/latex/lexer.rs
+++ b/support/texlab/src/syntax/latex/lexer.rs
@@ -6,8 +6,11 @@ use super::kind::SyntaxKind;
#[allow(non_camel_case_types)]
#[repr(u16)]
enum Token {
- #[regex(r"\s+")]
- WHITESPACE = 2,
+ #[regex(r"[\r\n]+", priority = 2)]
+ LINE_BREAK = 2,
+
+ #[regex(r"\s+", priority = 1)]
+ WHITESPACE,
#[regex(r"%[^\r\n]*")]
COMMENT,
@@ -166,7 +169,7 @@ enum Token {
#[regex(r"\\usepgflibrary|\\usetikzlibrary")]
TIKZ_LIBRARY_IMPORT_NAME,
- #[regex(r"\\newenvironment|\\newenvironment*")]
+ #[regex(r"\\newenvironment|\\newenvironment*|\\renewenvironment|\\renewenvironment*")]
ENVIRONMENT_DEFINITION_NAME,
}
@@ -249,4 +252,9 @@ mod tests {
fn test_invalid_parameter() {
assert_debug_snapshot!(verify(r#"#"#))
}
+
+ #[test]
+ fn test_line_break() {
+ assert_debug_snapshot!(verify("hello\nworld"));
+ }
}
diff --git a/support/texlab/src/syntax/latex/parser.rs b/support/texlab/src/syntax/latex/parser.rs
index a7fe3342f8..fcca6771a2 100644
--- a/support/texlab/src/syntax/latex/parser.rs
+++ b/support/texlab/src/syntax/latex/parser.rs
@@ -74,7 +74,7 @@ impl<'a> Parser<'a> {
fn trivia(&mut self) {
while self
.peek()
- .filter(|&kind| matches!(kind, WHITESPACE | COMMENT))
+ .filter(|&kind| matches!(kind, LINE_BREAK | WHITESPACE | COMMENT))
.is_some()
{
self.eat();
@@ -96,7 +96,7 @@ impl<'a> Parser<'a> {
fn content(&mut self, context: ParserContext) {
match self.peek().unwrap() {
- WHITESPACE | COMMENT => self.eat(),
+ LINE_BREAK | WHITESPACE | COMMENT => self.eat(),
L_CURLY if context.allow_environment => self.curly_group(),
L_CURLY => self.curly_group_without_environments(),
L_BRACK | L_PAREN => self.mixed_group(),
@@ -162,7 +162,7 @@ impl<'a> Parser<'a> {
while self
.peek()
.filter(|&kind| {
- matches!(kind, WHITESPACE | COMMENT | WORD | COMMA)
+ matches!(kind, LINE_BREAK | WHITESPACE | COMMENT | WORD | COMMA)
&& (context.allow_comma || kind != COMMA)
})
.is_some()
@@ -211,6 +211,9 @@ impl<'a> Parser<'a> {
Some(WORD) => {
self.key();
}
+ Some(kind) if kind.is_command_name() => {
+ self.content(ParserContext::default());
+ }
Some(_) | None => {
self.builder.token(MISSING.into(), "");
}
@@ -225,7 +228,7 @@ impl<'a> Parser<'a> {
while self
.peek()
- .filter(|&kind| matches!(kind, WHITESPACE | COMMENT | WORD | COMMA))
+ .filter(|&kind| matches!(kind, LINE_BREAK | WHITESPACE | COMMENT | WORD | COMMA))
.is_some()
{
if self.peek() == Some(WORD) {
@@ -340,6 +343,8 @@ impl<'a> Parser<'a> {
{
self.eat();
}
+
+ self.trivia();
self.builder.finish_node();
}
@@ -381,7 +386,7 @@ impl<'a> Parser<'a> {
self.builder.start_node(KEY_VALUE_BODY.into());
while let Some(kind) = self.peek() {
match kind {
- WHITESPACE | COMMENT => self.eat(),
+ LINE_BREAK | WHITESPACE | COMMENT => self.eat(),
WORD => {
self.key_value_pair();
if self.peek() == Some(COMMA) {
@@ -433,7 +438,7 @@ impl<'a> Parser<'a> {
self.eat();
while let Some(kind) = self.peek() {
match kind {
- WHITESPACE | COMMENT => self.eat(),
+ LINE_BREAK | WHITESPACE | COMMENT => self.eat(),
L_CURLY => self.curly_group(),
L_BRACK | L_PAREN => self.mixed_group(),
_ => break,
@@ -932,6 +937,10 @@ impl<'a> Parser<'a> {
if self.lexer.peek() == Some(L_BRACK) {
self.brack_group_word();
+
+ if self.lexer.peek() == Some(L_BRACK) {
+ self.brack_group();
+ }
}
if self.lexer.peek() == Some(L_CURLY) {
@@ -1566,6 +1575,11 @@ mod tests {
}
#[test]
+ fn test_command_definition_optional() {
+ assert_debug_snapshot!(setup(r#"\newcommand{\foo}[1][def]{#1}"#));
+ }
+
+ #[test]
fn test_command_definition_no_argc() {
assert_debug_snapshot!(setup(r#"\newcommand{\foo}{foo}"#));
}
@@ -1708,4 +1722,9 @@ mod tests {
r#"\DeclareAcronym{eg}{short = e.g,long = for example,tag = abbrev}"#
));
}
+
+ #[test]
+ fn test_label_definition_line_break() {
+ assert_debug_snapshot!(setup("\\label{hello\nworld}"));
+ }
}
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__comment.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__comment.snap
index 2186c957c5..19db458200 100644
--- a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__comment.snap
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__comment.snap
@@ -1,5 +1,6 @@
---
source: src/syntax/latex/lexer.rs
+assertion_line: 248
expression: "verify(\"hello %world\\r\\ntest %test\")"
---
@@ -17,7 +18,7 @@ expression: "verify(\"hello %world\\r\\ntest %test\")"
"%world",
),
(
- WHITESPACE,
+ LINE_BREAK,
"\r\n",
),
(
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__line_break.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__line_break.snap
new file mode 100644
index 0000000000..a8a392370e
--- /dev/null
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__lexer__tests__line_break.snap
@@ -0,0 +1,20 @@
+---
+source: src/syntax/latex/lexer.rs
+assertion_line: 258
+expression: "verify(\"hello\\nworld\")"
+
+---
+[
+ (
+ WORD,
+ "hello",
+ ),
+ (
+ LINE_BREAK,
+ "\n",
+ ),
+ (
+ WORD,
+ "world",
+ ),
+]
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_optional.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_optional.snap
new file mode 100644
index 0000000000..66c263e49a
--- /dev/null
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__command_definition_optional.snap
@@ -0,0 +1,30 @@
+---
+source: src/syntax/latex/parser.rs
+assertion_line: 1579
+expression: "setup(r#\"\\newcommand{\\foo}[1][def]{#1}\"#)"
+
+---
+ROOT@0..29
+ PREAMBLE@0..29
+ COMMAND_DEFINITION@0..29
+ COMMAND_DEFINITION_NAME@0..11 "\\newcommand"
+ CURLY_GROUP_COMMAND@11..17
+ L_CURLY@11..12 "{"
+ GENERIC_COMMAND_NAME@12..16 "\\foo"
+ R_CURLY@16..17 "}"
+ BRACK_GROUP_WORD@17..20
+ L_BRACK@17..18 "["
+ KEY@18..19
+ WORD@18..19 "1"
+ R_BRACK@19..20 "]"
+ BRACK_GROUP@20..25
+ L_BRACK@20..21 "["
+ TEXT@21..24
+ WORD@21..24 "def"
+ R_BRACK@24..25 "]"
+ CURLY_GROUP@25..29
+ L_CURLY@25..26 "{"
+ TEXT@26..28
+ WORD@26..28 "#1"
+ R_CURLY@28..29 "}"
+
diff --git a/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_line_break.snap b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_line_break.snap
new file mode 100644
index 0000000000..47187fabcd
--- /dev/null
+++ b/support/texlab/src/syntax/latex/snapshots/texlab__syntax__latex__parser__tests__label_definition_line_break.snap
@@ -0,0 +1,21 @@
+---
+source: src/syntax/latex/parser.rs
+assertion_line: 1719
+expression: "setup(\"\\\\label{hello\\nworld}\")"
+
+---
+ROOT@0..19
+ PREAMBLE@0..19
+ LABEL_DEFINITION@0..13
+ LABEL_DEFINITION_NAME@0..6 "\\label"
+ CURLY_GROUP_WORD@6..13
+ L_CURLY@6..7 "{"
+ KEY@7..13
+ WORD@7..12 "hello"
+ LINE_BREAK@12..13 "\n"
+ MISSING@13..13 ""
+ TEXT@13..18
+ WORD@13..18 "world"
+ ERROR@18..19
+ R_CURLY@18..19 "}"
+
diff --git a/support/texlab/src/workspace/api.rs b/support/texlab/src/workspace/api.rs
index 1ccd19d4e4..6a3c3d02c9 100644
--- a/support/texlab/src/workspace/api.rs
+++ b/support/texlab/src/workspace/api.rs
@@ -1,6 +1,7 @@
use std::{fs, path::PathBuf, sync::Arc};
use anyhow::Result;
+use notify::RecursiveMode;
use crate::{DocumentLanguage, Uri};
@@ -37,9 +38,9 @@ pub trait Workspace: Send + Sync {
return Ok(self.get(&uri));
}
- let data = fs::read(&path)?;
- let text = String::from_utf8_lossy(&data).into_owned();
if let Some(language) = DocumentLanguage::by_path(&path) {
+ let data = fs::read(&path)?;
+ let text = String::from_utf8_lossy(&data).into_owned();
Ok(Some(self.open(
uri,
text,
@@ -83,4 +84,6 @@ pub trait Workspace: Send + Sync {
fn is_open(&self, uri: &Uri) -> bool;
fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset>;
+
+ fn watch(&self, path: PathBuf, mode: RecursiveMode) -> Result<()>;
}
diff --git a/support/texlab/src/workspace/children_expand.rs b/support/texlab/src/workspace/children_expand.rs
index 006e7b17e2..8fecf2d503 100644
--- a/support/texlab/src/workspace/children_expand.rs
+++ b/support/texlab/src/workspace/children_expand.rs
@@ -1,5 +1,7 @@
-use std::sync::Arc;
+use std::{path::PathBuf, sync::Arc};
+use anyhow::Result;
+use notify::RecursiveMode;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use crate::{
@@ -89,4 +91,8 @@ impl<W: Workspace> Workspace for ChildrenExpander<W> {
fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset> {
self.workspace.subset(uri)
}
+
+ fn watch(&self, path: PathBuf, mode: RecursiveMode) -> Result<()> {
+ self.workspace.watch(path, mode)
+ }
}
diff --git a/support/texlab/src/workspace/parent_expand.rs b/support/texlab/src/workspace/parent_expand.rs
index 33b0ca3c5e..0eef06ce92 100644
--- a/support/texlab/src/workspace/parent_expand.rs
+++ b/support/texlab/src/workspace/parent_expand.rs
@@ -1,5 +1,7 @@
-use std::{fs, sync::Arc};
+use std::{fs, path::PathBuf, sync::Arc};
+use anyhow::Result;
+use notify::RecursiveMode;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use rustc_hash::FxHashSet;
@@ -96,6 +98,10 @@ where
fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset> {
self.workspace.subset(uri)
}
+
+ fn watch(&self, path: PathBuf, mode: RecursiveMode) -> Result<()> {
+ self.workspace.watch(path, mode)
+ }
}
impl<W> ParentExpander<W>
diff --git a/support/texlab/src/workspace/storage.rs b/support/texlab/src/workspace/storage.rs
index 964535a718..5f067a16aa 100644
--- a/support/texlab/src/workspace/storage.rs
+++ b/support/texlab/src/workspace/storage.rs
@@ -1,5 +1,10 @@
-use std::sync::{Arc, Mutex};
+use std::{
+ path::PathBuf,
+ sync::{Arc, Mutex},
+};
+use anyhow::Result;
+use notify::RecursiveMode;
use petgraph::{graphmap::UnGraphMap, visit::Dfs};
use rustc_hash::{FxHashMap, FxHashSet};
@@ -133,4 +138,8 @@ impl Workspace for Storage {
Some(WorkspaceSubset { documents })
}
+
+ fn watch(&self, _path: PathBuf, _mode: RecursiveMode) -> Result<()> {
+ Ok(())
+ }
}
diff --git a/support/texlab/src/workspace/watch.rs b/support/texlab/src/workspace/watch.rs
index 655872f603..4cc1834620 100644
--- a/support/texlab/src/workspace/watch.rs
+++ b/support/texlab/src/workspace/watch.rs
@@ -32,7 +32,7 @@ where
}
fn create_watcher(workspace: Arc<W>) -> Result<RecommendedWatcher> {
- let watcher = Watcher::new_immediate(move |event: notify::Result<notify::Event>| {
+ let watcher = notify::recommended_watcher(move |event: notify::Result<notify::Event>| {
if let Ok(event) = event {
if event.kind.is_modify() {
for path in event.paths {
@@ -57,20 +57,11 @@ impl<W: Workspace> Workspace for DocumentWatcher<W> {
if document.uri.scheme() == "file" {
if let Ok(mut path) = document.uri.to_file_path() {
path.pop();
- let mut watched_paths = self.watched_paths.lock().unwrap();
- if !watched_paths.contains(&path) {
- if let Err(why) = self
- .watcher
- .lock()
- .unwrap()
- .watch(&path, RecursiveMode::NonRecursive)
- {
- warn!(
- "Failed to watch folder of document \"{}\": {}",
- document.uri, why
- );
- }
- watched_paths.insert(path);
+ if let Err(why) = self.watch(path, RecursiveMode::NonRecursive) {
+ warn!(
+ "Failed to watch folder of document \"{}\": {}",
+ document.uri, why
+ );
}
}
}
@@ -104,4 +95,14 @@ impl<W: Workspace> Workspace for DocumentWatcher<W> {
fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset> {
self.workspace.subset(uri)
}
+
+ fn watch(&self, path: PathBuf, mode: RecursiveMode) -> Result<()> {
+ let mut watched_paths = self.watched_paths.lock().unwrap();
+ if !watched_paths.contains(&path) {
+ self.watcher.lock().unwrap().watch(&path, mode)?;
+ watched_paths.insert(path);
+ }
+
+ Ok(())
+ }
}