Linting things

This commit is contained in:
Andre Medeiros 2018-08-09 16:46:20 -04:00
parent 22d809ba22
commit 0ec3ff0ddc
6 changed files with 51 additions and 57 deletions

View File

@ -186,7 +186,7 @@
"no-unmodified-loop-condition": "error", "no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "error", "no-unneeded-ternary": "error",
"no-unused-expressions": "error", "no-unused-expressions": "error",
"no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], "no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_"}],
"no-use-before-define": "off", "no-use-before-define": "off",
"no-useless-call": "off", "no-useless-call": "off",
"no-useless-computed-key": "error", "no-useless-computed-key": "error",

View File

@ -23,23 +23,21 @@ class ContractSource {
} }
sourceMapToLocations(sourceMap) { sourceMapToLocations(sourceMap) {
var [offset, length, ..._rest] = sourceMap.split(":").map((val) => { var [offset, length, ..._] = sourceMap.split(":").map((val) => {
return parseInt(val, 10); return parseInt(val, 10);
}); });
var locations = {}; var locations = {};
for(var i = 0; i < this.lineCount; i++) { for(let i = 0; i < this.lineCount; i++) {
if(this.lineOffsets[i+1] <= offset) if(this.lineOffsets[i+1] <= offset) continue;
continue;
locations.start = {line: i, column: offset - this.lineOffsets[i]}; locations.start = {line: i, column: offset - this.lineOffsets[i]};
break; break;
} }
for(var i = locations.start.line; i < this.lineCount; i++) { for(var i = locations.start.line; i < this.lineCount; i++) {
if(this.lineOffsets[i+1] <= offset + length) if(this.lineOffsets[i+1] <= offset + length) continue;
continue;
locations.end = {line: i, column: ((offset + length) - this.lineOffsets[i])}; locations.end = {line: i, column: ((offset + length) - this.lineOffsets[i])};
break; break;
@ -81,7 +79,7 @@ class ContractSource {
instruction: instruction, instruction: instruction,
sourceMap: sourceMaps[instructions], sourceMap: sourceMaps[instructions],
seen: false seen: false
} };
pc += length; pc += length;
instructions++; instructions++;
@ -90,9 +88,9 @@ class ContractSource {
} }
} }
/*eslint complexity: ["error", 27]*/
generateCodeCoverage(trace) { generateCodeCoverage(trace) {
if(!this.ast || !this.contractBytecode) if(!this.ast || !this.contractBytecode) throw new Error('Error generating coverage: solc output was not assigned');
throw new Error('Error generating coverage: solc output was not assigned');
var coverage = { var coverage = {
code: this.body.split("\n"), code: this.body.split("\n"),
@ -103,18 +101,15 @@ class ContractSource {
f: {}, f: {},
fnMap: {}, fnMap: {},
statementMap: {}, statementMap: {},
branchMap: {}, branchMap: {}
}; };
var nodesRequiringVisiting = [this.ast]; var nodesRequiringVisiting = [this.ast];
var nodeStack = [];
var sourceMapToNodeType = {}; var sourceMapToNodeType = {};
do { do {
var node = nodesRequiringVisiting.pop(); var node = nodesRequiringVisiting.pop();
if(!node) continue;
if(!node)
continue;
var children = []; var children = [];
var markLocations = []; var markLocations = [];
@ -152,18 +147,15 @@ class ContractSource {
markLocations = [location, trueBranchLocation, falseBranchLocation]; markLocations = [location, trueBranchLocation, falseBranchLocation];
if(node.trueBody.statements[0]) if(node.trueBody.statements[0]) {
node.trueBody.statements[0]._parent = {type: 'b', id: node.id, idx: 0} node.trueBody.statements[0]._parent = {type: 'b', id: node.id, idx: 0};
}
if(node.falseBody && node.falseBody.statements[0]) if(node.falseBody && node.falseBody.statements[0]) {
node.falseBody.statements[0]._parent = {type: 'b', id: node.id, idx: 1} node.falseBody.statements[0]._parent = {type: 'b', id: node.id, idx: 1};
}
sourceMapToNodeType[node.src] = [{
type: 'b',
id: node.id,
body: {loc: location},
}]
sourceMapToNodeType[node.src] = [{type: 'b', id: node.id, body: {loc: location}}];
break; break;
case 'BinaryOperation': case 'BinaryOperation':
@ -175,12 +167,13 @@ class ContractSource {
// return "body". We don't `break` here on purpose so it can share the // return "body". We don't `break` here on purpose so it can share the
// same logic below. // same logic below.
node.src = node.expression.src; node.src = node.expression.src;
// falls through
case 'Assignment': case 'Assignment':
case 'ExpressionStatement': case 'ExpressionStatement':
coverage.s[node.id] = 0; coverage.s[node.id] = 0;
var location = this.sourceMapToLocations(node.src); location = this.sourceMapToLocations(node.src);
coverage.statementMap[node.id] = location; coverage.statementMap[node.id] = location;
if(!sourceMapToNodeType[node.src]) sourceMapToNodeType[node.src] = []; if(!sourceMapToNodeType[node.src]) sourceMapToNodeType[node.src] = [];
@ -188,7 +181,7 @@ class ContractSource {
type: 's', type: 's',
id: node.id, id: node.id,
body: {loc: coverage.statementMap[node.id]}, body: {loc: coverage.statementMap[node.id]},
parent: node._parent, parent: node._parent
}); });
@ -217,21 +210,17 @@ class ContractSource {
).toString(); ).toString();
var fnName = node.isConstructor ? "(constructor)" : node.name; var fnName = node.isConstructor ? "(constructor)" : node.name;
var location = this.sourceMapToLocations(functionDefinitionSourceMap); location = this.sourceMapToLocations(functionDefinitionSourceMap);
coverage.f[node.id] = 0; coverage.f[node.id] = 0;
coverage.fnMap[node.id] = { coverage.fnMap[node.id] = {
name: fnName, name: fnName,
line: location.start.line, line: location.start.line,
loc: location, loc: location
}; };
// Record function positions. // Record function positions.
sourceMapToNodeType[node.src] = [{ sourceMapToNodeType[node.src] = [{type: 'f', id: node.id, body: coverage.fnMap[node.id]}];
type: 'f',
id: node.id,
body: coverage.fnMap[node.id],
}];
if(node.body) children = node.body.statements; if(node.body) children = node.body.statements;
markLocations = [location]; markLocations = [location];
@ -266,17 +255,15 @@ class ContractSource {
contractMatches = false; contractMatches = false;
return; return;
} }
}) });
if(!contractMatches) break; if(!contractMatches) break;
trace.structLogs.forEach((step) => { trace.structLogs.forEach((step) => {
var step = bytecode[step.pc]; step = bytecode[step.pc];
if(!step.sourceMap || step.sourceMap == '') return;
if(!step.sourceMap || step.sourceMap == '') var nodes = sourceMapToNodeType[step.sourceMap];
return;
var nodes = sourceMapToNodeType[step.sourceMap] ;
if(!nodes) return; if(!nodes) return;
@ -291,16 +278,17 @@ class ContractSource {
recordedLineHit = true; recordedLineHit = true;
} }
if(node.type != 'b') if(node.type != 'b') coverage[node.type][node.id]++;
coverage[node.type][node.id]++;
if(!node.parent) if(!node.parent) return;
return;
switch(node.parent.type) { switch(node.parent.type) {
case 'b': case 'b':
coverage.b[node.parent.id][node.parent.idx]++; coverage.b[node.parent.id][node.parent.idx]++;
break; break;
default:
// do nothing
} }
}); });
}); });
@ -310,9 +298,7 @@ class ContractSource {
} }
_instructionLength(instruction) { _instructionLength(instruction) {
if(instruction.indexOf('PUSH') == -1) if(instruction.indexOf('PUSH') == -1) return 1;
return 1;
return parseInt(instruction.match(/PUSH(\d+)/m)[1], 10) + 1; return parseInt(instruction.match(/PUSH(\d+)/m)[1], 10) + 1;
} }
} }

View File

@ -19,6 +19,7 @@ class ContractSources {
// No 'break' statement here on purpose, as it shares // No 'break' statement here on purpose, as it shares
// the logic below. // the logic below.
files = [files]; files = [files];
// falls through
case '[object Array]': case '[object Array]':
files.forEach((file) => { files.forEach((file) => {
@ -31,6 +32,9 @@ class ContractSources {
} }
}); });
break; break;
default:
throw new Error(`Don't know how to initialize with ${Object.prototype.toString.call(files)}`);
} }
} }
@ -48,10 +52,7 @@ class ContractSources {
for(var file in output.contracts) { for(var file in output.contracts) {
var basename = path.basename(file); var basename = path.basename(file);
var contractSource = this.files[basename]; var contractSource = this.files[basename];
if(!contractSource){ if(!contractSource) continue;
continue; // TODO CHECK THIS LOGIC
throw new Error(`Can't attribute output to ${file}: file has not been read in.`);
}
contractSource.parseSolcOutput(output.sources[file], output.contracts[file]); contractSource.parseSolcOutput(output.sources[file], output.contracts[file]);
} }

View File

@ -45,15 +45,23 @@ class CodeCoverage {
} }
async runSolc(receipt) { async runSolc(receipt) {
var block = await web3.eth.getBlock(receipt.number); let block = await web3.eth.getBlock(receipt.number);
for(var i in block.transactions) { if(block.transactions.length == 0) return;
let requests = [];
for(let i in block.transactions) {
var txHash = block.transactions[i]; var txHash = block.transactions[i];
if(this.seenTransactions[txHash]) return; if(this.seenTransactions[txHash]) return;
this.seenTransactions[txHash] = true; this.seenTransactions[txHash] = true;
var trace = await web3.debug.traceTransaction(txHash, {}); requests.push(web3.debug.traceTransaction(txHash, {}));
var cov = this.contractSources.generateCodeCoverage(trace); }
let traces = await Promise.all(requests);
for(let i in traces) {
var cov = this.contractSources.generateCodeCoverage(traces[i]);
this.coverageReport = cov; this.coverageReport = cov;
} }
} }

View File

@ -1,7 +1,7 @@
class SourceMap { class SourceMap {
constructor(sourceMapStringOrOffset, length, id) { constructor(sourceMapStringOrOffset, length, id) {
if(typeof sourceMapStringOrOffset == 'string') { if(typeof sourceMapStringOrOffset == 'string') {
var [offset, length, id, ..._rest] = sourceMapStringOrOffset.split(":"); let [offset, length, id, ..._rest] = sourceMapStringOrOffset.split(":");
this.offset = parseInt(offset, 10); this.offset = parseInt(offset, 10);
this.length = parseInt(length, 10); this.length = parseInt(length, 10);

View File

@ -97,7 +97,6 @@ class Solidity {
return callback(err); return callback(err);
} }
output.errors = []; // TODO REMOVE THIS
if (output.errors) { if (output.errors) {
for (let i=0; i<output.errors.length; i++) { for (let i=0; i<output.errors.length; i++) {
if (output.errors[i].type === 'Warning') { if (output.errors[i].type === 'Warning') {