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

Unified Diff: tools/android/find_unused_resources.py

Issue 1841863002: Update monet. (Closed) Base URL: https://github.com/domokit/monet.git@master
Patch Set: Created 4 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/android/file_poller/file_poller.cc ('k') | tools/android/findbugs_plugin/README » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/android/find_unused_resources.py
diff --git a/tools/android/find_unused_resources.py b/tools/android/find_unused_resources.py
new file mode 100755
index 0000000000000000000000000000000000000000..1e8fa48abc3ce7b29a8ccac66c07f2b324ad4ff7
--- /dev/null
+++ b/tools/android/find_unused_resources.py
@@ -0,0 +1,145 @@
+#!/usr/bin/python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Lists unused Java strings and other resources."""
+
+import optparse
+import re
+import subprocess
+import sys
+
+
+def GetLibraryResources(r_txt_paths):
+ """Returns the resources packaged in a list of libraries.
+
+ Args:
+ r_txt_paths: paths to each library's generated R.txt file which lists the
+ resources it contains.
+
+ Returns:
+ The resources in the libraries as a list of tuples (type, name). Example:
+ [('drawable', 'arrow'), ('layout', 'month_picker'), ...]
+ """
+ resources = []
+ for r_txt_path in r_txt_paths:
+ with open(r_txt_path, 'r') as f:
+ for line in f:
+ line = line.strip()
+ if not line:
+ continue
+ data_type, res_type, name, _ = line.split(None, 3)
+ assert data_type in ('int', 'int[]')
+ # Hide attrs, which are redundant with styleables and always appear
+ # unused, and hide ids, which are innocuous even if unused.
+ if res_type in ('attr', 'id'):
+ continue
+ resources.append((res_type, name))
+ return resources
+
+
+def GetUsedResources(source_paths, resource_types):
+ """Returns the types and names of resources used in Java or resource files.
+
+ Args:
+ source_paths: a list of files or folders collectively containing all the
+ Java files, resource files, and the AndroidManifest.xml.
+ resource_types: a list of resource types to look for. Example:
+ ['string', 'drawable']
+
+ Returns:
+ The resources referenced by the Java and resource files as a list of tuples
+ (type, name). Example:
+ [('drawable', 'app_icon'), ('layout', 'month_picker'), ...]
+ """
+ type_regex = '|'.join(map(re.escape, resource_types))
+ patterns = [r'@(())(%s)/(\w+)' % type_regex,
+ r'\b((\w+\.)*)R\.(%s)\.(\w+)' % type_regex]
+ resources = []
+ for pattern in patterns:
+ p = subprocess.Popen(
+ ['grep', '-REIhoe', pattern] + source_paths,
+ stdout=subprocess.PIPE)
+ grep_out, grep_err = p.communicate()
+ # Check stderr instead of return code, since return code is 1 when no
+ # matches are found.
+ assert not grep_err, 'grep failed'
+ matches = re.finditer(pattern, grep_out)
+ for match in matches:
+ package = match.group(1)
+ if package == 'android.':
+ continue
+ type_ = match.group(3)
+ name = match.group(4)
+ resources.append((type_, name))
+ return resources
+
+
+def FormatResources(resources):
+ """Formats a list of resources for printing.
+
+ Args:
+ resources: a list of resources, given as (type, name) tuples.
+ """
+ return '\n'.join(['%-12s %s' % (t, n) for t, n in sorted(resources)])
+
+
+def ParseArgs(args):
+ parser = optparse.OptionParser()
+ parser.add_option('-v', help='Show verbose output', action='store_true')
+ parser.add_option('-s', '--source-path', help='Specify a source folder path '
+ '(e.g. ui/android/java)', action='append', default=[])
+ parser.add_option('-r', '--r-txt-path', help='Specify a "first-party" R.txt '
+ 'file (e.g. out/Debug/content_shell_apk/R.txt)',
+ action='append', default=[])
+ parser.add_option('-t', '--third-party-r-txt-path', help='Specify an R.txt '
+ 'file for a third party library', action='append',
+ default=[])
+ options, args = parser.parse_args(args=args)
+ if args:
+ parser.error('positional arguments not allowed')
+ if not options.source_path:
+ parser.error('at least one source folder path must be specified with -s')
+ if not options.r_txt_path:
+ parser.error('at least one R.txt path must be specified with -r')
+ return (options.v, options.source_path, options.r_txt_path,
+ options.third_party_r_txt_path)
+
+
+def main(args=None):
+ verbose, source_paths, r_txt_paths, third_party_r_txt_paths = ParseArgs(args)
+ defined_resources = (set(GetLibraryResources(r_txt_paths)) -
+ set(GetLibraryResources(third_party_r_txt_paths)))
+ resource_types = list(set([r[0] for r in defined_resources]))
+ used_resources = set(GetUsedResources(source_paths, resource_types))
+ unused_resources = defined_resources - used_resources
+ undefined_resources = used_resources - defined_resources
+
+ # aapt dump fails silently. Notify the user if things look wrong.
+ if not defined_resources:
+ print >> sys.stderr, (
+ 'Warning: No resources found. Did you provide the correct R.txt paths?')
+ if not used_resources:
+ print >> sys.stderr, (
+ 'Warning: No resources referenced from Java or resource files. Did you '
+ 'provide the correct source paths?')
+ if undefined_resources:
+ print >> sys.stderr, (
+ 'Warning: found %d "undefined" resources that are referenced by Java '
+ 'files or by other resources, but are not defined anywhere. Run with '
+ '-v to see them.' % len(undefined_resources))
+
+ if verbose:
+ print '%d undefined resources:' % len(undefined_resources)
+ print FormatResources(undefined_resources), '\n'
+ print '%d resources defined:' % len(defined_resources)
+ print FormatResources(defined_resources), '\n'
+ print '%d used resources:' % len(used_resources)
+ print FormatResources(used_resources), '\n'
+ print '%d unused resources:' % len(unused_resources)
+ print FormatResources(unused_resources)
+
+
+if __name__ == '__main__':
+ main()
« no previous file with comments | « tools/android/file_poller/file_poller.cc ('k') | tools/android/findbugs_plugin/README » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698