Extra functionality for deciding which elements to include in a graph

This commit is contained in:
Richard Ramos 2018-05-04 16:17:12 -04:00
parent 451c0bf2de
commit 3f8450f060
3 changed files with 32 additions and 18 deletions

View File

@ -191,11 +191,17 @@ class Cmd {
graph() { graph() {
program program
.command('graph [environment]') .command('graph [environment]')
.option('--skip-undeployed', 'Graph will not include undeployed contracts')
.option('--skip-functions', 'Graph will not include functions')
.option('--skip-events', 'Graph will not include events')
.description('generates documentation based on the smart contracts configured') .description('generates documentation based on the smart contracts configured')
.action(function (env, options) { .action(function (env, options) {
embark.graph({ embark.graph({
env: env || 'development', env: env || 'development',
logFile: options.logfile logFile: options.logfile,
skipUndeployed: options.skipUndeployed,
skipFunctions: options.skipFunctions,
skipEvents: options.skipEvents
}); });
}); });
} }

View File

@ -6,15 +6,16 @@ class GraphGenerator {
this.engine = engine; this.engine = engine;
} }
generate() { generate(options) {
let id = 0; let id = 0;
let contractString = ""; let contractString = "";
let relationshipString = ""; let relationshipString = "";
let idMapping = {}; let idMapping = {};
let contractInheritance = {}; let contractInheritance = {};
for (let contract in this.engine.contractsManager.contracts) { for (let contract in this.engine.contractsManager.contracts) {
if(options.skipUndeployed && !this.engine.contractsManager.contracts[contract].deploy) continue;
id++; id++;
idMapping[contract] = id; idMapping[contract] = id;
@ -30,23 +31,27 @@ class GraphGenerator {
contractLabel += ": " + this.engine.contractsManager.contracts[contract].instanceOf; contractLabel += ": " + this.engine.contractsManager.contracts[contract].instanceOf;
tooltip += " instance of " + this.engine.contractsManager.contracts[contract].instanceOf; tooltip += " instance of " + this.engine.contractsManager.contracts[contract].instanceOf;
} else { } else {
contractLabel += "|"; if(!(options.skipFunctions === true && options.skipEvents === true)) contractLabel += "|";
for(let i = 0; i < this.engine.contractsManager.contracts[contract].abiDefinition.length; i++){ for(let i = 0; i < this.engine.contractsManager.contracts[contract].abiDefinition.length; i++){
switch(this.engine.contractsManager.contracts[contract].abiDefinition[i].type){ let abiDef = this.engine.contractsManager.contracts[contract].abiDefinition[i];
if(abiDef.type == 'event' && options.skipEvents) continue;
if(['constructor', 'fallback'].indexOf(abiDef.type) > -1 && options.skipFunctions) continue;
switch(abiDef.type){
case 'fallback': case 'fallback':
contractLabel += "«fallback»()\\l"; contractLabel += "«fallback»()\\l";
break; break;
case 'constructor': case 'constructor':
contractLabel += "«constructor»("; contractLabel += "«constructor»(";
this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs.forEach(function(elem, index){ abiDef.inputs.forEach(function(elem, index){
contractLabel += (index == 0 ? "" : ", ") + elem.type; contractLabel += (index == 0 ? "" : ", ") + elem.type;
}); });
contractLabel += ")\\l"; contractLabel += ")\\l";
break; break;
case 'event': case 'event':
contractLabel += "«event»" + this.engine.contractsManager.contracts[contract].abiDefinition[i].name + "("; contractLabel += "«event»" + abiDef.name + "(";
this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs.forEach(function(elem, index){ abiDef.inputs.forEach(function(elem, index){
contractLabel += (index == 0 ? "" : ", ") + elem.type; contractLabel += (index == 0 ? "" : ", ") + elem.type;
}); });
contractLabel += ")\\l"; contractLabel += ")\\l";
@ -56,7 +61,7 @@ class GraphGenerator {
} }
let fHashes = this.engine.contractsManager.contracts[contract].functionHashes; let fHashes = this.engine.contractsManager.contracts[contract].functionHashes;
if(fHashes != {} && fHashes != undefined){ if(fHashes != {} && fHashes != undefined && !options.skipFunctions){
for(let method in this.engine.contractsManager.contracts[contract].functionHashes){ for(let method in this.engine.contractsManager.contracts[contract].functionHashes){
contractLabel += method + '\\l'; contractLabel += method + '\\l';
} }
@ -75,18 +80,21 @@ class GraphGenerator {
for (let c in this.engine.contractsManager.contractDependencies){ for (let c in this.engine.contractsManager.contractDependencies){
let contractDependencies = Array.from(new Set(this.engine.contractsManager.contractDependencies[c])); let contractDependencies = Array.from(new Set(this.engine.contractsManager.contractDependencies[c]));
contractDependencies.forEach(function(d){ contractDependencies.forEach((d) => {
if(idMapping[c] !== undefined && idMapping[d] !== undefined){ if(idMapping[c] !== undefined && idMapping[d] !== undefined){
relationshipString += `${idMapping[d]}->${idMapping[c]}[constraint=true, arrowtail=diamond, tooltip="${c} uses ${d}"]\n`; if(options.skipUndeployed && this.engine.contractsManager.contracts[c].deploy && this.engine.contractsManager.contracts[d].deploy){
relationshipString += `${idMapping[d]}->${idMapping[c]}[constraint=true, arrowtail=diamond, tooltip="${c} uses ${d}"]\n`;
}
} }
}); });
} }
for (let c in contractInheritance){ for (let c in contractInheritance){
if(options.skipUndeployed && !this.engine.contractsManager.contracts[contractInheritance[c]].deploy) continue;
relationshipString += `${idMapping[contractInheritance[c]]}->${idMapping[c]}[tooltip="${c} instance of ${contractInheritance[c]}"]\n`; relationshipString += `${idMapping[contractInheritance[c]]}->${idMapping[c]}[tooltip="${c} instance of ${contractInheritance[c]}"]\n`;
} }
let dot = ` let dot = `
digraph Contracts { digraph Contracts {
node[shape=record,style=filled] node[shape=record,style=filled]

View File

@ -254,7 +254,7 @@ class Embark {
callback(err); callback(err);
}); });
} }
], function (err, _result) { ], (err, _result) => {
if (err) { if (err) {
engine.logger.error(err.message); engine.logger.error(err.message);
engine.logger.info(err.stack); engine.logger.info(err.stack);
@ -262,9 +262,9 @@ class Embark {
const GraphGenerator = require('./cmds/graph.js'); const GraphGenerator = require('./cmds/graph.js');
let graphGen = new GraphGenerator(engine); let graphGen = new GraphGenerator(engine);
graphGen.generate(); graphGen.generate(options);
engine.logger.info("Done".underline); engine.logger.info("Done. ./diagram.svg generated".underline);
process.exit(); process.exit();
} }
}); });