All files / solidity-coverage/lib preprocessor.js

96.43% Statements 27/28
100% Branches 10/10
100% Functions 7/7
96.15% Lines 25/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 701x   1x 1x 1x                     108x                         173x 173x 173x   173x   85x 30x 30x   85x 22x 22x       4x 1x 1x       6x 1x 1x           279x 173x         173x       1x  
const SolidityParser = require('@solidity-parser/parser');
 
const crRegex = /[\r\n ]+$/g;
const OPEN = '{';
const CLOSE = '}';
 
/**
 * Inserts an open or close brace e.g. `{` or `}` at specified position in solidity source
 *
 * @param  {String} contract solidity source
 * @param  {Object} item     AST node to bracket
 * @param  {Number} offset   tracks the number of previously inserted braces
 * @return {String}          contract
 */
function insertBrace(contract, item, offset) {
  return contract.slice(0,item.pos + offset) + item.type + contract.slice(item.pos + offset)
}
 
/**
 * Locates unbracketed singleton statements attached to if, else, for and while statements
 * and brackets them. Instrumenter needs to inject events at these locations and having
 * them pre-bracketed simplifies the process.
 *
 * @param  {String} contract solidity source code
 * @return {String}          modified solidity source code
 */
function preprocess(contract) {
 
  try {
    const ast = SolidityParser.parse(contract, { range: true });
    insertions = [];
 
    SolidityParser.visit(ast, {
      IfStatement: function(node) {
        if (node.trueBody.type !== 'Block') {
          insertions.push({type: OPEN, pos: node.trueBody.range[0]});
          insertions.push({type: CLOSE, pos: node.trueBody.range[1] + 1});
        }
        if ( node.falseBody && node.falseBody.type !== 'Block' ) {
          insertions.push({type: OPEN, pos: node.falseBody.range[0]});
          insertions.push({type: CLOSE, pos: node.falseBody.range[1] + 1});
        }
      },
      ForStatement: function(node){
        if (node.body.type !== 'Block'){
          insertions.push({type: OPEN, pos: node.body.range[0]});
          insertions.push({type: CLOSE, pos: node.body.range[1] + 1});
        }
      },
      WhileStatement: function(node){
        if (node.body.type !== 'Block'){
          insertions.push({type: OPEN, pos: node.body.range[0]});
          insertions.push({type: CLOSE, pos: node.body.range[1] + 1});
        }
      }
    })
 
    // Sort the insertion points.
    insertions.sort((a,b) => a.pos - b.pos);
    insertions.forEach((item, idx) => contract = insertBrace(contract, item, idx));
 
  } catch (err) {
    contract = err;
  }
  return contract;
};
 
 
module.exports = preprocess;