diff options
Diffstat (limited to 'support/texlab/src/syntax')
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 "}" + |