Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate call-graphs for given javascript? [closed]

I have seen "https://stackoverflow.com/questions/1385335/how-to-generate-function-call-graphs-for-javascript", and tried it. It works well, if you want to get an abstract syntax tree.

Unfortunately Closure Compiler only seems to offer --print_tree, --print_ast and --print_pass_graph. None of them are useful for me.

I want to see a chart of which function calls which other functions.

like image 853
beatak Avatar asked Apr 16 '12 22:04

beatak


2 Answers

code2flow does exactly this. Full disclosure, I started this project

To run

$ code2flow source1.js source2.js -o out.gv 

Then, open out.gv with graphviz

Edit: For now, this project is unmaintained. I would suggest trying out a different solution before using code2flow.

like image 161
scottmrogowski Avatar answered Sep 26 '22 21:09

scottmrogowski


If you filter the output of closure --print_tree you get what you want.

For example take the following file:

var fib = function(n) {     if (n < 2) {         return n;     } else {         return fib(n - 1) + fib(n - 2);     } };  console.log(fib(fib(5))); 

Filter the output of closure --print_tree

            NAME fib 1                  FUNCTION  1                                      CALL 5                                          NAME fib 5                                          SUB 5                                              NAME a 5                                              NUMBER 1.0 5                                      CALL 5                                          NAME fib 5                                          SUB 5                                              NAME a 5                                              NUMBER 2.0 5          EXPR_RESULT 9              CALL 9                  GETPROP 9                      NAME console 9                      STRING log 9                  CALL 9                  CALL 9                      NAME fib 9                      CALL 9                      CALL 9                          NAME fib 9                          NUMBER 5.0 9  

And you can see all the call statements.

I wrote the following scripts to do this.

./call_tree

#! /usr/bin/env sh function make_tree() {     closure --print_tree $1 | grep $1 }  function parse_tree() {     gawk -f parse_tree.awk }  if [[ "$1" = "--tree" ]]; then     make_tree $2 else     make_tree $1 | parse_tree fi 

parse_tree.awk

BEGIN {     lines_c = 0     indent_width = 4     indent_offset = 0     string_offset = ""     calling = 0     call_indent = 0 }  {     sub(/\[source_file.*$/, "")     sub(/\[free_call.*$/, "") }  /SCRIPT/ {     indent_offset = calculate_indent($0)     root_indent = indent_offset - 1 }  /FUNCTION/ {     pl  = get_previous_line()     if (calculate_indent(pl) < calculate_indent($0))         print pl     print }  {     lines_v[lines_c] = $0     lines_c += 1 }  {     indent = calculate_indent($0)     if (indent <= call_indent) {         calling = 0     }     if (calling) {         print     } }  /CALL/ {     calling = 1     call_indent = calculate_indent($0)     print }  /EXPR/{     line_indent = calculate_indent($0)     if (line_indent == root_indent) {         if ($0 !~ /(FUNCTION)/) {             print         }     } }  function calculate_indent(line) {     match(line, /^ */)     return int(RLENGTH / indent_width) - indent_offset }  function get_previous_line() {     return lines_v[lines_c - 1] } 
like image 42
William Bettridge-Radford Avatar answered Sep 24 '22 21:09

William Bettridge-Radford