diff options
Diffstat (limited to 'support/texlab/src/diagnostics/bibtex.rs')
-rw-r--r-- | support/texlab/src/diagnostics/bibtex.rs | 197 |
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()); } } |