From da49db02014deca5636ae8d80d9911094c166319 Mon Sep 17 00:00:00 2001 From: Tommy Ip Date: Fri, 17 Mar 2017 19:30:19 +0000 Subject: [PATCH] Create tools/js-dep-visualizer.py. This tools lets us view circular dependencies in our JS code. It does regex parsing, so it has a few false positives, but it's an early draft of the tools. Steve Howell helped with this commit. --- tools/js-dep-visualizer.py | 74 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tools/js-dep-visualizer.py diff --git a/tools/js-dep-visualizer.py b/tools/js-dep-visualizer.py new file mode 100644 index 0000000000..93c5517bee --- /dev/null +++ b/tools/js-dep-visualizer.py @@ -0,0 +1,74 @@ +""" +$ python ./tools/js-dep-visualizer.py +$ dot -Tpng var/zulip-deps.dot -o var/zulip-deps.png +""" + +import os +import re +import sys + +from typing import Any, Dict, List + +TOOLS_DIR = os.path.abspath(os.path.dirname(__file__)) +ROOT_DIR = os.path.dirname(TOOLS_DIR) +sys.path.insert(0, ROOT_DIR) +from tools.lib.graph import Graph, make_dot_file + +JS_FILES_DIR = os.path.abspath(os.path.join(ROOT_DIR, 'static/js')) +OUTPUT_FILE_PATH = os.path.abspath(os.path.join(ROOT_DIR, 'var/zulip-deps.dot')) + +modules = [] # type: List[Dict[str, Any]] +for js_file in os.listdir(JS_FILES_DIR): + name = js_file[:-3] # remove .js + file_path = os.path.abspath(os.path.join(JS_FILES_DIR, js_file)) + + if os.path.isfile(file_path) and js_file != '.eslintrc.json': + modules.append(dict( + filename=js_file, + name=name, + path=file_path, + regex=re.compile('[^_]{}\.\w+\('.format(name)) + )) + +tuples = set() +for module in modules: + + other_modules = filter(lambda x: x['name'] != module['name'], modules) + + with open(module['path']) as f: + module_content = f.read() + for other_module in other_modules: + dependencies = re.findall(other_module['regex'], module_content) + if dependencies: + parent = module['name'] + child = other_module['name'] + tup = (parent, child) + if tup == ('stream_data', 'subs'): + continue # parsing mistake due to variable called "subs" + tuples.add(tup) + +# print(tuples) +graph = Graph(*tuples) +tricky_modules = [ + 'blueslip', + 'channel', + 'filter', + 'hashchange', + 'message_store', + 'narrow', + 'popovers', + 'reload', + 'resize', + 'server_events', # has restart code + 'socket', + 'stream_color', + 'ui', + 'zulip', # zulip.com false positives +] +for node in tricky_modules: + graph.remove(node) +graph.remove_exterior_nodes() +buffer = make_dot_file(graph) + +with open(OUTPUT_FILE_PATH, 'w') as f: + f.write(buffer)