package fr.inria.diversify.transformation.query;
import fr.inria.diversify.codeFragment.CodeFragment;
import fr.inria.diversify.diversification.InputProgram;
import fr.inria.diversify.transformation.CheckReturnTransformation;
import fr.inria.diversify.transformation.Transformation;
import fr.inria.diversify.transformation.ast.ASTReplace;
import spoon.reflect.code.*;
import spoon.reflect.reference.CtVariableReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/**
* Created by aelie on 30/01/15.
*/
public class CheckReturnQuery extends TransformationQuery {
protected List<CodeFragment> returnStatementList;
protected List<CodeFragment> ifStatementList;
public CheckReturnQuery(InputProgram inputProgram) {
super(inputProgram);
initFindReturnStatements();
initFindIfStatements();
}
protected void initFindReturnStatements() {
returnStatementList = new ArrayList<>();
for (CodeFragment cf : getInputProgram().getCodeFragments()) {
if (isReturnVariable(cf.getCtCodeFragment())) {
returnStatementList.add(cf);
}
}
}
protected boolean isReturnVariable(CtCodeElement stmt) {
if (stmt instanceof CtReturn) {
CtReturn ret = (CtReturn) stmt;
if (ret.getReturnedExpression() instanceof CtVariableReference ||
ret.getReturnedExpression() instanceof CtVariableAccess) {
return true;
}
}
return false;
}
protected boolean isThrowStatement(CtCodeElement stmt) {
return stmt instanceof CtThrow;
}
protected void initFindIfStatements() {
ifStatementList = new ArrayList<>();
List<CodeFragment> uniqueCodeFragmentsList = new ArrayList<>(getInputProgram().getCodeFragments().getUniqueCodeFragmentList());
for (CodeFragment codeFragment : uniqueCodeFragmentsList) {
try {
CtCodeElement codeElement = codeFragment.getCtCodeFragment();
if (codeElement instanceof CtIf) {
ifStatementList.add(codeFragment);
}
} catch (Exception e) {
}
}
}
@Override
public Transformation query() throws QueryException {
Transformation result;
Random random = new Random();
CodeFragment transplant = null;
CodeFragment transplantationPoint = null;
Collections.shuffle(ifStatementList, random);
int counter = ifStatementList.size();
while(transplant == null && counter-- > 0) {
transplantationPoint = returnStatementList.get(random.nextInt(returnStatementList.size() - 1));
for (CodeFragment ifCodeFragment : ifStatementList) {
if (transplantationPoint.getContext().getInputContext().containsAll(ifCodeFragment.getInputContext(), true)) {
transplant = ifCodeFragment;
}
}
}
result = new CheckReturnTransformation(transplantationPoint, transplant);
result.setInputProgram(getInputProgram());
return result;
}
protected CodeFragment findRandomReturnToReplace(boolean withCoverage) {
Random r = new Random();
int size = returnStatementList.size();
CodeFragment stmt = returnStatementList.get(r.nextInt(size));
while (withCoverage && getInputProgram().getCoverageReport().codeFragmentCoverage(stmt) == 0)
stmt = returnStatementList.get(r.nextInt(size));
return stmt;
}
}