File: Synopsis/Formatters/HTML/Views/InheritanceGraph.py 1
2
3
4
5
6
7
8
9from Synopsis.Processor import *
10from Synopsis import IR, ASG
11from Synopsis.Formatters.HTML.View import View
12from Synopsis.Formatters.HTML.Tags import *
13
14import os
15
16class DeclarationFinder(ASG.Visitor):
17 def __init__(self, types, verbose):
18
19 self.types = types
20 self.verbose = verbose
21
22 def __call__(self, name):
23 try:
24 typeobj = self.types[name]
25 except KeyError:
26
27 if self.verbose: print "Warning: %s not found in type dict."%(name,)
28 return None
29 self.__decl = None
30 typeobj.accept(self)
31
32
33 return self.__decl
34
35 def visit_buitin_type_id(self, type): return
36 def visit_unknown_type_id(self, type): return
37 def visit_declared_type_id(self, type): self.__decl = type.declaration
38 def visit_modifier_type_id(self, type): type.alias.accept(self)
39 def visit_array_type_id(self, type): type.alias.accept(self)
40 def visit_template_id(self, type): self.__decl = type.declaration
41 def visit_parametrized_type_id(self, type): type.template.accept(self)
42 def visit_function_type_id(self, type): return
43
44def find_common_name(graph):
45 common_name = list(graph[0])
46 for decl_name in graph[1:]:
47 if len(common_name) > len(decl_name):
48 common_name = common_name[:len(decl_name)]
49 for i in range(min(len(decl_name), len(common_name))):
50 if decl_name[i] != common_name[i]:
51 common_name = common_name[:i]
52 break
53 return '::'.join(common_name)
54
55class InheritanceGraph(View):
56
57 min_size = Parameter(2, 'minimum number of nodes for a graph to be displayed')
58 min_group_size = Parameter(5, 'how many nodes to put into a group')
59 direction = Parameter('vertical', 'layout of the graph')
60
61 def register(self, frame):
62
63 super(InheritanceGraph, self).register(frame)
64 self.decl_finder = DeclarationFinder(self.processor.ir.asg.types,
65 self.processor.verbose)
66
67 def filename(self):
68
69 if self.main:
70 return self.directory_layout.index()
71 else:
72 return self.directory_layout.special('InheritanceGraph')
73
74 def title(self):
75
76 return 'Inheritance Graph'
77
78 def root(self):
79
80 return self.filename(), self.title()
81
82 def consolidate(self, graphs):
83 """Consolidates small graphs into larger ones"""
84
85
86 common = {}
87 for graph in graphs:
88 len_graph = len(graph)
89 if len_graph < self.min_size:
90
91 continue
92 common.setdefault(find_common_name(graph), []).append(graph)
93
94 for name, graphs in common.items():
95 conned = []
96 pending = []
97 for graph in graphs:
98
99 for pend in pending:
100 if len_graph + len(pend) <= self.min_group_size:
101 pend.extend(graph)
102 graph = None
103 if len(pend) == self.min_group_size:
104 conned.append(pend)
105 pending.remove(pend)
106 break
107 if graph:
108 if len_graph >= self.min_group_size:
109
110 conned.append(graph)
111 else:
112
113 pending.append(graph)
114 graphs[:] = conned + pending
115 return common
116
117 def process(self):
118 """Creates a file with the inheritance graph"""
119
120 filename = self.filename()
121 self.start_file()
122 self.write_navigation_bar()
123 self.write(element('h1', "Inheritance Graph"))
124
125 from Synopsis.Formatters import Dot
126
127 toc_file = filename + "-dot.toc"
128 self.processor.toc.store(toc_file)
129 graphs = self.processor.class_tree.graphs()
130 count = 0
131
132 lensorter = lambda a, b: cmp(len(b),len(a))
133 common_graphs = self.consolidate(graphs)
134 names = common_graphs.keys()
135 names.sort()
136 for name in names:
137 graphs = common_graphs[name]
138 graphs.sort(lensorter)
139 if name:
140 self.write('<div class="inheritance-group">')
141 type_str = ''
142 types = self.processor.ir.asg.types
143 type = types.get(name, None)
144 if isinstance(type, ASG.DeclaredTypeId):
145 type_str = type.declaration.type + ' '
146 self.write('Graphs in '+type_str+name+':<br/>')
147 for graph in graphs:
148 if self.processor.verbose: print "Creating graph #%s - %s classes"%(count,len(graph))
149
150 declarations = map(self.decl_finder, graph)
151 declarations = filter(lambda x: x is not None, declarations)
152
153 output = os.path.join(self.processor.output,
154 os.path.splitext(self.filename())[0]) + '-%s'%count
155 dot = Dot.Formatter(bgcolor=self.processor.graph_color)
156 ir = IR.IR(files={}, asg=ASG.ASG(declarations, self.processor.ir.asg.types))
157 try:
158 dot.process(ir,
159 output=output,
160 format='html',
161 toc_in=[toc_file],
162 base_url=self.filename(),
163 title='Synopsis %s'%count,
164 layout=self.direction)
165 dot_file = open(output + '.html', 'r')
166 self.write(dot_file.read())
167 dot_file.close()
168 os.remove(output + ".html")
169 except InvalidCommand, e:
170 print 'Warning : %s'%str(e)
171 count = count + 1
172 if name:
173 self.write('</div>')
174
175 os.remove(toc_file)
176
177 self.end_file()
178
Generated on Thu Apr 16 16:27:14 2009 by
synopsis (version devel)