Add a HACK to detect coverage of the modifiers with no parameters
This commit is contained in:
@@ -7,6 +7,7 @@ export interface CoverageEntriesDescription {
|
|||||||
fnMap: FnMap;
|
fnMap: FnMap;
|
||||||
branchMap: BranchMap;
|
branchMap: BranchMap;
|
||||||
statementMap: StatementMap;
|
statementMap: StatementMap;
|
||||||
|
modifiersStatementIds: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BranchType {
|
enum BranchType {
|
||||||
@@ -19,6 +20,7 @@ export class ASTVisitor {
|
|||||||
private _entryId = 0;
|
private _entryId = 0;
|
||||||
private _fnMap: FnMap = {};
|
private _fnMap: FnMap = {};
|
||||||
private _branchMap: BranchMap = {};
|
private _branchMap: BranchMap = {};
|
||||||
|
private _modifiersStatementIds: number[] = [];
|
||||||
private _statementMap: StatementMap = {};
|
private _statementMap: StatementMap = {};
|
||||||
private _locationByOffset: LocationByOffset;
|
private _locationByOffset: LocationByOffset;
|
||||||
private static _doesLookLikeAnASTNode(ast: any): boolean {
|
private static _doesLookLikeAnASTNode(ast: any): boolean {
|
||||||
@@ -49,6 +51,7 @@ export class ASTVisitor {
|
|||||||
fnMap: this._fnMap,
|
fnMap: this._fnMap,
|
||||||
branchMap: this._branchMap,
|
branchMap: this._branchMap,
|
||||||
statementMap: this._statementMap,
|
statementMap: this._statementMap,
|
||||||
|
modifiersStatementIds: this._modifiersStatementIds,
|
||||||
};
|
};
|
||||||
return coverageEntriesDescription;
|
return coverageEntriesDescription;
|
||||||
}
|
}
|
||||||
@@ -91,6 +94,7 @@ export class ASTVisitor {
|
|||||||
private _visitModifierArgument(ast: SolidityParser.AST): void {
|
private _visitModifierArgument(ast: SolidityParser.AST): void {
|
||||||
const BUILTIN_MODIFIERS = ['public', 'view', 'payable', 'external', 'internal', 'pure', 'constant'];
|
const BUILTIN_MODIFIERS = ['public', 'view', 'payable', 'external', 'internal', 'pure', 'constant'];
|
||||||
if (!_.includes(BUILTIN_MODIFIERS, ast.name)) {
|
if (!_.includes(BUILTIN_MODIFIERS, ast.name)) {
|
||||||
|
this._modifiersStatementIds.push(this._entryId);
|
||||||
this._visitStatement(ast);
|
this._visitStatement(ast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -69,6 +69,30 @@ export class CoverageManager {
|
|||||||
);
|
);
|
||||||
functionCoverage[fnId] = isCovered;
|
functionCoverage[fnId] = isCovered;
|
||||||
}
|
}
|
||||||
|
// HACK: Solidity doesn't emit any opcodes that map back to modifiers with no args, that's why we map back to the
|
||||||
|
// function range and check if there is any covered statement within that range.
|
||||||
|
for (const modifierStatementId of coverageEntriesDescription.modifiersStatementIds) {
|
||||||
|
if (statementCoverage[modifierStatementId]) {
|
||||||
|
// Already detected as covered
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const modifierDescription = coverageEntriesDescription.statementMap[modifierStatementId];
|
||||||
|
const enclosingFunction = _.find(coverageEntriesDescription.fnMap, functionDescription =>
|
||||||
|
utils.isRangeInside(modifierDescription, functionDescription.loc),
|
||||||
|
) as FunctionDescription;
|
||||||
|
const isModifierCovered = _.some(
|
||||||
|
coverageEntriesDescription.statementMap,
|
||||||
|
(statementDescription: StatementDescription, statementId: number) => {
|
||||||
|
const isInsideTheModifierEnclosingFunction = utils.isRangeInside(
|
||||||
|
statementDescription,
|
||||||
|
enclosingFunction.loc,
|
||||||
|
);
|
||||||
|
const isCovered = statementCoverage[statementId];
|
||||||
|
return isInsideTheModifierEnclosingFunction && isCovered;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
statementCoverage[modifierStatementId] = isModifierCovered;
|
||||||
|
}
|
||||||
const partialCoverage = {
|
const partialCoverage = {
|
||||||
[contractData.sources[fileIndex]]: {
|
[contractData.sources[fileIndex]]: {
|
||||||
...coverageEntriesDescription,
|
...coverageEntriesDescription,
|
||||||
|
Reference in New Issue
Block a user