01: package soot.toolkits.astmetrics;
02:
03: import polyglot.ast.Binary;
04: import polyglot.ast.Expr;
05: import polyglot.ast.If;
06: import polyglot.ast.Loop;
07: import polyglot.ast.Node;
08: import polyglot.ast.Unary;
09: import polyglot.visit.NodeVisitor;
10:
11: /*
12: * TODO compute avarge complexity weighted by depth similar to expression complexity
13: *
14: *
15: * A unary boolean condition should have the complexity (BooleanLit) 1
16: * A noted condition (!) +0.5
17: * A binary relational operation ( < > <= >= == !=) +0.5
18: * A boolean logical operator ( AND and OR) +1.0
19: */
20: public class ConditionComplexityMetric extends ASTMetric {
21: int loopComplexity;
22: int ifComplexity;
23:
24: public ConditionComplexityMetric(polyglot.ast.Node node) {
25: super (node);
26: }
27:
28: public void reset() {
29: loopComplexity = ifComplexity = 0;
30: }
31:
32: public void addMetrics(ClassData data) {
33: data.addMetric(new MetricData("Loop-Cond-Complexity",
34: new Integer(loopComplexity)));
35: data.addMetric(new MetricData("If-Cond-Complexity",
36: new Integer(ifComplexity)));
37: data.addMetric(new MetricData("Total-Cond-Complexity",
38: new Integer(loopComplexity + ifComplexity)));
39: }
40:
41: public NodeVisitor enter(Node parent, Node n) {
42: if (n instanceof Loop) {
43: Expr expr = ((Loop) n).cond();
44: loopComplexity += condComplexity(expr);
45: } else if (n instanceof If) {
46: Expr expr = ((If) n).cond();
47: ifComplexity += condComplexity(expr);
48: }
49:
50: return enter(n);
51: }
52:
53: private double condComplexity(Expr expr) {
54:
55: //boolean literal
56: //binary check for AND and OR ... else its relational!!
57: //unary (Check for NOT)
58:
59: if (expr instanceof Binary) {
60: Binary b = (Binary) expr;
61: if (b.operator() == Binary.COND_AND
62: || b.operator() == Binary.COND_OR) {
63: //System.out.println(">>>>>>>> Binary (AND or OR) "+expr);
64: return 1.0 + condComplexity(b.left())
65: + condComplexity(b.right());
66: } else {
67: //System.out.println(">>>>>>>> Binary (relatinal) "+expr);
68: return 0.5 + condComplexity(b.left())
69: + condComplexity(b.right());
70: }
71: } else if (expr instanceof Unary) {
72: if (((Unary) expr).operator() == Unary.NOT) {
73: //System.out.println(">>>>>>>>>>>>>>Unary: !"+expr);
74: return 0.5 + condComplexity(((Unary) expr).expr());
75: } else {
76: //System.out.println(">>>>>>>>>>>>>>unary but Not ! "+expr);
77: return condComplexity(((Unary) expr).expr());
78: }
79: } else
80: return 1;//should return something as it is a condition after all
81: }
82:
83: }
|