package fr.inria.diversify.processor.main; import fr.inria.diversify.diversification.InputProgram; import spoon.reflect.code.*; import spoon.reflect.cu.SourcePosition; import spoon.reflect.declaration.*; import spoon.reflect.visitor.Query; import spoon.reflect.visitor.filter.TypeFilter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * User: Simon * Date: 21/05/15 * Time: 14:31 */ public class BranchPositionProcessor extends AbstractLoggingInstrumenter<CtExecutable> { List<String> methodsId; Map<Integer, Integer> blockIds; Map<String,SourcePosition> branchPosition; Map<String, String> branchConditionType; public BranchPositionProcessor(InputProgram inputProgram) { super(inputProgram); branchPosition = new HashMap<>(); branchConditionType = new HashMap<>(); methodsId = new ArrayList<>(); blockIds = new HashMap<>(); } @Override public boolean isToBeProcessed(CtExecutable method) { return method.getBody() != null; } @Override public void process(CtExecutable method) { int methodId = methodId(method); addBranch(methodId, "b", method.getBody()); branchConditionType.put(methodId+".b", methodVisibility(method)); for(Object object : Query.getElements(method, new TypeFilter(CtIf.class))) { CtIf ctIf = (CtIf) object; int branchId = idBranch(methodId); addBranch(methodId, "t" + branchId, ctIf.getThenStatement()); updateBranchConditionType(ctIf, methodId+".t" + branchId); conditionType(ctIf.getCondition()); if (ctIf.getElseStatement() == null) { // addBranch(methodId, "e" + branchId, ctIf.getParent(CtBlock.class)); // updateBranchConditionType(ctIf, methodId+".e" + branchId); } else { addBranch(methodId, "e" + branchId, ctIf.getElseStatement()); updateBranchConditionType(ctIf, methodId+".e" + branchId); } } for(Object object : Query.getElements(method, new TypeFilter(CtCase.class))) { CtCase ctCase = (CtCase) object; int branchId = idBranch(methodId); addBranch(methodId, "s" + branchId, ctCase); } for(Object object : Query.getElements(method, new TypeFilter(CtLoop.class))) { CtLoop ctLoop = (CtLoop) object; int branchId = idBranch(methodId); addBranch(methodId, "l" + branchId, ctLoop.getBody()); } for(Object object : Query.getElements(method, new TypeFilter(CtCatch.class))) { CtCatch ctCatch = (CtCatch) object; int branchId = idBranch(methodId); addBranch(methodId, methodId+".c" + branchId, ctCatch.getBody()); } } protected void addBranch(int methodId, String branchId, CtStatement blockOrStmt) { branchPosition.put(methodId + "." + branchId, blockOrStmt.getPosition()); } protected int idBranch(int methodId) { if(!blockIds.containsKey(methodId)) { blockIds.put(methodId, 0); } blockIds.put(methodId, blockIds.get(methodId) + 1); return blockIds.get(methodId); } protected void updateBranchConditionType(CtElement element, String branchId) { if(element instanceof CtIf) { branchConditionType.put(branchId, conditionType(((CtIf) element).getCondition())); } if(element instanceof CtWhile) { branchConditionType.put(branchId, conditionType(((CtWhile) element).getLoopingExpression())); } if(element instanceof CtDo) { branchConditionType.put(branchId, conditionType(((CtDo) element).getLoopingExpression())); } } protected String conditionType(CtExpression condition) { List<CtBinaryOperator> binaryOperators = Query.getElements(condition, new TypeFilter(CtBinaryOperator.class)); List<CtInvocation> methodCall = Query.getElements(condition, new TypeFilter(CtInvocation.class)); if(binaryOperators.isEmpty()) { if(methodCall.isEmpty()) { return "boolean"; } else { if(methodCall.contains("equal(")) { return "equal"; } else { return "methodCall"; } } } else { if(binaryOperators.size() == 1) { return binaryOperators.get(0).getKind().toString(); } else { return "binaryOperator" + binaryOperators.size(); } } } protected String methodVisibility(CtExecutable executable) { if(executable instanceof CtModifiable) { CtModifiable modifiable = (CtModifiable) executable; if(modifiable.getModifiers().contains(ModifierKind.PRIVATE)) { return "private"; } if(modifiable.getModifiers().contains(ModifierKind.PROTECTED)) { return "protected"; } if(modifiable.getModifiers().contains(ModifierKind.PUBLIC)) { return "public"; } return "package-private"; } else { return "none"; } } public Map<String, SourcePosition> getBranchPosition() { return branchPosition; } public Map<String, String> getBranchConditionType() { return branchConditionType; } }