package soot.dava.toolkits.base.AST.transformations;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import soot.Local;
import soot.SootClass;
import soot.Type;
import soot.dava.internal.AST.ASTNode;
import soot.dava.internal.AST.ASTStatementSequenceNode;
import soot.dava.internal.AST.ASTSwitchNode;
import soot.dava.internal.AST.ASTTryNode;
import soot.dava.internal.asg.AugmentedStmt;
import soot.dava.toolkits.base.AST.analysis.DepthFirstAdapter;
import soot.dava.toolkits.base.AST.structuredAnalysis.UnreachableCodeFinder;
import soot.jimple.Stmt;
public class UnreachableCodeEliminator extends DepthFirstAdapter {
public boolean DUBUG=true;
ASTNode AST;
UnreachableCodeFinder codeFinder;
public UnreachableCodeEliminator(ASTNode AST) {
super();
this.AST = AST;
setup();
}
public UnreachableCodeEliminator(boolean verbose, ASTNode AST) {
super(verbose);
this.AST = AST;
setup();
}
private void setup() {
codeFinder = new UnreachableCodeFinder(AST);
//parentOf = new ASTParentNodeFinder();
//AST.apply(parentOf);
}
public void inASTStatementSequenceNode(ASTStatementSequenceNode node){
List<Object> toRemove = new ArrayList<Object>();
List<Object> stmts = node.getStatements();
Iterator<Object> it = stmts.iterator();
while(it.hasNext()){
AugmentedStmt as = (AugmentedStmt)it.next();
Stmt s = as.get_Stmt();
//System.out.println("HERE!!!"+s.toString());
if(!codeFinder.isConstructReachable(s)){
toRemove.add(as);
//if(DEBUG) System.out.println("Statement "+s.toString()+ " is NOT REACHABLE REMOVE IT");
}
}
it = toRemove.iterator();
while(it.hasNext()){
stmts.remove(it.next());
}
}
public void normalRetrieving(ASTNode node) {
if(node instanceof ASTSwitchNode){
dealWithSwitchNode((ASTSwitchNode)node);
return;
}
//from the Node get the subBodes
List<ASTNode> toReturn = new ArrayList<ASTNode>();
Iterator<Object> sbit = node.get_SubBodies().iterator();
while (sbit.hasNext()) {
Object subBody = sbit.next();
Iterator<ASTNode> it = ((List<ASTNode>) subBody).iterator();
//go over the ASTNodes in this subBody and apply
while (it.hasNext()) {
ASTNode temp = it.next();
if(!codeFinder.isConstructReachable(temp)){
//System.out.println("-------------------------A child of node of type "+node.getClass()+" whose type is "+temp.getClass()+" is unreachable");
toReturn.add(temp);
}
else{
//only apply on reachable nodes
temp.apply(this);
}
}
it = toReturn.iterator();
while(it.hasNext()){
//System.out.println("Removed");
((List)subBody).remove(it.next());
}
}//end of going over subBodies
}
//TODO
public void caseASTTryNode(ASTTryNode node) {
//get try body
List<Object> tryBody = node.get_TryBody();
Iterator<Object> it = tryBody.iterator();
//go over the ASTNodes in this tryBody and apply
List<Object> toReturn = new ArrayList<Object>();
while (it.hasNext()){
ASTNode temp = (ASTNode) it.next();
if(!codeFinder.isConstructReachable(temp)){
toReturn.add(temp);
}
else{
//only apply on reachable nodes
temp.apply(this);
}
}
it = toReturn.iterator();
while(it.hasNext()){
tryBody.remove(it.next());
}
Map<Object, Object> exceptionMap = node.get_ExceptionMap();
Map<Object, Object> paramMap = node.get_ParamMap();
//get catch list and apply on the following
// a, type of exception caught
// b, local of exception
// c, catchBody
List<Object> catchList = node.get_CatchList();
Iterator<Object> itBody = null;
it = catchList.iterator();
while (it.hasNext()) {
ASTTryNode.container catchBody = (ASTTryNode.container) it.next();
SootClass sootClass = ((SootClass) exceptionMap.get(catchBody));
Type type = sootClass.getType();
//apply on type of exception
caseType(type);
//apply on local of exception
Local local = (Local) paramMap.get(catchBody);
/*
* March 18th, 2006, Since these are always locals we dont have access to ValueBox
*/
decideCaseExprOrRef(local);
//apply on catchBody
List<Object> body = (List<Object>) catchBody.o;
toReturn = new ArrayList<Object>();
itBody = body.iterator();
while (itBody.hasNext()) {
ASTNode temp = (ASTNode) itBody.next();
if(!codeFinder.isConstructReachable(temp)){
toReturn.add(temp);
}
else{
//only apply on reachable nodes
temp.apply(this);
}
}
itBody = toReturn.iterator();
while(itBody.hasNext()){
body.remove(itBody.next());
}
}
}
private void dealWithSwitchNode(ASTSwitchNode node){
//System.out.println("dealing with SwitchNode");
//do a depthfirst on elements of the switchNode
List<Object> indexList = node.getIndexList();
Map<Object, List<Object>> index2BodyList = node.getIndex2BodyList();
Iterator<Object> it = indexList.iterator();
while (it.hasNext()) {//going through all the cases of the switch statement
Object currentIndex = it.next();
List body = index2BodyList.get( currentIndex);
if (body == null)
continue;
//this body is a list of ASTNodes
List<ASTNode> toReturn = new ArrayList<ASTNode>();
Iterator itBody = body.iterator();
//go over the ASTNodes and apply
while (itBody.hasNext()){
ASTNode temp = (ASTNode) itBody.next();
//System.out.println("Checking whether child of type "+temp.getClass()+" is reachable");
if(!codeFinder.isConstructReachable(temp)){
//System.out.println(">>>>>>>>>>>>>>>>>-------------------------A child of node of type "+node.getClass()+" whose type is "+temp.getClass()+" is unreachable");
toReturn.add(temp);
}
else{
//System.out.println("child of type "+temp.getClass()+" is reachable");
//only apply on reachable nodes
temp.apply(this);
}
}
Iterator<ASTNode> newit = toReturn.iterator();
while(newit.hasNext()){
//System.out.println("Removed");
body.remove(newit.next());
}
}
}
}