/* eslint no-unused-expressions: ["error", { "allowShortCircuit": true }] */ /** * Methods in this file walk the AST and call the instrumenter * functions where appropriate, which determine where to inject events. * (Listed in alphabetical order) */ const parse = {}; const instrumenter = require('./instrumenter'); parse.AssignmentExpression = function parseAssignmentExpression(contract, expression) { instrumenter.prePosition(expression); instrumenter.instrumentStatement(contract, expression); instrumenter.instrumentAssignmentExpression(contract, expression); }; parse.Block = function parseBlock(contract, expression) { for (let x = 0; x < expression.statements.length; x++) { instrumenter.instrumentLine(contract, expression.statements[x]); parse[expression.statements[x].type] && parse[expression.statements[x].type](contract, expression.statements[x]); } }; parse.BinaryOperation = function parseBinaryOperation(contract, expression) { instrumenter.instrumentStatement(contract, expression); } parse.FunctionCall = function parseCallExpression(contract, expression) { // In any given chain of call expressions, only the last one will fail this check. This makes sure // we don't instrument a chain of expressions multiple times. if (expression.expression.type !== 'FunctionCall') { instrumenter.instrumentStatement(contract, expression); if (expression.expression.name === 'assert' || expression.expression.name === 'require') { instrumenter.instrumentAssertOrRequire(contract, expression); } parse[expression.expression.type] && parse[expression.expression.type](contract, expression.expression); } else { parse[expression.expression.type] && parse[expression.expression.type](contract, expression.expression); } }; parse.ConditionalExpression = function parseConditionalExpression(contract, expression) { instrumenter.instrumentStatement(contract, expression); instrumenter.instrumentConditionalExpression(contract, expression); }; parse.ContractDefinition = function ParseContractStatement(contract, expression) { parse.ContractOrLibraryStatement(contract, expression); }; parse.ContractOrLibraryStatement = function parseContractOrLibraryStatement(contract, expression) { // From the start of this contract statement, find the first '{', and inject there. const injectionPoint = expression.range[0] + contract.instrumented.slice(expression.range[0]).indexOf('{') + 1; if (contract.injectionPoints[injectionPoint]) { contract.injectionPoints[expression.range[0] + contract.instrumented.slice(expression.range[0]).indexOf('{') + 1].push({ type: 'eventDefinition', }); } else { contract.injectionPoints[expression.range[0] + contract.instrumented.slice(expression.range[0]).indexOf('{') + 1] = [{ type: 'eventDefinition', }]; } if (expression.subNodes) { expression.subNodes.forEach(construct => { parse[construct.type] && parse[construct.type](contract, construct); }); } }; parse.EmitStatement = function parseExpressionStatement(contract, expression){ instrumenter.instrumentStatement(contract, expression); }; parse.ExpressionStatement = function parseExpressionStatement(contract, content) { parse[content.expression.type] && parse[content.expression.type](contract, content.expression); }; parse.ForStatement = function parseForStatement(contract, expression) { instrumenter.instrumentStatement(contract, expression); parse[expression.body.type] && parse[expression.body.type](contract, expression.body); }; parse.FunctionDefinition = function parseFunctionDefinition(contract, expression) { parse.Modifiers(contract, expression.modifiers); if (expression.body) { instrumenter.instrumentFunctionDeclaration(contract, expression); parse[expression.body.type] && parse[expression.body.type](contract, expression.body); } }; parse.IfStatement = function parseIfStatement(contract, expression) { instrumenter.instrumentStatement(contract, expression); instrumenter.instrumentIfStatement(contract, expression); parse[expression.trueBody.type] && parse[expression.trueBody.type](contract, expression.trueBody); if (expression.falseBody) { parse[expression.falseBody.type] && parse[expression.falseBody.type](contract, expression.falseBody); } }; parse.InterfaceStatement = function parseInterfaceStatement(contract, expression) { parse.ContractOrLibraryStatement(contract, expression); }; parse.LibraryStatement = function parseLibraryStatement(contract, expression) { parse.ContractOrLibraryStatement(contract, expression); }; parse.MemberExpression = function parseMemberExpression(contract, expression) { parse[expression.object.type] && parse[expression.object.type](contract, expression.object); }; parse.Modifiers = function parseModifier(contract, modifiers) { if (modifiers) { modifiers.forEach(modifier => { parse[modifier.type] && parse[modifier.type](contract, modifier); }); } }; parse.ModifierDefinition = function parseModifierDefinition(contract, expression) { instrumenter.instrumentFunctionDeclaration(contract, expression); parse[expression.body.type] && parse[expression.body.type](contract, expression.body); }; parse.NewExpression = function parseNewExpression(contract, expression) { parse[expression.typeName.type] && parse[expression.typeName.type](contract, expression.typeName); }; parse.SourceUnit = function parseSourceUnit(contract, expression) { expression.children.forEach(construct => { parse[construct.type] && parse[construct.type](contract, construct); }); }; parse.ReturnStatement = function parseReturnStatement(contract, expression) { instrumenter.instrumentStatement(contract, expression); }; parse.UnaryExpression = function parseUnaryExpression(contract, expression) { parse[expression.argument.type] && parse[expression.argument.type](contract, expression.argument); }; parse.UsingStatement = function parseUsingStatement(contract, expression) { parse[expression.for.type] && parse[expression.for.type](contract, expression.for); }; parse.VariableDeclarationStatement = function parseVariableDeclarationStatement(contract, expression) { instrumenter.instrumentStatement(contract, expression); // parse[expression.declarations[0].id.type] && // parse[expression.declarations[0].id.type](contract, expression.declarations[0].id); }; parse.VariableDeclarationTuple = function parseVariableDeclarationTuple(contract, expression) { instrumenter.instrumentStatement(contract, expression); parse[expression.declarations[0].id.type] && parse[expression.declarations[0].id.type](contract, expression.declarations[0].id); }; parse.WhileStatement = function parseWhileStatement(contract, expression) { instrumenter.instrumentStatement(contract, expression); parse[expression.body.type] && parse[expression.body.type](contract, expression.body); }; module.exports = parse;