package fr.inria.diversify.codeFragment; import fr.inria.diversify.codeFragmentProcessor.SubStatementVisitor; import fr.inria.diversify.util.Log; import org.json.JSONException; import org.json.JSONObject; import spoon.reflect.code.*; import spoon.reflect.cu.CompilationUnit; import spoon.reflect.declaration.*; import spoon.reflect.factory.Factory; import spoon.reflect.factory.FactoryImpl; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.reference.CtVariableReference; import spoon.support.reflect.code.CtLocalVariableImpl; import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; /** * The code fragment is the basic unit of diversification. Also known as "Reaction" * * User: Simon * Date: 5/3/13 * Time: 3:21 PM */ public abstract class CodeFragment { /** * Context of the Code fragment, see article by Baudry, et. al "Tailored Source Code Transformations to Synthesize * Computationally Diverse Program Variants" 2013 */ protected Context context; /** * An Spoon code fragment */ protected CtCodeElement codeFragment; /** * Source code string */ protected String equalString; /** * Position string <Fully_qualified_name>:<Line_number> */ private String positionString; public void init(CtCodeElement cf) { codeFragment = cf; context = new Context(initInputContext(), initOutputContext()); // this.initOutputContext(); // this.initInputContext(); } /** * Returns the simple name of the Code fragment's type * @return A string with the name */ public String getCodeFragmentTypeSimpleName() { return getCodeFragmentType().getSimpleName(); } public CtTypeReference<?> getOutputContext() { return context.getOutputContext(); } public InputContext getInputContext() { return context.getInputContext(); } protected CtTypeReference<?> initOutputContext() { if (codeFragment instanceof CtTypedElement) { return ((CtTypedElement<?>) codeFragment).getType(); } else return getFactory().Type().createReference(void.class); } protected Factory getFactory() { return codeFragment.getFactory(); } protected InputContext initInputContext() { VariableVisitor visitor = new VariableVisitor(); codeFragment.accept(visitor); return visitor.input(); } @Override public String toString() { String tmp =" Source: " + codeFragment; tmp += "\nPosition:" + codeFragment.getPosition(); tmp += "\nInput:" + getInputContext(); tmp += "\nOutput: " + getOutputContext(); return tmp; } public abstract String codeFragmentString(); public String equalString() { if (equalString != null) return equalString; CodeFragmentEqualPrinter pp = new CodeFragmentEqualPrinter(getFactory().getEnvironment()); codeFragment.accept(pp); equalString = pp.toString(); return equalString; } //attention !!!!!!! public boolean equals(Object other) { if(!(other instanceof CodeFragment)) return false; CodeFragment otherCf = (CodeFragment) other; return equalString().equals(otherCf.equalString()) && positionString().equals(otherCf.positionString()); } public int hashCode() { return 1; } public void replaceVar(CodeFragment other, Map<String,String> varMapping) { if ( varMapping == null || varMapping.size() == 0 ) { Log.debug("No replacement where made, varMapping null or zero size"); return; } Log.debug("replace variable"); Log.debug("avant:"); Log.debug("{}",codeFragment); for (String varName: varMapping.keySet()) { CtVariableReference variable = getInputContext().getVariableOrFieldNamed(varName); CtVariableReference candidate = other.getInputContext().getVariableOrFieldNamed(varMapping.get(varName)); ReplaceVariableVisitor visitor = new ReplaceVariableVisitor(variable, candidate); codeFragment.accept(visitor); } if(codeFragment instanceof CtLocalVariableImpl) ((CtLocalVariableImpl)codeFragment).setSimpleName(((CtLocalVariableImpl) other.codeFragment).getSimpleName()); Log.debug("apres: {}",codeFragment); } //validate if this can be replaced by other public abstract boolean isReplaceableBy(CodeFragment other, boolean varNameMatch , boolean subType); public Map<String,String> randomVariableMapping(CodeFragment other, boolean subType) { Map<String,String> varMap = new HashMap<>(); Random r = new Random(); for (CtVariableReference<?> variable : other.getInputContext().getVar()) { List<CtVariableReference> list = getInputContext().allCandidate(variable.getType(), subType); if ( list.size() > 0 ) { CtVariableReference candidate = list.get(r.nextInt(list.size())); varMap.put(variable.toString(), candidate.toString()); } } return varMap; } public JSONObject toJSONObject() throws JSONException { JSONObject object = new JSONObject(); object.put("position", positionString()); object.put("type", getCodeFragmentType().getSimpleName()); object.put("sourcecode", equalString()); return object; } public String positionString() { if ( positionString == null ) { StringBuilder sb = new StringBuilder(); sb.append(getSourcePackage().getQualifiedName()).append("."). append(getSourceClass().getSimpleName()).append(":").append(codeFragment.getPosition().getLine()); positionString = sb.toString(); } return positionString; } public CtTypeReference<?> getMethodReturnType() { CtMethod mth = codeFragment.getParent(CtMethod.class); if(mth != null) return mth.getType(); return null; } protected CtTypeReference<?> hasReturn() { SubStatementVisitor sub = new SubStatementVisitor(); codeFragment.accept(sub); for(CtStatement stm : sub.getStatements()) if(stm instanceof CtReturn) return getMethodReturnType(); return null; } public CtCodeElement getCtCodeFragment() { return codeFragment; } public Context getContext() { return context; } public Class<?> getCodeFragmentType() { return codeFragment.getClass(); } public CtType<?> getSourceClass() { return getCompilationUnit().getMainType(); } public int getStartLine() { return codeFragment.getPosition().getLine(); } public int getEndLine() { return codeFragment.getPosition().getEndLine(); } public CtPackage getSourcePackage() { return getSourceClass().getPackage(); } public int id() { return equalString().hashCode() + context.hashCode(); } public File getSourceFile() { return codeFragment.getPosition().getFile(); } public CompilationUnit getCompilationUnit() { return codeFragment.getPosition().getCompilationUnit(); } public Class<?> getCodeFragmentSuperType() { if(codeFragment instanceof CtIf || codeFragment instanceof CtCase || codeFragment instanceof CtLoop || codeFragment instanceof CtSynchronized || codeFragment instanceof CtTry) return CtBlock.class; // if(codeFragment instanceof CtExpression) // return CtExpression.class; return CtStatement.class; } public abstract CodeFragment clone(); protected CtElement copyElem(CtElement elem) { Factory factory = elem.getFactory(); CtElement tmp = factory.Core().clone(elem); tmp.setParent(elem.getParent()); return tmp; } }