ui: Add planned dependency viz to check_imports and /widgets rules
Change-Id: I76dc010aa7dc9f189a3684284b55346895de9f20
diff --git a/python/tools/check_imports.py b/python/tools/check_imports.py
index ef4ff29..dd096fb 100755
--- a/python/tools/check_imports.py
+++ b/python/tools/check_imports.py
@@ -37,6 +37,91 @@
os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
UI_SRC_DIR = os.path.join(ROOT_DIR, 'ui', 'src')
+# Current plan for the dependency tree of the UI code (2023-09-21)
+# black = current
+# red = planning to remove
+# green = planning to add
+PLAN_DOT = """
+digraph g {
+ mithril [shape=rectangle, label="mithril"];
+ protos [shape=rectangle, label="//protos/perfetto"];
+
+ _gen [shape=ellipse, label="/gen"];
+ _base [shape=ellipse, label="/base"];
+ _core [shape=ellipse, label="/core"];
+ _engine [shape=ellipse, label="/engine"];
+
+ _frontend [shape=ellipse, label="/frontend" color=red];
+ _common [shape=ellipse, label="/common" color=red];
+ _controller [shape=ellipse, label="/controller" color=red];
+ _tracks [shape=ellipse, label="/tracks" color=red];
+
+ _widgets [shape=ellipse, label="/widgets"];
+
+ _public [shape=ellipse, label="/public"];
+ _plugins [shape=ellipse, label="/plugins"];
+ _chrome_extension [shape=ellipse, label="/chrome_extension"];
+ _trace_processor [shape=ellipse, label="/trace_processor" color="green"];
+ _protos [shape=ellipse, label="/protos" color="green"];
+ engine_worker_bundle [shape=cds, label="Engine worker bundle"];
+ frontend_bundle [shape=cds, label="Frontend bundle"];
+
+ engine_worker_bundle -> _engine;
+ frontend_bundle -> _core [color=green];
+ frontend_bundle -> _frontend [color=red];
+
+ _core -> _public;
+ _plugins -> _public;
+
+ _widgets -> _base;
+ _core -> _base;
+ _core -> _widgets;
+
+
+ _widgets -> mithril;
+ _plugins -> mithril;
+ _core -> mithril
+
+ _plugins -> _widgets;
+
+ _core -> _chrome_extension;
+
+ _frontend -> _widgets [color=red];
+ _common -> _core [color=red];
+ _frontend -> _core [color=red];
+ _controller -> _core [color=red];
+
+ _frontend -> _controller [color=red];
+ _frontend -> _common [color=red];
+ _controller -> _frontend [color=red];
+ _controller -> _common [color=red];
+ _common -> _controller [color=red];
+ _common -> _frontend [color=red];
+ _tracks -> _frontend [color=red];
+ _tracks -> _controller [color=red];
+ _common -> _chrome_extension [color=red];
+
+ _core -> _trace_processor [color=green];
+
+ _engine -> _trace_processor [color=green];
+ _engine -> _common [color=red];
+ _engine -> _base;
+
+ _gen -> protos;
+ _core -> _gen [color=red];
+
+ _core -> _protos [color=green];
+ _protos -> _gen [color=green];
+ _trace_processor -> _protos [color=green];
+
+ _trace_processor -> _public [color=green];
+
+ npm_trace_processor [shape=cds, label="npm trace_processor" color="green"];
+ npm_trace_processor -> engine_worker_bundle [color="green"];
+ npm_trace_processor -> _trace_processor [color="green"];
+}
+"""
+
class Failure(object):
@@ -183,6 +268,23 @@
'chrome_extension must be a leaf',
),
+ # Widgets
+ NoDep(
+ r'/widgets/.*',
+ r'/frontend/.*',
+ 'widgets should only depend on base',
+ ),
+ NoDep(
+ r'/widgets/.*',
+ r'/core/.*',
+ 'widgets should only depend on base',
+ ),
+ NoDep(
+ r'/widgets/.*',
+ r'/plugins/.*',
+ 'widgets should only depend on base',
+ ),
+
# Fails at the moment as we have several circular dependencies. One
# example:
# ui/src/frontend/cookie_consent.ts
@@ -340,6 +442,11 @@
return 0
+def do_plan_dot(options, _):
+ print(PLAN_DOT, file=sys.stdout)
+ return 0
+
+
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.set_defaults(func=do_check)
@@ -371,6 +478,12 @@
help='Don\'t show external dependencies',
)
+ plan_dot_command = subparsers.add_parser(
+ 'plan-dot',
+ help='Output planned dependency graph in dot format suitble for use in graphviz (e.g. ./tools/check_imports plan-dot | dot -Tpng -ograph.png)'
+ )
+ plan_dot_command.set_defaults(func=do_plan_dot)
+
graph = collections.defaultdict(set)
for path in all_source_files():
for src, target in find_imports(path):