Implement graph output in erlcode-find-calls
[khome.git] / home / bin / erlcode-find-calls
CommitLineData
2b05907b
SK
1#! /bin/bash
2
f038cbff
SK
3declare -A opts=(
4 ['--fun']=''
5 ['--out']='report' # report | edges | graph
6)
7
8while :
9do
10 case "$1" in
11 --)
12 shift
13 break
14 ;;
15 --*)
16 key="$1"
17 val="$2"
18 if [ -v opts["$key"] ]
19 then
20 if [ "$val" != "" ]
21 then
22 opts["$key"]="$val"
23 shift
24 shift
25 else
26 echo "Option $key requires an argument" >&2
27 exit 1
28 fi
29 else
30 echo "Unknown option: $key" >&2
31 exit 1
32 fi
33 ;;
34 *)
35 break
36 esac
37done
38
2b05907b 39target_module="$1"
f038cbff
SK
40shift
41target_fun_regex="${opts['--fun']}"
42output_type="${opts['--out']}"
2b05907b
SK
43dirs=$@
44
f038cbff
SK
45printf '[DEBUG] target_module : "%s"\n' "$target_module" >&2
46printf '[DEBUG] target_fun_regex : "%s"\n' "$target_fun_regex" >&2
47printf '[DEBUG] dirs : "%s"\n' "$dirs" >&2
48printf '[DEBUG] output_type : "%s"\n' "$output_type" >&2
49
2b05907b
SK
50find $dirs -type f -name '*.erl' -exec grep -Hn "\<$target_module\>:" '{}' \; \
51| sed 's/%.*$//g' \
15f22284
SK
52| awk \
53 -F "${target_module}:" \
54 -v target_module="$target_module" \
f038cbff 55 -v output_type="$output_type" \
15f22284 56 -v target_fun_regex="$target_fun_regex" '
2b05907b
SK
57 $1 && $2 {
58 caller_module_file = $1
59 sub(":.*$", "", caller_module_file)
60
61 called_function = $2
62 sub("\\(.*$", "", called_function)
63
64 if (called_function ~ /^[a-z][a-zA-Z_0-9]+$/) {
fc84ff9c 65 if (called_function ~ target_fun_regex) {
4cc39e2a 66 Calls[called_function]++
fc84ff9c
SK
67 Calls_from[caller_module_file, called_function]++
68 Caller_modules[caller_module_file]++
69 }
2b05907b
SK
70 } else {
71 printf \
72 "[WARN] skipped an invalid erlang function name. File: \"%s\", function: \"%s\", original line: \"%s\"\n", \
73 caller_module_file, called_function, $0 \
74 > "/dev/stderr"
75 }
76 }
77
78 END {
f038cbff
SK
79 if (output_type == "report") {
80 report()
81 } else if (output_type == "edges") {
82 edges()
83 } else if (output_type == "graph") {
84 printf "digraph {\n"
85 vertices() # Vertices must be printed before edges, else records arent recognized.
86 edges()
87 printf "}\n"
88 } else {
89 printf "[ERROR] Unknown output type: \"%s\"\n", output_type > "/dev/stderr"
90 }
91 }
4cc39e2a 92
f038cbff
SK
93 function vertices() {
94 printf "node [shape=record];\n"
95 printf "%s [label=\"", target_module;
96 sep = ""
97 for (called_fun in Calls) {
98 printf "%s<%s> %s", sep, called_fun, called_fun
99 sep = " | "
100 }
101 printf "\"];\n"
102 }
103
104 function edges() {
105 for (cf in Calls_from) {
106 split(cf, call, SUBSEP)
107 caller_mod = call[1]
108 called_mod = target_module
109 called_fun = call[2]
110 printf("\"%s\" -> %s:%s\n", caller_mod, called_mod, called_fun)
111 }
112 }
113
114 function report() {
115 indent = " "
4cc39e2a 116 print "group-by-caller"
2b05907b 117 for (caller_module_file in Caller_modules) {
4cc39e2a 118 printf "%s%s\n", indent, caller_module_file;
6a53be4c 119 sort = "sort -n -k 2 -r | column -t | sed \"s/^/" indent indent "/\""
2b05907b
SK
120 for (cf in Calls_from) {
121 split(cf, call, SUBSEP);
fc84ff9c 122 if (call[1] == caller_module_file)
6a53be4c 123 printf "%s %d\n", call[2], Calls_from[cf] | sort;
2b05907b 124 }
6a53be4c 125 close(sort)
2b05907b
SK
126 }
127
4cc39e2a 128 print "all"
6a53be4c 129 sort = "sort -n -k 2 -r | column -t | sed \"s/^/" indent "/\""
2b05907b 130 for (called_function in Calls)
6a53be4c
SK
131 printf "%s %d\n", called_function, Calls[called_function] | sort
132 close(sort)
2b05907b 133 }'
This page took 0.041232 seconds and 4 git commands to generate.