TL;DR Use codegraph to visualize dependencies within a Clojure file. Codegraph applied to itself will for example generate this graph:
Here is how it works.
The other day I wished I had a visualization of the dependencies in a piece of ClojureScript code that over the course of the year has gotten a bit unwieldy. I did some thinking and some codeing and it turns out it's quite easy. Here are some of the highlights in code & images, but mostly code.
Reading a string and have it evaluates in Clojure is done with
read-string. Reading a string and have it not evaluated is as easy as wrapping the string in an additional set of square brackets.
(read-string (str "[" (slurp path) "]")))
This returns the content of the file given by
path as a Clojure data structure. In less homoiconic languages you would probably call this an Abstract Syntax Tree. Homoiconicity for the win!
The data structure is a tree that we want to walk to find dependencies in the code. Here
clojure.walk/prewalk comes in handy. We'll pass it a function which will be called for every node in the tree. I went with a multimethod since I initially expected that different typo of nodes would require different action, but it turns out the only thing we're actually interested in are symbols.
If the symbol is member of a given set, namely
defmethod, we will pay special attention to the next symbol, because it will be the dependant of the upcoming dependencies that we will record. Every subsequent occurrence of a symbol will then constitute a dependency.
From there the only thing left to do is to limit the dependencies to those where the dependee is also the dependant of another dependency; and render the remainder in dot syntax to be visualized by graphviz.
Check out the code for more details.