Add option to show dependency tags in soongdbg

Test: soongdbg between --svg ~/Desktop/foo.svg --deptags android.content.pm.flags-aconfig PackageInstaller
Change-Id: I00786ff982ecff71e6f3cdc8d72bba5f23a093b5
diff --git a/bin/soongdbg b/bin/soongdbg
index a4c2398..215d9d2 100755
--- a/bin/soongdbg
+++ b/bin/soongdbg
@@ -30,6 +30,7 @@
                 dep = get_or_make_node(self.nodes, d.id, None)
                 node.deps.add(dep)
                 dep.rdeps.add(node)
+                node.dep_tags.setdefault(dep, list()).append(d)
 
     def find_paths(self, id1, id2):
         # Throws KeyError if one of the names isn't found
@@ -63,6 +64,7 @@
         self.module = module
         self.deps = set()
         self.rdeps = set()
+        self.dep_tags = {}
 
 
 PROVIDERS = [
@@ -71,6 +73,20 @@
 ]
 
 
+def format_dep_label(node, dep):
+    tags = node.dep_tags.get(dep)
+    labels = []
+    if tags:
+        labels = [tag.tag_type.split("/")[-1] for tag in tags]
+        labels = sorted(set(labels))
+    if labels:
+        result = "<<table border=\"0\" cellborder=\"0\" cellspacing=\"0\" cellpadding=\"0\">"
+        for label in labels:
+            result += f"<tr><td>{label}</td></tr>"
+        result += "</table>>"
+        return result
+
+
 def format_node_label(node, module_formatter):
     result = "<<table border=\"0\" cellborder=\"0\" cellspacing=\"0\" cellpadding=\"0\">"
 
@@ -196,6 +212,8 @@
 def print_args(parser):
     parser.add_argument("--label", action="append", metavar="JQ_FILTER",
                         help="jq query for each module metadata")
+    parser.add_argument("--deptags", action="store_true",
+                        help="show dependency tags (makes the graph much more complex)")
 
     group = parser.add_argument_group("output formats",
                                       "If no format is provided, a dot file will be written to"
@@ -209,13 +227,24 @@
 
 def print_nodes(args, nodes, module_formatter):
     # Generate the graphviz
+    dep_tag_id = 0
     dot = io.StringIO()
     dot.write("digraph {\n")
+    dot.write("node [shape=box];")
+
     for node in nodes:
-        dot.write(f"\"{node.id}\"[label={format_node_label(node, module_formatter)}];\n")
+        dot.write(f"\"{node.id}\" [label={format_node_label(node, module_formatter)}];\n")
         for dep in node.deps:
             if dep in nodes:
-                dot.write(f"\"{node.id}\" -> \"{dep.id}\";\n")
+                if args.deptags:
+                    dot.write(f"\"{node.id}\" -> \"__dep_tag_{dep_tag_id}\" [ arrowhead=none ];\n")
+                    dot.write(f"\"__dep_tag_{dep_tag_id}\" -> \"{dep.id}\";\n")
+                    dot.write(f"\"__dep_tag_{dep_tag_id}\""
+                                  + f"[label={format_dep_label(node, dep)} shape=ellipse"
+                                  + " color=\"#666666\" fontcolor=\"#666666\"];\n")
+                else:
+                    dot.write(f"\"{node.id}\" -> \"{dep.id}\";\n")
+                dep_tag_id += 1
     dot.write("}\n")
     text = dot.getvalue()
 
@@ -224,7 +253,7 @@
         with open(args.dot, "w") as f:
             f.write(text)
     elif args.svg:
-        subprocess.run(["dot", "-Tsvg", "-Nshape=box", "-o", args.svg],
+        subprocess.run(["dot", "-Tsvg", "-o", args.svg],
                               input=text, text=True, check=True)
     else:
         sys.stdout.write(text)