Index: chrome/browser/resources/chromeos/chromevox/tools/print_js_deps.py |
diff --git a/chrome/browser/resources/chromeos/chromevox/tools/print_js_deps.py b/chrome/browser/resources/chromeos/chromevox/tools/print_js_deps.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..4782c3d6f8dad8258ef6e8620173fc28105dde71 |
--- /dev/null |
+++ b/chrome/browser/resources/chromeos/chromevox/tools/print_js_deps.py |
@@ -0,0 +1,89 @@ |
+#!/usr/bin/env python |
+ |
+# 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. |
+ |
+'''Print the dependency tree for a JavaScript module. |
+ |
+Given one or more root directories, specified by -r options and one top-level |
+file, walk the dependency tree and print all modules encountered. |
+A module is only expanded once; on a second encounter, its dependencies |
+are represented by a line containing the characters '[...]' as a short-hand. |
+''' |
+ |
+import optparse |
+import os |
+import sys |
+ |
+from jsbundler import ReadSources |
+ |
+ |
+def Die(message): |
+ '''Prints an error message and exit the program.''' |
+ print >>sys.stderr, message |
+ sys.exit(1) |
+ |
+ |
+def CreateOptionParser(): |
+ parser = optparse.OptionParser(description=__doc__) |
+ parser.usage = '%prog [options] <top_level_file>' |
+ parser.add_option('-r', '--root', dest='roots', action='append', default=[], |
+ metavar='ROOT', |
+ help='Roots of directory trees to scan for sources. ' |
+ 'If none specified, all of ChromeVox and closure sources ' |
+ 'are scanned.') |
+ return parser |
+ |
+ |
+def DefaultRoots(): |
+ script_dir = os.path.dirname(os.path.abspath(__file__)) |
+ source_root_dir = os.path.join(script_dir, *[os.path.pardir] * 6) |
+ return [os.path.relpath(os.path.join(script_dir, os.path.pardir)), |
+ os.path.relpath( |
+ os.path.join(source_root_dir, 'chrome', 'third_party', |
+ 'chromevox', 'third_party', |
+ 'closure-library', 'closure'))] |
+ |
+ |
+def WalkDeps(sources, start_source): |
+ def Walk(source, depth): |
+ indent = ' ' * depth |
+ if source.GetInPath() in expanded and len(source.requires) > 0: |
+ print '%s[...]' % indent |
+ return |
+ expanded.add(source.GetInPath()) |
+ for require in source.requires: |
+ if not require in providers: |
+ Die('%s not provided, required by %s' % (require, source.GetInPath())) |
+ require_source = providers[require] |
+ print '%s%s (%s)' % (indent, require, require_source.GetInPath()) |
+ Walk(require_source, depth + 1) |
+ |
+ # Create a map from provided module names to source objects. |
+ providers = {} |
+ expanded = set() |
+ for source in sources.values(): |
+ for provide in source.provides: |
+ if provide in providers: |
+ Die('%s provided multiple times' % provide) |
+ providers[provide] = source |
+ |
+ print '(%s)' % start_source.GetInPath() |
+ Walk(start_source, 1) |
+ |
+ |
+def main(): |
+ parser = CreateOptionParser() |
+ options, args = parser.parse_args() |
+ if len(args) != 1: |
+ Die('Exactly one top-level source file must be specified.') |
+ start_path = args[0] |
+ roots = options.roots or DefaultRoots() |
+ sources = ReadSources(roots=roots, source_files=[start_path]) |
+ start_source = sources[start_path] |
+ WalkDeps(sources, start_source) |
+ |
+ |
+if __name__ == '__main__': |
+ main() |