OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """A tool to scan source files for unneeded grit includes. | 6 """A tool to scan source files for unneeded grit includes. |
7 | 7 |
8 Example: | 8 Example: |
9 cd /work/chrome/src | 9 cd /work/chrome/src |
10 tools/resources/list_unused_grit_header.py ui/strings/ui_strings.grd chrome ui | 10 tools/resources/list_unused_grit_header.py ui/strings/ui_strings.grd chrome ui |
11 """ | 11 """ |
12 | 12 |
13 import os | 13 import os |
14 import sys | 14 import sys |
15 import xml.etree.ElementTree | 15 import xml.etree.ElementTree |
16 | 16 |
17 from find_unused_resources import GetBaseResourceId | 17 from find_unused_resources import GetBaseResourceId |
18 | 18 |
19 IF_ELSE_TAGS = ('if', 'else') | 19 IF_ELSE_THEN_TAGS = ('if', 'else', 'then') |
20 | 20 |
21 | 21 |
22 def Usage(prog_name): | 22 def Usage(prog_name): |
23 print prog_name, 'GRD_FILE PATHS_TO_SCAN' | 23 print prog_name, 'GRD_FILE PATHS_TO_SCAN' |
24 | 24 |
25 | 25 |
26 def FilterResourceIds(resource_id): | 26 def FilterResourceIds(resource_id): |
27 """If the resource starts with IDR_, find its base resource id.""" | 27 """If the resource starts with IDR_, find its base resource id.""" |
28 if resource_id.startswith('IDR_'): | 28 if resource_id.startswith('IDR_'): |
29 return GetBaseResourceId(resource_id) | 29 return GetBaseResourceId(resource_id) |
30 return resource_id | 30 return resource_id |
31 | 31 |
32 | 32 |
33 def GetResourcesForNode(node, parent_file, resource_tag): | 33 def GetResourcesForNode(node, parent_file, resource_tag): |
34 """Recursively iterate through a node and extract resource names. | 34 """Recursively iterate through a node and extract resource names. |
35 | 35 |
36 Args: | 36 Args: |
37 node: The node to iterate through. | 37 node: The node to iterate through. |
38 parent_file: The file that contains node. | 38 parent_file: The file that contains node. |
39 resource_tag: The resource tag to extract names from. | 39 resource_tag: The resource tag to extract names from. |
40 | 40 |
41 Returns: | 41 Returns: |
42 A list of resource names. | 42 A list of resource names. |
43 """ | 43 """ |
44 resources = [] | 44 resources = [] |
45 for child in node.getchildren(): | 45 for child in node.getchildren(): |
46 if child.tag == resource_tag: | 46 if child.tag == resource_tag: |
47 resources.append(child.attrib['name']) | 47 resources.append(child.attrib['name']) |
48 elif child.tag in IF_ELSE_TAGS: | 48 elif child.tag in IF_ELSE_THEN_TAGS: |
49 resources.extend(GetResourcesForNode(child, parent_file, resource_tag)) | 49 resources.extend(GetResourcesForNode(child, parent_file, resource_tag)) |
50 elif child.tag == 'part': | 50 elif child.tag == 'part': |
51 parent_dir = os.path.dirname(parent_file) | 51 parent_dir = os.path.dirname(parent_file) |
52 part_file = os.path.join(parent_dir, child.attrib['file']) | 52 part_file = os.path.join(parent_dir, child.attrib['file']) |
53 part_tree = xml.etree.ElementTree.parse(part_file) | 53 part_tree = xml.etree.ElementTree.parse(part_file) |
54 part_root = part_tree.getroot() | 54 part_root = part_tree.getroot() |
55 assert part_root.tag == 'grit-part' | 55 assert part_root.tag == 'grit-part' |
56 resources.extend(GetResourcesForNode(part_root, part_file, resource_tag)) | 56 resources.extend(GetResourcesForNode(part_root, part_file, resource_tag)) |
57 else: | 57 else: |
58 raise Exception('unknown tag:', child.tag) | 58 raise Exception('unknown tag:', child.tag) |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 | 113 |
114 Returns: | 114 Returns: |
115 A grit header file name. | 115 A grit header file name. |
116 """ | 116 """ |
117 output_file = None | 117 output_file = None |
118 for child in node.getchildren(): | 118 for child in node.getchildren(): |
119 if child.tag == 'output': | 119 if child.tag == 'output': |
120 if child.attrib['type'] == 'rc_header': | 120 if child.attrib['type'] == 'rc_header': |
121 assert output_file is None | 121 assert output_file is None |
122 output_file = child.attrib['filename'] | 122 output_file = child.attrib['filename'] |
123 elif child.tag in IF_ELSE_TAGS: | 123 elif child.tag in IF_ELSE_THEN_TAGS: |
124 child_output_file = GetOutputFileForNode(child) | 124 child_output_file = GetOutputFileForNode(child) |
125 if not child_output_file: | 125 if not child_output_file: |
126 continue | 126 continue |
127 assert output_file is None | 127 assert output_file is None |
128 output_file = child_output_file | 128 output_file = child_output_file |
129 else: | 129 else: |
130 raise Exception('unknown tag:', child.tag) | 130 raise Exception('unknown tag:', child.tag) |
131 return output_file | 131 return output_file |
132 | 132 |
133 | 133 |
(...skipping 28 matching lines...) Expand all Loading... |
162 resources: The list of resource names in grit_header. | 162 resources: The list of resource names in grit_header. |
163 filename: The file to scan. | 163 filename: The file to scan. |
164 | 164 |
165 Returns: | 165 Returns: |
166 True if the file should include the grit header. | 166 True if the file should include the grit header. |
167 """ | 167 """ |
168 # A list of special keywords that implies the file needs grit headers. | 168 # A list of special keywords that implies the file needs grit headers. |
169 # To be more thorough, one would need to run a pre-processor. | 169 # To be more thorough, one would need to run a pre-processor. |
170 SPECIAL_KEYWORDS = ( | 170 SPECIAL_KEYWORDS = ( |
171 '#include "ui_localizer_table.h"', # ui_localizer.mm | 171 '#include "ui_localizer_table.h"', # ui_localizer.mm |
172 'DEFINE_RESOURCE_ID', # chrome/browser/android/resource_mapper.cc | 172 'DECLARE_RESOURCE_ID', # chrome/browser/android/resource_mapper.cc |
173 ) | 173 ) |
174 with open(filename, 'rb') as f: | 174 with open(filename, 'rb') as f: |
175 grit_header_line = grit_header + '"\n' | 175 grit_header_line = grit_header + '"\n' |
176 has_grit_header = False | 176 has_grit_header = False |
177 while True: | 177 while True: |
178 line = f.readline() | 178 line = f.readline() |
179 if not line: | 179 if not line: |
180 break | 180 break |
181 if line.endswith(grit_header_line): | 181 if line.endswith(grit_header_line): |
182 has_grit_header = True | 182 has_grit_header = True |
(...skipping 13 matching lines...) Expand all Loading... |
196 grd_file = argv[1] | 196 grd_file = argv[1] |
197 paths_to_scan = argv[2:] | 197 paths_to_scan = argv[2:] |
198 for f in paths_to_scan: | 198 for f in paths_to_scan: |
199 if not os.path.exists(f): | 199 if not os.path.exists(f): |
200 print 'Error: %s does not exist' % f | 200 print 'Error: %s does not exist' % f |
201 return 1 | 201 return 1 |
202 | 202 |
203 tree = xml.etree.ElementTree.parse(grd_file) | 203 tree = xml.etree.ElementTree.parse(grd_file) |
204 grit_header = GetOutputHeaderFile(tree) | 204 grit_header = GetOutputHeaderFile(tree) |
205 if not grit_header: | 205 if not grit_header: |
206 print 'Error: %s does not generate any output headers.' % grit_header | 206 print 'Error: %s does not generate any output headers.' % grd_file |
207 return 1 | 207 return 1 |
| 208 |
208 resources = GetResourcesForGrdFile(tree, grd_file) | 209 resources = GetResourcesForGrdFile(tree, grd_file) |
209 | 210 |
210 files_with_unneeded_grit_includes = [] | 211 files_with_unneeded_grit_includes = [] |
211 for path_to_scan in paths_to_scan: | 212 for path_to_scan in paths_to_scan: |
212 if os.path.isdir(path_to_scan): | 213 if os.path.isdir(path_to_scan): |
213 for root, dirs, files in os.walk(path_to_scan): | 214 for root, dirs, files in os.walk(path_to_scan): |
214 if '.git' in dirs: | 215 if '.git' in dirs: |
215 dirs.remove('.git') | 216 dirs.remove('.git') |
216 full_paths = [os.path.join(root, f) for f in files if ShouldScanFile(f)] | 217 full_paths = [os.path.join(root, f) for f in files if ShouldScanFile(f)] |
217 files_with_unneeded_grit_includes.extend( | 218 files_with_unneeded_grit_includes.extend( |
218 [f for f in full_paths | 219 [f for f in full_paths |
219 if not NeedsGritInclude(grit_header, resources, f)]) | 220 if not NeedsGritInclude(grit_header, resources, f)]) |
220 elif os.path.isfile(path_to_scan): | 221 elif os.path.isfile(path_to_scan): |
221 if not NeedsGritInclude(grit_header, resources, path_to_scan): | 222 if not NeedsGritInclude(grit_header, resources, path_to_scan): |
222 files_with_unneeded_grit_includes.append(path_to_scan) | 223 files_with_unneeded_grit_includes.append(path_to_scan) |
223 else: | 224 else: |
224 print 'Warning: Skipping %s' % path_to_scan | 225 print 'Warning: Skipping %s' % path_to_scan |
225 | 226 |
226 if files_with_unneeded_grit_includes: | 227 if files_with_unneeded_grit_includes: |
227 print '\n'.join(files_with_unneeded_grit_includes) | 228 print '\n'.join(files_with_unneeded_grit_includes) |
228 return 2 | 229 return 2 |
229 return 0 | 230 return 0 |
230 | 231 |
231 | 232 |
232 if __name__ == '__main__': | 233 if __name__ == '__main__': |
233 sys.exit(main(sys.argv)) | 234 sys.exit(main(sys.argv)) |
OLD | NEW |