use super::elements::ContentItem;
use super::elements::VerbatimLine;
use super::range::{Position, Range};
pub trait Visitor {
fn visit_session(&mut self, _session: &super::Session) {}
fn leave_session(&mut self, _session: &super::Session) {}
fn visit_definition(&mut self, _definition: &super::Definition) {}
fn leave_definition(&mut self, _definition: &super::Definition) {}
fn visit_list(&mut self, _list: &super::List) {}
fn leave_list(&mut self, _list: &super::List) {}
fn visit_list_item(&mut self, _list_item: &super::ListItem) {}
fn leave_list_item(&mut self, _list_item: &super::ListItem) {}
fn visit_paragraph(&mut self, _paragraph: &super::Paragraph) {}
fn leave_paragraph(&mut self, _paragraph: &super::Paragraph) {}
fn visit_text_line(&mut self, _text_line: &super::elements::paragraph::TextLine) {}
fn leave_text_line(&mut self, _text_line: &super::elements::paragraph::TextLine) {}
fn visit_verbatim_block(&mut self, _verbatim_block: &super::Verbatim) {}
fn leave_verbatim_block(&mut self, _verbatim_block: &super::Verbatim) {}
fn visit_table(&mut self, _table: &super::Table) {}
fn leave_table(&mut self, _table: &super::Table) {}
fn visit_verbatim_group(&mut self, _group: &super::elements::verbatim::VerbatimGroupItemRef) {}
fn leave_verbatim_group(&mut self, _group: &super::elements::verbatim::VerbatimGroupItemRef) {}
fn visit_verbatim_line(&mut self, _verbatim_line: &VerbatimLine) {}
fn leave_verbatim_line(&mut self, _verbatim_line: &VerbatimLine) {}
fn visit_annotation(&mut self, _annotation: &super::Annotation) {}
fn leave_annotation(&mut self, _annotation: &super::Annotation) {}
fn visit_blank_line_group(
&mut self,
_blank_line_group: &super::elements::blank_line_group::BlankLineGroup,
) {
}
fn leave_blank_line_group(
&mut self,
_blank_line_group: &super::elements::blank_line_group::BlankLineGroup,
) {
}
}
pub fn visit_children(visitor: &mut dyn Visitor, items: &[ContentItem]) {
for item in items {
item.accept(visitor);
}
}
pub trait AstNode {
fn node_type(&self) -> &'static str;
fn display_label(&self) -> String;
fn range(&self) -> &Range;
fn start_position(&self) -> Position {
self.range().start
}
fn accept(&self, visitor: &mut dyn Visitor);
}
pub trait Container: AstNode {
fn label(&self) -> &str;
fn children(&self) -> &[ContentItem];
fn children_mut(&mut self) -> &mut Vec<ContentItem>;
}
pub trait VisualStructure: AstNode {
fn is_source_line_node(&self) -> bool {
false
}
fn has_visual_header(&self) -> bool {
false
}
fn collapses_with_children(&self) -> bool {
false
}
}
#[cfg(test)]
mod tests {
use super::super::elements::{Paragraph, Session};
use super::*;
#[test]
fn test_visitor_traversal() {
let para = Paragraph::from_line("Hello, World!".to_string());
let session = Session::with_title("Test Session".to_string());
struct CountingVisitor {
session_count: usize,
paragraph_count: usize,
text_line_count: usize,
}
impl Visitor for CountingVisitor {
fn visit_session(&mut self, _: &super::super::Session) {
self.session_count += 1;
}
fn visit_paragraph(&mut self, _: &super::super::Paragraph) {
self.paragraph_count += 1;
}
fn visit_text_line(&mut self, _: &super::super::elements::paragraph::TextLine) {
self.text_line_count += 1;
}
}
let mut visitor = CountingVisitor {
session_count: 0,
paragraph_count: 0,
text_line_count: 0,
};
para.accept(&mut visitor);
assert_eq!(visitor.paragraph_count, 1);
assert_eq!(visitor.text_line_count, 1); assert_eq!(visitor.session_count, 0);
visitor.session_count = 0;
visitor.paragraph_count = 0;
visitor.text_line_count = 0;
session.accept(&mut visitor);
assert_eq!(visitor.session_count, 1);
assert_eq!(visitor.paragraph_count, 0); }
}