1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
pub mod segment;
pub mod item;
use self::segment::Segment;
use self::item::{Item, ItemState};
use self::item::relation::Relation;
use std::{slice, iter};
use std::borrow::Cow;
use std::ops::BitOr;
use ::syntex_syntax::{ptr, ast};
use ::dot::{Nodes, Edges, Arrow, Style, GraphWalk, Labeller, LabelText, Id};
use ::itertools::Itertools;
#[derive(Debug, Clone)]
pub struct ListItem <'a> {
parse: Item<'a>,
}
impl <'a> From<Item<'a>> for ListItem <'a> {
fn from(parse: Item<'a>) -> ListItem <'a> {
ListItem {
parse: parse,
}
}
}
impl <'a> From<iter::Peekable<slice::Iter<'a, ptr::P<ast::Item>>>> for ListItem <'a> {
fn from(list: iter::Peekable<slice::Iter<'a, ptr::P<ast::Item>>>) -> ListItem <'a> {
ListItem::from(Item::from(list))
}
}
impl <'a>Iterator for ListItem<'a> {
type Item = ItemState<'a>;
fn next(&mut self) -> Option<ItemState<'a>> {
self.parse.by_ref().skip_while(|state| state.is_none()).next()
}
}
impl<'a> Labeller<'a, ItemState<'a>, Segment<'a>> for ListItem<'a> {
fn graph_id(&'a self) -> Id<'a> {
Id::new("ml").unwrap()
}
fn node_id(&'a self, state: &ItemState<'a>) -> Id<'a> {
match state.as_name() {
Some(name) => Id::new(format!("nd{}", name)).unwrap(),
_ => unreachable!(),
}
}
fn node_shape(&'a self, _node: &ItemState<'a>) -> Option<LabelText<'a>> {
Some(LabelText::LabelStr(Cow::from(format!("record"))))
}
fn node_label(&'a self, state: &ItemState<'a>) -> LabelText<'a> {
LabelText::LabelStr(format!("{}", state).into())
}
fn edge_end_arrow(&'a self, ref seg: &Segment<'a>) -> Arrow {
match (
seg.left.as_arrow(&seg.right),
seg.right.as_arrow(&seg.left)
) {
(Relation::Association, Relation::Association) => Arrow::none(),
(edge_left, _) => Arrow::from_arrow(edge_left.as_style()),
}
}
fn edge_style(&'a self, ref seg: &Segment<'a>) -> Style {
if seg.left.is_realization(&seg.right).bitor(seg.left.is_dependency(&seg.right)) {
Style::Dashed
} else {
Style::None
}
}
}
impl<'a> GraphWalk<'a, ItemState<'a>, Segment<'a>> for ListItem<'a> {
fn nodes(&'a self) -> Nodes<'a, ItemState<'a>> {
Cow::Owned(self.clone().collect::<Vec<ItemState<'a>>>())
}
fn edges(&'a self) -> Edges<'a, Segment<'a>> {
let items = self.clone().collect::<Vec<ItemState<'a>>>();
Cow::Owned(items.iter()
.map(|item| items.iter()
.filter(|rhs| item.ne(rhs))
.filter(|rhs| item.is_relation(rhs))
.map(|rhs| Segment::from((item.clone(), rhs.clone())))
.collect::<Vec<Segment<'a>>>())
.collect::<Vec<Vec<Segment<'a>>>>()
.concat()
.into_iter()
.unique()
.collect::<Vec<Segment<'a>>>())
}
fn source(&self, seg: &Segment<'a>) -> ItemState<'a> { seg.left.clone() }
fn target(&self, seg: &Segment<'a>) -> ItemState<'a> { seg.right.clone() }
}