summaryrefslogtreecommitdiff
path: root/support/texlab/crates
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2024-03-17 03:01:42 +0000
committerNorbert Preining <norbert@preining.info>2024-03-17 03:01:42 +0000
commit55140d5421e1ad0024c9acbfa72bd06402c2aa9f (patch)
treeb6c0d76888f025b58f1221d8dadbefb0264e9f6c /support/texlab/crates
parent966f9ba332e49c29e961cb86e08f97d70eda51f6 (diff)
CTAN sync 202403170301
Diffstat (limited to 'support/texlab/crates')
-rw-r--r--support/texlab/crates/base-db/Cargo.toml2
-rw-r--r--support/texlab/crates/base-db/src/document.rs1
-rw-r--r--support/texlab/crates/base-db/src/semantics/bib.rs10
-rw-r--r--support/texlab/crates/base-db/src/workspace.rs13
-rw-r--r--support/texlab/crates/bibtex-utils/src/field.rs5
-rw-r--r--support/texlab/crates/bibtex-utils/src/field/author.rs6
-rw-r--r--support/texlab/crates/bibtex-utils/src/field/date.rs6
-rw-r--r--support/texlab/crates/bibtex-utils/src/field/number.rs6
-rw-r--r--support/texlab/crates/bibtex-utils/src/field/text.rs46
-rw-r--r--support/texlab/crates/citeproc/Cargo.toml1
-rw-r--r--support/texlab/crates/citeproc/src/driver.rs5
-rw-r--r--support/texlab/crates/citeproc/src/entry.rs34
-rw-r--r--support/texlab/crates/citeproc/src/lib.rs5
-rw-r--r--support/texlab/crates/citeproc/src/tests.rs8
-rw-r--r--support/texlab/crates/commands/Cargo.toml8
-rw-r--r--support/texlab/crates/completion-data/Cargo.toml2
-rw-r--r--support/texlab/crates/completion/Cargo.toml2
-rw-r--r--support/texlab/crates/diagnostics/Cargo.toml4
-rw-r--r--support/texlab/crates/diagnostics/src/citations.rs24
-rw-r--r--support/texlab/crates/diagnostics/src/labels.rs25
-rw-r--r--support/texlab/crates/diagnostics/src/manager.rs43
-rw-r--r--support/texlab/crates/diagnostics/src/tests.rs2
-rw-r--r--support/texlab/crates/distro/src/file_name_db.rs5
-rw-r--r--support/texlab/crates/hover/src/citation.rs2
-rw-r--r--support/texlab/crates/hover/src/string_ref.rs2
-rw-r--r--support/texlab/crates/parser/Cargo.toml2
-rw-r--r--support/texlab/crates/parser/src/config.rs28
-rw-r--r--support/texlab/crates/parser/src/latex.rs32
-rw-r--r--support/texlab/crates/parser/src/latex/lexer/commands.rs4
-rw-r--r--support/texlab/crates/parser/src/latex/tests.rs69
-rw-r--r--support/texlab/crates/texlab/Cargo.toml14
-rw-r--r--support/texlab/crates/texlab/src/client.rs10
-rw-r--r--support/texlab/crates/texlab/src/features/completion.rs16
-rw-r--r--support/texlab/crates/texlab/src/server.rs2
-rw-r--r--support/texlab/crates/texlab/src/server/options.rs6
35 files changed, 333 insertions, 117 deletions
diff --git a/support/texlab/crates/base-db/Cargo.toml b/support/texlab/crates/base-db/Cargo.toml
index 0aceff8e5f..010c83d0e4 100644
--- a/support/texlab/crates/base-db/Cargo.toml
+++ b/support/texlab/crates/base-db/Cargo.toml
@@ -12,7 +12,7 @@ dirs = "5.0.1"
distro = { path = "../distro" }
itertools = "0.12.0"
line-index = { path = "../line-index" }
-log = "0.4.20"
+log = "0.4.21"
notify = "6.0.1"
once_cell = "1.19.0"
parser = { path = "../parser" }
diff --git a/support/texlab/crates/base-db/src/document.rs b/support/texlab/crates/base-db/src/document.rs
index 9f45876d7e..25607a1bf5 100644
--- a/support/texlab/crates/base-db/src/document.rs
+++ b/support/texlab/crates/base-db/src/document.rs
@@ -12,6 +12,7 @@ use crate::{semantics, Config};
pub enum Owner {
Client,
Server,
+ Distro,
}
#[derive(Debug)]
diff --git a/support/texlab/crates/base-db/src/semantics/bib.rs b/support/texlab/crates/base-db/src/semantics/bib.rs
index 14fa98fb6e..1a03fbb2c2 100644
--- a/support/texlab/crates/base-db/src/semantics/bib.rs
+++ b/support/texlab/crates/base-db/src/semantics/bib.rs
@@ -2,6 +2,7 @@ use bibtex_utils::field::text::TextFieldData;
use itertools::Itertools;
use rowan::{ast::AstNode, TextRange};
use syntax::bibtex::{self, HasName, HasType, HasValue};
+use rustc_hash::FxHashMap;
use crate::data::{BibtexEntryType, BibtexEntryTypeCategory};
@@ -11,6 +12,8 @@ use super::Span;
pub struct Semantics {
pub entries: Vec<Entry>,
pub strings: Vec<StringDef>,
+ /// Map from string definition keys to their expanded values.
+ pub expanded_defs: FxHashMap<String, String>,
}
impl Semantics {
@@ -32,7 +35,7 @@ impl Semantics {
let field_values = entry
.fields()
- .filter_map(|field| Some(TextFieldData::parse(&field.value()?)?.text));
+ .filter_map(|field| Some(TextFieldData::parse(&field.value()?, &self.expanded_defs)?.text));
let keywords = [name.text().into(), type_token.text().into()]
.into_iter()
@@ -60,6 +63,11 @@ impl Semantics {
},
full_range: string.syntax().text_range(),
});
+ if let Some(value) = string.value() {
+ if let Some(data) = TextFieldData::parse(&value, &self.expanded_defs) {
+ self.expanded_defs.insert(name.text().into(), data.text);
+ }
+ }
}
}
}
diff --git a/support/texlab/crates/base-db/src/workspace.rs b/support/texlab/crates/base-db/src/workspace.rs
index 330ed5a493..0fe347f1b3 100644
--- a/support/texlab/crates/base-db/src/workspace.rs
+++ b/support/texlab/crates/base-db/src/workspace.rs
@@ -67,7 +67,7 @@ impl Workspace {
}));
}
- pub fn load(&mut self, path: &Path, language: Language, owner: Owner) -> std::io::Result<()> {
+ pub fn load(&mut self, path: &Path, language: Language) -> std::io::Result<()> {
log::debug!("Loading document {} from disk...", path.display());
let uri = Url::from_file_path(path).unwrap();
let data = std::fs::read(path)?;
@@ -76,6 +76,12 @@ impl Workspace {
Cow::Owned(text) => text,
};
+ let owner = if self.distro.file_name_db.contains(&path) {
+ Owner::Distro
+ } else {
+ Owner::Server
+ };
+
if let Some(document) = self.lookup_path(path) {
if document.text == text {
return Ok(());
@@ -329,7 +335,7 @@ impl Workspace {
}
if self.lookup_path(&file).is_none() && file.exists() {
- changed |= self.load(&file, lang, Owner::Server).is_ok();
+ changed |= self.load(&file, lang).is_ok();
checked_paths.insert(file);
}
}
@@ -350,8 +356,9 @@ impl Workspace {
let mut changed = false;
for file in files {
let language = Language::from_path(&file).unwrap_or(Language::Tex);
+
if self.lookup_path(&file).is_none() && file.exists() {
- changed |= self.load(&file, language, Owner::Server).is_ok();
+ changed |= self.load(&file, language).is_ok();
checked_paths.insert(file);
}
}
diff --git a/support/texlab/crates/bibtex-utils/src/field.rs b/support/texlab/crates/bibtex-utils/src/field.rs
index d9f3adacab..71bd25f6d0 100644
--- a/support/texlab/crates/bibtex-utils/src/field.rs
+++ b/support/texlab/crates/bibtex-utils/src/field.rs
@@ -1,4 +1,9 @@
+use rustc_hash::FxHashMap;
+
pub mod author;
pub mod date;
pub mod number;
pub mod text;
+
+/// A cache used to accelerate related field parses.
+pub type FieldParseCache = FxHashMap<String, String>; \ No newline at end of file
diff --git a/support/texlab/crates/bibtex-utils/src/field/author.rs b/support/texlab/crates/bibtex-utils/src/field/author.rs
index d8576cbaa4..4be999efbd 100644
--- a/support/texlab/crates/bibtex-utils/src/field/author.rs
+++ b/support/texlab/crates/bibtex-utils/src/field/author.rs
@@ -4,7 +4,7 @@ use human_name::Name;
use itertools::Itertools;
use syntax::bibtex::Value;
-use super::text::TextFieldData;
+use super::{text::TextFieldData, FieldParseCache};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub enum AuthorField {
@@ -58,8 +58,8 @@ impl fmt::Display for AuthorFieldData {
}
impl AuthorFieldData {
- pub fn parse(value: &Value) -> Option<Self> {
- let TextFieldData { text } = TextFieldData::parse(value)?;
+ pub fn parse(value: &Value, cache: &FieldParseCache) -> Option<Self> {
+ let TextFieldData { text } = TextFieldData::parse(value, cache)?;
let mut authors = Vec::new();
let mut words = Vec::new();
for word in text.split_whitespace() {
diff --git a/support/texlab/crates/bibtex-utils/src/field/date.rs b/support/texlab/crates/bibtex-utils/src/field/date.rs
index 8e2c0b7d72..4e3dfd19d9 100644
--- a/support/texlab/crates/bibtex-utils/src/field/date.rs
+++ b/support/texlab/crates/bibtex-utils/src/field/date.rs
@@ -3,7 +3,7 @@ use std::{fmt, ops::Add, str::FromStr};
use chrono::{Datelike, Month, NaiveDate};
use syntax::bibtex::Value;
-use super::text::TextFieldData;
+use super::{text::TextFieldData, FieldParseCache};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub enum DateField {
@@ -73,8 +73,8 @@ impl fmt::Display for DateFieldData {
}
impl DateFieldData {
- pub fn parse(value: &Value) -> Option<Self> {
- let TextFieldData { text } = TextFieldData::parse(value)?;
+ pub fn parse(value: &Value, cache: &FieldParseCache) -> Option<Self> {
+ let TextFieldData { text } = TextFieldData::parse(value, cache)?;
NaiveDate::from_str(&text)
.ok()
.map(Self::Date)
diff --git a/support/texlab/crates/bibtex-utils/src/field/number.rs b/support/texlab/crates/bibtex-utils/src/field/number.rs
index 227f3d5b75..34240bcfb3 100644
--- a/support/texlab/crates/bibtex-utils/src/field/number.rs
+++ b/support/texlab/crates/bibtex-utils/src/field/number.rs
@@ -2,7 +2,7 @@ use std::fmt;
use syntax::bibtex::Value;
-use super::text::TextFieldData;
+use super::{text::TextFieldData, FieldParseCache};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub enum NumberField {
@@ -48,8 +48,8 @@ impl fmt::Display for NumberFieldData {
}
impl NumberFieldData {
- pub fn parse(value: &Value) -> Option<Self> {
- let TextFieldData { text } = TextFieldData::parse(value)?;
+ pub fn parse(value: &Value, cache: &FieldParseCache) -> Option<Self> {
+ let TextFieldData { text } = TextFieldData::parse(value, cache)?;
text.split_once("--")
.or_else(|| text.split_once('-'))
.and_then(|(a, b)| Some((a.parse().ok()?, b.parse().ok()?)))
diff --git a/support/texlab/crates/bibtex-utils/src/field/text.rs b/support/texlab/crates/bibtex-utils/src/field/text.rs
index 9689264779..b3eabaff0e 100644
--- a/support/texlab/crates/bibtex-utils/src/field/text.rs
+++ b/support/texlab/crates/bibtex-utils/src/field/text.rs
@@ -1,11 +1,12 @@
use rowan::{ast::AstNode, NodeOrToken};
-use rustc_hash::FxHashSet;
use syntax::bibtex::{
- Accent, Command, CurlyGroup, HasAccentName, HasCommandName, HasName, HasValue, HasWord, Join,
- Literal, QuoteGroup, Root, SyntaxKind::*, SyntaxToken, Value,
+ Accent, Command, CurlyGroup, HasAccentName, HasCommandName, HasName, HasWord, Join,
+ Literal, QuoteGroup, SyntaxKind::*, SyntaxToken, Value,
};
+use super::FieldParseCache;
+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub enum TextField {
Abstract,
@@ -118,20 +119,28 @@ pub struct TextFieldData {
}
impl TextFieldData {
- pub fn parse(value: &Value) -> Option<Self> {
- let mut builder = TextFieldDataBuilder::default();
+ pub fn parse(value: &Value, cache: &FieldParseCache) -> Option<Self> {
+ let mut builder = TextFieldDataBuilder::new(cache);
builder.visit_value(value)?;
Some(builder.data)
}
}
-#[derive(Default)]
-struct TextFieldDataBuilder {
+struct TextFieldDataBuilder<'a> {
data: TextFieldData,
- string_stack: FxHashSet<String>,
+ cache: &'a FieldParseCache,
+}
+
+impl<'a> TextFieldDataBuilder<'a> {
+ fn new(cache: &'a FieldParseCache) -> Self {
+ TextFieldDataBuilder {
+ data: Default::default(),
+ cache,
+ }
+ }
}
-impl TextFieldDataBuilder {
+impl<'a> TextFieldDataBuilder<'a> {
fn visit_value(&mut self, value: &Value) -> Option<()> {
match value {
Value::Literal(lit) => {
@@ -170,24 +179,9 @@ impl TextFieldDataBuilder {
}
fn visit_string_reference(&mut self, name: &SyntaxToken) -> Option<()> {
- let root = Root::cast(name.parent_ancestors().last()?)?;
let name = name.text();
-
- let value = root
- .strings()
- .filter(|string| {
- string
- .name_token()
- .map_or(false, |token| token.text() == name)
- })
- .find_map(|string| string.value())?;
-
- if !self.string_stack.insert(name.to_string()) {
- return None;
- }
-
- let _ = self.visit_value(&value);
- self.string_stack.remove(name);
+ let value = self.cache.get(name)?;
+ self.data.text.push_str(value);
Some(())
}
diff --git a/support/texlab/crates/citeproc/Cargo.toml b/support/texlab/crates/citeproc/Cargo.toml
index c87b2d17c3..9d356b3778 100644
--- a/support/texlab/crates/citeproc/Cargo.toml
+++ b/support/texlab/crates/citeproc/Cargo.toml
@@ -8,6 +8,7 @@ rust-version.workspace = true
[dependencies]
bibtex-utils = { path = "../bibtex-utils" }
+base-db = { path = "../base-db" }
isocountry = "0.3.2"
itertools = "0.12.0"
rowan = "0.15.15"
diff --git a/support/texlab/crates/citeproc/src/driver.rs b/support/texlab/crates/citeproc/src/driver.rs
index 778e2539b5..cee6bb097e 100644
--- a/support/texlab/crates/citeproc/src/driver.rs
+++ b/support/texlab/crates/citeproc/src/driver.rs
@@ -1,3 +1,4 @@
+use base_db::semantics::bib::Semantics;
use bibtex_utils::field::{
author::AuthorField,
date::DateField,
@@ -21,8 +22,8 @@ pub struct Driver {
}
impl Driver {
- pub fn process(&mut self, entry: &bibtex::Entry) {
- let entry = EntryData::from(entry);
+ pub fn process(&mut self, entry: &bibtex::Entry, semantics: &Semantics) {
+ let entry = EntryData::from_entry(entry, semantics);
match entry.kind {
EntryKind::Article
| EntryKind::DataSet
diff --git a/support/texlab/crates/citeproc/src/entry.rs b/support/texlab/crates/citeproc/src/entry.rs
index 243908da95..f544858efc 100644
--- a/support/texlab/crates/citeproc/src/entry.rs
+++ b/support/texlab/crates/citeproc/src/entry.rs
@@ -3,7 +3,9 @@ use bibtex_utils::field::{
date::{DateField, DateFieldData},
number::{NumberField, NumberFieldData},
text::{TextField, TextFieldData},
+ FieldParseCache,
};
+use base_db::semantics::bib::Semantics;
use rustc_hash::FxHashMap;
use syntax::bibtex::{Entry, Field, HasName, HasType, HasValue, Value};
@@ -103,8 +105,8 @@ pub struct EntryData {
pub number: FxHashMap<NumberField, NumberFieldData>,
}
-impl From<&Entry> for EntryData {
- fn from(entry: &Entry) -> Self {
+impl EntryData {
+ pub fn from_entry(entry: &Entry, semantics: &Semantics) -> Self {
let mut data = EntryData {
kind: entry.type_token().map_or(EntryKind::Unknown, |token| {
EntryKind::parse(&token.text()[1..])
@@ -113,7 +115,7 @@ impl From<&Entry> for EntryData {
};
for field in entry.fields() {
- let _ = data.parse_field(&field);
+ let _ = data.parse_field(&field, &semantics.expanded_defs);
}
data
@@ -121,40 +123,40 @@ impl From<&Entry> for EntryData {
}
impl EntryData {
- fn parse_field(&mut self, field: &Field) -> Option<()> {
+ fn parse_field(&mut self, field: &Field, expanded_defs: &FieldParseCache) -> Option<()> {
let name = field.name_token()?;
let name = name.text();
let value = field.value()?;
- self.parse_author_field(name, &value)
- .or_else(|| self.parse_date_field(name, &value))
- .or_else(|| self.parse_number_field(name, &value))
- .or_else(|| self.parse_text_field(name, &value))
+ self.parse_author_field(name, &value, expanded_defs)
+ .or_else(|| self.parse_date_field(name, &value, expanded_defs))
+ .or_else(|| self.parse_number_field(name, &value, expanded_defs))
+ .or_else(|| self.parse_text_field(name, &value, expanded_defs))
}
- fn parse_author_field(&mut self, name: &str, value: &Value) -> Option<()> {
+ fn parse_author_field(&mut self, name: &str, value: &Value, expanded_defs: &FieldParseCache) -> Option<()> {
let name = AuthorField::parse(name)?;
- let data = AuthorFieldData::parse(value)?;
+ let data = AuthorFieldData::parse(value, expanded_defs)?;
self.author.insert(name, data);
Some(())
}
- fn parse_date_field(&mut self, name: &str, value: &Value) -> Option<()> {
+ fn parse_date_field(&mut self, name: &str, value: &Value, expanded_defs: &FieldParseCache) -> Option<()> {
let name = DateField::parse(name)?;
- let data = DateFieldData::parse(value)?;
+ let data = DateFieldData::parse(value, expanded_defs)?;
self.date.insert(name, data);
Some(())
}
- fn parse_number_field(&mut self, name: &str, value: &Value) -> Option<()> {
+ fn parse_number_field(&mut self, name: &str, value: &Value, expanded_defs: &FieldParseCache) -> Option<()> {
let name = NumberField::parse(name)?;
- let data = NumberFieldData::parse(value)?;
+ let data = NumberFieldData::parse(value, expanded_defs)?;
self.number.insert(name, data);
Some(())
}
- fn parse_text_field(&mut self, name: &str, value: &Value) -> Option<()> {
+ fn parse_text_field(&mut self, name: &str, value: &Value, expanded_defs: &FieldParseCache) -> Option<()> {
let name = TextField::parse(name).unwrap_or(TextField::Unknown);
- let data = TextFieldData::parse(value)?;
+ let data = TextFieldData::parse(value, expanded_defs)?;
self.text.insert(name, data);
Some(())
}
diff --git a/support/texlab/crates/citeproc/src/lib.rs b/support/texlab/crates/citeproc/src/lib.rs
index de24306583..915d3d69ba 100644
--- a/support/texlab/crates/citeproc/src/lib.rs
+++ b/support/texlab/crates/citeproc/src/lib.rs
@@ -2,16 +2,17 @@ mod driver;
mod entry;
mod output;
+use base_db::semantics::bib::Semantics;
use syntax::bibtex;
use unicode_normalization::UnicodeNormalization;
use self::{driver::Driver, output::Inline};
#[must_use]
-pub fn render(entry: &bibtex::Entry) -> Option<String> {
+pub fn render(entry: &bibtex::Entry, semantics: &Semantics) -> Option<String> {
let mut output = String::new();
let mut driver = Driver::default();
- driver.process(entry);
+ driver.process(entry, semantics);
driver.finish().for_each(|(inline, punct)| {
let text = match inline {
Inline::Regular(text) => text,
diff --git a/support/texlab/crates/citeproc/src/tests.rs b/support/texlab/crates/citeproc/src/tests.rs
index 1c91580f39..b5838b52b5 100644
--- a/support/texlab/crates/citeproc/src/tests.rs
+++ b/support/texlab/crates/citeproc/src/tests.rs
@@ -1,3 +1,4 @@
+use base_db::semantics::bib::Semantics;
use expect_test::{expect, Expect};
use parser::parse_bibtex;
use rowan::ast::AstNode;
@@ -5,9 +6,12 @@ use syntax::bibtex;
fn check(input: &str, expect: Expect) {
let green = parse_bibtex(input);
- let root = bibtex::Root::cast(bibtex::SyntaxNode::new_root(green)).unwrap();
+ let root = bibtex::SyntaxNode::new_root(green);
+ let mut semantics = Semantics::default();
+ semantics.process_root(&root);
+ let root = bibtex::Root::cast(root).unwrap();
let entry = root.entries().next().unwrap();
- let output = super::render(&entry).unwrap();
+ let output = super::render(&entry, &semantics).unwrap();
expect.assert_eq(&output);
}
diff --git a/support/texlab/crates/commands/Cargo.toml b/support/texlab/crates/commands/Cargo.toml
index c54d77abf4..512a05ee61 100644
--- a/support/texlab/crates/commands/Cargo.toml
+++ b/support/texlab/crates/commands/Cargo.toml
@@ -9,15 +9,15 @@ rust-version.workspace = true
[dependencies]
anyhow = "1.0.72"
base-db = { path = "../base-db" }
-bstr = "1.8.0"
+bstr = "1.9.0"
crossbeam-channel = "0.5.11"
itertools = "0.12.0"
-libc = "0.2.150"
-log = "0.4.19"
+libc = "0.2.153"
+log = "0.4.21"
rowan = "0.15.15"
rustc-hash = "1.1.0"
syntax = { path = "../syntax" }
-thiserror = "1.0.56"
+thiserror = "1.0.57"
url = "2.5.0"
[dev-dependencies]
diff --git a/support/texlab/crates/completion-data/Cargo.toml b/support/texlab/crates/completion-data/Cargo.toml
index c32c02d3bc..37ecf1b3cf 100644
--- a/support/texlab/crates/completion-data/Cargo.toml
+++ b/support/texlab/crates/completion-data/Cargo.toml
@@ -12,7 +12,7 @@ itertools = "0.12.0"
once_cell = "1.19.0"
rustc-hash = "1.1.0"
serde = { version = "1.0.195", features = ["derive"] }
-serde_json = "1.0.108"
+serde_json = "1.0.114"
[lib]
doctest = false
diff --git a/support/texlab/crates/completion/Cargo.toml b/support/texlab/crates/completion/Cargo.toml
index 5bcebea435..fbdd2d7201 100644
--- a/support/texlab/crates/completion/Cargo.toml
+++ b/support/texlab/crates/completion/Cargo.toml
@@ -11,7 +11,7 @@ base-db = { path = "../base-db" }
completion-data = { path = "../completion-data" }
fuzzy-matcher = { version = "0.3.7", features = ["compact"] }
line-index = { path = "../line-index" }
-rayon = "1.7.0"
+rayon = "1.8.1"
rowan = "0.15.15"
rustc-hash = "1.1.0"
syntax = { path = "../syntax" }
diff --git a/support/texlab/crates/diagnostics/Cargo.toml b/support/texlab/crates/diagnostics/Cargo.toml
index 1fb4b2171d..91c2ff9dbd 100644
--- a/support/texlab/crates/diagnostics/Cargo.toml
+++ b/support/texlab/crates/diagnostics/Cargo.toml
@@ -14,8 +14,8 @@ encoding_rs = "0.8.33"
encoding_rs_io = "0.1.7"
itertools = "0.12.0"
line-index = { path = "../line-index" }
-log = "0.4.20"
-multimap = "0.9.1"
+log = "0.4.21"
+multimap = "0.10.0"
once_cell = "1.19.0"
parking_lot = "0.12.1"
regex = "1.10.2"
diff --git a/support/texlab/crates/diagnostics/src/citations.rs b/support/texlab/crates/diagnostics/src/citations.rs
index 403d2f5bfc..ea4ef03d58 100644
--- a/support/texlab/crates/diagnostics/src/citations.rs
+++ b/support/texlab/crates/diagnostics/src/citations.rs
@@ -3,8 +3,7 @@ use base_db::{
util::queries::{self, Object},
Document, Project, Workspace,
};
-use multimap::MultiMap;
-use rustc_hash::FxHashSet;
+use rustc_hash::{FxHashMap, FxHashSet};
use url::Url;
use crate::types::{BibError, Diagnostic, TexError};
@@ -14,7 +13,7 @@ const MAX_UNUSED_ENTRIES: usize = 1000;
pub fn detect_undefined_citations<'a>(
project: &Project<'a>,
document: &'a Document,
- results: &mut MultiMap<Url, Diagnostic>,
+ results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) -> Option<()> {
let data = document.data.as_tex()?;
@@ -26,7 +25,10 @@ pub fn detect_undefined_citations<'a>(
let name = citation.name_text();
if name != "*" && !entries.contains(name) {
let diagnostic = Diagnostic::Tex(citation.name.range, TexError::UndefinedCitation);
- results.insert(document.uri.clone(), diagnostic);
+ results
+ .entry(document.uri.clone())
+ .or_default()
+ .push(diagnostic);
}
}
@@ -36,7 +38,7 @@ pub fn detect_undefined_citations<'a>(
pub fn detect_unused_entries<'a>(
project: &Project<'a>,
document: &'a Document,
- results: &mut MultiMap<Url, Diagnostic>,
+ results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) -> Option<()> {
let data = document.data.as_bib()?;
@@ -52,7 +54,10 @@ pub fn detect_unused_entries<'a>(
for entry in &data.semantics.entries {
if !citations.contains(entry.name.text.as_str()) {
let diagnostic = Diagnostic::Bib(entry.name.range, BibError::UnusedEntry);
- results.insert(document.uri.clone(), diagnostic);
+ results
+ .entry(document.uri.clone())
+ .or_default()
+ .push(diagnostic);
}
}
@@ -61,7 +66,7 @@ pub fn detect_unused_entries<'a>(
pub fn detect_duplicate_entries<'a>(
workspace: &'a Workspace,
- results: &mut MultiMap<Url, Diagnostic>,
+ results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) {
for conflict in queries::Conflict::find_all::<Entry>(workspace) {
let others = conflict
@@ -71,6 +76,9 @@ pub fn detect_duplicate_entries<'a>(
.collect();
let diagnostic = Diagnostic::Bib(conflict.main.range, BibError::DuplicateEntry(others));
- results.insert(conflict.main.document.uri.clone(), diagnostic);
+ results
+ .entry(conflict.main.document.uri.clone())
+ .or_default()
+ .push(diagnostic);
}
}
diff --git a/support/texlab/crates/diagnostics/src/labels.rs b/support/texlab/crates/diagnostics/src/labels.rs
index 92f9072918..9a39f3f24b 100644
--- a/support/texlab/crates/diagnostics/src/labels.rs
+++ b/support/texlab/crates/diagnostics/src/labels.rs
@@ -4,15 +4,14 @@ use base_db::{
DocumentData, Workspace,
};
use itertools::Itertools;
-use multimap::MultiMap;
-use rustc_hash::FxHashSet;
+use rustc_hash::{FxHashMap, FxHashSet};
use url::Url;
use crate::types::{Diagnostic, TexError};
pub fn detect_undefined_and_unused_labels(
workspace: &Workspace,
- results: &mut MultiMap<Url, Diagnostic>,
+ results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) {
let graphs: Vec<_> = workspace
.iter()
@@ -45,18 +44,27 @@ pub fn detect_undefined_and_unused_labels(
for label in &data.semantics.labels {
if label.kind != LabelKind::Definition && !label_defs.contains(&label.name.text) {
let diagnostic = Diagnostic::Tex(label.name.range, TexError::UndefinedLabel);
- results.insert(document.uri.clone(), diagnostic);
+ results
+ .entry(document.uri.clone())
+ .or_default()
+ .push(diagnostic);
}
if label.kind == LabelKind::Definition && !label_refs.contains(&label.name.text) {
let diagnostic = Diagnostic::Tex(label.name.range, TexError::UnusedLabel);
- results.insert(document.uri.clone(), diagnostic);
+ results
+ .entry(document.uri.clone())
+ .or_default()
+ .push(diagnostic);
}
}
}
}
-pub fn detect_duplicate_labels(workspace: &Workspace, results: &mut MultiMap<Url, Diagnostic>) {
+pub fn detect_duplicate_labels(
+ workspace: &Workspace,
+ results: &mut FxHashMap<Url, Vec<Diagnostic>>,
+) {
for conflict in queries::Conflict::find_all::<Label>(workspace) {
let others = conflict
.rest
@@ -65,6 +73,9 @@ pub fn detect_duplicate_labels(workspace: &Workspace, results: &mut MultiMap<Url
.collect();
let diagnostic = Diagnostic::Tex(conflict.main.range, TexError::DuplicateLabel(others));
- results.insert(conflict.main.document.uri.clone(), diagnostic);
+ results
+ .entry(conflict.main.document.uri.clone())
+ .or_default()
+ .push(diagnostic);
}
}
diff --git a/support/texlab/crates/diagnostics/src/manager.rs b/support/texlab/crates/diagnostics/src/manager.rs
index 1ce5e194b8..38c0a514f4 100644
--- a/support/texlab/crates/diagnostics/src/manager.rs
+++ b/support/texlab/crates/diagnostics/src/manager.rs
@@ -16,6 +16,10 @@ pub struct Manager {
impl Manager {
/// Updates the syntax-based diagnostics for the given document.
pub fn update_syntax(&mut self, workspace: &Workspace, document: &Document) {
+ if !Self::is_relevant(document) {
+ return;
+ }
+
self.grammar.remove(&document.uri);
super::grammar::tex::update(document, workspace.config(), &mut self.grammar);
super::grammar::bib::update(document, &mut self.grammar);
@@ -30,14 +34,20 @@ impl Manager {
}
/// Returns all filtered diagnostics for the given workspace.
- pub fn get(&self, workspace: &Workspace) -> MultiMap<Url, Diagnostic> {
- let mut results = MultiMap::default();
+ pub fn get(&self, workspace: &Workspace) -> FxHashMap<Url, Vec<Diagnostic>> {
+ let mut results: FxHashMap<Url, Vec<Diagnostic>> = FxHashMap::default();
for (uri, diagnostics) in &self.grammar {
- results.insert_many_from_slice(uri.clone(), diagnostics);
+ results
+ .entry(uri.clone())
+ .or_default()
+ .extend(diagnostics.iter().cloned());
}
for (uri, diagnostics) in self.build_log.values().flatten() {
- results.insert_many_from_slice(uri.clone(), diagnostics);
+ results
+ .entry(uri.clone())
+ .or_default()
+ .extend(diagnostics.iter().cloned());
}
for (uri, diagnostics) in &self.chktex {
@@ -45,11 +55,17 @@ impl Manager {
.lookup(uri)
.map_or(false, |document| document.owner == Owner::Client)
{
- results.insert_many_from_slice(uri.clone(), diagnostics);
+ results
+ .entry(uri.clone())
+ .or_default()
+ .extend(diagnostics.iter().cloned());
}
}
- for document in workspace.iter() {
+ for document in workspace
+ .iter()
+ .filter(|document| Self::is_relevant(document))
+ {
let project = workspace.project(document);
super::citations::detect_undefined_citations(&project, document, &mut results);
super::citations::detect_unused_entries(&project, document, &mut results);
@@ -60,6 +76,13 @@ impl Manager {
super::labels::detect_undefined_and_unused_labels(workspace, &mut results);
let config = &workspace.config().diagnostics;
+
+ results.retain(|uri, _| {
+ workspace
+ .lookup(uri)
+ .map_or(false, |document| Self::is_relevant(document))
+ });
+
for (_, diagnostics) in &mut results {
diagnostics.retain(|diagnostic| {
filter_regex_patterns(
@@ -72,4 +95,12 @@ impl Manager {
results
}
+
+ fn is_relevant(document: &Document) -> bool {
+ match document.owner {
+ Owner::Client => true,
+ Owner::Server => true,
+ Owner::Distro => false,
+ }
+ }
}
diff --git a/support/texlab/crates/diagnostics/src/tests.rs b/support/texlab/crates/diagnostics/src/tests.rs
index b7c6004d19..3688abeaf4 100644
--- a/support/texlab/crates/diagnostics/src/tests.rs
+++ b/support/texlab/crates/diagnostics/src/tests.rs
@@ -11,7 +11,7 @@ fn check(input: &str, expect: Expect) {
let results = manager.get(&fixture.workspace);
let results = results
- .iter_all()
+ .iter()
.filter(|(_, diags)| !diags.is_empty())
.sorted_by(|(uri1, _), (uri2, _)| uri1.cmp(&uri2))
.map(|(uri, diags)| (uri.as_str(), diags))
diff --git a/support/texlab/crates/distro/src/file_name_db.rs b/support/texlab/crates/distro/src/file_name_db.rs
index 06871bde83..fd6750fffa 100644
--- a/support/texlab/crates/distro/src/file_name_db.rs
+++ b/support/texlab/crates/distro/src/file_name_db.rs
@@ -55,6 +55,11 @@ impl FileNameDB {
self.files.get(name).map(|file| file.path())
}
+ pub fn contains(&self, path: &Path) -> bool {
+ let name = path.file_name().unwrap().to_str().unwrap();
+ self.get(name) == Some(path)
+ }
+
pub fn iter(&self) -> impl Iterator<Item = (&str, &Path)> + '_ {
self.files.iter().map(|file| (file.name(), file.path()))
}
diff --git a/support/texlab/crates/hover/src/citation.rs b/support/texlab/crates/hover/src/citation.rs
index 372668997e..a39ea2e5f5 100644
--- a/support/texlab/crates/hover/src/citation.rs
+++ b/support/texlab/crates/hover/src/citation.rs
@@ -31,7 +31,7 @@ pub(super) fn find_hover<'a>(params: &HoverParams<'a>) -> Option<Hover<'a>> {
let data = document.data.as_bib()?;
let root = bibtex::Root::cast(data.root_node())?;
let entry = root.find_entry(name)?;
- citeproc::render(&entry)
+ citeproc::render(&entry, &data.semantics)
})?;
let data = HoverData::Citation(text);
diff --git a/support/texlab/crates/hover/src/string_ref.rs b/support/texlab/crates/hover/src/string_ref.rs
index 6726041af2..cf8062a5a0 100644
--- a/support/texlab/crates/hover/src/string_ref.rs
+++ b/support/texlab/crates/hover/src/string_ref.rs
@@ -24,7 +24,7 @@ pub(super) fn find_hover<'a>(params: &HoverParams<'a>) -> Option<Hover<'a>> {
continue;
}
- let value = TextFieldData::parse(&string.value()?)?.text;
+ let value = TextFieldData::parse(&string.value()?, &data.semantics.expanded_defs)?.text;
return Some(Hover {
range: name.text_range(),
data: HoverData::StringRef(value),
diff --git a/support/texlab/crates/parser/Cargo.toml b/support/texlab/crates/parser/Cargo.toml
index c3e31b7022..0fd8889899 100644
--- a/support/texlab/crates/parser/Cargo.toml
+++ b/support/texlab/crates/parser/Cargo.toml
@@ -13,7 +13,7 @@ regex = "1.10.2"
rowan = "0.15.15"
rustc-hash = "1.1.0"
syntax = { path = "../syntax" }
-tempfile = "3.8.1"
+tempfile = "3.10.1"
[dev-dependencies]
expect-test = "1.4.1"
diff --git a/support/texlab/crates/parser/src/config.rs b/support/texlab/crates/parser/src/config.rs
index 3a2e9e3e93..6537d21b0d 100644
--- a/support/texlab/crates/parser/src/config.rs
+++ b/support/texlab/crates/parser/src/config.rs
@@ -7,6 +7,7 @@ pub struct SyntaxConfig {
pub enum_environments: FxHashSet<String>,
pub verbatim_environments: FxHashSet<String>,
pub citation_commands: FxHashSet<String>,
+ pub label_reference_commands: FxHashSet<String>,
}
impl Default for SyntaxConfig {
@@ -31,12 +32,18 @@ impl Default for SyntaxConfig {
.map(ToString::to_string)
.collect();
+ let label_reference_commands = DEFAULT_LABEL_REFERENCE_COMMANDS
+ .iter()
+ .map(ToString::to_string)
+ .collect();
+
Self {
follow_package_links: false,
math_environments,
enum_environments,
verbatim_environments,
citation_commands,
+ label_reference_commands,
}
}
}
@@ -155,3 +162,24 @@ static DEFAULT_CITATION_COMMANDS: &[&str] = &[
"citeA",
"citeA*",
];
+
+static DEFAULT_LABEL_REFERENCE_COMMANDS: &[&str] = &[
+ "ref",
+ "vref",
+ "Vref",
+ "autoref",
+ "pageref",
+ "cref",
+ "cref*",
+ "Cref",
+ "Cref*",
+ "namecref",
+ "nameCref",
+ "lcnamecref",
+ "namecrefs",
+ "nameCrefs",
+ "lcnamecrefs",
+ "labelcref",
+ "labelcpageref",
+ "eqref",
+];
diff --git a/support/texlab/crates/parser/src/latex.rs b/support/texlab/crates/parser/src/latex.rs
index d88eb39556..4a6fabae21 100644
--- a/support/texlab/crates/parser/src/latex.rs
+++ b/support/texlab/crates/parser/src/latex.rs
@@ -25,6 +25,13 @@ impl Default for ParserContext {
}
}
+#[derive(Debug, Clone, Copy)]
+struct KeyOptions {
+ allow_eq: bool,
+ allow_parens: bool,
+ allow_bracks: bool,
+}
+
#[derive(Debug)]
struct Parser<'a> {
lexer: Lexer<'a>,
@@ -309,7 +316,11 @@ impl<'a> Parser<'a> {
self.trivia();
match self.peek() {
Some(Token::Word | Token::Pipe) => {
- self.key();
+ self.key_with_opts(KeyOptions {
+ allow_eq: true,
+ allow_bracks: false,
+ allow_parens: true,
+ });
}
Some(_) | None => {}
}
@@ -340,16 +351,22 @@ impl<'a> Parser<'a> {
}
fn key(&mut self) {
- self.key_with_eq(true);
+ self.key_with_opts(KeyOptions {
+ allow_eq: true,
+ allow_parens: true,
+ allow_bracks: true,
+ });
}
- fn key_with_eq(&mut self, allow_eq: bool) {
+ fn key_with_opts(&mut self, options: KeyOptions) {
self.builder.start_node(KEY.into());
self.eat();
while let Some(kind) = self.peek() {
match kind {
Token::Whitespace | Token::LineComment | Token::Word | Token::Pipe => self.eat(),
- Token::Eq if allow_eq => self.eat(),
+ Token::LBrack | Token::RBrack if options.allow_bracks => self.eat(),
+ Token::LParen | Token::RParen if options.allow_parens => self.eat(),
+ Token::Eq if options.allow_eq => self.eat(),
_ => break,
}
}
@@ -374,7 +391,12 @@ impl<'a> Parser<'a> {
fn key_value_pair(&mut self) {
self.builder.start_node(KEY_VALUE_PAIR.into());
- self.key_with_eq(false);
+ self.key_with_opts(KeyOptions {
+ allow_eq: false,
+ allow_parens: true,
+ allow_bracks: false,
+ });
+
if self.peek() == Some(Token::Eq) {
self.eat();
self.trivia();
diff --git a/support/texlab/crates/parser/src/latex/lexer/commands.rs b/support/texlab/crates/parser/src/latex/lexer/commands.rs
index b6e1d11737..95eef4becd 100644
--- a/support/texlab/crates/parser/src/latex/lexer/commands.rs
+++ b/support/texlab/crates/parser/src/latex/lexer/commands.rs
@@ -30,9 +30,6 @@ pub fn classify(name: &str, config: &SyntaxConfig) -> CommandName {
CommandName::Import
}
"label" => CommandName::LabelDefinition,
- "ref" | "vref" | "Vref" | "autoref" | "pageref" | "cref" | "cref*" | "Cref" | "Cref*"
- | "namecref" | "nameCref" | "lcnamecref" | "namecrefs" | "nameCrefs" | "lcnamecrefs"
- | "labelcref" | "labelcpageref" | "eqref" => CommandName::LabelReference,
"crefrange" | "crefrange*" | "Crefrange" | "Crefrange*" => CommandName::LabelReferenceRange,
"newlabel" => CommandName::LabelNumber,
"newcommand"
@@ -81,6 +78,7 @@ pub fn classify(name: &str, config: &SyntaxConfig) -> CommandName {
"fi" => CommandName::EndBlockComment,
"verb" => CommandName::VerbatimBlock,
_ if config.citation_commands.contains(name) => CommandName::Citation,
+ _ if config.label_reference_commands.contains(name) => CommandName::LabelReference,
_ => CommandName::Generic,
}
}
diff --git a/support/texlab/crates/parser/src/latex/tests.rs b/support/texlab/crates/parser/src/latex/tests.rs
index 6e5019776f..5e1a4044cd 100644
--- a/support/texlab/crates/parser/src/latex/tests.rs
+++ b/support/texlab/crates/parser/src/latex/tests.rs
@@ -3542,3 +3542,72 @@ fn test_command_subscript() {
"#]],
);
}
+
+#[test]
+fn test_label_parens() {
+ check(
+ r#"\label{foo (bar)}"#,
+ expect![[r#"
+ ROOT@0..17
+ PREAMBLE@0..17
+ LABEL_DEFINITION@0..17
+ COMMAND_NAME@0..6 "\\label"
+ CURLY_GROUP_WORD@6..17
+ L_CURLY@6..7 "{"
+ KEY@7..16
+ WORD@7..10 "foo"
+ WHITESPACE@10..11 " "
+ L_PAREN@11..12 "("
+ WORD@12..15 "bar"
+ R_PAREN@15..16 ")"
+ R_CURLY@16..17 "}"
+
+ "#]],
+ );
+}
+
+#[test]
+fn test_label_brackets() {
+ check(
+ r#"\label{foo [bar]}"#,
+ expect![[r#"
+ ROOT@0..17
+ PREAMBLE@0..17
+ LABEL_DEFINITION@0..17
+ COMMAND_NAME@0..6 "\\label"
+ CURLY_GROUP_WORD@6..17
+ L_CURLY@6..7 "{"
+ KEY@7..16
+ WORD@7..10 "foo"
+ WHITESPACE@10..11 " "
+ L_BRACK@11..12 "["
+ WORD@12..15 "bar"
+ R_BRACK@15..16 "]"
+ R_CURLY@16..17 "}"
+
+ "#]],
+ );
+}
+
+#[test]
+fn test_label_brackets_unbalanced() {
+ check(
+ r#"\label{foo ]bar[}"#,
+ expect![[r#"
+ ROOT@0..17
+ PREAMBLE@0..17
+ LABEL_DEFINITION@0..17
+ COMMAND_NAME@0..6 "\\label"
+ CURLY_GROUP_WORD@6..17
+ L_CURLY@6..7 "{"
+ KEY@7..16
+ WORD@7..10 "foo"
+ WHITESPACE@10..11 " "
+ R_BRACK@11..12 "]"
+ WORD@12..15 "bar"
+ L_BRACK@15..16 "["
+ R_CURLY@16..17 "}"
+
+ "#]],
+ );
+}
diff --git a/support/texlab/crates/texlab/Cargo.toml b/support/texlab/crates/texlab/Cargo.toml
index 53b63ded3e..ccc02bff01 100644
--- a/support/texlab/crates/texlab/Cargo.toml
+++ b/support/texlab/crates/texlab/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "texlab"
description = "LaTeX Language Server"
-version = "5.12.3"
+version = "5.13.1"
license.workspace = true
readme = "README.md"
authors.workspace = true
@@ -26,7 +26,7 @@ anyhow = "1.0.75"
base-db = { path = "../base-db" }
bibfmt = { path = "../bibfmt" }
citeproc = { path = "../citeproc" }
-clap = { version = "4.4.10", features = ["derive"] }
+clap = { version = "4.4.18", features = ["derive"] }
commands = { path = "../commands" }
completion = { path = "../completion" }
completion-data = { path = "../completion-data" }
@@ -43,9 +43,9 @@ hover = { path = "../hover" }
inlay-hints = { path = "../inlay-hints" }
line-index = { path = "../line-index" }
links = { path = "../links" }
-log = "0.4.19"
+log = "0.4.21"
lsp-server = "0.7.6"
-lsp-types = "0.94.1"
+lsp-types = "0.95.0"
notify = "6.1.1"
notify-debouncer-full = "0.3.1"
once_cell = "1.19.0"
@@ -57,12 +57,12 @@ rename = { path = "../rename" }
rowan = "0.15.15"
rustc-hash = "1.1.0"
serde = "1.0.195"
-serde_json = "1.0.108"
+serde_json = "1.0.114"
serde_regex = "1.1.0"
-serde_repr = "0.1.17"
+serde_repr = "0.1.18"
symbols = { path = "../symbols" }
syntax = { path = "../syntax" }
-tempfile = "3.8.0"
+tempfile = "3.10.1"
threadpool = "1.8.1"
[dev-dependencies]
diff --git a/support/texlab/crates/texlab/src/client.rs b/support/texlab/crates/texlab/src/client.rs
index 9bbace9938..b79f876436 100644
--- a/support/texlab/crates/texlab/src/client.rs
+++ b/support/texlab/crates/texlab/src/client.rs
@@ -93,8 +93,14 @@ impl LspClient {
Ok(())
}
- pub fn parse_options(&self, value: serde_json::Value) -> Result<Options> {
- let options = match serde_json::from_value(value) {
+ pub fn parse_options(&self, mut value: serde_json::Value) -> Result<Options> {
+ // if there are multiple servers, we need to extract the options for texlab first
+ let options = match value.get_mut("texlab") {
+ Some(section) => section.take(),
+ None => value,
+ };
+
+ let options = match serde_json::from_value(options) {
Ok(new_options) => new_options,
Err(why) => {
let message = format!(
diff --git a/support/texlab/crates/texlab/src/features/completion.rs b/support/texlab/crates/texlab/src/features/completion.rs
index 5d32588970..5bca0070ef 100644
--- a/support/texlab/crates/texlab/src/features/completion.rs
+++ b/support/texlab/crates/texlab/src/features/completion.rs
@@ -1,4 +1,4 @@
-use base_db::{util::RenderedObject, Workspace};
+use base_db::{util::RenderedObject, MatchingAlgo, Workspace};
use completion::{ArgumentData, CompletionItem, CompletionItemData, EntryTypeData, FieldTypeData};
use line_index::LineIndex;
use rowan::ast::AstNode;
@@ -20,8 +20,16 @@ pub fn complete(
client_flags,
};
- let is_incomplete =
- client_flags.completion_always_incomplete || result.items.len() >= completion::LIMIT;
+ let is_fuzzy = match workspace.config().completion.matcher {
+ MatchingAlgo::Skim => true,
+ MatchingAlgo::SkimIgnoreCase => true,
+ MatchingAlgo::Prefix => false,
+ MatchingAlgo::PrefixIgnoreCase => false,
+ };
+
+ let is_incomplete = client_flags.completion_always_incomplete
+ || !is_fuzzy
+ || result.items.len() >= completion::LIMIT;
let items = result
.items
@@ -53,7 +61,7 @@ pub fn resolve(workspace: &Workspace, item: &mut lsp_types::CompletionItem) -> O
let data = workspace.lookup(&uri)?.data.as_bib()?;
let root = bibtex::Root::cast(data.root_node())?;
let entry = root.find_entry(&key)?;
- let value = citeproc::render(&entry)?;
+ let value = citeproc::render(&entry, &data.semantics)?;
item.documentation = Some(lsp_types::Documentation::MarkupContent(
lsp_types::MarkupContent {
kind: lsp_types::MarkupKind::Markdown,
diff --git a/support/texlab/crates/texlab/src/server.rs b/support/texlab/crates/texlab/src/server.rs
index 0fb186f688..fc16775bc9 100644
--- a/support/texlab/crates/texlab/src/server.rs
+++ b/support/texlab/crates/texlab/src/server.rs
@@ -813,7 +813,7 @@ impl Server {
.map_or(true, |document| document.owner == Owner::Server)
{
if let Some(language) = Language::from_path(&path) {
- changed |= workspace.load(&path, language, Owner::Server).is_ok();
+ changed |= workspace.load(&path, language).is_ok();
if let Some(document) = workspace.lookup_path(&path) {
self.diagnostic_manager.update_syntax(&workspace, document);
diff --git a/support/texlab/crates/texlab/src/server/options.rs b/support/texlab/crates/texlab/src/server/options.rs
index 72b2b127fb..60c0bf90f7 100644
--- a/support/texlab/crates/texlab/src/server/options.rs
+++ b/support/texlab/crates/texlab/src/server/options.rs
@@ -128,6 +128,7 @@ pub struct ExperimentalOptions {
pub enum_environments: Vec<String>,
pub verbatim_environments: Vec<String>,
pub citation_commands: Vec<String>,
+ pub label_reference_commands: Vec<String>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
@@ -283,5 +284,10 @@ impl From<Options> for Config {
.extend(value.experimental.citation_commands);
config
+ .syntax
+ .label_reference_commands
+ .extend(value.experimental.label_reference_commands);
+
+ config
}
}