🍱 Add --ignore-subpackages to print_package_dependencies.

The output of print_package_dependencies includes a lot of dependencies
between the package you give it and its subpackages. For example between
browser.customtabs and:
- browser.customtabs.content
- browser.customtabs.dependency_injection
- browser.customtabs.features

For modularization, I care more about dependencies between
browser.customtabs and other packages of the same level.

I added the default off --ignore-subpackages flag to exclude these
dependencies from the output.

Change-Id: I53cd37a01a72394285b836335bd0391c7bb37d0b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2287431
Auto-Submit: Peter Conn <peconn@chromium.org>
Commit-Queue: Henrique Nakashima <hnakashima@chromium.org>
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#786809}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 1dd037c4d09a777eae16b4291a4b409b9f82de13
diff --git a/dependency_analysis/print_package_dependencies.py b/dependency_analysis/print_package_dependencies.py
index bdf9288..b27650e 100755
--- a/dependency_analysis/print_package_dependencies.py
+++ b/dependency_analysis/print_package_dependencies.py
@@ -26,7 +26,7 @@
         print(f'\t\t{begin_class.class_name} -> {end_class.class_name}')
 
 
-def print_package_dependencies_for_key(package_graph, key):
+def print_package_dependencies_for_key(package_graph, key, ignore_subpackages):
     """Prints dependencies for a valid key into the package graph.
 
     Since we store self-edges for the package graph
@@ -38,15 +38,18 @@
     print(f'{len(inbound_without_self)} inbound dependency(ies) '
           f'for {node.name}:')
     for inbound_dep in graph.sorted_nodes_by_name(inbound_without_self):
+        if ignore_subpackages and inbound_dep.name.startswith(node.name):
+            continue
         print_package_dependencies_for_edge(inbound_dep, node)
 
     outbound_without_self = [other for other in node.outbound if other != node]
     print(f'{len(outbound_without_self)} outbound dependency(ies) '
           f'for {node.name}:')
     for outbound_dep in graph.sorted_nodes_by_name(outbound_without_self):
+        if ignore_subpackages and outbound_dep.name.startswith(node.name):
+            continue
         print_package_dependencies_for_edge(node, outbound_dep)
 
-
 def main():
     """Prints package-level dependencies for an input package."""
     arg_parser = argparse.ArgumentParser(
@@ -67,6 +70,15 @@
         help='Case-insensitive name of the package to print dependencies for. '
         'Matches names of the form ...input, for example '
         '`browser` matches `org.chromium.browser`.')
+    optional_arg_group = arg_parser.add_argument_group('optional arguments')
+    optional_arg_group.add_argument(
+        '-s',
+        '--ignore-subpackages',
+        action='store_true',
+        help='If present, this tool will ignore dependencies between the '
+        'given package and subpackages. For example, if given '
+        'browser.customtabs, it won\'t print a dependency between '
+        'browser.customtabs and browser.customtabs.content.')
     arguments = arg_parser.parse_args()
 
     _, package_graph = serialization.load_class_and_package_graphs_from_file(
@@ -84,7 +96,8 @@
             print(f'\t{valid_key}')
     else:
         print(f'Printing package dependencies for {valid_keys[0]}:')
-        print_package_dependencies_for_key(package_graph, valid_keys[0])
+        print_package_dependencies_for_key(package_graph, valid_keys[0],
+                                           arguments.ignore_subpackages)
 
 
 if __name__ == '__main__':