add ability to ignore covering specific code blocks
This commit is contained in:
@@ -23,8 +23,11 @@ export class ASTVisitor {
|
||||
private _modifiersStatementIds: number[] = [];
|
||||
private _statementMap: StatementMap = {};
|
||||
private _locationByOffset: LocationByOffset;
|
||||
constructor(locationByOffset: LocationByOffset) {
|
||||
private _ignoreRangesBeginingAt: number[];
|
||||
private _ignoreRangesWithin: Array<[number, number]> = [];
|
||||
constructor(locationByOffset: LocationByOffset, ignoreRangesBeginingAt: number[] = []) {
|
||||
this._locationByOffset = locationByOffset;
|
||||
this._ignoreRangesBeginingAt = ignoreRangesBeginingAt;
|
||||
}
|
||||
public getCollectedCoverageEntries(): CoverageEntriesDescription {
|
||||
const coverageEntriesDescription = {
|
||||
@@ -96,6 +99,9 @@ export class ASTVisitor {
|
||||
public ModifierInvocation(ast: Parser.ModifierInvocation): void {
|
||||
const BUILTIN_MODIFIERS = ['public', 'view', 'payable', 'external', 'internal', 'pure', 'constant'];
|
||||
if (!_.includes(BUILTIN_MODIFIERS, ast.name)) {
|
||||
if (this._ignoreExpression(ast)) {
|
||||
return;
|
||||
}
|
||||
this._modifiersStatementIds.push(this._entryId);
|
||||
this._visitStatement(ast);
|
||||
}
|
||||
@@ -106,6 +112,9 @@ export class ASTVisitor {
|
||||
right: Parser.ASTNode,
|
||||
type: BranchType,
|
||||
): void {
|
||||
if (this._ignoreExpression(ast)) {
|
||||
return;
|
||||
}
|
||||
this._branchMap[this._entryId++] = {
|
||||
line: this._getExpressionRange(ast).start.line,
|
||||
type,
|
||||
@@ -113,6 +122,9 @@ export class ASTVisitor {
|
||||
};
|
||||
}
|
||||
private _visitStatement(ast: Parser.ASTNode): void {
|
||||
if (this._ignoreExpression(ast)) {
|
||||
return;
|
||||
}
|
||||
this._statementMap[this._entryId++] = this._getExpressionRange(ast);
|
||||
}
|
||||
private _getExpressionRange(ast: Parser.ASTNode): SingleFileSourceRange {
|
||||
@@ -125,7 +137,22 @@ export class ASTVisitor {
|
||||
};
|
||||
return range;
|
||||
}
|
||||
private _ignoreExpression(ast: Parser.ASTNode): boolean {
|
||||
const [astStart, astEnd] = ast.range as [number, number];
|
||||
const isRangeIgnored = _.some(
|
||||
this._ignoreRangesWithin,
|
||||
([rangeStart, rangeEnd]: [number, number]) => astStart >= rangeStart && astEnd <= rangeEnd,
|
||||
);
|
||||
return this._ignoreRangesBeginingAt.includes(astStart) || isRangeIgnored;
|
||||
}
|
||||
private _visitFunctionLikeDefinition(ast: Parser.ModifierDefinition | Parser.FunctionDefinition): void {
|
||||
if (this._ignoreExpression(ast)) {
|
||||
// we want to ignore everything within this function
|
||||
// add this nodes range to the ignoreRangesWithin array
|
||||
// so we can ignore any later nodes that are children of this node
|
||||
this._ignoreRangesWithin.push(ast.range as [number, number]);
|
||||
return;
|
||||
}
|
||||
const loc = this._getExpressionRange(ast);
|
||||
this._fnMap[this._entryId++] = {
|
||||
name: ast.name,
|
||||
|
||||
@@ -13,10 +13,29 @@ export const collectCoverageEntries = (contractSource: string) => {
|
||||
if (_.isUndefined(coverageEntriesBySourceHash[sourceHash]) && !_.isUndefined(contractSource)) {
|
||||
const ast = parser.parse(contractSource, { range: true });
|
||||
const locationByOffset = getLocationByOffset(contractSource);
|
||||
const visitor = new ASTVisitor(locationByOffset);
|
||||
const ignoreRangesBegingingAt = gatherRangesToIgnore(contractSource);
|
||||
const visitor = new ASTVisitor(locationByOffset, ignoreRangesBegingingAt);
|
||||
parser.visit(ast, visitor);
|
||||
coverageEntriesBySourceHash[sourceHash] = visitor.getCollectedCoverageEntries();
|
||||
}
|
||||
const coverageEntriesDescription = coverageEntriesBySourceHash[sourceHash];
|
||||
return coverageEntriesDescription;
|
||||
};
|
||||
|
||||
const IGNORE_RE = /\/\*\s*solcov\s+ignore\s+next\s*\*\/\s*/gm;
|
||||
|
||||
// Gather the start index of all code blocks preceeded by "/* solcov ignore next */"
|
||||
function gatherRangesToIgnore(contractSource: string): number[] {
|
||||
const ignoreRangesStart = [];
|
||||
|
||||
let match;
|
||||
do {
|
||||
match = IGNORE_RE.exec(contractSource);
|
||||
if (match) {
|
||||
const matchLen = match[0].length;
|
||||
ignoreRangesStart.push(match.index + matchLen);
|
||||
}
|
||||
} while (match);
|
||||
|
||||
return ignoreRangesStart;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user