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

Side by Side Diff: tools/unused-grit-header.py

Issue 504503002: Add a tool to look for source files that have unneeded grit header includes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: look through else tags too Created 6 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | 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 2014 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 """A tool to scan source files for unneeded grit includes."""
7
8 import os
9 import sys
10 import xml.etree.ElementTree
11
12 IF_ELSE_TAGS = ('if', 'else')
13
14
15 def Usage(prog_name):
16 print prog_name, 'GRD_FILE DIRS_TO_SCAN'
17
18
19 def GetResourcesForNode(node, parent_file, resource_tag):
20 """Recursively iterate through a node and extract resource names.
21
22 Args:
23 node: The node to iterate through.
24 parent_file: The file that contains node.
25 resource_tag: The resource tag to extract names from.
26
27 Returns:
28 A list of resource names.
29 """
30 resources = []
31 for child in node.getchildren():
32 if child.tag == resource_tag:
33 resources.append(child.attrib['name'])
34 elif child.tag in IF_ELSE_TAGS:
35 resources.extend(GetResourcesForNode(child, parent_file, resource_tag))
36 elif child.tag == 'part':
37 parent_dir = os.path.dirname(parent_file)
38 part_file = os.path.join(parent_dir, child.attrib['file'])
39 part_tree = xml.etree.ElementTree.parse(part_file)
40 part_root = part_tree.getroot()
41 assert part_root.tag == 'grit-part'
42 resources.extend(GetResourcesForNode(part_root, part_file, resource_tag))
43 else:
44 raise Exception('unknown tag:', child.tag)
45 return resources
46
47
48 def FindNodeWithTag(node, tag):
49 """Look through a node's children for a child node with a given tag.
50
51 Args:
52 root: The node to examine.
53 tag: The tag on a child node to look for.
54
55 Returns:
56 A child node with the given tag, or None.
57 """
58 result = None
59 for n in node.getchildren():
60 if n.tag == tag:
61 assert not result
62 result = n
63 return result
64
65
66 def GetResourcesForGrdFile(tree, grd_file):
67 """Find all the message and include resources from a given grit file.
68
69 Args:
70 tree: The XML tree.
71 grd_file: The file that contains the XML tree.
72
73 Returns:
74 A list of resource names.
75 """
76 root = tree.getroot()
77 assert root.tag == 'grit'
78 release_node = FindNodeWithTag(root, 'release')
79 assert release_node != None
80
81 messages_node = FindNodeWithTag(root, 'messages')
82 messages = set()
83 if messages_node != None:
84 messages = set(GetResourcesForNode(messages_node, grd_file, 'message'))
85
86 includes_node = FindNodeWithTag(root, 'includes')
87 includes = set()
88 if includes_node != None:
89 includes = set(GetResourcesForNode(includes_node, grd_file, 'include'))
90 return messages.union(includes)
91
92
93 def GetOutputFileForNode(node):
94 """Find the output file starting from a given node.
95
96 Args:
97 node: The root node to scan from.
98
99 Returns:
100 A grit header file name.
101 """
102 output_file = None
103 for child in node.getchildren():
104 if child.tag == 'output':
105 if child.attrib['type'] == 'rc_header':
106 assert output_file is None
107 output_file = child.attrib['filename']
108 elif child.tag in IF_ELSE_TAGS:
109 child_output_file = GetOutputFileForNode(child)
110 if not child_output_file:
111 continue
112 assert output_file is None
113 output_file = child_output_file
114 else:
115 raise Exception('unknown tag:', child.tag)
116 return output_file
117
118
119 def GetOutputHeaderFile(tree):
120 """Find the output file for a given tree.
121
122 Args:
123 tree: The tree to scan.
124
125 Returns:
126 A grit header file name.
127 """
128 root = tree.getroot()
129 assert root.tag == 'grit'
130 output_node = FindNodeWithTag(root, 'outputs')
131 assert output_node != None
132 return GetOutputFileForNode(output_node)
133
134
135 def ShouldScanFile(filename):
136 """Return if the filename has one of the extensions below."""
137 extensions = ['.cc', '.cpp', '.h', '.mm']
138 file_extension = os.path.splitext(filename)[1]
139 return file_extension in extensions
140
141
142 def NeedsGritInclude(grit_header, resources, filename):
143 """Return whether a file needs a given grit header or not.
144
145 Args:
146 grit_header: The grit header file name.
147 resources: The list of resource names in grit_header.
148 filename: The file to scan.
149
150 Returns:
151 True if the file should include the grit header.
152 """
153 with open(filename, 'rb') as f:
154 grit_header_line = grit_header + '"\n'
155 has_grit_header = False
156 while True:
157 line = f.readline()
158 if not line:
159 break
160 if line.endswith(grit_header_line):
161 has_grit_header = True
162 break
163
164 if not has_grit_header:
165 return True
166 rest_of_the_file = f.read()
167 return any(resource in rest_of_the_file for resource in resources)
168
169
170 def main(argv):
171 if len(argv) < 3:
172 Usage(argv[0])
173 return 1
174 grd_file = argv[1]
175 dirs_to_scan = argv[2:]
176 for f in dirs_to_scan:
177 if not os.path.exists(f):
178 print 'Error: %s does not exist' % f
179 return 1
180
181 tree = xml.etree.ElementTree.parse(grd_file)
182 grit_header = GetOutputHeaderFile(tree)
183 resources = GetResourcesForGrdFile(tree, grd_file)
184
185 files_with_unneeded_grit_includes = []
186 for dir_to_scan in dirs_to_scan:
187 for root, dirs, files in os.walk(dir_to_scan):
188 if '.git' in dirs:
189 dirs.remove('.git')
190 full_paths = [os.path.join(root, f) for f in files if ShouldScanFile(f)]
191 files_with_unneeded_grit_includes.extend(
192 [f for f in full_paths
193 if not NeedsGritInclude(grit_header, resources, f)])
194 if files_with_unneeded_grit_includes:
195 print '\n'.join(files_with_unneeded_grit_includes)
196 return 2
197 return 0
198
199
200 if __name__ == '__main__':
201 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698