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.*; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtVariableReference; import java.util.Map; /** * Transformation that adds AST nodes * * User: Simon * Date: 7/11/13 * Time: 4:33 PM */ public class ASTAdd extends ASTTransformation { protected CodeFragment transplant; protected Map<String, String> variableMapping; protected boolean adTransplantBefore = false; public ASTAdd() { name = "add"; type = "adrStmt"; } @Override public JSONObject toJSONObject() throws JSONException { JSONObject object = super.toJSONObject(); object.put("transplantationPoint", transplantationPoint.toJSONObject()); object.put("transplant", transplant.toJSONObject()); object.put("variableMap", variableMapping); return object; } 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("transplant: ({})\n{}", getTransplant().getCodeFragmentType(), getTransplant()); } protected CtCodeElement buildReplacementElement() { try { CodeFragment stmtToAdd = transplant.clone(); if (withVarMapping()) { if (variableMapping == null) variableMapping = transplantationPoint.randomVariableMapping(getTransplant(), subType); Log.debug("random variable mapping: {}", variableMapping); stmtToAdd.replaceVar(transplantationPoint, variableMapping); } Factory factory = transplantationPoint.getCtCodeFragment().getFactory(); CtIf stmtIf = factory.Core().createIf(); stmtIf.setParent(transplantationPoint.getCtCodeFragment().getParent()); stmtIf.setCondition(factory.Code().createLiteral(true)); CtBlock body = factory.Core().createBlock(); stmtIf.setThenStatement(body); CtStatement tmp = (CtStatement) factory.Core().clone(transplantationPoint.getCtCodeFragment()); tmp.setParent(stmtIf); stmtToAdd.getCtCodeFragment().setParent(stmtIf); if(adTransplantBefore) { body.addStatement((CtStatement) factory.Core().clone(stmtToAdd.getCtCodeFragment())); body.addStatement(tmp); } else { body.addStatement(tmp); body.addStatement((CtStatement) factory.Core().clone(stmtToAdd.getCtCodeFragment())); } return stmtIf; } catch (Exception e) { throw new RuntimeException(new BuildTransplantException("", e)); } } protected boolean withVarMapping() { return name.equals("add"); } public void setVarMapping(Map<String, String> mapping) { variableMapping = mapping; } public void setTransplant(CodeFragment add) { this.transplant = add; } public int hashCode() { return super.hashCode() * transplant.getCompilationUnit().hashCode() * transplant.getStartLine() * transplantationPoint.getCompilationUnit().hashCode() * transplantationPoint.getStartLine(); } public boolean equals(Object other) { if(other == null) return false; if(!this.getClass().isAssignableFrom(other.getClass())) return false; ASTAdd otherASTAdd = (ASTAdd)other; if(!equalParent(otherASTAdd.parent)) return false; return status == otherASTAdd.status && name.equals(otherASTAdd.name) && failures.equals(otherASTAdd.failures) && ((variableMapping == null && otherASTAdd.variableMapping == null) || variableMapping.equals(otherASTAdd.variableMapping)) && transplantationPoint.getCtCodeFragment().equals(otherASTAdd.transplantationPoint.getCtCodeFragment()) && transplant.getCtCodeFragment().getPosition().equals(otherASTAdd.transplant.getCtCodeFragment().getPosition()); } @Override public String toString() { String ret = "add\n"; ret = ret + "transplantationPoint: "+ transplantationPoint.toString()+"\n" + "varMapping: "+variableMapping+"\n"; return ret; } public CodeFragment getTransplant() { return transplant; } public boolean usedOfSubType() { 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() {} public Map<String, String> getVarMapping() { return variableMapping; } }