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

Unified Diff: third_party/polymer/v1_0/find_unused_elements.py

Issue 1918333005: Add script to find unused Polymer elements (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: pylint Created 4 years, 8 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 | « no previous file | third_party/polymer/v1_0/reproduce.sh » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/polymer/v1_0/find_unused_elements.py
diff --git a/third_party/polymer/v1_0/find_unused_elements.py b/third_party/polymer/v1_0/find_unused_elements.py
new file mode 100755
index 0000000000000000000000000000000000000000..7bb727a7f434d136e6bdb30c03a527fae5b4b246
--- /dev/null
+++ b/third_party/polymer/v1_0/find_unused_elements.py
@@ -0,0 +1,156 @@
+#!/usr/bin/python2
+
+# Copyright 2016 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.
+
+# Copyright 2015 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.
+
+"""Identifies Polymer elements that downloaded but not used by Chrome.
+
+Only finds "first-order" unused elements; re-run after removing unused elements
+to check if other elements have become unused.
+"""
+
+import os
+import pyparsing
stevenjb 2016/04/29 20:34:56 Used?
michaelpg 2016/05/02 19:31:45 Done.
+import re
+import subprocess
+import sys
stevenjb 2016/04/29 20:34:55 Used?
michaelpg 2016/05/02 19:31:45 Done.
+
+
+class UnusedElementsDetector:
Dan Beam 2016/05/03 19:22:08 this should probably inherit from (object)
michaelpg 2016/05/03 21:29:19 Done.
+ """Finds unused Polymer elements."""
+
+ # Unused elements to ignore because we plan to use them soon.
+ __whitelist = (
Dan Beam 2016/05/03 19:22:08 nit: I think it's more common to use 4\s indent in
Dan Beam 2016/05/03 19:22:08 nit: __WHITELIST (Class contant https://google.git
michaelpg 2016/05/03 21:29:19 Done.
michaelpg 2016/05/03 21:29:19 the examples in PEP-8 use 4 spaces (as with other
+ # TODO(dschuyler): Use element or remove from whitelist.
+ 'carbon-route',
+ # TODO(tsergeant): Use element or remove from whitelist.
+ 'iron-scroll-threshold',
+ # Necessary for closure.
+ 'polymer-externs',
+ )
+
+ @staticmethod
+ def __StripHtmlComments(filename):
+ """Returns the contents of an HTML file with <!-- --> comments stripped.
+
+ Not a real parser.
+
+ Args:
+ filename: The name of the file to read.
+
+ Returns:
+ A string consisting of the file contents with comments removed.
+ """
+ text = open(filename).read()
+ return re.sub('<!--.*?-->', '', text, flags=re.MULTILINE|re.DOTALL)
Dan Beam 2016/05/03 19:22:08 nit: flags=re.MULTILINE | re.DOTALL)
michaelpg 2016/05/03 21:29:19 Done. Looked weird to me inside a param=value expr
+
+ @staticmethod
+ def __StripJsComments(filename):
+ """Returns the minified contents of a JavaScript file with comments and
+ grit directives removed.
+
+ Args:
+ filename: The name of the file to read.
+
+ Returns:
+ A string consisting of the minified file contents with comments and grit
+ directives removed.
+ """
+ text = open(filename).read()
+ text = re.sub('<if .*?>', '', text)
Dan Beam 2016/05/03 19:22:07 nit: case-insensitive maybe?
michaelpg 2016/05/03 21:29:19 Done.
+ text = re.sub('</if>', '', text)
+
+ proc = subprocess.Popen(['uglifyjs', filename], stdout=subprocess.PIPE)
+ return proc.stdout.read()
+
+ @staticmethod
+ def __StripComments(filename):
+ """Returns the contents of a JavaScript or HTML file with comments removed.
+
+ Args:
+ filename: The name of the file to read.
+
+ Returns:
+ A string consisting of the file contents processed via
+ __StripHtmlComments or __StripJsComments.
+ """
+ if filename.endswith('.html'):
+ text = UnusedElementsDetector.__StripHtmlComments(filename)
+ elif filename.endswith('.js'):
+ text = UnusedElementsDetector.__StripJsComments(filename)
+ else:
+ assert False, 'Invalid filename: %s' % filename
+ return text
+
+ @staticmethod
+ def Run():
+ """Finds unused Polymer elements and prints a summary."""
+ proc = subprocess.Popen(
+ ['git', 'rev-parse', '--show-toplevel'],
+ stdout=subprocess.PIPE)
+ src_dir = proc.stdout.read().strip()
+ polymer_dir = os.path.dirname(os.path.realpath(__file__))
+ components_dir = os.path.join(polymer_dir, 'components-chromium')
+
+ elements = []
+ for name in os.listdir(components_dir):
+ path = os.path.join(components_dir, name)
+ if os.path.isdir(path):
+ elements.append(name)
+
+ unused_elements = []
+ for element in elements:
+ if element in UnusedElementsDetector.__whitelist:
+ continue
+
+ relevant_src_dirs = (
+ os.path.join(src_dir, 'chrome'),
+ os.path.join(src_dir, 'ui'),
+ os.path.join(src_dir, 'components'),
+ components_dir
+ )
+ used = False
+ for path in relevant_src_dirs:
+ # Find an import or script referencing the tag's directory.
+ for (dirpath, _, filenames) in os.walk(path):
+ # Ignore the element's own files.
+ if dirpath.startswith(os.path.join(components_dir, element)):
+ continue
+
+ for filename in [f for f in filenames if f.endswith('.html') or
+ f.endswith('.js')]:
+ # Skip generated files that may include the element source.
+ if filename in ('crisper.js', 'vulcanized.html'):
+ continue
+
+ text = open(os.path.join(dirpath, filename)).read()
+ if not re.search('/%s/' % element, text):
+ continue
+
+ # Check the file again, ignoring comments (e.g. example imports and
+ # scripts).
+ if re.search(
+ '/%s' % element,
stevenjb 2016/04/29 20:34:56 My python formatting fu is weak, but I suspect thi
michaelpg 2016/05/02 19:31:45 Done (both are valid, but your way looks better)
+ UnusedElementsDetector.__StripComments(
+ os.path.join(dirpath, filename))):
+ used = True
+ break
+ if used:
+ break
+ if used:
+ break
stevenjb 2016/04/29 20:34:55 This would be more readable if the entire for loop
michaelpg 2016/05/02 19:31:45 Meant to do that, forgot, done now. Thanks!
+ if not used:
+ unused_elements.append(element)
+
+ if len(unused_elements):
+ print 'Found unused elements: %s\nRemove from bower.json and re-run ' \
+ 'reproduce.sh, or add to whitelist in %s' % (
+ ', '.join(unused_elements), os.path.basename(__file__))
+
+
+UnusedElementsDetector.Run()
Dan Beam 2016/05/03 19:22:07 if __name__ == '__main__': UnusedElementDetector
michaelpg 2016/05/03 21:29:19 Done.
« no previous file with comments | « no previous file | third_party/polymer/v1_0/reproduce.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698