package fr.inria.diversify.transformation.query; import com.sun.org.apache.bcel.internal.classfile.Code; import fr.inria.diversify.codeFragment.CodeFragment; import fr.inria.diversify.codeFragment.Statement; import fr.inria.diversify.coverage.ICoverageReport; import fr.inria.diversify.diversification.InputProgram; import fr.inria.diversify.transformation.Transformation; import fr.inria.diversify.transformation.other.ShuffleCollectionBeforeReturn; import fr.inria.diversify.util.Log; import spoon.reflect.code.CtCodeElement; import spoon.reflect.code.CtCodeSnippetStatement; import spoon.reflect.code.CtReturn; import spoon.reflect.code.CtVariableAccess; import spoon.reflect.reference.CtArrayTypeReference; import spoon.reflect.reference.CtVariableReference; import java.util.*; import java.util.stream.Collectors; /** * Created by Simon on 04/02/15. */ public class ShuffleCollectionBeforeReturnQuery extends TransformationQuery { protected List<CodeFragment> returnsCollection; protected List<CodeFragment> returnsArray; public ShuffleCollectionBeforeReturnQuery(InputProgram inputProgram) { super(inputProgram); initReturn(); } protected void initReturn() { returnsCollection = new LinkedList<>(); returnsArray = allCoveredCodeFragment().stream() .filter(cf -> isReturnArray(cf.getCtCodeFragment())) .collect(Collectors.toList()); returnsCollection = allCoveredCodeFragment().stream() .filter(cf -> isReturnCollection(cf.getCtCodeFragment())) .collect(Collectors.toList()); } protected boolean isReturnCollection(CtCodeElement stmt) { Class cl = null; try { if (stmt instanceof CtReturn) { Object ret = ((CtReturn) stmt).getReturnedExpression(); if (ret instanceof CtVariableReference) { CtVariableReference var = (CtVariableReference) ret; cl = var.getType().getActualClass(); } if (ret instanceof CtVariableAccess) { CtVariableAccess var = (CtVariableAccess) ret; cl = var.getType().getActualClass(); } } } catch (Exception e) { e.printStackTrace(); Log.debug(""); } return cl != null && instanceOfCollection(cl); } protected boolean isReturnArray(CtCodeElement stmt) { Class cl = null; try { if (stmt instanceof CtReturn) { Object ret = ((CtReturn) stmt).getReturnedExpression(); if (ret instanceof CtVariableReference) { CtVariableReference var = (CtVariableReference) ret; cl = var.getType().getActualClass(); } if(ret instanceof CtVariableAccess) { CtVariableAccess var = (CtVariableAccess) ret; cl = var.getType().getActualClass(); } } } catch (Exception e) { e.printStackTrace(); Log.debug(""); } return cl != null && instanceOfArray(cl); } protected boolean instanceOfCollection(Class cl) { return Collection.class.isAssignableFrom(cl); } protected boolean instanceOfArray(Class cl) { return cl.isArray(); } @Override public Transformation query() throws QueryException { ShuffleCollectionBeforeReturn transformation = new ShuffleCollectionBeforeReturn(); CodeFragment transplantationPoint; Random random = new Random(); CtCodeSnippetStatement snippet = inputProgram.getFactory().Core().createCodeSnippetStatement(); CodeFragment transplant = new Statement(snippet); if(random.nextBoolean()) { transplantationPoint = returnsCollection.get(random.nextInt(returnsCollection.size())); String transplantationPointString = transplantationPoint.getCtCodeFragment().toString(); String varName = varName(transplantationPoint); snippet.setValue("java.util.Collections.shuffle(" + varName + ");\n" + transplantationPointString); } else { transplantationPoint = returnsArray.get(random.nextInt(returnsArray.size())); String transplantationPointString = transplantationPoint.getCtCodeFragment().toString(); String varName = varName(transplantationPoint); snippet.setValue( "java.util.Random rnd = new java.util.Random();\n" + "for (int i = " + varName + ".length - 1; i > 0; i--){\n" + " int index = rnd.nextInt(i + 1);\n" + " "+ getArrayType(transplantationPoint) +" a = " + varName + "[index];\n" + " " + varName + "[index] = " + varName + "[i];\n" + " " + varName + "[i] = a;\n" + "}\n" + transplantationPointString); } snippet.setParent(transplantationPoint.getCtCodeFragment().getParent()); transformation.setTransplantationPoint(transplantationPoint); transformation.setTransplant(transplant); return transformation; } private String getArrayType(CodeFragment stmt) { Object ret = ((CtReturn) stmt.getCtCodeFragment()).getReturnedExpression(); if (ret instanceof CtVariableReference) { CtVariableReference var = (CtVariableReference) ret; return ((CtArrayTypeReference)var.getType()).getComponentType().toString(); } else { CtVariableAccess var = (CtVariableAccess) ret; return ((CtArrayTypeReference) var.getType()).getComponentType().toString(); } } protected String varName(CodeFragment stmt) { Object ret = ((CtReturn) stmt.getCtCodeFragment()).getReturnedExpression(); if (ret instanceof CtVariableReference) { CtVariableReference var = (CtVariableReference) ret; return var.getSimpleName(); } else { CtVariableAccess var = (CtVariableAccess) ret; return var.getVariable().getSimpleName(); } } protected List<CodeFragment> allCoveredCodeFragment() { ICoverageReport coverageReport = getInputProgram().getCoverageReport(); return getInputProgram().getCodeFragments().stream() .distinct() .filter(cf -> coverageReport.codeFragmentCoverage(cf) != 0) .collect(Collectors.toList()); } }