embark/lib/cmds/graph.js

111 lines
4.5 KiB
JavaScript
Raw Normal View History

const Viz = require('viz.js');
const fs = require('fs');
class GraphGenerator {
constructor(engine) {
this.engine = engine;
}
generate() {
let id = 0;
let contractString = "";
2018-03-22 21:11:11 +00:00
let relationshipString = "";
let idMapping = {};
let contractInheritance = {};
2018-03-22 21:11:11 +00:00
for (let contract in this.engine.contractsManager.contracts) {
id++;
2018-03-22 21:11:11 +00:00
idMapping[contract] = id;
let contractLabel = "";
contractLabel += `${contract}`;
2018-03-23 15:37:56 +00:00
let tooltip = contract;
2018-03-22 21:11:11 +00:00
if(this.engine.contractsManager.contracts[contract].instanceOf !== undefined &&
this.engine.contractsManager.contracts[this.engine.contractsManager.contracts[contract].instanceOf] !== undefined){
contractInheritance[contract] = this.engine.contractsManager.contracts[contract].instanceOf;
2018-03-23 15:37:56 +00:00
contractLabel += ": " + this.engine.contractsManager.contracts[contract].instanceOf;
tooltip += " instance of " + this.engine.contractsManager.contracts[contract].instanceOf;
} else {
contractLabel += "|";
for(let i = 0; i < this.engine.contractsManager.contracts[contract].abiDefinition.length; i++){
switch(this.engine.contractsManager.contracts[contract].abiDefinition[i].type){
case 'fallback':
contractLabel += "«fallback»()\\l";
break;
case 'constructor':
contractLabel += "«constructor»(";
for(let j = 0; j < this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs.length; j++){
contractLabel += (j == 0 ? "" : ", ") + this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs[j].type;
}
contractLabel += ")\\l";
break;
case 'event':
contractLabel += "«event»" + this.engine.contractsManager.contracts[contract].abiDefinition[i].name + "(";
for(let j = 0; j < this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs.length; j++){
contractLabel += (j == 0 ? "" : ", ") + this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs[j].type;
}
contractLabel += ")\\l";
break;
default: break;
}
}
2018-03-22 21:11:11 +00:00
2018-03-23 15:37:56 +00:00
let fHashes = this.engine.contractsManager.contracts[contract].functionHashes;
if(fHashes != {} && fHashes != undefined){
for(let method in this.engine.contractsManager.contracts[contract].functionHashes){
contractLabel += method + '\\l';
}
}
}
2018-03-23 15:37:56 +00:00
let others = ''
if(!this.engine.contractsManager.contracts[contract].deploy){
others = 'fontcolor="#c3c3c3", color="#a0a0a0"';
tooltip += " (not deployed)";
}
2018-03-23 15:39:42 +00:00
2018-03-23 15:37:56 +00:00
contractString += `${id}[label = "{${contractLabel}}", tooltip="${tooltip}", fillcolor=gray95, ${others}]\n`;
}
2018-03-22 21:11:11 +00:00
for (let c in this.engine.contractsManager.contractDependencies){
let contractDependencies = Array.from(new Set(this.engine.contractsManager.contractDependencies[c]));
contractDependencies.forEach(function(d){
if(idMapping[c] !== undefined && idMapping[d] !== undefined){
2018-03-23 15:39:42 +00:00
relationshipString += `${idMapping[d]}->${idMapping[c]}[constraint=true, arrowtail=diamond, tooltip="${c} uses ${d}"]\n`;
2018-03-22 21:11:11 +00:00
}
});
}
for (let c in contractInheritance){
2018-03-23 15:37:56 +00:00
relationshipString += `${idMapping[contractInheritance[c]]}->${idMapping[c]}[tooltip="${c} instance of ${contractInheritance[c]}"]\n`;
2018-03-22 21:11:11 +00:00
}
let dot = `
2018-03-23 15:37:56 +00:00
digraph Contracts {
node[shape=record,style=filled]
edge[dir=back, arrowtail=empty]
${contractString}
2018-03-22 21:11:11 +00:00
${relationshipString}
}`;
let svg = Viz(dot);
let filename = "diagram.svg";
fs.writeFileSync(filename, svg, (err) => {
if (err) throw err;
});
}
}
module.exports = GraphGenerator;