Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(199)

Side by Side Diff: tools/ui/dialog_audit.py

Issue 2675653002: Chrome dialog audit
Patch Set: Fix some bugs, find more dialogs Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/ui/dialog_audit.cache ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2017 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Systematically search the Chrome codebase for dialog invocations.
8 """
9
10 import subprocess
11 import sys
12 import re
13 import mmap
14 import os
15
16 def InheritsRe(klass):
17 return r'public.*[: ]{}[, ]'.format(klass)
18
19 def ChildRe(klass):
20 return r'class ([\w :]+)\s*:[^{]*' + klass + r'[^{]*[{]'
21
22 def FindFilesInheritingFromClass(klass):
23 process = subprocess.Popen(['git', 'grep', '-l', InheritsRe(klass), '--',
24 '*.h', '*.mm', '*.cc'],
25 stdout=subprocess.PIPE)
26 return process.communicate()[0].splitlines();
27
28 def ToLine(lines, offset):
29 line = 0
30 pos = 0
31 while pos < offset[0]:
32 pos += len(lines[line])
33 line += 1
34 return line
35
36 def FindClassesInFilesInheritingFromClass(files, klass):
37 children = []
38 child_re = re.compile(ChildRe(klass), re.MULTILINE)
39 for filename in files:
40 with open(filename, 'r+') as f:
41 lines = f.readlines()
42 text = " ".join([l[:-1] for l in lines])
43 found = child_re.finditer(text)
44 before = len(children)
45 for child in found:
46 child_klass = child.group(1).split()[-1]
47 children.append((child_klass, filename, ToLine(lines, child.span()),
48 re.sub(' +', ' ', child.group(0)), klass))
49 if len(children) == before:
50 sys.stderr.write(
51 "ERROR: Couldn't find a child of {} in {}\n".format(klass,
52 filename))
53 return children
54
55 def HuntForDecendants(result, parent, klasses, depth=''):
56 for klass in klasses:
57 result.append(klass)
58 sys.stderr.write('{}{}'.format(depth, klass[0]))
59 files = FindFilesInheritingFromClass(klass[0])
60 children = FindClassesInFilesInheritingFromClass(files, klass[0]);
61 sys.stderr.write( ' has {} children\n'.format(len(children)))
62 HuntForDecendants(result, klass, children, depth + ' ')
63
64 def DefaultHunt():
65 seed = 'DialogDelegate'
66 #seed = 'DialogDelegateView'
67 #seed = 'LocationBarBubbleDelegateView'
68 result = []
69 HuntForDecendants(result, 'Seed', [(seed, '', 0, '', 'Seed')])
70 return result
71
72 def ToUrl(filename, klass, line):
73 return 'https://cs.chromium.org/chromium/src/{}?q={}&l={}'.format(
74 filename, klass, line)
75
76 def Process(data):
77 cells = eval("".join(open('tools/ui/cells.cache').readlines()))
78 cellmap = {}
79 for row in range(len(cells)):
80 if cells[row][0] == '' and cells[row][1] != '':
81 print "Unmatched: {} {}".format(row, cells[row][1])
82 else:
83 cellmap[cells[row][0]] = row
84 ignored = []
85 parents = {}
86 missing = {}
87 for (klass, filename, line, match, parent) in data:
88 if klass in cellmap:
89 row = cells[cellmap[klass]]
90 cells[cellmap[klass]] = (row[1], klass, )
91 print 'Matched: {}'.format(klass)
92 continue
93
94 # Ignore test files
95 if filename.find('test.') > 0:
96 ignored.append((klass, filename))
97 continue
98
99 # Track classes that have children and ignore them.
100 parents.setdefault(parent, [('f', 'c', 0), []])[1].append(klass)
101 if parent in missing:
102 parents[parent][0] = missing[parent]
103 del missing[parent]
104 continue
105
106 missing[klass] = (filename, klass, line)
107
108 sys.stderr.write('\nIgnored (Tests):')
109 for ignore in ignored:
110 sys.stderr.write(' {}({})'.format(ignore[0], os.path.basename(ignore[1])))
111 sys.stderr.write('\n')
112
113 sys.stderr.write('\nIgnored (Parents):')
114 for pk in parents:
115 parent = parents[pk]
116 filename, klass, line = parent[0]
117 children = " ".join(parent[1])
118 basename = os.path.basename(filename)
119 sys.stderr.write('\n\t {}({}): {}'.format(pk, basename, children))
120 sys.stderr.write('\n')
121
122 # Sort by filename.
123 missing_list = missing.values()
124 missing_list.sort();
125
126 for m in missing_list:
127 (filename, klass, line) = m
128 print 'Missing: {:40} from {}'.format(klass, ToUrl(filename, klass, line))
129
130 def main():
131 try:
132 data = eval(open('tools/ui/dialog_audit.cache').readline())
133 Process(data)
134 except IOError as e:
135 data = DefaultHunt()
136 print data
137 sys.stderr.write("""
138 Try `tools/ui/dialog_audit.py > tools/ui/dialog_audit.cache.new && \
139 mv tools/ui/dialog_audit.cache.new tools/ui/dialog_audit.cache`
140 """)
141
142 if __name__ == '__main__':
143 sys.exit(main())
OLDNEW
« no previous file with comments | « tools/ui/dialog_audit.cache ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698