blob: 71ba386dacbdf9ec283d3b495e8a807fd3f3cf9d [file] [log] [blame]
[email protected]2fac3752011-11-27 20:56:511#!/usr/bin/env python
[email protected]2b1fbb9d2012-02-08 07:30:512# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]f16943a12010-04-09 13:07:193# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Without any args, this simply loads the IDs out of a bunch of the Chrome GRD
7files, and then checks the subset of the code that loads the strings to try
8and figure out what isn't in use any more.
9You can give paths to GRD files and source directories to control what is
10check instead.
11"""
12
13import os
14import re
15import sys
16import xml.sax
17
18# Extra messages along the way
19# 1 - Print ids that are found in sources but not in the found id set
20# 2 - Files that aren't processes (don't match the source name regex)
21DEBUG = 0
22
23
24class GrdIDExtractor(xml.sax.handler.ContentHandler):
25 """Extracts the IDs from messages in GRIT files"""
26 def __init__(self):
27 self.id_set_ = set()
28
29 def startElement(self, name, attrs):
30 if name == 'message':
31 self.id_set_.add(attrs['name'])
32
33 def allIDs(self):
34 """Return all the IDs found"""
35 return self.id_set_.copy()
36
37
38def CheckForUnusedGrdIDsInSources(grd_files, src_dirs):
39 """Will collect the message ids out of the given GRD files and then scan
40 the source directories to try and figure out what ids are not currently
41 being used by any source.
42
43 grd_files:
44 A list of GRD files to collect the ids from.
45 src_dirs:
46 A list of directories to walk looking for source files.
47 """
48 # Collect all the ids into a large map
49 all_ids = set()
50 file_id_map = {}
51 for y in grd_files:
52 handler = GrdIDExtractor()
53 xml.sax.parse(y, handler)
54 files_ids = handler.allIDs()
55 file_id_map[y] = files_ids
56 all_ids |= files_ids
57
58
59 # The regex that will be used to check sources
60 id_regex = re.compile('IDS_[A-Z0-9_]+')
61
62 # Make sure the regex matches every id found.
63 got_err = False
64 for x in all_ids:
65 match = id_regex.search(x)
66 if match is None:
67 print 'ERROR: "%s" did not match our regex' % (x)
68 got_err = True
69 if not match.group(0) is x:
70 print 'ERROR: "%s" did not fully match our regex' % (x)
71 got_err = True
72 if got_err:
73 return 1
74
75 # The regex for deciding what is a source file
[email protected]cf83d252011-11-30 00:20:2176 src_regex = re.compile('\.(([chm])|(mm)|(cc)|(cp)|(cpp)|(xib)|(py))$')
[email protected]f16943a12010-04-09 13:07:1977
78 ids_left = all_ids.copy()
79
80 # Scanning time.
81 for src_dir in src_dirs:
82 for root, dirs, files in os.walk(src_dir):
83 # Remove svn directories from recursion
84 if '.svn' in dirs:
85 dirs.remove('.svn')
86 for file in files:
87 if src_regex.search(file.lower()):
88 full_path = os.path.join(root, file)
89 src_file_contents = open(full_path).read()
90 for match in sorted(set(id_regex.findall(src_file_contents))):
91 if match in ids_left:
92 ids_left.remove(match)
93 if DEBUG:
94 if not match in all_ids:
95 print '%s had "%s", which was not in the found IDs' % \
96 (full_path, match)
97 elif DEBUG > 1:
98 full_path = os.path.join(root, file)
99 print 'Skipping %s.' % (full_path)
100
101 # Anything left?
102 if len(ids_left) > 0:
103 print 'The following ids are in GRD files, but *appear* to be unused:'
104 for file_path, file_ids in file_id_map.iteritems():
105 missing = ids_left.intersection(file_ids)
106 if len(missing) > 0:
107 print ' %s:' % (file_path)
108 print '\n'.join(' %s' % (x) for x in sorted(missing))
109
110 return 0
111
112
[email protected]2fac3752011-11-27 20:56:51113def main():
tfarinac9fc1902014-08-29 16:19:04114 # script lives in src/tools
115 tools_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
116 src_dir = os.path.dirname(tools_dir)
[email protected]f16943a12010-04-09 13:07:19117
118 # Collect the args into the right buckets
119 src_dirs = []
120 grd_files = []
121 for arg in sys.argv[1:]:
Steven Bennetts528eec52017-11-10 19:21:19122 if arg.lower().endswith('.grd') or arg.lower().endswith('.grdp'):
[email protected]f16943a12010-04-09 13:07:19123 grd_files.append(arg)
124 else:
125 src_dirs.append(arg)
126
127 # If no GRD files were given, default them:
128 if len(grd_files) == 0:
[email protected]2b1fbb9d2012-02-08 07:30:51129 ash_base_dir = os.path.join(src_dir, 'ash')
wutaocd13722f2018-02-21 22:00:35130 ash_components_dir = os.path.join(ash_base_dir, 'components')
tfarinac9fc1902014-08-29 16:19:04131 chrome_dir = os.path.join(src_dir, 'chrome')
[email protected]f16943a12010-04-09 13:07:19132 chrome_app_dir = os.path.join(chrome_dir, 'app')
133 chrome_app_res_dir = os.path.join(chrome_app_dir, 'resources')
[email protected]8a92bbd2013-02-22 01:07:29134 device_base_dir = os.path.join(src_dir, 'device')
[email protected]02040842014-08-21 04:29:10135 ui_dir = os.path.join(src_dir, 'ui')
136 ui_strings_dir = os.path.join(ui_dir, 'strings')
137 ui_chromeos_dir = os.path.join(ui_dir, 'chromeos')
[email protected]f16943a12010-04-09 13:07:19138 grd_files = [
[email protected]2b1fbb9d2012-02-08 07:30:51139 os.path.join(ash_base_dir, 'ash_strings.grd'),
wutaocd13722f2018-02-21 22:00:35140 os.path.join(ash_components_dir, 'ash_components_strings.grd'),
141 os.path.join(ash_components_dir, 'resources',
142 'ash_components_resources.grd'),
[email protected]f16943a12010-04-09 13:07:19143 os.path.join(chrome_app_dir, 'chromium_strings.grd'),
144 os.path.join(chrome_app_dir, 'generated_resources.grd'),
145 os.path.join(chrome_app_dir, 'google_chrome_strings.grd'),
146 os.path.join(chrome_app_res_dir, 'locale_settings.grd'),
[email protected]80b1adf2012-11-17 14:20:11147 os.path.join(chrome_app_res_dir, 'locale_settings_chromiumos.grd'),
148 os.path.join(chrome_app_res_dir, 'locale_settings_google_chromeos.grd'),
[email protected]f16943a12010-04-09 13:07:19149 os.path.join(chrome_app_res_dir, 'locale_settings_linux.grd'),
150 os.path.join(chrome_app_res_dir, 'locale_settings_mac.grd'),
151 os.path.join(chrome_app_res_dir, 'locale_settings_win.grd'),
152 os.path.join(chrome_app_dir, 'theme', 'theme_resources.grd'),
153 os.path.join(chrome_dir, 'browser', 'browser_resources.grd'),
154 os.path.join(chrome_dir, 'common', 'common_resources.grd'),
[email protected]8d0d4f7d2012-09-11 03:31:29155 os.path.join(chrome_dir, 'renderer', 'resources',
156 'renderer_resources.grd'),
[email protected]e3a9ccfc2013-06-03 00:22:30157 os.path.join(device_base_dir, 'bluetooth', 'bluetooth_strings.grd'),
Martin Kreichgauer2d30db42018-08-13 18:02:31158 os.path.join(device_base_dir, 'fido', 'fido_strings.grd'),
Li Linc5838fe2018-08-28 22:52:13159 os.path.join(src_dir, 'chromeos', 'chromeos_strings.grd'),
jamescook488cf9d2017-04-06 19:39:35160 os.path.join(src_dir, 'extensions', 'strings', 'extensions_strings.grd'),
[email protected]29b25d092011-06-29 20:57:34161 os.path.join(src_dir, 'ui', 'resources', 'ui_resources.grd'),
[email protected]70fd3bb2013-02-28 08:55:04162 os.path.join(src_dir, 'ui', 'webui', 'resources', 'webui_resources.grd'),
[email protected]02040842014-08-21 04:29:10163 os.path.join(ui_strings_dir, 'app_locale_settings.grd'),
164 os.path.join(ui_strings_dir, 'ui_strings.grd'),
[email protected]ece882c82014-07-13 04:03:42165 os.path.join(ui_chromeos_dir, 'ui_chromeos_strings.grd'),
[email protected]f16943a12010-04-09 13:07:19166 ]
167
168 # If no source directories were given, default them:
169 if len(src_dirs) == 0:
170 src_dirs = [
171 os.path.join(src_dir, 'app'),
[email protected]3923c132012-08-22 16:45:54172 os.path.join(src_dir, 'ash'),
[email protected]f16943a12010-04-09 13:07:19173 os.path.join(src_dir, 'chrome'),
[email protected]79c24cd2013-03-12 04:37:37174 os.path.join(src_dir, 'components'),
[email protected]cf83d252011-11-30 00:20:21175 os.path.join(src_dir, 'content'),
[email protected]050ed6842013-03-04 20:18:18176 os.path.join(src_dir, 'device'),
[email protected]99c0125b2014-04-17 05:21:57177 os.path.join(src_dir, 'extensions'),
[email protected]4c9101d2011-03-15 20:49:48178 os.path.join(src_dir, 'ui'),
[email protected]f16943a12010-04-09 13:07:19179 # nsNSSCertHelper.cpp has a bunch of ids
180 os.path.join(src_dir, 'third_party', 'mozilla_security_manager'),
[email protected]cf83d252011-11-30 00:20:21181 os.path.join(chrome_dir, 'installer'),
[email protected]f16943a12010-04-09 13:07:19182 ]
183
[email protected]2fac3752011-11-27 20:56:51184 return CheckForUnusedGrdIDsInSources(grd_files, src_dirs)
185
186
187if __name__ == '__main__':
188 sys.exit(main())