aboutsummaryrefslogtreecommitdiffstats
path: root/packages/sol-cov/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/sol-cov/src')
-rw-r--r--packages/sol-cov/src/ast_visitor.ts90
-rw-r--r--packages/sol-cov/src/collect_coverage_entries.ts10
-rw-r--r--packages/sol-cov/src/coverage_subprovider.ts2
-rw-r--r--packages/sol-cov/src/globals.d.ts317
4 files changed, 356 insertions, 63 deletions
diff --git a/packages/sol-cov/src/ast_visitor.ts b/packages/sol-cov/src/ast_visitor.ts
index 701cbbc88..0dddbb16e 100644
--- a/packages/sol-cov/src/ast_visitor.ts
+++ b/packages/sol-cov/src/ast_visitor.ts
@@ -1,5 +1,5 @@
import * as _ from 'lodash';
-import * as SolidityParser from 'solidity-parser-sc';
+import * as Parser from 'solidity-parser-antlr';
import { BranchMap, FnMap, LocationByOffset, SingleFileSourceRange, StatementMap } from './types';
@@ -23,29 +23,9 @@ export class ASTVisitor {
private _modifiersStatementIds: number[] = [];
private _statementMap: StatementMap = {};
private _locationByOffset: LocationByOffset;
- private static _doesLookLikeAnASTNode(ast: any): boolean {
- const isAST = _.isObject(ast) && _.isString(ast.type) && _.isNumber(ast.start) && _.isNumber(ast.end);
- return isAST;
- }
constructor(locationByOffset: LocationByOffset) {
this._locationByOffset = locationByOffset;
}
- public walkAST(astNode: SolidityParser.AST): void {
- if (_.isArray(astNode) || _.isObject(astNode)) {
- if (ASTVisitor._doesLookLikeAnASTNode(astNode)) {
- const nodeType = astNode.type;
- const visitorFunctionName = `_visit${nodeType}`;
- // tslint:disable-next-line:no-this-assignment
- const self: { [visitorFunctionName: string]: (ast: SolidityParser.AST) => void } = this as any;
- if (_.isFunction(self[visitorFunctionName])) {
- self[visitorFunctionName](astNode);
- }
- }
- _.forEach(astNode, subtree => {
- this.walkAST(subtree);
- });
- }
- }
public getCollectedCoverageEntries(): CoverageEntriesDescription {
const coverageEntriesDescription = {
fnMap: this._fnMap,
@@ -55,43 +35,38 @@ export class ASTVisitor {
};
return coverageEntriesDescription;
}
- private _visitConditionalExpression(ast: SolidityParser.AST): void {
- this._visitBinaryBranch(ast, ast.consequent, ast.alternate, BranchType.ConditionalExpression);
- }
- private _visitFunctionDeclaration(ast: SolidityParser.AST): void {
- const loc = this._getExpressionRange(ast);
- this._fnMap[this._entryId++] = {
- name: ast.name,
- line: loc.start.line,
- loc,
- };
+ public IfStatement(ast: Parser.IfStatement): void {
+ this._visitStatement(ast);
+ this._visitBinaryBranch(ast, ast.trueBody, ast.falseBody || ast, BranchType.If);
}
- private _visitBinaryExpression(ast: SolidityParser.AST): void {
- this._visitBinaryBranch(ast, ast.left, ast.right, BranchType.BinaryExpression);
+ public FunctionDefinition(ast: Parser.FunctionDefinition): void {
+ this._visitFunctionLikeDefinition(ast);
}
- private _visitIfStatement(ast: SolidityParser.AST): void {
- this._visitStatement(ast);
- this._visitBinaryBranch(ast, ast.consequent, ast.alternate || ast, BranchType.If);
+ public ModifierDefinition(ast: Parser.ModifierDefinition): void {
+ this._visitFunctionLikeDefinition(ast);
}
- private _visitBreakStatement(ast: SolidityParser.AST): void {
+ public ForStatement(ast: Parser.ForStatement): void {
this._visitStatement(ast);
}
- private _visitContractStatement(ast: SolidityParser.AST): void {
+ public ReturnStatement(ast: Parser.ReturnStatement): void {
this._visitStatement(ast);
}
- private _visitExpressionStatement(ast: SolidityParser.AST): void {
+ public BreakStatement(ast: Parser.BreakStatement): void {
this._visitStatement(ast);
}
- private _visitForStatement(ast: SolidityParser.AST): void {
- this._visitStatement(ast);
+ public ExpressionStatement(ast: Parser.ExpressionStatement): void {
+ this._visitStatement(ast.expression);
}
- private _visitPlaceholderStatement(ast: SolidityParser.AST): void {
- this._visitStatement(ast);
+ public BinaryOperation(ast: Parser.BinaryOperation): void {
+ const BRANCHING_BIN_OPS = ['&&', '||'];
+ if (_.includes(BRANCHING_BIN_OPS, ast.operator)) {
+ this._visitBinaryBranch(ast, ast.left, ast.right, BranchType.BinaryExpression);
+ }
}
- private _visitReturnStatement(ast: SolidityParser.AST): void {
- this._visitStatement(ast);
+ public Conditional(ast: Parser.Conditional): void {
+ this._visitBinaryBranch(ast, ast.trueExpression, ast.falseExpression, BranchType.ConditionalExpression);
}
- private _visitModifierArgument(ast: SolidityParser.AST): void {
+ public ModifierInvocation(ast: Parser.ModifierInvocation): void {
const BUILTIN_MODIFIERS = ['public', 'view', 'payable', 'external', 'internal', 'pure', 'constant'];
if (!_.includes(BUILTIN_MODIFIERS, ast.name)) {
this._modifiersStatementIds.push(this._entryId);
@@ -99,9 +74,9 @@ export class ASTVisitor {
}
}
private _visitBinaryBranch(
- ast: SolidityParser.AST,
- left: SolidityParser.AST,
- right: SolidityParser.AST,
+ ast: Parser.ASTNode,
+ left: Parser.ASTNode,
+ right: Parser.ASTNode,
type: BranchType,
): void {
this._branchMap[this._entryId++] = {
@@ -110,16 +85,25 @@ export class ASTVisitor {
locations: [this._getExpressionRange(left), this._getExpressionRange(right)],
};
}
- private _visitStatement(ast: SolidityParser.AST): void {
+ private _visitStatement(ast: Parser.ASTNode): void {
this._statementMap[this._entryId++] = this._getExpressionRange(ast);
}
- private _getExpressionRange(ast: SolidityParser.AST): SingleFileSourceRange {
- const start = this._locationByOffset[ast.start - 1];
- const end = this._locationByOffset[ast.end - 1];
+ private _getExpressionRange(ast: Parser.ASTNode): SingleFileSourceRange {
+ const start = this._locationByOffset[ast.range[0] - 1];
+ const end = this._locationByOffset[ast.range[1]];
const range = {
start,
end,
};
return range;
}
+ private _visitFunctionLikeDefinition(ast: Parser.ModifierDefinition | Parser.FunctionDefinition): void {
+ const loc = this._getExpressionRange(ast);
+ this._fnMap[this._entryId++] = {
+ name: ast.name,
+ line: loc.start.line,
+ loc,
+ };
+ this._visitStatement(ast);
+ }
}
diff --git a/packages/sol-cov/src/collect_coverage_entries.ts b/packages/sol-cov/src/collect_coverage_entries.ts
index d29fa2c37..6da81fbfc 100644
--- a/packages/sol-cov/src/collect_coverage_entries.ts
+++ b/packages/sol-cov/src/collect_coverage_entries.ts
@@ -2,7 +2,7 @@ import * as ethUtil from 'ethereumjs-util';
import * as fs from 'fs';
import * as _ from 'lodash';
import * as path from 'path';
-import * as SolidityParser from 'solidity-parser-sc';
+import * as parser from 'solidity-parser-antlr';
import { ASTVisitor, CoverageEntriesDescription } from './ast_visitor';
import { getLocationByOffset } from './source_maps';
@@ -13,11 +13,11 @@ const coverageEntriesBySourceHash: { [sourceHash: string]: CoverageEntriesDescri
export const collectCoverageEntries = (contractSource: string, fileName: string) => {
const sourceHash = ethUtil.sha3(contractSource).toString('hex');
if (_.isUndefined(coverageEntriesBySourceHash[sourceHash])) {
- const ast = SolidityParser.parse(contractSource);
+ const ast = parser.parse(contractSource, { range: true });
const locationByOffset = getLocationByOffset(contractSource);
- const astVisitor = new ASTVisitor(locationByOffset);
- astVisitor.walkAST(ast);
- coverageEntriesBySourceHash[sourceHash] = astVisitor.getCollectedCoverageEntries();
+ const visitor = new ASTVisitor(locationByOffset);
+ parser.visit(ast, visitor);
+ coverageEntriesBySourceHash[sourceHash] = visitor.getCollectedCoverageEntries();
}
const coverageEntriesDescription = coverageEntriesBySourceHash[sourceHash];
return coverageEntriesDescription;
diff --git a/packages/sol-cov/src/coverage_subprovider.ts b/packages/sol-cov/src/coverage_subprovider.ts
index ba7552fe6..71d90bba7 100644
--- a/packages/sol-cov/src/coverage_subprovider.ts
+++ b/packages/sol-cov/src/coverage_subprovider.ts
@@ -137,9 +137,9 @@ export class CoverageSubprovider extends Subprovider {
await this._lock.acquire();
const snapshotId = Number((await this.emitPayloadAsync({ method: 'evm_snapshot' })).result);
const fakeTxData: MaybeFakeTxData = {
- from: this._defaultFromAddress,
isFakeTransaction: true, // This transaction (and only it) is allowed to come through when the lock is locked
...callData,
+ from: callData.from || this._defaultFromAddress,
};
try {
await this.emitPayloadAsync({
diff --git a/packages/sol-cov/src/globals.d.ts b/packages/sol-cov/src/globals.d.ts
index f807730cc..54ee64684 100644
--- a/packages/sol-cov/src/globals.d.ts
+++ b/packages/sol-cov/src/globals.d.ts
@@ -1,6 +1,315 @@
// tslint:disable:completed-docs
-declare module 'solidity-parser-sc' {
- // This is too time-consuming to define and we don't rely on it anyway
- export type AST = any;
- export function parse(sourceCode: string): AST;
+declare module 'solidity-parser-antlr' {
+ export interface BaseASTNode {
+ range: [number, number];
+ }
+ export interface SourceUnit extends BaseASTNode {}
+ export interface PragmaDirective extends BaseASTNode {}
+ export interface PragmaName extends BaseASTNode {}
+ export interface PragmaValue extends BaseASTNode {}
+ export interface Version extends BaseASTNode {}
+ export interface VersionOperator extends BaseASTNode {}
+ export interface VersionConstraint extends BaseASTNode {}
+ export interface ImportDeclaration extends BaseASTNode {}
+ export interface ImportDirective extends BaseASTNode {}
+ export interface ContractDefinition extends BaseASTNode {}
+ export interface InheritanceSpecifier extends BaseASTNode {}
+ export interface ContractPart extends BaseASTNode {}
+ export interface StateVariableDeclaration extends BaseASTNode {
+ variables: VariableDeclaration[];
+ }
+ export interface UsingForDeclaration extends BaseASTNode {}
+ export interface StructDefinition extends BaseASTNode {}
+ export interface ModifierDefinition extends BaseASTNode {
+ name: string;
+ }
+ export interface ModifierInvocation extends BaseASTNode {
+ name: string;
+ }
+ export interface FunctionDefinition extends BaseASTNode {
+ name: string;
+ }
+ export interface ReturnParameters extends BaseASTNode {}
+ export interface ModifierList extends BaseASTNode {}
+ export interface EventDefinition extends BaseASTNode {}
+ export interface EnumValue extends BaseASTNode {}
+ export interface EnumDefinition extends BaseASTNode {}
+ export interface ParameterList extends BaseASTNode {}
+ export interface Parameter extends BaseASTNode {}
+ export interface EventParameterList extends BaseASTNode {}
+ export interface EventParameter extends BaseASTNode {}
+ export interface FunctionTypeParameterList extends BaseASTNode {}
+ export interface FunctionTypeParameter extends BaseASTNode {}
+ export interface VariableDeclaration extends BaseASTNode {
+ visibility: 'public' | 'private';
+ isStateVar: boolean;
+ }
+ export interface TypeName extends BaseASTNode {}
+ export interface UserDefinedTypeName extends BaseASTNode {}
+ export interface Mapping extends BaseASTNode {}
+ export interface FunctionTypeName extends BaseASTNode {}
+ export interface StorageLocation extends BaseASTNode {}
+ export interface StateMutability extends BaseASTNode {}
+ export interface Block extends BaseASTNode {}
+ export interface Statement extends BaseASTNode {}
+ export interface ExpressionStatement extends BaseASTNode {
+ expression: ASTNode;
+ }
+ export interface IfStatement extends BaseASTNode {
+ trueBody: ASTNode;
+ falseBody: ASTNode;
+ }
+ export interface WhileStatement extends BaseASTNode {}
+ export interface SimpleStatement extends BaseASTNode {}
+ export interface ForStatement extends BaseASTNode {}
+ export interface InlineAssemblyStatement extends BaseASTNode {}
+ export interface DoWhileStatement extends BaseASTNode {}
+ export interface ContinueStatement extends BaseASTNode {}
+ export interface BreakStatement extends BaseASTNode {}
+ export interface ReturnStatement extends BaseASTNode {}
+ export interface ThrowStatement extends BaseASTNode {}
+ export interface VariableDeclarationStatement extends BaseASTNode {}
+ export interface IdentifierList extends BaseASTNode {}
+ export interface ElementaryTypeName extends BaseASTNode {}
+ export interface Expression extends BaseASTNode {}
+ export interface PrimaryExpression extends BaseASTNode {}
+ export interface ExpressionList extends BaseASTNode {}
+ export interface NameValueList extends BaseASTNode {}
+ export interface NameValue extends BaseASTNode {}
+ export interface FunctionCallArguments extends BaseASTNode {}
+ export interface AssemblyBlock extends BaseASTNode {}
+ export interface AssemblyItem extends BaseASTNode {}
+ export interface AssemblyExpression extends BaseASTNode {}
+ export interface AssemblyCall extends BaseASTNode {}
+ export interface AssemblyLocalDefinition extends BaseASTNode {}
+ export interface AssemblyAssignment extends BaseASTNode {}
+ export interface AssemblyIdentifierOrList extends BaseASTNode {}
+ export interface AssemblyIdentifierList extends BaseASTNode {}
+ export interface AssemblyStackAssignment extends BaseASTNode {}
+ export interface LabelDefinition extends BaseASTNode {}
+ export interface AssemblySwitch extends BaseASTNode {}
+ export interface AssemblyCase extends BaseASTNode {}
+ export interface AssemblyFunctionDefinition extends BaseASTNode {}
+ export interface AssemblyFunctionReturns extends BaseASTNode {}
+ export interface AssemblyFor extends BaseASTNode {}
+ export interface AssemblyIf extends BaseASTNode {}
+ export interface AssemblyLiteral extends BaseASTNode {}
+ export interface SubAssembly extends BaseASTNode {}
+ export interface TupleExpression extends BaseASTNode {}
+ export interface ElementaryTypeNameExpression extends BaseASTNode {}
+ export interface NumberLiteral extends BaseASTNode {}
+ export interface Identifier extends BaseASTNode {}
+ export type BinOp =
+ | '+'
+ | '-'
+ | '*'
+ | '/'
+ | '**'
+ | '%'
+ | '<<'
+ | '>>'
+ | '&&'
+ | '||'
+ | '&'
+ | '|'
+ | '^'
+ | '<'
+ | '>'
+ | '<='
+ | '>='
+ | '=='
+ | '!='
+ | '='
+ | '|='
+ | '^='
+ | '&='
+ | '<<='
+ | '>>='
+ | '+='
+ | '-='
+ | '*='
+ | '/='
+ | '%=';
+ export interface BinaryOperation extends BaseASTNode {
+ left: ASTNode;
+ right: ASTNode;
+ operator: BinOp;
+ }
+ export interface Conditional extends BaseASTNode {
+ trueExpression: ASTNode;
+ falseExpression: ASTNode;
+ }
+
+ export type ASTNode =
+ | SourceUnit
+ | PragmaDirective
+ | PragmaName
+ | PragmaValue
+ | Version
+ | VersionOperator
+ | VersionConstraint
+ | ImportDeclaration
+ | ImportDirective
+ | ContractDefinition
+ | InheritanceSpecifier
+ | ContractPart
+ | StateVariableDeclaration
+ | UsingForDeclaration
+ | StructDefinition
+ | ModifierDefinition
+ | ModifierInvocation
+ | FunctionDefinition
+ | ReturnParameters
+ | ModifierList
+ | EventDefinition
+ | EnumValue
+ | EnumDefinition
+ | ParameterList
+ | Parameter
+ | EventParameterList
+ | EventParameter
+ | FunctionTypeParameterList
+ | FunctionTypeParameter
+ | VariableDeclaration
+ | TypeName
+ | UserDefinedTypeName
+ | Mapping
+ | FunctionTypeName
+ | StorageLocation
+ | StateMutability
+ | Block
+ | Statement
+ | ExpressionStatement
+ | IfStatement
+ | WhileStatement
+ | SimpleStatement
+ | ForStatement
+ | InlineAssemblyStatement
+ | DoWhileStatement
+ | ContinueStatement
+ | BreakStatement
+ | ReturnStatement
+ | ThrowStatement
+ | VariableDeclarationStatement
+ | IdentifierList
+ | ElementaryTypeName
+ | Expression
+ | PrimaryExpression
+ | ExpressionList
+ | NameValueList
+ | NameValue
+ | FunctionCallArguments
+ | AssemblyBlock
+ | AssemblyItem
+ | AssemblyExpression
+ | AssemblyCall
+ | AssemblyLocalDefinition
+ | AssemblyAssignment
+ | AssemblyIdentifierOrList
+ | AssemblyIdentifierList
+ | AssemblyStackAssignment
+ | LabelDefinition
+ | AssemblySwitch
+ | AssemblyCase
+ | AssemblyFunctionDefinition
+ | AssemblyFunctionReturns
+ | AssemblyFor
+ | AssemblyIf
+ | AssemblyLiteral
+ | SubAssembly
+ | TupleExpression
+ | ElementaryTypeNameExpression
+ | NumberLiteral
+ | Identifier
+ | BinaryOperation
+ | Conditional;
+ export interface Visitor {
+ SourceUnit?: (node: SourceUnit) => void;
+ PragmaDirective?: (node: PragmaDirective) => void;
+ PragmaName?: (node: PragmaName) => void;
+ PragmaValue?: (node: PragmaValue) => void;
+ Version?: (node: Version) => void;
+ VersionOperator?: (node: VersionOperator) => void;
+ VersionConstraint?: (node: VersionConstraint) => void;
+ ImportDeclaration?: (node: ImportDeclaration) => void;
+ ImportDirective?: (node: ImportDirective) => void;
+ ContractDefinition?: (node: ContractDefinition) => void;
+ InheritanceSpecifier?: (node: InheritanceSpecifier) => void;
+ ContractPart?: (node: ContractPart) => void;
+ StateVariableDeclaration?: (node: StateVariableDeclaration) => void;
+ UsingForDeclaration?: (node: UsingForDeclaration) => void;
+ StructDefinition?: (node: StructDefinition) => void;
+ ModifierDefinition?: (node: ModifierDefinition) => void;
+ ModifierInvocation?: (node: ModifierInvocation) => void;
+ FunctionDefinition?: (node: FunctionDefinition) => void;
+ ReturnParameters?: (node: ReturnParameters) => void;
+ ModifierList?: (node: ModifierList) => void;
+ EventDefinition?: (node: EventDefinition) => void;
+ EnumValue?: (node: EnumValue) => void;
+ EnumDefinition?: (node: EnumDefinition) => void;
+ ParameterList?: (node: ParameterList) => void;
+ Parameter?: (node: Parameter) => void;
+ EventParameterList?: (node: EventParameterList) => void;
+ EventParameter?: (node: EventParameter) => void;
+ FunctionTypeParameterList?: (node: FunctionTypeParameterList) => void;
+ FunctionTypeParameter?: (node: FunctionTypeParameter) => void;
+ VariableDeclaration?: (node: VariableDeclaration) => void;
+ TypeName?: (node: TypeName) => void;
+ UserDefinedTypeName?: (node: UserDefinedTypeName) => void;
+ Mapping?: (node: Mapping) => void;
+ FunctionTypeName?: (node: FunctionTypeName) => void;
+ StorageLocation?: (node: StorageLocation) => void;
+ StateMutability?: (node: StateMutability) => void;
+ Block?: (node: Block) => void;
+ Statement?: (node: Statement) => void;
+ ExpressionStatement?: (node: ExpressionStatement) => void;
+ IfStatement?: (node: IfStatement) => void;
+ WhileStatement?: (node: WhileStatement) => void;
+ SimpleStatement?: (node: SimpleStatement) => void;
+ ForStatement?: (node: ForStatement) => void;
+ InlineAssemblyStatement?: (node: InlineAssemblyStatement) => void;
+ DoWhileStatement?: (node: DoWhileStatement) => void;
+ ContinueStatement?: (node: ContinueStatement) => void;
+ BreakStatement?: (node: BreakStatement) => void;
+ ReturnStatement?: (node: ReturnStatement) => void;
+ ThrowStatement?: (node: ThrowStatement) => void;
+ VariableDeclarationStatement?: (node: VariableDeclarationStatement) => void;
+ IdentifierList?: (node: IdentifierList) => void;
+ ElementaryTypeName?: (node: ElementaryTypeName) => void;
+ Expression?: (node: Expression) => void;
+ PrimaryExpression?: (node: PrimaryExpression) => void;
+ ExpressionList?: (node: ExpressionList) => void;
+ NameValueList?: (node: NameValueList) => void;
+ NameValue?: (node: NameValue) => void;
+ FunctionCallArguments?: (node: FunctionCallArguments) => void;
+ AssemblyBlock?: (node: AssemblyBlock) => void;
+ AssemblyItem?: (node: AssemblyItem) => void;
+ AssemblyExpression?: (node: AssemblyExpression) => void;
+ AssemblyCall?: (node: AssemblyCall) => void;
+ AssemblyLocalDefinition?: (node: AssemblyLocalDefinition) => void;
+ AssemblyAssignment?: (node: AssemblyAssignment) => void;
+ AssemblyIdentifierOrList?: (node: AssemblyIdentifierOrList) => void;
+ AssemblyIdentifierList?: (node: AssemblyIdentifierList) => void;
+ AssemblyStackAssignment?: (node: AssemblyStackAssignment) => void;
+ LabelDefinition?: (node: LabelDefinition) => void;
+ AssemblySwitch?: (node: AssemblySwitch) => void;
+ AssemblyCase?: (node: AssemblyCase) => void;
+ AssemblyFunctionDefinition?: (node: AssemblyFunctionDefinition) => void;
+ AssemblyFunctionReturns?: (node: AssemblyFunctionReturns) => void;
+ AssemblyFor?: (node: AssemblyFor) => void;
+ AssemblyIf?: (node: AssemblyIf) => void;
+ AssemblyLiteral?: (node: AssemblyLiteral) => void;
+ SubAssembly?: (node: SubAssembly) => void;
+ TupleExpression?: (node: TupleExpression) => void;
+ ElementaryTypeNameExpression?: (node: ElementaryTypeNameExpression) => void;
+ NumberLiteral?: (node: NumberLiteral) => void;
+ Identifier?: (node: Identifier) => void;
+ BinaryOperation?: (node: BinaryOperation) => void;
+ Conditional?: (node: Conditional) => void;
+ }
+ export interface ParserOpts {
+ range?: boolean;
+ }
+ export function parse(sourceCode: string, parserOpts: ParserOpts): ASTNode;
+ export function visit(ast: ASTNode, visitor: Visitor): void;
}