package fr.inria.diversify.transformation.ast; import fr.inria.diversify.codeFragment.CodeFragment; import fr.inria.diversify.codeFragment.InputContext; import fr.inria.diversify.transformation.ast.exception.BuildTransplantException; import fr.inria.diversify.util.Log; import org.json.JSONException; import org.json.JSONObject; import spoon.reflect.code.CtCodeElement; import spoon.reflect.reference.CtVariableReference; import java.util.Map; /** * AST transform to perform a replace * <p/> * User: Simon * Date: 7/11/13 * Time: 4:42 PM */ public class ASTReplace extends ASTTransformation { /** * Transplant code fragment, i.e. the code that is going to be inserted */ protected CodeFragment transplant; /** * Map to perform variable mapping. See article: */ protected Map<String, String> variableMapping; /** * Transplant code fragment, i.e. the code that is going to be inserted */ public CodeFragment getTransplant() { return transplant; } public void setTransplant(CodeFragment transplant) { this.transplant = transplant; } public boolean setCodeFragmentToReplace(CodeFragment replace) { this.setTransplant(replace); return true; } public void setVarMapping(Map<String, String> mapping) { variableMapping = mapping; } public Map<String, String> getVarMapping() { return variableMapping; } public ASTReplace() { name = "replace"; type = "adrStmt"; } protected void applyInfo() { Log.debug("transformation: {}, {}", type, name); Log.debug("transplantation point:\n{}", transplantationPoint); Log.debug("{}", transplantationPoint.getCtCodeFragment().getPosition()); Log.debug("{}", transplantationPoint.getCodeFragmentType()); Log.debug("replace by: ({})\n{}", getTransplant().getCodeFragmentType(), getTransplant()); } protected CtCodeElement buildReplacementElement() { try { CodeFragment stmt = transplant.clone(); if (withVarMapping()) { if (variableMapping == null) { variableMapping = transplantationPoint.randomVariableMapping(getTransplant(), subType); } Log.debug("random variable mapping: {}", variableMapping); stmt.replaceVar(transplantationPoint, variableMapping); if (stmt.codeFragmentString().equals(transplantationPoint.codeFragmentString())) { throw new BuildTransplantException("same statement"); } } return stmt.getCtCodeFragment(); } catch (Exception e) { throw new RuntimeException(new BuildTransplantException("", e)); } } protected boolean withVarMapping() { //todo a remplacer par un attribut return name.equals("replace"); } public int hashCode() { return super.hashCode() * getTransplant().getCompilationUnit().hashCode() * getTransplant().getStartLine() * transplantationPoint.getCompilationUnit().hashCode() * transplantationPoint.getStartLine(); } public boolean equals(Object other) { if (other == null) return false; if (!this.getClass().isAssignableFrom(other.getClass())) return false; ASTReplace otherReplace = (ASTReplace) other; if (!equalParent(otherReplace.parent)) return false; return status == otherReplace.status && failures.equals(otherReplace.failures) && ((variableMapping == null && otherReplace.variableMapping == null) || variableMapping.equals(otherReplace.variableMapping)) && transplantationPoint.getCtCodeFragment().getPosition().equals(otherReplace.transplantationPoint.getCtCodeFragment().getPosition()) && getTransplant().getCtCodeFragment().getPosition().equals(otherReplace.getTransplant().getCtCodeFragment().getPosition()); } @Override public JSONObject toJSONObject() throws JSONException { JSONObject object = super.toJSONObject(); object.put("transplantationPoint", transplantationPoint.toJSONObject()); object.put("transplant", getTransplant().toJSONObject()); object.put("variableMap", variableMapping); return object; } @Override public String toString() { String ret = "replace\n"; ret = ret + "transplantationPoint: " + transplantationPoint.toString() + "\n" + type + ": " + getTransplant().toString() + "\n" + "varMapping: " + variableMapping + "\n"; return ret; } public void setType(String type) { this.type = type; } public boolean usedOfSubType() { //return variableMapping.entrySet().stream() // .anyMatch(var -> { // CtVariableReference variable = tpInputContext.getVariableOrFieldNamed(var.getKey()); // CtVariableReference candidate = tInputContext.getVariableOrFieldNamed(var.getValue()); // return !variable.getType().equals(candidate.getType()); // }); InputContext tpInputContext = transplant.getContext().getInputContext(); InputContext tInputContext = transplantationPoint.getContext().getInputContext(); for (Map.Entry<String, String> var : variableMapping.entrySet()) { CtVariableReference variable = tpInputContext.getVariableOrFieldNamed(var.getKey()); CtVariableReference candidate = tInputContext.getVariableOrFieldNamed(var.getValue()); if (!variable.getType().equals(candidate.getType())) return true; } return false; } public void updateStatementList() { getInputProgram().getCodeFragments().remove(transplantationPoint); } }