summaryrefslogtreecommitdiff
path: root/support/texlab/src/diagnostics/bibtex.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/diagnostics/bibtex.rs')
-rw-r--r--support/texlab/src/diagnostics/bibtex.rs197
1 files changed, 109 insertions, 88 deletions
diff --git a/support/texlab/src/diagnostics/bibtex.rs b/support/texlab/src/diagnostics/bibtex.rs
index 8e5b602bcd..80cca80319 100644
--- a/support/texlab/src/diagnostics/bibtex.rs
+++ b/support/texlab/src/diagnostics/bibtex.rs
@@ -1,6 +1,9 @@
-use crate::syntax::*;
-use crate::workspace::Document;
-use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Range};
+use crate::{
+ protocol::{Diagnostic, DiagnosticSeverity, Position, Range},
+ syntax::{bibtex, SyntaxNode},
+ workspace::{Document, DocumentContent},
+};
+use petgraph::graph::NodeIndex;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum BibtexErrorCode {
@@ -38,82 +41,91 @@ impl BibtexError {
Self { code, position }
}
- pub fn analyze(tree: &BibtexSyntaxTree) -> Vec<Self> {
+ pub fn analyze(tree: &bibtex::Tree) -> Vec<Self> {
let mut errors = Vec::new();
- for entry in tree.entries() {
- if entry.is_comment() {
- continue;
- }
-
- if entry.left.is_none() {
- errors.push(BibtexError::new(
- BibtexErrorCode::MissingBeginBrace,
- entry.ty.end(),
- ));
- continue;
- }
-
- if entry.key.is_none() {
- errors.push(BibtexError::new(
- BibtexErrorCode::MissingEntryKey,
- entry.left.as_ref().unwrap().end(),
- ));
- continue;
- }
-
- if entry.comma.is_none() {
- errors.push(BibtexError::new(
- BibtexErrorCode::MissingComma,
- entry.key.as_ref().unwrap().end(),
- ));
- continue;
- }
+ for entry_node in tree.children(tree.root) {
+ if let Some(entry) = tree.as_entry(entry_node) {
+ if entry.is_comment() {
+ continue;
+ }
- for i in 0..entry.fields.len() {
- let field = &entry.fields[i];
- if field.assign.is_none() {
+ if entry.left.is_none() {
errors.push(BibtexError::new(
- BibtexErrorCode::MissingAssign,
- field.name.end(),
+ BibtexErrorCode::MissingBeginBrace,
+ entry.ty.end(),
));
continue;
}
- if field.content.is_none() {
+ if entry.key.is_none() {
errors.push(BibtexError::new(
- BibtexErrorCode::MissingContent,
- field.assign.as_ref().unwrap().end(),
+ BibtexErrorCode::MissingEntryKey,
+ entry.left.as_ref().unwrap().end(),
));
continue;
}
- Self::analyze_content(&mut errors, &field.content.as_ref().unwrap());
-
- if i != entry.fields.len() - 1 && field.comma.is_none() {
+ if entry.comma.is_none() {
errors.push(BibtexError::new(
BibtexErrorCode::MissingComma,
- field.content.as_ref().unwrap().end(),
+ entry.key.as_ref().unwrap().end(),
));
continue;
}
- }
- if entry.right.is_none() {
- errors.push(BibtexError::new(
- BibtexErrorCode::MissingEndBrace,
- entry.end(),
- ));
- continue;
+ let field_count = tree.children(entry_node).count();
+ for (i, field_node) in tree.children(entry_node).enumerate() {
+ let field = tree.as_field(field_node).unwrap();
+ if field.assign.is_none() {
+ errors.push(BibtexError::new(
+ BibtexErrorCode::MissingAssign,
+ field.name.end(),
+ ));
+ continue;
+ }
+
+ let content = tree.children(field_node).next();
+
+ if content.is_none() {
+ errors.push(BibtexError::new(
+ BibtexErrorCode::MissingContent,
+ field.assign.as_ref().unwrap().end(),
+ ));
+ continue;
+ }
+
+ Self::analyze_content(&mut errors, tree, content.unwrap());
+
+ if i != field_count - 1 && field.comma.is_none() {
+ errors.push(BibtexError::new(
+ BibtexErrorCode::MissingComma,
+ tree.graph[content.unwrap()].end(),
+ ));
+ continue;
+ }
+ }
+
+ if entry.right.is_none() {
+ errors.push(BibtexError::new(
+ BibtexErrorCode::MissingEndBrace,
+ entry.end(),
+ ));
+ continue;
+ }
}
}
errors
}
- fn analyze_content(mut errors: &mut Vec<BibtexError>, content: &BibtexContent) {
- match content {
- BibtexContent::QuotedContent(content) => {
- for child in &content.children {
- Self::analyze_content(&mut errors, &child);
+ fn analyze_content(
+ mut errors: &mut Vec<BibtexError>,
+ tree: &bibtex::Tree,
+ content_node: NodeIndex,
+ ) {
+ match &tree.graph[content_node] {
+ bibtex::Node::QuotedContent(content) => {
+ for child in tree.children(content_node) {
+ Self::analyze_content(&mut errors, tree, child);
}
if content.right.is_none() {
@@ -123,9 +135,9 @@ impl BibtexError {
));
}
}
- BibtexContent::BracedContent(content) => {
- for child in &content.children {
- Self::analyze_content(&mut errors, &child);
+ bibtex::Node::BracedContent(content) => {
+ for child in tree.children(content_node) {
+ Self::analyze_content(&mut errors, tree, child);
}
if content.right.is_none() {
@@ -135,11 +147,12 @@ impl BibtexError {
));
}
}
- BibtexContent::Concat(concat) => {
- Self::analyze_content(&mut errors, &concat.left);
- match &concat.right {
+ bibtex::Node::Concat(concat) => {
+ let mut children = tree.children(content_node);
+ Self::analyze_content(&mut errors, tree, children.next().unwrap());
+ match children.next() {
Some(right) => {
- Self::analyze_content(&mut errors, right);
+ Self::analyze_content(&mut errors, tree, right);
}
None => {
errors.push(BibtexError::new(
@@ -149,7 +162,14 @@ impl BibtexError {
}
}
}
- BibtexContent::Word(_) | BibtexContent::Command(_) => {}
+ bibtex::Node::Root(_)
+ | bibtex::Node::Comment(_)
+ | bibtex::Node::Preamble(_)
+ | bibtex::Node::String(_)
+ | bibtex::Node::Entry(_)
+ | bibtex::Node::Field(_)
+ | bibtex::Node::Word(_)
+ | bibtex::Node::Command(_) => {}
}
}
}
@@ -163,6 +183,7 @@ impl Into<Diagnostic> for BibtexError {
severity: Some(DiagnosticSeverity::Error),
code: None,
related_information: None,
+ tags: None,
}
}
}
@@ -171,8 +192,8 @@ impl Into<Diagnostic> for BibtexError {
pub struct BibtexDiagnosticsProvider;
impl BibtexDiagnosticsProvider {
- pub fn get(self, document: &Document) -> Vec<Diagnostic> {
- if let SyntaxTree::Bibtex(tree) = &document.tree {
+ pub fn get(self, doc: &Document) -> Vec<Diagnostic> {
+ if let DocumentContent::Bibtex(tree) = &doc.content {
BibtexError::analyze(&tree)
.into_iter()
.map(Into::into)
@@ -188,8 +209,8 @@ mod tests {
use super::*;
#[test]
- fn test_begin_brace() {
- let errors = BibtexError::analyze(&"@article".into());
+ fn begin_brace() {
+ let errors = BibtexError::analyze(&bibtex::open("@article"));
assert_eq!(
errors,
vec![BibtexError::new(
@@ -200,8 +221,8 @@ mod tests {
}
#[test]
- fn test_entry_key() {
- let errors = BibtexError::analyze(&"@article{".into());
+ fn entry_key() {
+ let errors = BibtexError::analyze(&bibtex::open("@article{"));
assert_eq!(
errors,
vec![BibtexError::new(
@@ -212,8 +233,8 @@ mod tests {
}
#[test]
- fn test_entry_comma() {
- let errors = BibtexError::analyze(&"@article{foo".into());
+ fn entry_comma() {
+ let errors = BibtexError::analyze(&bibtex::open("@article{foo"));
assert_eq!(
errors,
vec![BibtexError::new(
@@ -224,8 +245,8 @@ mod tests {
}
#[test]
- fn test_entry_end_brace() {
- let errors = BibtexError::analyze(&"@article{foo,".into());
+ fn entry_end_brace() {
+ let errors = BibtexError::analyze(&bibtex::open("@article{foo,"));
assert_eq!(
errors,
vec![BibtexError::new(
@@ -236,8 +257,8 @@ mod tests {
}
#[test]
- fn test_field_equals() {
- let errors = BibtexError::analyze(&"@article{foo, bar}".into());
+ fn field_equals() {
+ let errors = BibtexError::analyze(&bibtex::open("@article{foo, bar}"));
assert_eq!(
errors,
vec![BibtexError::new(
@@ -248,8 +269,8 @@ mod tests {
}
#[test]
- fn test_field_content() {
- let errors = BibtexError::analyze(&"@article{foo,\nbar = }".into());
+ fn field_content() {
+ let errors = BibtexError::analyze(&bibtex::open("@article{foo,\nbar = }"));
assert_eq!(
errors,
vec![BibtexError::new(
@@ -260,9 +281,9 @@ mod tests {
}
#[test]
- fn test_field_comma() {
+ fn field_comma() {
let text = "@article{foo,\nfoo = bar\nbaz = qux}";
- let errors = BibtexError::analyze(&text.into());
+ let errors = BibtexError::analyze(&bibtex::open(text));
assert_eq!(
errors,
vec![BibtexError::new(
@@ -273,9 +294,9 @@ mod tests {
}
#[test]
- fn test_content_quote() {
+ fn content_quote() {
let text = "@article{foo, bar =\n\"}";
- let errors = BibtexError::analyze(&text.into());
+ let errors = BibtexError::analyze(&bibtex::open(text));
assert_eq!(
errors,
vec![BibtexError::new(
@@ -286,9 +307,9 @@ mod tests {
}
#[test]
- fn test_content_brace() {
+ fn content_brace() {
let text = "@article{foo, bar =\n{";
- let errors = BibtexError::analyze(&text.into());
+ let errors = BibtexError::analyze(&bibtex::open(text));
assert_eq!(
errors,
vec![
@@ -299,9 +320,9 @@ mod tests {
}
#[test]
- fn test_content_concat() {
+ fn content_concat() {
let text = "@article{foo, bar = baz \n# }";
- let errors = BibtexError::analyze(&text.into());
+ let errors = BibtexError::analyze(&bibtex::open(text));
assert_eq!(
errors,
vec![BibtexError::new(
@@ -312,9 +333,9 @@ mod tests {
}
#[test]
- fn test_entry_valid() {
+ fn entry_valid() {
let text = "@article{foo, bar = \"baz {qux}\" # quux}";
- let errors = BibtexError::analyze(&text.into());
+ let errors = BibtexError::analyze(&bibtex::open(text));
assert_eq!(errors, Vec::new());
}
}