package soot.toolkits.astmetrics; import polyglot.ast.Binary; import polyglot.ast.Expr; import polyglot.ast.If; import polyglot.ast.Loop; import polyglot.ast.Node; import polyglot.ast.Unary; import polyglot.visit.NodeVisitor; /* * TODO compute avarge complexity weighted by depth similar to expression complexity * * * A unary boolean condition should have the complexity (BooleanLit) 1 * A noted condition (!) +0.5 * A binary relational operation ( < > <= >= == !=) +0.5 * A boolean logical operator ( AND and OR) +1.0 */ public class ConditionComplexityMetric extends ASTMetric { int loopComplexity; int ifComplexity; public ConditionComplexityMetric(polyglot.ast.Node node){ super(node); } public void reset() { loopComplexity=ifComplexity=0; } public void addMetrics(ClassData data) { data.addMetric(new MetricData("Loop-Cond-Complexity",new Integer(loopComplexity))); data.addMetric(new MetricData("If-Cond-Complexity",new Integer(ifComplexity))); data.addMetric(new MetricData("Total-Cond-Complexity",new Integer(loopComplexity+ifComplexity))); } public NodeVisitor enter(Node parent, Node n){ if(n instanceof Loop){ Expr expr = ((Loop)n).cond(); loopComplexity += condComplexity(expr); } else if (n instanceof If){ Expr expr = ((If)n).cond(); ifComplexity += condComplexity(expr); } return enter(n); } private double condComplexity(Expr expr){ //boolean literal //binary check for AND and OR ... else its relational!! //unary (Check for NOT) if(expr instanceof Binary){ Binary b = (Binary)expr; if( b.operator() == Binary.COND_AND || b.operator() == Binary.COND_OR){ //System.out.println(">>>>>>>> Binary (AND or OR) "+expr); return 1.0 + condComplexity(b.left()) + condComplexity(b.right()); } else{ //System.out.println(">>>>>>>> Binary (relatinal) "+expr); return 0.5 + condComplexity(b.left()) + condComplexity(b.right()); } } else if(expr instanceof Unary){ if(((Unary)expr).operator() == Unary.NOT){ //System.out.println(">>>>>>>>>>>>>>Unary: !"+expr); return 0.5 + condComplexity(((Unary)expr).expr()); } else{ //System.out.println(">>>>>>>>>>>>>>unary but Not ! "+expr); return condComplexity(((Unary)expr).expr()); } } else return 1;//should return something as it is a condition after all } }