summaryrefslogtreecommitdiff
path: root/support/texlab/src/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/syntax')
-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
11 files changed, 129 insertions, 16 deletions
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 "}"
+