comparison tests/analyzers/dep_analyzer.py @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children 81641655bc38
comparison
equal deleted inserted replaced
-1:000000000000 0:4a0efb7baf70
1 #!/usr/bin/python
2 import sys, re, os
3
4 try:
5 from os.shutil import copyfile
6
7 except ImportError:
8 def copyfile(src,dest):
9 srcf = open(src)
10 destf = open(dest,"w")
11 destf.write( srcf.read() )
12 destf.close()
13 srcf.close()
14
15
16 if '.' not in sys.path:
17 sys.path.append('.')
18 from utils.util_scripts.path import path
19 from _allowed_dependencies import ALLOWED_MODULE_DEPS
20
21 _S = os.path.sep
22 ROOTDIRNAME = 'engine%score' % _S
23 FILE_DEPS_OUT = 'doc%sdependencies%sfiledeps' % (_S, _S)
24 DIR_DEPS_OUT = 'doc%sdependencies%sdirdeps' % (_S, _S)
25 MODULE_DEPS_OUT = 'doc%sdependencies%smoduledeps' % (_S, _S)
26 SKIPPED_PROVIDERS = []
27 SKIPPED_USERS = []
28
29 reInc = re.compile('#include "(.*?)"')
30
31 def add_to_dictset(d, key, val):
32 try:
33 d[key].add(val)
34 except KeyError:
35 d[key] = set([val])
36
37 # return error string in case of possible error
38 unknown_modules = []
39 def check_dep_error(allowed_deps, user, provider):
40 global unknown_modules
41
42 msg = ''
43 try:
44 if not provider in allowed_deps[user]:
45 msg = 'Illegal dependency between %s -> %s, % s can use only:\n' % (user, provider, user)
46 for d in allowed_deps[user]:
47 msg += ' %s\n' % d
48 except KeyError:
49 print unknown_modules
50 if user not in unknown_modules:
51 msg = 'Unknown module %s found in static check\n' % user
52 msg += ' please adjust dep_analyzer script to match new structure'
53 unknown_modules.append(user)
54 return msg
55
56 def get_file2inc(sources):
57 file2inc = {}
58 for f in sources:
59 inComment = False
60 for line in open(f):
61 if not inComment and line.find('/*') != -1:
62 inComment = True
63 continue
64 elif inComment:
65 if line.find('*/') != -1:
66 inComment = False
67 continue
68 elif line.strip().startswith('//'):
69 continue
70 m = reInc.search(line)
71 if m:
72 add_to_dictset(file2inc, f, m.group(1).replace( '/', _S ))
73
74 return file2inc
75
76 def fill_dep_infos(file2inc, fileUser2provider, dirUser2provider, moduleUser2provider, unknownIncludes, dirclusters):
77 for f, incs in file2inc.items():
78 #if f.find('engine.cpp') != -1:
79 # import pdb; pdb.set_trace()
80 skip = False
81 for user in SKIPPED_USERS:
82 if f.find(user) != -1:
83 skip = True
84 break
85 if skip:
86 continue
87
88 for i in incs:
89 user = str(f.dirname()).replace(ROOTDIRNAME + _S, '')
90 header = path((f.dirname() / path(i)).abspath().split(ROOTDIRNAME + _S)[1])
91 if not header.isfile():
92 header = path(ROOTDIRNAME) + _S + path(i)
93 if not header.isfile():
94 add_to_dictset(unknownIncludes, str(f), str(i))
95 continue
96 provider = str(header.dirname()).replace(ROOTDIRNAME + _S, '')
97 skip = False
98 for skipped in SKIPPED_PROVIDERS:
99 if header.find(skipped) != -1:
100 skip = True
101 break
102 if skip:
103 continue
104 add_to_dictset(dirUser2provider, user, provider)
105 usermodule = user.split(_S)[0]
106 providermodule = provider.split(_S)[0]
107 userfile = user.split(_S)[-1].split('.')[0]
108 providerfile = provider.split(_S)[-1].split('.')[0]
109
110 add_to_dictset(dirclusters, usermodule, user)
111 add_to_dictset(dirclusters, providermodule, provider)
112 add_to_dictset(moduleUser2provider, usermodule, providermodule)
113 add_to_dictset(fileUser2provider, userfile, providerfile)
114
115 def write_dot_file(fname, contents):
116 lines = []
117 a = lines.append
118 a('digraph "source tree" {')
119 a(' overlap=scale;')
120 a(' size="8,10";')
121 a(' ratio="fill";')
122 a(' fontsize="16";')
123 a(' fontname="Helvetica";')
124 a(' clusterrank="local";')
125 if type(contents) in (list, tuple):
126 lines += contents
127 else:
128 lines.append(contents)
129 a('}')
130 open(fname, 'w').write('\n'.join(lines))
131
132 def get_cluster_str(ind, elements, label):
133 lines = []
134 a = lines.append
135 a('subgraph cluster_%d {' % ind)
136 a(' style=filled;')
137 a(' color=lightgrey;')
138 a(' node [style=filled,color=white];')
139 a(' %s' % '; '.join('"%s"' % d for d in elements))
140 a(' label = "%s";' % label)
141 a('}')
142 return '\n'.join(lines)
143
144 def run_dot(basename,type):
145 dotname = basename + ".dot"
146 outname = basename + "." + type
147
148 dotchanged = True
149
150 try:
151 olddot = open(dotname + "~").read()
152 dotchanged = olddot != open(dotname).read()
153 dotchanged = dotchanged or not os.path.exists(outname)
154 except IOError: pass
155 if not dotchanged:
156 return
157 print "Generating: ",outname
158 cmd = 'dot -T%(type)s %(dotname)s > %(outname)s' % locals()
159 os.system(cmd)
160 copyfile(dotname,dotname + "~")
161
162 def analyze(write_postscript=False):
163 root = path(ROOTDIRNAME)
164 headers = list(root.walkfiles('*.h'))
165 sources = headers + list(root.walkfiles('*.cpp'))
166 file2inc = get_file2inc(sources)
167
168 moduleUser2provider = {}
169 dirUser2provider = {}
170 fileUser2provider = {}
171 unknownIncludes = {}
172 dirclusters = {}
173 fill_dep_infos(file2inc, fileUser2provider, dirUser2provider, moduleUser2provider, unknownIncludes, dirclusters)
174
175 # write module dep graph
176 out = []
177 illegalModuleDeps = []
178 for user, providers in sorted(moduleUser2provider.items()):
179 for provider in sorted(providers):
180 if user != provider:
181 out.append(' "' + user + '" -> "' + provider + '"')
182 msg = check_dep_error(ALLOWED_MODULE_DEPS, user, provider)
183 if msg:
184 illegalModuleDeps.append(msg)
185 write_dot_file('%s.dot' % MODULE_DEPS_OUT, out)
186 if write_postscript:
187 run_dot(MODULE_DEPS_OUT, "ps")
188 run_dot(MODULE_DEPS_OUT,"png")
189
190 # write dir dep graph
191 out = []
192 for cluster, subdirs in sorted(dirclusters.items()):
193 out.append(get_cluster_str(len(out), sorted(subdirs), cluster))
194 for user, providers in sorted(dirUser2provider.items()):
195 for provider in sorted(providers):
196 if user != provider:
197 out.append(' "' + user + '" -> "' + provider + '"')
198 write_dot_file('%s.dot' % DIR_DEPS_OUT, out)
199 if write_postscript:
200 run_dot(DIR_DEPS_OUT, "ps")
201
202 # write file dep graph
203 out = []
204 for user, providers in sorted(file2inc.items()):
205 for provider in sorted(providers):
206 if user != provider:
207 out.append(' "' + user + '" -> "' + provider + '"')
208 write_dot_file('%s.dot' % FILE_DEPS_OUT, out)
209 # os.system('dot -Tps %s.dot > %s.ps' % (MODULE_DEPS_OUT, MODULE_DEPS_OUT))
210
211 # write raw dep info
212 #out = []
213 #for f, file2inc
214 result = '\n'.join(illegalModuleDeps)
215 if result:
216 print result
217 else:
218 print "no dependency analyzer errors found"
219 return result
220
221
222 _ANALYZE_FN_ = analyze
223
224 if __name__ == '__main__':
225 analyze(True)