mirror of https://github.com/embarklabs/embark.git
fix(@embark/coverage): function types and single statement ifs
This commit is contained in:
parent
610d8f1baa
commit
2ce9ca6bb0
|
@ -4,3 +4,5 @@
|
|||
|
||||
Visit [embark.status.im](https://embark.status.im/) to get started with
|
||||
[Embark](https://github.com/embark-framework/embark).
|
||||
|
||||
Contracts in `test/fixture/contracts` are from [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-solidity) and [Gnosis Prediction Markets](https://github.com/gnosis/pm-contracts)
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"type": "git",
|
||||
"url": "https://github.com/embark-framework/embark.git"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"main": "./dist/lib/index.js",
|
||||
"scripts": {
|
||||
"build": "cross-env BABEL_ENV=node babel src --extensions \".ts\" --out-dir dist --root-mode upward --source-maps",
|
||||
"ci": "npm run qa",
|
||||
|
@ -35,6 +35,7 @@
|
|||
"qa": "npm-run-all lint typecheck build package",
|
||||
"reset": "npx rimraf dist embark-*.tgz package",
|
||||
"start": "npm run watch",
|
||||
"test": "nyc --reporter=html --reporter=json mocha dist/test/**/*.js --exit --no-timeouts --require source-map-support/register",
|
||||
"typecheck": "tsc",
|
||||
"watch": "run-p watch:*",
|
||||
"watch:build": "npm run build -- --verbose --watch",
|
||||
|
@ -46,16 +47,20 @@
|
|||
"embark-utils": "^4.1.0-beta.3",
|
||||
"fs-extra": "7.0.1",
|
||||
"globule": "1.2.1",
|
||||
"prettier-plugin-solidity": "1.0.0-alpha.25",
|
||||
"semver": "5.6.0",
|
||||
"solidity-parser-antlr": "0.4.2",
|
||||
"solidity-parser-antlr": "0.4.5",
|
||||
"web3-eth-contract": "1.0.0-beta.37"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.2.3",
|
||||
"@babel/core": "7.2.2",
|
||||
"@types/mocha": "5.2.0",
|
||||
"@types/prettier": "1.16.4",
|
||||
"@types/web3": "1.0.12",
|
||||
"cross-env": "5.2.0",
|
||||
"eslint": "5.7.0",
|
||||
"mocha": "5.2.0",
|
||||
"npm-run-all": "4.1.5",
|
||||
"rimraf": "2.6.3",
|
||||
"tslint": "5.16.0",
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import * as semver from "semver";
|
||||
import { ContractEnhanced } from "./contractEnhanced";
|
||||
import { encrypt } from "./eventId";
|
||||
import { InjectionPoint } from "./types";
|
||||
|
||||
const EMIT_VERSION = "0.4.21";
|
||||
|
||||
export class Injector {
|
||||
private isEmitSupported: boolean;
|
||||
|
||||
constructor(private contract: ContractEnhanced) {
|
||||
this.isEmitSupported = semver.gte(this.contract.solcVersion, EMIT_VERSION);
|
||||
}
|
||||
|
||||
public process(injectionPoint: InjectionPoint) {
|
||||
switch (injectionPoint.type) {
|
||||
case "statement":
|
||||
return this.statement(injectionPoint);
|
||||
case "contractDefinition":
|
||||
return this.contractDefinition(injectionPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private statement(injectionPoint: InjectionPoint) {
|
||||
const data = `${this.isEmitSupported ? "emit" : ""} __StatementCoverage(${encrypt(this.contract.id, injectionPoint.id)});`;
|
||||
this.insertAt(injectionPoint.location.start.line - 1, data);
|
||||
}
|
||||
|
||||
private contractDefinition(injectionPoint: InjectionPoint) {
|
||||
const data = [
|
||||
"event __StatementCoverage(uint32 value);",
|
||||
].join("\n");
|
||||
|
||||
this.insertAt(injectionPoint.location.start.line, data);
|
||||
}
|
||||
|
||||
private insertAt(line: number, data: string) {
|
||||
const lines = this.contract.source.split("\n");
|
||||
lines.splice(line, 0, data);
|
||||
this.contract.source = lines.join("\n");
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
import parser, {
|
||||
ASTNode,
|
||||
BreakStatement,
|
||||
ContinueStatement,
|
||||
ContractDefinition,
|
||||
EmitStatement,
|
||||
ExpressionStatement,
|
||||
FunctionDefinition,
|
||||
IfStatement,
|
||||
ModifierDefinition,
|
||||
ReturnStatement,
|
||||
ThrowStatement,
|
||||
VariableDeclarationStatement,
|
||||
WhileStatement,
|
||||
} from "solidity-parser-antlr";
|
||||
import { Instrumenter } from "./instrumenter";
|
||||
|
||||
export class InstrumentWalker {
|
||||
constructor(private instrumenter: Instrumenter) {
|
||||
}
|
||||
|
||||
public walk(ast: ASTNode) {
|
||||
parser.visit(ast, {
|
||||
BreakStatement: (node: BreakStatement) => {
|
||||
this.instrumenter.instrumentStatement(node);
|
||||
},
|
||||
ContinueStatement: (node: ContinueStatement) => {
|
||||
this.instrumenter.instrumentStatement(node);
|
||||
},
|
||||
ContractDefinition: (node: ContractDefinition) => {
|
||||
this.instrumenter.instrumentContractDefinition(node);
|
||||
},
|
||||
EmitStatement: (node: EmitStatement) => {
|
||||
this.instrumenter.instrumentStatement(node);
|
||||
},
|
||||
ExpressionStatement: (node: ExpressionStatement) => {
|
||||
this.instrumenter.instrumentStatement(node);
|
||||
},
|
||||
FunctionDefinition: (node: FunctionDefinition) => {
|
||||
this.instrumenter.instrumentFunction(node);
|
||||
},
|
||||
IfStatement: (node: IfStatement) => {
|
||||
this.instrumenter.instrumentStatement(node);
|
||||
this.instrumenter.instrumentIfStatement(node);
|
||||
},
|
||||
ModifierDefinition: (node: ModifierDefinition) => {
|
||||
this.instrumenter.instrumentFunction(node);
|
||||
},
|
||||
ReturnStatement: (node: ReturnStatement) => {
|
||||
this.instrumenter.instrumentStatement(node);
|
||||
},
|
||||
ThrowStatement: (node: ThrowStatement) => {
|
||||
this.instrumenter.instrumentStatement(node);
|
||||
},
|
||||
VariableDeclarationStatement: (node: VariableDeclarationStatement) => {
|
||||
this.instrumenter.instrumentStatement(node);
|
||||
},
|
||||
WhileStatement: (node: WhileStatement) => {
|
||||
this.instrumenter.instrumentStatement(node);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
import {
|
||||
ContractDefinition,
|
||||
FunctionDefinition,
|
||||
IfStatement,
|
||||
Location,
|
||||
Statement,
|
||||
} from "solidity-parser-antlr";
|
||||
|
||||
import { ContractEnhanced } from "./contractEnhanced";
|
||||
import { InjectionPoint, InjectionPointType } from "./types";
|
||||
|
||||
export class Instrumenter {
|
||||
private injectionPoints: InjectionPoint[] = [];
|
||||
|
||||
constructor(private contract: ContractEnhanced) {
|
||||
}
|
||||
|
||||
public getInjectionPoints() {
|
||||
return this.injectionPoints.sort((a, b) => b.location.start.line - a.location.start.line);
|
||||
}
|
||||
|
||||
public instrumentContractDefinition(node: ContractDefinition) {
|
||||
if (!node.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.loc.start.line === node.loc.end.line) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.addInjectionPoints("contractDefinition", 1, node.loc);
|
||||
}
|
||||
|
||||
public instrumentFunction(node: FunctionDefinition) {
|
||||
if (!node.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node.body || !node.body.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.body.loc.start.line === node.body.loc.end.line) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.contract.addFunction(node.loc, node.name, node.body.loc);
|
||||
}
|
||||
|
||||
public instrumentStatement(node: Statement) {
|
||||
if (!node.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.contract.addStatement(node.loc);
|
||||
this.addInjectionPoints("statement", id, node.loc);
|
||||
}
|
||||
|
||||
public instrumentIfStatement(node: IfStatement) {
|
||||
if (!node.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
const locations = [node.trueBody, node.falseBody].reduce((acc: Location[], body) => {
|
||||
if (body && body.loc) {
|
||||
acc.push(body.loc);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
this.contract.addBranch(node.loc.start.line, "if", locations);
|
||||
}
|
||||
|
||||
private addInjectionPoints(type: InjectionPointType, id: number, location: Location) {
|
||||
this.injectionPoints.push({type, id, location});
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { File } from "embark-utils";
|
||||
import * as fs from "fs-extra";
|
||||
import * as path from "path";
|
||||
import parser, { LineColumn, Location } from "solidity-parser-antlr";
|
||||
import parser, { LineColumn, Location, SourceUnit } from "solidity-parser-antlr";
|
||||
import { EventLog } from "web3/types";
|
||||
|
||||
import { decrypt } from "./eventId";
|
||||
|
@ -9,6 +9,7 @@ import { Injector } from "./injector";
|
|||
import { Instrumenter } from "./instrumenter";
|
||||
import { InstrumentWalker } from "./instrumentWalker";
|
||||
import { coverageContractsPath } from "./path";
|
||||
import { Printer } from "./printer";
|
||||
import { BranchType, Coverage } from "./types";
|
||||
|
||||
const STATEMENT_EVENT = "__StatementCoverage";
|
||||
|
@ -26,7 +27,7 @@ export class ContractEnhanced {
|
|||
public coverageFilepath: string;
|
||||
public originalSource: string;
|
||||
public source: string;
|
||||
private ast!: parser.ASTNode;
|
||||
private ast!: SourceUnit;
|
||||
private functionsBodyLocation: {[id: number]: Location} = {};
|
||||
|
||||
constructor(public filepath: string, public solcVersion: string) {
|
||||
|
@ -38,7 +39,7 @@ export class ContractEnhanced {
|
|||
try {
|
||||
this.source = fs.readFileSync(filepath, "utf-8");
|
||||
this.originalSource = this.source;
|
||||
this.ast = parser.parse(this.source, {loc: true, range: true});
|
||||
this.ast = parser.parse(this.source, {loc: true, range: true}) as SourceUnit;
|
||||
} catch (error) {
|
||||
const {line, column, message} = error.errors[0];
|
||||
console.warn(`Error on ${this.filepath}:${line}:${column}: "${message}". Could not setup for coverage.`);
|
||||
|
@ -67,13 +68,26 @@ export class ContractEnhanced {
|
|||
const instrumentWalker = new InstrumentWalker(instrumenter);
|
||||
instrumentWalker.walk(this.ast);
|
||||
|
||||
const injector = new Injector(this);
|
||||
const injector = new Injector(this, this.solcVersion);
|
||||
instrumenter.getInjectionPoints().forEach(injector.process.bind(injector));
|
||||
}
|
||||
|
||||
public save() {
|
||||
fs.ensureFileSync(this.coverageFilepath);
|
||||
fs.writeFileSync(this.coverageFilepath, this.source);
|
||||
|
||||
if (!this.ast) {
|
||||
return fs.writeFileSync(this.coverageFilepath, this.source);
|
||||
}
|
||||
|
||||
try {
|
||||
const printer = new Printer(this.ast);
|
||||
this.source = printer.print();
|
||||
} catch (err) {
|
||||
// Something might have happened with the printer. Write the original source.
|
||||
console.warn(`Error with coverage printer for ${this.filepath}. Please submit an issue with this code.`);
|
||||
} finally {
|
||||
fs.writeFileSync(this.coverageFilepath, this.source);
|
||||
}
|
||||
}
|
||||
|
||||
public updateCoverage(events: EventLog[]) {
|
|
@ -1,4 +1,4 @@
|
|||
import { dappPath, File, removePureView } from "embark-utils";
|
||||
import { dappPath, File } from "embark-utils";
|
||||
import * as globule from "globule";
|
||||
import * as path from "path";
|
||||
import Web3Contract from "web3/eth/contract";
|
||||
|
@ -44,7 +44,6 @@ export default class Coverage {
|
|||
contract.save();
|
||||
});
|
||||
await Promise.all(promises);
|
||||
removePureView(coverageContractsPath());
|
||||
}
|
||||
|
||||
private swapContracts() {
|
|
@ -0,0 +1,83 @@
|
|||
import { ContractEnhanced } from "./contractEnhanced";
|
||||
import { encrypt } from "./eventId";
|
||||
import { CoverageEmitNodeType, InjectionPoint } from "./types";
|
||||
|
||||
import * as semver from "semver";
|
||||
import parser, { ASTNode, ContractDefinition, EmitStatement, EventDefinition, ExpressionStatement } from "solidity-parser-antlr";
|
||||
|
||||
const EMIT_VERSION = "0.4.21";
|
||||
|
||||
const EVENT_NODE = {
|
||||
name: "__StatementCoverage",
|
||||
parameters: {
|
||||
parameters: [
|
||||
{
|
||||
name: "value",
|
||||
type: "VariableDeclaration",
|
||||
typeName: { name: "uint32", type: "ElementaryTypeName" },
|
||||
},
|
||||
],
|
||||
type: "ParameterList",
|
||||
},
|
||||
type: "EventDefinition",
|
||||
};
|
||||
|
||||
export class Injector {
|
||||
private isEmitSupported: boolean;
|
||||
|
||||
constructor(private contract: ContractEnhanced, private solcVersion: string) {
|
||||
this.solcVersion = solcVersion;
|
||||
this.isEmitSupported = semver.gte(this.solcVersion, EMIT_VERSION);
|
||||
}
|
||||
|
||||
public process(injectionPoint: InjectionPoint) {
|
||||
switch (injectionPoint.type) {
|
||||
case "statement":
|
||||
return this.statement(injectionPoint);
|
||||
case "contractDefinition":
|
||||
return this.contractDefinition(injectionPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private emitStatementNode(id: number): CoverageEmitNodeType {
|
||||
// Depending on what solidity version we're handling, "emit" statements might not
|
||||
// be supported, so we check here.
|
||||
const functionCall = {
|
||||
arguments: [{ number: id.toString(), type: "NumberLiteral", subdenomination: null }],
|
||||
expression: { name: "__StatementCoverage", type: "Identifier" },
|
||||
names: [],
|
||||
type: "FunctionCall",
|
||||
};
|
||||
|
||||
if (this.isEmitSupported) {
|
||||
return { eventCall: functionCall, type: "EmitStatement" } as EmitStatement;
|
||||
}
|
||||
|
||||
return { expression: functionCall, type: "ExpressionStatement" } as ExpressionStatement;
|
||||
}
|
||||
|
||||
private statement(injectionPoint: InjectionPoint) {
|
||||
const eventId = encrypt(this.contract.id, injectionPoint.id);
|
||||
|
||||
// Get the proper node that we're going to inject instead of building a string.
|
||||
// There _might_ be a better way to do this.
|
||||
const node = this.emitStatementNode(eventId);
|
||||
this.insertAt(node, injectionPoint);
|
||||
}
|
||||
|
||||
private contractDefinition(injectionPoint: InjectionPoint) {
|
||||
const contractNode = injectionPoint.node as ContractDefinition;
|
||||
contractNode.subNodes.splice(0, 0, EVENT_NODE as EventDefinition);
|
||||
}
|
||||
|
||||
private insertAt(emit: CoverageEmitNodeType, injectionPoint: InjectionPoint) {
|
||||
const { parent, node } = injectionPoint;
|
||||
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idx = parent.statements.findIndex((s: ASTNode) => s.loc === node.loc);
|
||||
parent.statements.splice(idx, 0, emit);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
import parser, {
|
||||
ASTNode,
|
||||
Block,
|
||||
BreakStatement,
|
||||
ContinueStatement,
|
||||
ContractDefinition,
|
||||
EmitStatement,
|
||||
ExpressionStatement,
|
||||
FunctionDefinition,
|
||||
IfStatement,
|
||||
ReturnStatement,
|
||||
SourceUnit,
|
||||
ThrowStatement,
|
||||
VariableDeclarationStatement,
|
||||
WhileStatement,
|
||||
} from "solidity-parser-antlr";
|
||||
import { Instrumenter } from "./instrumenter";
|
||||
|
||||
export class InstrumentWalker {
|
||||
private blockStack: Block[];
|
||||
|
||||
constructor(private instrumenter: Instrumenter) {
|
||||
this.blockStack = [];
|
||||
}
|
||||
|
||||
private blockTail(): Block {
|
||||
return this.blockStack[this.blockStack.length - 1];
|
||||
}
|
||||
|
||||
public walk(ast: ASTNode) {
|
||||
parser.visit(ast, {
|
||||
"Block": (node: Block) => {
|
||||
this.blockStack.push(node);
|
||||
},
|
||||
"Block:exit": (node: Block) => {
|
||||
this.blockStack.pop();
|
||||
},
|
||||
"BreakStatement": (node: BreakStatement) => {
|
||||
this.instrumenter.instrumentStatement(node, this.blockTail());
|
||||
},
|
||||
"ContinueStatement": (node: ContinueStatement) => {
|
||||
this.instrumenter.instrumentStatement(node, this.blockTail());
|
||||
},
|
||||
"ContractDefinition": (node: ContractDefinition) => {
|
||||
this.instrumenter.instrumentContractDefinition(node);
|
||||
},
|
||||
"EmitStatement": (node: EmitStatement) => {
|
||||
this.instrumenter.instrumentStatement(node, this.blockTail());
|
||||
},
|
||||
"ExpressionStatement": (node: ExpressionStatement) => {
|
||||
this.instrumenter.instrumentStatement(node, this.blockTail());
|
||||
},
|
||||
"FunctionDefinition": (node: FunctionDefinition) => {
|
||||
this.instrumenter.instrumentFunction(node);
|
||||
},
|
||||
"IfStatement": (node: IfStatement) => {
|
||||
this.instrumenter.instrumentStatement(node, this.blockTail());
|
||||
this.instrumenter.instrumentIfStatement(node);
|
||||
},
|
||||
"ReturnStatement": (node: ReturnStatement) => {
|
||||
this.instrumenter.instrumentStatement(node, this.blockTail());
|
||||
},
|
||||
"ThrowStatement": (node: ThrowStatement) => {
|
||||
this.instrumenter.instrumentStatement(node, this.blockTail());
|
||||
},
|
||||
"VariableDeclarationStatement": (node: VariableDeclarationStatement) => {
|
||||
this.instrumenter.instrumentStatement(node, this.blockTail());
|
||||
},
|
||||
"WhileStatement": (node: WhileStatement) => {
|
||||
this.instrumenter.instrumentStatement(node, this.blockTail());
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
import {
|
||||
ASTNode,
|
||||
Block,
|
||||
ContractDefinition,
|
||||
FunctionDefinition,
|
||||
IfStatement,
|
||||
Location,
|
||||
ModifierDefinition,
|
||||
Statement,
|
||||
} from "solidity-parser-antlr";
|
||||
|
||||
import {ContractEnhanced} from "./contractEnhanced";
|
||||
import {InjectionPoint, InjectionPointType} from "./types";
|
||||
|
||||
export class Instrumenter {
|
||||
private injectionPoints: InjectionPoint[] = [];
|
||||
|
||||
constructor(private contract: ContractEnhanced) {
|
||||
}
|
||||
|
||||
public getInjectionPoints() {
|
||||
return this.injectionPoints.sort((a, b) => {
|
||||
return (a.node.loc && b.node.loc) ? b.node.loc.start.line - a.node.loc.start.line : 0;
|
||||
});
|
||||
}
|
||||
|
||||
public instrumentContractDefinition(node: ContractDefinition) {
|
||||
if (!node.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.loc.start.line === node.loc.end.line) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.addInjectionPoints("contractDefinition", 1, node);
|
||||
}
|
||||
|
||||
public instrumentFunction(node: FunctionDefinition) {
|
||||
// Remove stateMutability so that the function is not exported
|
||||
// as "view" or "pure", seen as it will contain some emit
|
||||
// statements and those require a transaction.
|
||||
if (node.stateMutability === "view" || node.stateMutability === "pure") {
|
||||
node.stateMutability = undefined;
|
||||
}
|
||||
|
||||
if (!node.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node.body || !node.body.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.body.loc.start.line === node.body.loc.end.line) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.contract.addFunction(node.loc, node.name || "", node.body.loc);
|
||||
}
|
||||
|
||||
public instrumentStatement(node: Statement, parent: Block) {
|
||||
if (!node.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.contract.addStatement(node.loc);
|
||||
this.addInjectionPoints("statement", id, node, parent);
|
||||
}
|
||||
|
||||
public instrumentIfStatement(node: IfStatement) {
|
||||
if (!node.loc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that the trueBody and falseBody are Blocks. This prevents single
|
||||
// statement `if` checks from breaking when we try to add an emit statement.
|
||||
node.trueBody = this.wrapInBlock(node.trueBody);
|
||||
|
||||
if (node.falseBody) {
|
||||
node.falseBody = this.wrapInBlock(node.falseBody);
|
||||
}
|
||||
|
||||
const locations = [node.trueBody, node.falseBody].reduce((acc: Location[], body) => {
|
||||
if (body && body.loc) {
|
||||
acc.push(body.loc);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
this.contract.addBranch(node.loc.start.line, "if", locations);
|
||||
}
|
||||
|
||||
private wrapInBlock(node: Statement): Block {
|
||||
if (node.type === "Block") {
|
||||
return node;
|
||||
}
|
||||
|
||||
const newNode: Block = {
|
||||
loc: node.loc,
|
||||
range: node.range,
|
||||
statements: [node],
|
||||
type: "Block",
|
||||
};
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
private addInjectionPoints(type: InjectionPointType, id: number, node: ASTNode, parent?: Block | undefined) {
|
||||
this.injectionPoints.push({type, id, node, parent});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import fs from "fs";
|
||||
|
||||
import prettier from "prettier";
|
||||
import { printers } from "prettier-plugin-solidity";
|
||||
import { SourceUnit } from "solidity-parser-antlr";
|
||||
|
||||
export class Printer {
|
||||
constructor(private ast: SourceUnit) {}
|
||||
|
||||
public print() {
|
||||
const { ast } = this;
|
||||
|
||||
// Yes, yes. This is ridiculous. But go and try and write
|
||||
// an AST to code writer and then tell me it's ridiculous.
|
||||
let code = prettier.format("<code>", {
|
||||
parser(_, parsers, options) {
|
||||
// The types on this library don't account for Options.printer,
|
||||
// so we'll ask the typechecker to ignore this one, as it errors.
|
||||
//
|
||||
// @ts-ignore
|
||||
options.printer = printers["solidity-ast"];
|
||||
return ast;
|
||||
},
|
||||
});
|
||||
|
||||
// Fix some weird cases with the library.
|
||||
code = code.replace(/;\)/gm, ")");
|
||||
code = code.replace(/;;/gm, ";");
|
||||
|
||||
return code;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
import { Location } from "solidity-parser-antlr";
|
||||
import { ASTNode, Block, EmitStatement, ExpressionStatement, Location } from "solidity-parser-antlr";
|
||||
|
||||
export type InjectionPointType = "statement" | "contractDefinition";
|
||||
export type BranchType = "if" | "switch";
|
||||
export type CoverageEmitNodeType = EmitStatement | ExpressionStatement;
|
||||
|
||||
export interface InjectionPoint {
|
||||
type: InjectionPointType;
|
||||
id: number;
|
||||
location: Location;
|
||||
node: ASTNode;
|
||||
parent: Block | undefined;
|
||||
}
|
||||
|
||||
export interface Coverage {
|
|
@ -0,0 +1,228 @@
|
|||
pragma solidity ^0.5.0;
|
||||
|
||||
import "./IERC20.sol";
|
||||
import "../../math/SafeMath.sol";
|
||||
|
||||
/**
|
||||
* @dev Implementation of the `IERC20` interface.
|
||||
*
|
||||
* This implementation is agnostic to the way tokens are created. This means
|
||||
* that a supply mechanism has to be added in a derived contract using `_mint`.
|
||||
* For a generic mechanism see `ERC20Mintable`.
|
||||
*
|
||||
* *For a detailed writeup see our guide [How to implement supply
|
||||
* mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*
|
||||
*
|
||||
* We have followed general OpenZeppelin guidelines: functions revert instead
|
||||
* of returning `false` on failure. This behavior is nonetheless conventional
|
||||
* and does not conflict with the expectations of ERC20 applications.
|
||||
*
|
||||
* Additionally, an `Approval` event is emitted on calls to `transferFrom`.
|
||||
* This allows applications to reconstruct the allowance for all accounts just
|
||||
* by listening to said events. Other implementations of the EIP may not emit
|
||||
* these events, as it isn't required by the specification.
|
||||
*
|
||||
* Finally, the non-standard `decreaseAllowance` and `increaseAllowance`
|
||||
* functions have been added to mitigate the well-known issues around setting
|
||||
* allowances. See `IERC20.approve`.
|
||||
*/
|
||||
contract ERC20 is IERC20 {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping (address => uint256) private _balances;
|
||||
|
||||
mapping (address => mapping (address => uint256)) private _allowances;
|
||||
|
||||
uint256 private _totalSupply;
|
||||
|
||||
/**
|
||||
* @dev See `IERC20.totalSupply`.
|
||||
*/
|
||||
function totalSupply() public view returns (uint256) {
|
||||
return _totalSupply;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See `IERC20.balanceOf`.
|
||||
*/
|
||||
function balanceOf(address account) public view returns (uint256) {
|
||||
return _balances[account];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See `IERC20.transfer`.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - `recipient` cannot be the zero address.
|
||||
* - the caller must have a balance of at least `amount`.
|
||||
*/
|
||||
function transfer(address recipient, uint256 amount) public returns (bool) {
|
||||
_transfer(msg.sender, recipient, amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See `IERC20.allowance`.
|
||||
*/
|
||||
function allowance(address owner, address spender) public view returns (uint256) {
|
||||
return _allowances[owner][spender];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See `IERC20.approve`.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - `spender` cannot be the zero address.
|
||||
*/
|
||||
function approve(address spender, uint256 value) public returns (bool) {
|
||||
_approve(msg.sender, spender, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See `IERC20.transferFrom`.
|
||||
*
|
||||
* Emits an `Approval` event indicating the updated allowance. This is not
|
||||
* required by the EIP. See the note at the beginning of `ERC20`;
|
||||
*
|
||||
* Requirements:
|
||||
* - `sender` and `recipient` cannot be the zero address.
|
||||
* - `sender` must have a balance of at least `value`.
|
||||
* - the caller must have allowance for `sender`'s tokens of at least
|
||||
* `amount`.
|
||||
*/
|
||||
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
|
||||
_transfer(sender, recipient, amount);
|
||||
_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Atomically increases the allowance granted to `spender` by the caller.
|
||||
*
|
||||
* This is an alternative to `approve` that can be used as a mitigation for
|
||||
* problems described in `IERC20.approve`.
|
||||
*
|
||||
* Emits an `Approval` event indicating the updated allowance.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - `spender` cannot be the zero address.
|
||||
*/
|
||||
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
|
||||
_approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Atomically decreases the allowance granted to `spender` by the caller.
|
||||
*
|
||||
* This is an alternative to `approve` that can be used as a mitigation for
|
||||
* problems described in `IERC20.approve`.
|
||||
*
|
||||
* Emits an `Approval` event indicating the updated allowance.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - `spender` cannot be the zero address.
|
||||
* - `spender` must have allowance for the caller of at least
|
||||
* `subtractedValue`.
|
||||
*/
|
||||
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
|
||||
_approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Moves tokens `amount` from `sender` to `recipient`.
|
||||
*
|
||||
* This is internal function is equivalent to `transfer`, and can be used to
|
||||
* e.g. implement automatic token fees, slashing mechanisms, etc.
|
||||
*
|
||||
* Emits a `Transfer` event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - `sender` cannot be the zero address.
|
||||
* - `recipient` cannot be the zero address.
|
||||
* - `sender` must have a balance of at least `amount`.
|
||||
*/
|
||||
function _transfer(address sender, address recipient, uint256 amount) internal {
|
||||
require(sender != address(0), "ERC20: transfer from the zero address");
|
||||
require(recipient != address(0), "ERC20: transfer to the zero address");
|
||||
|
||||
_balances[sender] = _balances[sender].sub(amount);
|
||||
_balances[recipient] = _balances[recipient].add(amount);
|
||||
emit Transfer(sender, recipient, amount);
|
||||
}
|
||||
|
||||
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
|
||||
* the total supply.
|
||||
*
|
||||
* Emits a `Transfer` event with `from` set to the zero address.
|
||||
*
|
||||
* Requirements
|
||||
*
|
||||
* - `to` cannot be the zero address.
|
||||
*/
|
||||
function _mint(address account, uint256 amount) internal {
|
||||
require(account != address(0), "ERC20: mint to the zero address");
|
||||
|
||||
_totalSupply = _totalSupply.add(amount);
|
||||
_balances[account] = _balances[account].add(amount);
|
||||
emit Transfer(address(0), account, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Destoys `amount` tokens from `account`, reducing the
|
||||
* total supply.
|
||||
*
|
||||
* Emits a `Transfer` event with `to` set to the zero address.
|
||||
*
|
||||
* Requirements
|
||||
*
|
||||
* - `account` cannot be the zero address.
|
||||
* - `account` must have at least `amount` tokens.
|
||||
*/
|
||||
function _burn(address account, uint256 value) internal {
|
||||
require(account != address(0), "ERC20: burn from the zero address");
|
||||
|
||||
_totalSupply = _totalSupply.sub(value);
|
||||
_balances[account] = _balances[account].sub(value);
|
||||
emit Transfer(account, address(0), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
|
||||
*
|
||||
* This is internal function is equivalent to `approve`, and can be used to
|
||||
* e.g. set automatic allowances for certain subsystems, etc.
|
||||
*
|
||||
* Emits an `Approval` event.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - `owner` cannot be the zero address.
|
||||
* - `spender` cannot be the zero address.
|
||||
*/
|
||||
function _approve(address owner, address spender, uint256 value) internal {
|
||||
require(owner != address(0), "ERC20: approve from the zero address");
|
||||
require(spender != address(0), "ERC20: approve to the zero address");
|
||||
|
||||
_allowances[owner][spender] = value;
|
||||
emit Approval(owner, spender, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Destoys `amount` tokens from `account`.`amount` is then deducted
|
||||
* from the caller's allowance.
|
||||
*
|
||||
* See `_burn` and `_approve`.
|
||||
*/
|
||||
function _burnFrom(address account, uint256 amount) internal {
|
||||
_burn(account, amount);
|
||||
_approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
|
||||
}
|
||||
}
|
111
packages/embark-coverage/src/test/fixtures/contracts/GnosisStandardToken.sol
vendored
Normal file
111
packages/embark-coverage/src/test/fixtures/contracts/GnosisStandardToken.sol
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
pragma solidity ^0.4.21;
|
||||
import "./Token.sol";
|
||||
import "./Math.sol";
|
||||
import "./Proxy.sol";
|
||||
|
||||
/**
|
||||
* Deprecated: Use Open Zeppeling one instead
|
||||
*/
|
||||
contract StandardTokenData {
|
||||
|
||||
/*
|
||||
* Storage
|
||||
*/
|
||||
mapping (address => uint) balances;
|
||||
mapping (address => mapping (address => uint)) allowances;
|
||||
uint totalTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated: Use Open Zeppeling one instead
|
||||
*/
|
||||
/// @title Standard token contract with overflow protection
|
||||
contract GnosisStandardToken is Token, StandardTokenData {
|
||||
using Math for *;
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
*/
|
||||
/// @dev Transfers sender's tokens to a given address. Returns success
|
||||
/// @param to Address of token receiver
|
||||
/// @param value Number of tokens to transfer
|
||||
/// @return Was transfer successful?
|
||||
function transfer(address to, uint value)
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
if ( !balances[msg.sender].safeToSub(value)
|
||||
|| !balances[to].safeToAdd(value))
|
||||
return false;
|
||||
balances[msg.sender] -= value;
|
||||
balances[to] += value;
|
||||
emit Transfer(msg.sender, to, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @dev Allows allowed third party to transfer tokens from one address to another. Returns success
|
||||
/// @param from Address from where tokens are withdrawn
|
||||
/// @param to Address to where tokens are sent
|
||||
/// @param value Number of tokens to transfer
|
||||
/// @return Was transfer successful?
|
||||
function transferFrom(address from, address to, uint value)
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
if ( !balances[from].safeToSub(value)
|
||||
|| !allowances[from][msg.sender].safeToSub(value)
|
||||
|| !balances[to].safeToAdd(value))
|
||||
return false;
|
||||
balances[from] -= value;
|
||||
allowances[from][msg.sender] -= value;
|
||||
balances[to] += value;
|
||||
emit Transfer(from, to, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @dev Sets approved amount of tokens for spender. Returns success
|
||||
/// @param spender Address of allowed account
|
||||
/// @param value Number of approved tokens
|
||||
/// @return Was approval successful?
|
||||
function approve(address spender, uint value)
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
allowances[msg.sender][spender] = value;
|
||||
emit Approval(msg.sender, spender, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @dev Returns number of allowed tokens for given address
|
||||
/// @param owner Address of token owner
|
||||
/// @param spender Address of token spender
|
||||
/// @return Remaining allowance for spender
|
||||
function allowance(address owner, address spender)
|
||||
public
|
||||
view
|
||||
returns (uint)
|
||||
{
|
||||
return allowances[owner][spender];
|
||||
}
|
||||
|
||||
/// @dev Returns number of tokens owned by given address
|
||||
/// @param owner Address of token owner
|
||||
/// @return Balance of owner
|
||||
function balanceOf(address owner)
|
||||
public
|
||||
view
|
||||
returns (uint)
|
||||
{
|
||||
return balances[owner];
|
||||
}
|
||||
|
||||
/// @dev Returns total supply of tokens
|
||||
/// @return Total supply
|
||||
function totalSupply()
|
||||
public
|
||||
view
|
||||
returns (uint)
|
||||
{
|
||||
return totalTokens;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
pragma solidity ^0.5.0;
|
||||
|
||||
import "../access/roles/SignerRole.sol";
|
||||
import "../cryptography/ECDSA.sol";
|
||||
|
||||
/**
|
||||
* @title SignatureBouncer
|
||||
* @author PhABC, Shrugs and aflesher
|
||||
* @dev SignatureBouncer allows users to submit a signature as a permission to
|
||||
* do an action.
|
||||
* If the signature is from one of the authorized signer addresses, the
|
||||
* signature is valid.
|
||||
* Note that SignatureBouncer offers no protection against replay attacks, users
|
||||
* must add this themselves!
|
||||
*
|
||||
* Signer addresses can be individual servers signing grants or different
|
||||
* users within a decentralized club that have permission to invite other
|
||||
* members. This technique is useful for whitelists and airdrops; instead of
|
||||
* putting all valid addresses on-chain, simply sign a grant of the form
|
||||
* keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a
|
||||
* valid signer address.
|
||||
* Then restrict access to your crowdsale/whitelist/airdrop using the
|
||||
* `onlyValidSignature` modifier (or implement your own using _isValidSignature).
|
||||
* In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and
|
||||
* `onlyValidSignatureAndData` can be used to restrict access to only a given
|
||||
* method or a given method with given parameters respectively.
|
||||
* See the tests in SignatureBouncer.test.js for specific usage examples.
|
||||
*
|
||||
* @notice A method that uses the `onlyValidSignatureAndData` modifier must make
|
||||
* the _signature parameter the "last" parameter. You cannot sign a message that
|
||||
* has its own signature in it so the last 128 bytes of msg.data (which
|
||||
* represents the length of the _signature data and the _signature data itself)
|
||||
* is ignored when validating. Also non fixed sized parameters make constructing
|
||||
* the data in the signature much more complex.
|
||||
* See https://ethereum.stackexchange.com/a/50616 for more details.
|
||||
*/
|
||||
contract SignatureBouncer is SignerRole {
|
||||
using ECDSA for bytes32;
|
||||
|
||||
// Function selectors are 4 bytes long, as documented in
|
||||
// https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector
|
||||
uint256 private constant _METHOD_ID_SIZE = 4;
|
||||
// Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes
|
||||
uint256 private constant _SIGNATURE_SIZE = 96;
|
||||
|
||||
constructor () internal {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Requires that a valid signature of a signer was provided.
|
||||
*/
|
||||
modifier onlyValidSignature(bytes memory signature) {
|
||||
require(_isValidSignature(msg.sender, signature), "SignatureBouncer: invalid signature for caller");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Requires that a valid signature with a specified method of a signer was provided.
|
||||
*/
|
||||
modifier onlyValidSignatureAndMethod(bytes memory signature) {
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(_isValidSignatureAndMethod(msg.sender, signature), "SignatureBouncer: invalid signature for caller and method");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Requires that a valid signature with a specified method and params of a signer was provided.
|
||||
*/
|
||||
modifier onlyValidSignatureAndData(bytes memory signature) {
|
||||
// solhint-disable-next-line max-line-length
|
||||
require(_isValidSignatureAndData(msg.sender, signature), "SignatureBouncer: invalid signature for caller and data");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + account` from a signer?
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignature(address account, bytes memory signature) internal view returns (bool) {
|
||||
return _isValidDataHash(keccak256(abi.encodePacked(address(this), account)), signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + account + methodId` from a signer?
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignatureAndMethod(address account, bytes memory signature) internal view returns (bool) {
|
||||
bytes memory data = new bytes(_METHOD_ID_SIZE);
|
||||
for (uint i = 0; i < data.length; i++) {
|
||||
data[i] = msg.data[i];
|
||||
}
|
||||
return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev is the signature of `this + account + methodId + params(s)` from a signer?
|
||||
* @notice the signature parameter of the method being validated must be the "last" parameter
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) {
|
||||
require(msg.data.length > _SIGNATURE_SIZE, "SignatureBouncer: data is too short");
|
||||
|
||||
bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE);
|
||||
for (uint i = 0; i < data.length; i++) {
|
||||
data[i] = msg.data[i];
|
||||
}
|
||||
|
||||
return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal function to convert a hash to an eth signed message
|
||||
* and then recover the signature and check it against the signer role.
|
||||
* @return bool
|
||||
*/
|
||||
function _isValidDataHash(bytes32 hash, bytes memory signature) internal view returns (bool) {
|
||||
address signer = hash.toEthSignedMessageHash().recover(signature);
|
||||
|
||||
return signer != address(0) && isSigner(signer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
pragma solidity ^0.5.0;
|
||||
|
||||
/**
|
||||
* @title SignedSafeMath
|
||||
* @dev Signed math operations with safety checks that revert on error.
|
||||
*/
|
||||
library SignedSafeMath {
|
||||
int256 constant private INT256_MIN = -2**255;
|
||||
|
||||
/**
|
||||
* @dev Multiplies two signed integers, reverts on overflow.
|
||||
*/
|
||||
function mul(int256 a, int256 b) internal pure returns (int256) {
|
||||
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
|
||||
// benefit is lost if 'b' is also tested.
|
||||
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
require(!(a == -1 && b == INT256_MIN), "SignedSafeMath: multiplication overflow");
|
||||
|
||||
int256 c = a * b;
|
||||
require(c / a == b, "SignedSafeMath: multiplication overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
|
||||
*/
|
||||
function div(int256 a, int256 b) internal pure returns (int256) {
|
||||
require(b != 0, "SignedSafeMath: division by zero");
|
||||
require(!(b == -1 && a == INT256_MIN), "SignedSafeMath: division overflow");
|
||||
|
||||
int256 c = a / b;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Subtracts two signed integers, reverts on overflow.
|
||||
*/
|
||||
function sub(int256 a, int256 b) internal pure returns (int256) {
|
||||
int256 c = a - b;
|
||||
require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds two signed integers, reverts on overflow.
|
||||
*/
|
||||
function add(int256 a, int256 b) internal pure returns (int256) {
|
||||
int256 c = a + b;
|
||||
require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import assert from "assert";
|
||||
import fs from "fs";
|
||||
import { describe, it } from "mocha";
|
||||
import path from "path";
|
||||
import parser, { SourceUnit } from "solidity-parser-antlr";
|
||||
|
||||
import { Printer } from "../lib/printer";
|
||||
|
||||
const FIXTURE_PATH = path.join(__dirname, "../", "../", "src", "test", "fixtures", "contracts");
|
||||
const FIXTURES = fs.readdirSync(FIXTURE_PATH).map((f) => {
|
||||
const fp = path.join(FIXTURE_PATH, f);
|
||||
|
||||
return {
|
||||
basename: f,
|
||||
path: fp,
|
||||
source: fs.readFileSync(fp, "utf8"),
|
||||
};
|
||||
});
|
||||
|
||||
describe("Printer", () => {
|
||||
describe("printing an AST", () => {
|
||||
describe("prints equivalent code", () => {
|
||||
for (const fixture of FIXTURES) {
|
||||
it(fixture.basename, () => {
|
||||
const astBefore = parser.parse(fixture.source, {loc: false, range: false}) as SourceUnit;
|
||||
const printer = new Printer(astBefore);
|
||||
|
||||
const source = printer.print();
|
||||
const astAfter = parser.parse(source, {loc: false, range: false}) as SourceUnit;
|
||||
|
||||
// Remove .tokens from the AST as it gets walked and processed by
|
||||
// prettier. This is not consequential for anything else. Also, the
|
||||
// tokens property is added without types, and as we can't remove it
|
||||
// without Typescript doing some type checks, we'll have to ask it to
|
||||
// ignore those here.
|
||||
//
|
||||
// @ts-ignore
|
||||
delete astBefore.tokens;
|
||||
|
||||
assert.deepEqual(astBefore, astAfter);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
|
@ -214,6 +214,7 @@ class Solidity {
|
|||
fileCb();
|
||||
}).catch((e) => {
|
||||
self.logger.error(__('Error while loading the content of ') + filename);
|
||||
self.logger.error(JSON.stringify(e));
|
||||
self.logger.debug(e);
|
||||
fileCb();
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import "./src/prettier-plugin-solidity";
|
||||
import "./src/remix-debug-debugtest";
|
||||
import "./src/solidity-parser-antlr";
|
||||
|
||||
export * from "./src/callbacks";
|
||||
export * from "./src/contract";
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
declare module "prettier-plugin-solidity";
|
|
@ -1,332 +0,0 @@
|
|||
declare module "solidity-parser-antlr" {
|
||||
export interface LineColumn {
|
||||
line: number;
|
||||
column: number;
|
||||
}
|
||||
export interface Location {
|
||||
start: LineColumn;
|
||||
end: LineColumn;
|
||||
}
|
||||
export interface BaseASTNode {
|
||||
type: string;
|
||||
range?: [number, number];
|
||||
loc?: Location;
|
||||
}
|
||||
export interface SourceUnit extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface PragmaDirective extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface PragmaName extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface PragmaValue extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface Version extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface VersionOperator extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface VersionConstraint extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ImportDeclaration extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ImportDirective extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ContractDefinition extends BaseASTNode {
|
||||
name: string;
|
||||
}
|
||||
export interface InheritanceSpecifier extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ContractPart extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface StateVariableDeclaration extends BaseASTNode {
|
||||
variables: VariableDeclaration[];
|
||||
}
|
||||
export interface UsingForDeclaration extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface StructDefinition extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ModifierDefinition extends BaseASTNode {
|
||||
name: string;
|
||||
}
|
||||
export interface ModifierInvocation extends BaseASTNode {
|
||||
name: string;
|
||||
}
|
||||
export interface FunctionDefinition extends BaseASTNode {
|
||||
name: string;
|
||||
body?: Block;
|
||||
}
|
||||
export interface ReturnParameters extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ModifierList extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface EventDefinition extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface EnumValue extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface EnumDefinition extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ParameterList extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface Parameter extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface EventParameterList extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface EventParameter extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface FunctionTypeParameterList extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface FunctionTypeParameter extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface VariableDeclaration extends BaseASTNode {
|
||||
visibility: "public" | "private";
|
||||
isStateVar: boolean;
|
||||
}
|
||||
export interface TypeName extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface UserDefinedTypeName extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface Mapping extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface FunctionTypeName extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface StorageLocation extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface StateMutability extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface Block extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface Statement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface EmitStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ExpressionStatement extends BaseASTNode {
|
||||
expression: ASTNode;
|
||||
}
|
||||
export interface IfStatement extends BaseASTNode {
|
||||
trueBody: ASTNode;
|
||||
falseBody: ASTNode;
|
||||
}
|
||||
export interface WhileStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface SimpleStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ForStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface InlineAssemblyStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface DoWhileStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ContinueStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface BreakStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ReturnStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ThrowStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface VariableDeclarationStatement extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface IdentifierList extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ElementaryTypeName extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface Expression extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface PrimaryExpression extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ExpressionList extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface NameValueList extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface NameValue extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface FunctionCallArguments extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyBlock extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyItem extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyExpression extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyCall extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyLocalDefinition extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyAssignment extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyIdentifierOrList extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyIdentifierList extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyStackAssignment extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface LabelDefinition extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblySwitch extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyCase extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyFunctionDefinition extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyFunctionReturns extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyFor extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyIf extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface AssemblyLiteral extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface SubAssembly extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface TupleExpression extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface ElementaryTypeNameExpression extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface NumberLiteral extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
export interface Identifier extends BaseASTNode {} // tslint:disable-line:no-empty-interface
|
||||
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
|
||||
| EmitStatement
|
||||
| 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;
|
||||
EmitStatement?: (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 {
|
||||
tolerant?: boolean;
|
||||
range?: boolean;
|
||||
loc?: boolean;
|
||||
}
|
||||
export function parse(sourceCode: string, parserOpts: ParserOpts): ASTNode;
|
||||
export function visit(ast: ASTNode, visitor: Visitor): void;
|
||||
}
|
|
@ -48,7 +48,6 @@ const { extendZeroAddressShorthand, replaceZeroAddressShorthand } = AddressUtils
|
|||
|
||||
import { compact, last, recursiveMerge, groupBy } from './collections';
|
||||
import { prepareForCompilation } from './solidity/remapImports';
|
||||
import { removePureView } from './solidity/code';
|
||||
import { File, getExternalContractUrl, Types } from './file';
|
||||
|
||||
function timer(ms) {
|
||||
|
@ -320,7 +319,6 @@ const Utils = {
|
|||
Types,
|
||||
unitRegex,
|
||||
urlJoin,
|
||||
removePureView,
|
||||
runCmd,
|
||||
escapeHtml: logUtils.escapeHtml,
|
||||
normalizeInput: logUtils.normalizeInput,
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import * as fs from "fs-extra";
|
||||
import * as globule from "globule";
|
||||
import * as path from "path";
|
||||
|
||||
export const removePureView = (dir: string) => {
|
||||
globule.find(path.join(dir, "**/*.sol")).forEach((filepath) => {
|
||||
let source = fs.readFileSync(filepath, "utf-8");
|
||||
source = replacePureView(source);
|
||||
fs.writeFileSync(filepath, source);
|
||||
});
|
||||
};
|
||||
|
||||
export const replacePureView = (source: string) => {
|
||||
return source.replace(/pure/g, "").replace(/view/g, "");
|
||||
};
|
|
@ -3,7 +3,6 @@ import * as path from "path";
|
|||
import { groupBy } from "../collections";
|
||||
import { File, Types } from "../file";
|
||||
import { dappPath, embarkPath, urlJoin } from "../pathUtils";
|
||||
import { removePureView, replacePureView } from "./code";
|
||||
|
||||
const FIND_IMPORTS_REGEX = /^import[\s]*(['"])(.*)\1;/gm;
|
||||
const FIND_FILE_REGEX = /import[\s]*(['"])(.*)\1;/;
|
||||
|
@ -197,10 +196,5 @@ export const prepareForCompilation = async (file: File, isCoverage = false) => {
|
|||
content = await file.content;
|
||||
}
|
||||
|
||||
if (!isCoverage) {
|
||||
return content;
|
||||
}
|
||||
|
||||
removePureView(dappPath(".embark"));
|
||||
return replacePureView(content);
|
||||
return content;
|
||||
};
|
||||
|
|
|
@ -177,7 +177,6 @@
|
|||
"shelljs": "0.5.3",
|
||||
"simples": "0.8.8",
|
||||
"solc": "0.5.0",
|
||||
"solidity-parser-antlr": "0.4.2",
|
||||
"source-map-support": "0.5.9",
|
||||
"stream-json": "1.1.3",
|
||||
"string-replace-async": "1.2.1",
|
||||
|
|
64
yarn.lock
64
yarn.lock
|
@ -2823,6 +2823,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||
|
||||
"@types/mocha@5.2.0":
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.0.tgz#b3c8e69f038835db1a7fdc0b3d879fc50506e29e"
|
||||
integrity sha512-YeDiSEzznwZwwp766SJ6QlrTyBYUGPSIwmREHVTmktUYiT/WADdWtpt9iH0KuUSf8lZLdI4lP0X6PBzPo5//JQ==
|
||||
|
||||
"@types/node-fetch@^1.6.8":
|
||||
version "1.6.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-1.6.9.tgz#a750fb0f4cf2960bf72b462e4c86908022dd69c5"
|
||||
|
@ -2845,6 +2850,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/os-locale/-/os-locale-2.1.0.tgz#0ded736612a79e900fa76f02c6ad566d046ad17a"
|
||||
integrity sha512-1FI8uCzD//cYu6eDMrik91BevmE8xQLeV5Br2+dDjiluhTM5vtxTDXSaVY20rRV8V/XT6l+A1H12g5+hBtSQZg==
|
||||
|
||||
"@types/prettier@1.16.4":
|
||||
version "1.16.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.16.4.tgz#5e5e97702cb68498aaba7349b941648daaf2385c"
|
||||
integrity sha512-MG7ExKBo7AQ5UrL1awyYLNinNM/kyXgE4iP4Ul9fB+T7n768Z5Xem8IZeP6Bna0xze8gkDly49Rgge2HOEw4xA==
|
||||
|
||||
"@types/pretty-ms@3.2.0":
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/pretty-ms/-/pretty-ms-3.2.0.tgz#cdd35f7edac2310bbe2af86f5244625db7a101b1"
|
||||
|
@ -6789,6 +6799,11 @@ dir-glob@^2.0.0:
|
|||
dependencies:
|
||||
path-type "^3.0.0"
|
||||
|
||||
dir-to-object@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dir-to-object/-/dir-to-object-2.0.0.tgz#29723e9bd1c3e58e4f307bd04ff634c0370c8f8a"
|
||||
integrity sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA==
|
||||
|
||||
dns-equal@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
|
||||
|
@ -7095,7 +7110,7 @@ emoji-regex@^6.5.1:
|
|||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.5.1.tgz#9baea929b155565c11ea41c6626eaa65cef992c2"
|
||||
integrity sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ==
|
||||
|
||||
emoji-regex@^7.0.1:
|
||||
emoji-regex@^7.0.1, emoji-regex@^7.0.3:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
||||
|
@ -7487,6 +7502,13 @@ espree@^4.0.0:
|
|||
acorn-jsx "^5.0.0"
|
||||
eslint-visitor-keys "^1.0.0"
|
||||
|
||||
esprima-extract-comments@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz#0dacab567a5900240de6d344cf18c33617becbc9"
|
||||
integrity sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw==
|
||||
dependencies:
|
||||
esprima "^4.0.0"
|
||||
|
||||
esprima@2.7.x, esprima@^2.7.1:
|
||||
version "2.7.3"
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
|
||||
|
@ -8042,6 +8064,14 @@ extglob@^2.0.4:
|
|||
snapdragon "^0.8.1"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
extract-comments@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/extract-comments/-/extract-comments-1.1.0.tgz#b90bca033a056bd69b8ba1c6b6b120fc2ee95c18"
|
||||
integrity sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q==
|
||||
dependencies:
|
||||
esprima-extract-comments "^1.1.0"
|
||||
parse-code-context "^1.0.0"
|
||||
|
||||
extract-opts@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d"
|
||||
|
@ -13562,6 +13592,11 @@ parse-asn1@^5.0.0:
|
|||
evp_bytestokey "^1.0.0"
|
||||
pbkdf2 "^3.0.3"
|
||||
|
||||
parse-code-context@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e"
|
||||
integrity sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA==
|
||||
|
||||
parse-github-repo-url@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50"
|
||||
|
@ -14520,11 +14555,30 @@ preserve@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
|
||||
integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
|
||||
|
||||
prettier-plugin-solidity@1.0.0-alpha.25:
|
||||
version "1.0.0-alpha.25"
|
||||
resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.25.tgz#45b5c7aa68f69f2aa160cd1d2590c459cd89e6d4"
|
||||
integrity sha512-NsjhpK/td17apZz8Jnp5FDzIvXyrTGqKIg7PNrpLcKMi+XBDoMV/sFrWiN1VLI4oqjHnDJo/e4VhALiUCBHfBQ==
|
||||
dependencies:
|
||||
dir-to-object "^2.0.0"
|
||||
emoji-regex "^7.0.3"
|
||||
escape-string-regexp "^1.0.5"
|
||||
extract-comments "^1.1.0"
|
||||
prettier "^1.15.3"
|
||||
semver "^5.6.0"
|
||||
solidity-parser-antlr "^0.4.4"
|
||||
string-width "^3.0.0"
|
||||
|
||||
prettier@^1.14.2:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.1.tgz#534c2c9d7853f8845e5e078384e71973bd74089f"
|
||||
integrity sha512-XXUITwIkGb3CPJ2hforHah/zTINRyie5006Jd2HKy2qz7snEJXl0KLfsJZW/wst9g6R2rFvqba3VpNYdu1hDcA==
|
||||
|
||||
prettier@^1.15.3:
|
||||
version "1.18.2"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
|
||||
integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
|
||||
|
||||
pretty-bytes@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
|
||||
|
@ -16868,10 +16922,10 @@ solc@^0.4.13, solc@^0.4.25:
|
|||
semver "^5.3.0"
|
||||
yargs "^4.7.1"
|
||||
|
||||
solidity-parser-antlr@0.4.2:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.4.2.tgz#b862eba5936e7a90b4f5f1c8eb1d33fe86650f78"
|
||||
integrity sha512-0OKT2YKZAqPe14HN7Nbo24hjmnyUYh92UjyZG0Zz2rpQhl/w8asX8qHb+ASSXfayQaiW8g9zGIupXEE355tOQQ==
|
||||
solidity-parser-antlr@0.4.5, solidity-parser-antlr@^0.4.4:
|
||||
version "0.4.5"
|
||||
resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.4.5.tgz#4de1867f1a12df4553886209225bc80328aeb0c1"
|
||||
integrity sha512-5GzhIs4hpY3XnGwMndgrOksD567O5WdUQPbpy2n2WA1m3algzUKYMf+Ne/QHd36TTUNvVV+iTWD5tKaCZfaOjg==
|
||||
|
||||
sort-keys@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
|
Loading…
Reference in New Issue