node-theseus
node-theseus copied to clipboard
Feature Request: Highlight execution path
After coming across theseus, I have to say that I'm loving it. So far, there are just a few things away from making this perfect. One is the bug found here: #21
The other is a feature request that I'm not sure has been mentioned before. Before theseus I was using tracegl which shows you the execution path using colors. Currently theseus only highlights the entire method when hovering above "$num calls" (exe: 1 call). See code example below for more information.
Additionally, how difficult would it be to see the count of calls that happen on if, else, switch, etc style statements?
Take the following code for example:
var user = "me";
if (user === "me") {
// This path would be highlighted in green.
} else {
// This path would be highlighted in red.
}
Something similar is done in code-highlighting in Brackets using the opening and closing brackets like { } and [ ], etc
Highlighting code paths: most of the infrastructure for this is in-place. IIRC, fondue records which branches are taken (it's part of the call graph); the data just isn't used in the Theseus UI yet.
Showing call counts for branches and loops: Since this data is in fondue's call graph just like function calls, the counts could be displayed as well. Again, most of the infrastructure is in place; it just isn't used in the UI yet.
I don't think I'll get the chance to work on these features for a while, but I'm very happy to chart a course for doing so if someone else has the time. These are great feature ideas!
I would be interested in knowing what course I should move forward with to be in compliance with your expectations and potential pull requests. I'll be adding these features for myself anyway. ;)
Branch/loop call counts first, I think. :)
- It looks like node IDs are being generated for branches, but no tracing code is being inserted, so that needs to be done. You can probably pretty much copy how it's done for functions. I don't remember
IfStatementnodes being finicky, but check the syntax tree here to visualize them. - I'd add a test that the nodes are generated correctly and that the call counts are incrementing as expected. Updating these tests is by far the easiest way to check that this stuff works. And the AST-rewriting part of fondue is really fragile, which is why I hope to rewrite it with esprima-selector and falafel-helpers eventually, and why the tests are so important.
- You could make a fondue pull request at this point. The rest of the work will be in Theseus.
setupEditor()in Theseus needs to add gutter markers for branches instead of just for functions. You'll want an Agent function for getting all the branch nodes in the current file that'll work likefunctionsInFile(). Maybe it's time to rewritefunctionsInFile()andprobesInFile()in terms of a new functionnodesInFile()that takes one or more node types. :) I think your job will be simpler if, to start, the call counts for branches are not clickable. Maybe make a class on those call counts to distinguish them and prevent these event handlers from firing.
At this point, this periodic call to refreshHitCounts ought to update the call counts for branches like it does for functions... assuming I haven't missed anything big.
The process for getting call counts for loops should be very similar.
Highlighting code paths is going to be a very different challenge, so I have to think about that for a bit.
Highlighting code paths.
The biggest question is how the user indicates which invocation of the function to show the call path for. Maybe you'd do it by hovering over a particular invocation in the log. This is the best I've come up with so far. :)
Regardless, we need a way to highlight a code path. That means getting a slice of the call graph.
Agent has a trackLogs() function for getting slices of the call graph. Here's how it's called to populate the log window. Basically it takes arrays of all the node IDs, event names, etc that you want information about, and it returns to you a handle you can pass to Agent.refreshLogs() to get information about every invocation. The call graph is a DAG, but it's returned as an array of invocations. Each invocation has an ID, and contains the IDs of its callers. Theseus turns that array back into a graph as the data arrives here.
If you've done the branch call counts, then branches are now in the graph. If you create a query with the ID of the function and the IDs of all the branches in that function, then the data you get back will have every invocation of the function and every 'call' to one of the branches in it. You can use that to figure out, for any call to the function, which branches were taken and which weren't. Just descend the graph from the function call down and keep track of whether you've seen an invocation of each branch.
When you hover over a call count, _gutterCallCountMouseOver() fires and highlights the whole function. The marker clears when you mouse away. Markers are tricky to get right because order matters and they don't always overlap the way you'd expect. I recommend highlighting the whole function (as happens now), then adding a gray background to any branches that weren't hit, as done here. Store references to the markers so that you can clear them when the mouse moves away.
This is tricky enough that I can't imagine the whole solution in my head as I could for the previous feature, so unfortunately I can't make a procedure to get it done. :) Hopefully this is most of the information you need, though.