<commit_before>// var SolidityParser = require("solidity-parser");
var solparse = require("solparse");

var path = require("path");
module.exports = function(contract, fileName, instrumentingActive){

	// var result = SolidityParser.parseFile("./" + pathToFile);
	var result = solparse.parse(contract);
	var instrumented = "";
	const __INDENTATION__ = "    ";
	var parse = {};
	var runnableLines=[];
	var fnMap = {};
	var fnId = 0;
	var branchMap = {};
	var branchId = 0;
	var statementMap = {};
	var statementId = 0;
	var linecount = 1;
	var injectionPoints = {};

	function createOrAppendInjectionPoint(key, value){
		if (injectionPoints[key]){
			injectionPoints[key].push(value);
		}else{
			injectionPoints[key] = [value];
		}
	}

	function instrumentAssignmentExpression(expression){
		//The only time we instrument an assignment expression is if there's a conditional expression on
		//the right
		if (expression.right.type==='ConditionalExpression'){
			if (expression.left.type==='DeclarativeExpression'){
				//Then we need to go from bytes32 varname = (conditional expression)
				//to 					  bytes32 varname; (,varname) = (conditional expression)
				createOrAppendInjectionPoint(expression.left.end, {type:"literal", string:"; (," + expression.left.name + ")"});
			}else {
				console.log(expression.left)
				process.exit();
			}
		}
	}

	function instrumentConditionalExpression(expression){
		branchId +=1;

		startline = (contract.slice(0,expression.start).match(/\n/g)||[]).length + 1;
		var startcol = expression.start - contract.slice(0,expression.start).lastIndexOf('\n') -1;
		consequentStartCol = startcol + expression.consequent.start - expression.start;
		consequentEndCol = consequentStartCol + expression.consequent.end - expression.consequent.start;
		alternateStartCol = startcol + expression.alternate.start - expression.start;
		alternateEndCol = alternateStartCol + expression.alternate.end - expression.alternate.start;
		//NB locations for conditional branches in istanbul are length 1 and associated with the : and ?.
		branchMap[branchId] = {line:startline, type:'cond-expr', locations:[{start:{line:startline, column:consequentStartCol},end:{line:startline,column:consequentEndCol}},{start:{line:startline, column:alternateStartCol},end:{line:startline,column:alternateEndCol}}]}

		//Right, this could be being used just by itself or as an assignment. In the case of the latter, because
		//the comma operator doesn't exist, we're going to have to get funky.
		//if we're on a line by ourselves, this is easier
		//
		//Now if we've got to wrap the expression it's being set equal to, do that...


		//Wrap the consequent
		createOrAppendInjectionPoint(expression.consequent.start, {type:"openParen"});
		createOrAppendInjectionPoint(expression.consequent.start, {type:"callBranchEvent",comma:true, branchId: branchId, locationIdx: 0});
		createOrAppendInjectionPoint(expression.consequent.end, {type:"closeParen"});

		//Wrap the alternate
		createOrAppendInjectionPoint(expression.alternate.start, {type:"openParen"});
		createOrAppendInjectionPoint(expression.alternate.start, {type:"callBranchEvent",comma:true, branchId: branchId, locationIdx: 1});
		createOrAppendInjectionPoint(expression.alternate.end, {type:"closeParen"});
	}

	function instrumentStatement(expression){
		canCover = false;
		//Can only instrument here if this is a self-contained statement
		//So if this is the start of the line, we're good
		if ( contract.slice(contract.slice(0,expression.start).lastIndexOf('\n'), expression.start).trim().length===0 ){
			canCover=true;
		}
		//If it's preceeded by a '{', we're good
		if ( contract.slice(contract.slice(0,expression.start).lastIndexOf('{')+1, expression.start).trim().length===0 ){
			canCover=true;
		}

		//If it's preceeded by a ';', we're good
		if ( contract.slice(contract.slice(0,expression.start).lastIndexOf(';')+1, expression.start).trim().length===0 ){
			canCover=true;
		}

		if (!canCover){return;}
		//We need to work out the lines and columns the expression starts and ends
		statementId +=1;
		linecount = (contract.slice(0,expression.start).match(/\n/g)||[]).length + 1;
		var startline = linecount;
		var startcol = expression.start - contract.slice(0,expression.start).lastIndexOf('\n') -1;
		var expressionContent = contract.slice(expression.start, expression.end);

		var endline = startline + (expressionContent.match('/\n/g') || []).length ;
		var endcol;
		if (expressionContent.lastIndexOf('\n')>=0){
			endcol = contract.slice(expressionContent.lastIndexOf('\n'), expression.end).length -1;
		}else{
			endcol = startcol + expressionContent.length -1;

		}
		statementMap[statementId] = {start:{line: startline, column:startcol},end:{line:endline, column:endcol}}

		createOrAppendInjectionPoint(expression.start, {type:"statement", statementId: statementId});
	}

	function instrumentLine(expression){
		//what's the position of the most recent newline?
		var startchar = expression.start
		var endchar = expression.end
		lastNewLine = contract.slice(0, startchar).lastIndexOf('\n');
		nextNewLine = startchar + contract.slice(startchar).indexOf('\n');
		var contractSnipped = contract.slice(lastNewLine, nextNewLine);
		//Remove comments
		while (contractSnipped.trim().slice(0,2)==='//'){
			contractSnipped.replace(/\/\/.*?/g,"");
		}
		// Is everything before us and after us on this line whitespace?
		if (contract.slice(lastNewLine, startchar).trim().length===0 && contract.slice(endchar,nextNewLine).replace(';','').trim().length===0){
			createOrAppendInjectionPoint(lastNewLine+1,{type:"callEvent"});
		}
	}

	function instrumentFunctionDeclaration(expression){
		fnId+=1;
		linecount = (contract.slice(0,expression.start).match(/\n/g)||[]).length + 1;
		//We need to work out the lines and columns the function declaration starts and ends
		var startline = linecount;
		var startcol = expression.start - contract.slice(0,expression.start).lastIndexOf('\n') -1;
		var endlineDelta = contract.slice(expression.start).indexOf('{')+1;
		var functionDefinition = contract.slice(expression.start, expression.start + endlineDelta);
		var endline = startline + (functionDefinition.match(/\n/g)||[]).length;
		var endcol = functionDefinition.length - functionDefinition.lastIndexOf('\n')
		fnMap[fnId] = {name: expression.name, line: linecount, loc:{start:{line: startline, column:startcol},end:{line:endline, column:endcol}}}
		createOrAppendInjectionPoint(expression.start + endlineDelta+1,{type: "callFunctionEvent", fnId: fnId} );
	}

	function instrumentIfStatement(expression){
		branchId +=1;
		startline = (contract.slice(0,expression.start).match(/\n/g)||[]).length + 1;
		var startcol = expression.start - contract.slice(0,expression.start).lastIndexOf('\n') -1;
		//NB locations for if branches in istanbul are zero length and associated with the start of the if.<commit_msg>Handle empty function body edge case<commit_after>// var SolidityParser = require("solidity-parser");
var solparse = require("solparse");

var path = require("path");
module.exports = function(contract, fileName, instrumentingActive){

	// var result = SolidityParser.parseFile("./" + pathToFile);
	var result = solparse.parse(contract);
	var instrumented = "";
	const __INDENTATION__ = "    ";
	var parse = {};
	var runnableLines=[];
	var fnMap = {};
	var fnId = 0;
	var branchMap = {};
	var branchId = 0;
	var statementMap = {};
	var statementId = 0;
	var linecount = 1;
	var injectionPoints = {};

	function createOrAppendInjectionPoint(key, value){
		if (injectionPoints[key]){
			injectionPoints[key].push(value);
		}else{
			injectionPoints[key] = [value];
		}
	}

	function instrumentAssignmentExpression(expression){
		//The only time we instrument an assignment expression is if there's a conditional expression on
		//the right
		if (expression.right.type==='ConditionalExpression'){
			if (expression.left.type==='DeclarativeExpression'){
				//Then we need to go from bytes32 varname = (conditional expression)
				//to 					  bytes32 varname; (,varname) = (conditional expression)
				createOrAppendInjectionPoint(expression.left.end, {type:"literal", string:"; (," + expression.left.name + ")"});
			}else {
				console.log(expression.left)
				process.exit();
			}
		}
	}

	function instrumentConditionalExpression(expression){
		branchId +=1;

		startline = (contract.slice(0,expression.start).match(/\n/g)||[]).length + 1;
		var startcol = expression.start - contract.slice(0,expression.start).lastIndexOf('\n') -1;
		consequentStartCol = startcol + expression.consequent.start - expression.start;
		consequentEndCol = consequentStartCol + expression.consequent.end - expression.consequent.start;
		alternateStartCol = startcol + expression.alternate.start - expression.start;
		alternateEndCol = alternateStartCol + expression.alternate.end - expression.alternate.start;
		//NB locations for conditional branches in istanbul are length 1 and associated with the : and ?.
		branchMap[branchId] = {line:startline, type:'cond-expr', locations:[{start:{line:startline, column:consequentStartCol},end:{line:startline,column:consequentEndCol}},{start:{line:startline, column:alternateStartCol},end:{line:startline,column:alternateEndCol}}]}

		//Right, this could be being used just by itself or as an assignment. In the case of the latter, because
		//the comma operator doesn't exist, we're going to have to get funky.
		//if we're on a line by ourselves, this is easier
		//
		//Now if we've got to wrap the expression it's being set equal to, do that...


		//Wrap the consequent
		createOrAppendInjectionPoint(expression.consequent.start, {type:"openParen"});
		createOrAppendInjectionPoint(expression.consequent.start, {type:"callBranchEvent",comma:true, branchId: branchId, locationIdx: 0});
		createOrAppendInjectionPoint(expression.consequent.end, {type:"closeParen"});

		//Wrap the alternate
		createOrAppendInjectionPoint(expression.alternate.start, {type:"openParen"});
		createOrAppendInjectionPoint(expression.alternate.start, {type:"callBranchEvent",comma:true, branchId: branchId, locationIdx: 1});
		createOrAppendInjectionPoint(expression.alternate.end, {type:"closeParen"});
	}

	function instrumentStatement(expression){
		canCover = false;
		//Can only instrument here if this is a self-contained statement
		//So if this is the start of the line, we're good
		if ( contract.slice(contract.slice(0,expression.start).lastIndexOf('\n'), expression.start).trim().length===0 ){
			canCover=true;
		}
		//If it's preceeded by a '{', we're good
		if ( contract.slice(contract.slice(0,expression.start).lastIndexOf('{')+1, expression.start).trim().length===0 ){
			canCover=true;
		}

		//If it's preceeded by a ';', we're good
		if ( contract.slice(contract.slice(0,expression.start).lastIndexOf(';')+1, expression.start).trim().length===0 ){
			canCover=true;
		}

		if (!canCover){return;}
		//We need to work out the lines and columns the expression starts and ends
		statementId +=1;
		linecount = (contract.slice(0,expression.start).match(/\n/g)||[]).length + 1;
		var startline = linecount;
		var startcol = expression.start - contract.slice(0,expression.start).lastIndexOf('\n') -1;
		var expressionContent = contract.slice(expression.start, expression.end);

		var endline = startline + (expressionContent.match('/\n/g') || []).length ;
		var endcol;
		if (expressionContent.lastIndexOf('\n')>=0){
			endcol = contract.slice(expressionContent.lastIndexOf('\n'), expression.end).length -1;
		}else{
			endcol = startcol + expressionContent.length -1;

		}
		statementMap[statementId] = {start:{line: startline, column:startcol},end:{line:endline, column:endcol}}

		createOrAppendInjectionPoint(expression.start, {type:"statement", statementId: statementId});
	}

	function instrumentLine(expression){
		//what's the position of the most recent newline?
		var startchar = expression.start
		var endchar = expression.end
		lastNewLine = contract.slice(0, startchar).lastIndexOf('\n');
		nextNewLine = startchar + contract.slice(startchar).indexOf('\n');
		var contractSnipped = contract.slice(lastNewLine, nextNewLine);
		//Remove comments
		while (contractSnipped.trim().slice(0,2)==='//'){
			contractSnipped.replace(/\/\/.*?/g,"");
		}
		// Is everything before us and after us on this line whitespace?
		if (contract.slice(lastNewLine, startchar).trim().length===0 && contract.slice(endchar,nextNewLine).replace(';','').trim().length===0){
			createOrAppendInjectionPoint(lastNewLine+1,{type:"callEvent"});
		}
	}

	function instrumentFunctionDeclaration(expression){
		fnId+=1;
		linecount = (contract.slice(0,expression.start).match(/\n/g)||[]).length + 1;
		//We need to work out the lines and columns the function declaration starts and ends
		var startline = linecount;
		var startcol = expression.start - contract.slice(0,expression.start).lastIndexOf('\n') -1;
		var endlineDelta = contract.slice(expression.start).indexOf('{')+1;
		var functionDefinition = contract.slice(expression.start, expression.start + endlineDelta);
		var lastChar = contract.slice(expression.start, expression.start + endlineDelta + 1).slice(-1);
		var endline = startline + (functionDefinition.match(/\n/g)||[]).length;
		var endcol = functionDefinition.length - functionDefinition.lastIndexOf('\n')
		fnMap[fnId] = {name: expression.name, line: linecount, loc:{start:{line: startline, column:startcol},end:{line:endline, column:endcol}}}
		if (lastChar === '}'){
		    createOrAppendInjectionPoint(expression.start + endlineDelta,{type: "callFunctionEvent", fnId: fnId} );
		} else {
		    createOrAppendInjectionPoint(expression.start + endlineDelta+1,{type: "callFunctionEvent", fnId: fnId} );
		}
	}

	function instrumentIfStatement(expression){
		branchId +=1;
		startline = (contract.slice(0,expression.start).match(/\n/g)||[]).length + 1;
		var startcol = expression.start - contract.slice(0,expression.start).lastIndexOf('\n') -1;
		//NB locations for if branches in istanbul are zero length and associated with the start of the if.
{'fraction_non_alphanumeric': 0.1441383728379244, 'fraction_numerical': 0.007260303224428785, 'mean_word_length': 5.108695652173913, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2932702', 'n_tokens_mistral': 4598, 'n_tokens_neox': 4205, 'n_words': 984}