-
Notifications
You must be signed in to change notification settings - Fork 20
/
cascade.ts
85 lines (68 loc) · 1.93 KB
/
cascade.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
interface NodeForGraphing {
id: string,
parents: string[],
}
// Some globals
let myMap: Map<string, string[]>;
let final = [];
let calledAlready = []; // to keep track of what has been called; prevent reculsion!
/**
* Take a parent function and return all children in proper format
* @param parent
*/
function generateFromOneParent(parent: string): NodeForGraphing[] {
const newElements = [];
if (myMap.has(parent)) {
const children = myMap.get(parent);
children.forEach((element) => {
if (!calledAlready.includes(element)) { // PREVENT RECURSION !
newElements.push({ id: element, parents: [parent] });
}
});
}
return newElements;
}
/**
* Recursive function to generate each subsequent level
* @param parents
* @param stackDepth - maximum depth of calls to trace
*/
function generateNextLevel(parents: string[], stackDepth: number): void {
calledAlready.push(...parents);
if (stackDepth === 0) {
return;
}
// Generate the NodeForGraphing[] for this 'level'
let thisLevel = [];
parents.forEach(parent => {
thisLevel.push(...generateFromOneParent(parent));
});
if (thisLevel.length) {
final.push([...thisLevel]);
}
// start building the next `level`
let nextLevel = [];
parents.forEach(parent => {
if (myMap.has(parent)) {
nextLevel.push(...myMap.get(parent));
}
});
if (nextLevel.length) {
generateNextLevel(nextLevel, stackDepth - 1);
}
}
/**
* Convert the call map to format D3 wants
* @param calledFunctions
* @param startFunction -- string of the function name we want to use as start of call graph
*/
export function convertForCascade(calledFunctions: Map<string, string[]>, startFunction: string) {
myMap = calledFunctions;
final = [];
calledAlready = [];
// 1st case -- handle manually
final.push([{ id: startFunction }]);
// all next cases generate automatically
generateNextLevel([startFunction], 10);
return final;
}