如何为给定的javascript生成调用图?

bea*_*tak 34 javascript visualization graph call-graph

我看过" /sf/ask/96973481/ ",并试了一下.如果你想得到一个抽象的语法树,它运作良好.

不幸的是关闭编译器似乎只提供--print_tree,--print_ast--print_pass_graph.它们都不适合我.

我想查看哪个函数调用其他函数的图表.

sco*_*ski 16

code2flow正是这样做的.完全披露,我开始这个项目

跑步

$ code2flow source1.js source2.js -o out.gv
Run Code Online (Sandbox Code Playgroud)

然后,用graphviz打开out.gv

编辑:目前,这个项目没有维护.我建议在使用code2flow之前尝试不同的解决方案.

  • @scottmrogowski,你的项目对我来说非常好.对于其他使用此解决方案的人,我想指出[本页](http://dl9obn.darc.de/programming/python/dottoxml/)将graphviz转换为yEd可以打开的文件.Scott,我调整了你的python脚本,根据函数名称命名节点,它产生了很好的yEd可读输出. (3认同)

Wil*_*ord 5

如果你过滤输出closure --print_tree你得到你想要的.

例如,请使用以下文件:

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

console.log(fib(fib(5)));
Run Code Online (Sandbox Code Playgroud)

过滤输出 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 
Run Code Online (Sandbox Code Playgroud)

你可以看到所有的调用语句.

我编写了以下脚本来执行此操作.

./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
Run Code Online (Sandbox Code Playgroud)

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]
}
Run Code Online (Sandbox Code Playgroud)