Skip to content

Commit 8253562

Browse files
authored
Merge pull request #89 from IBM/cyclomatic-complexity-analysis-level1
Cyclomatic complexity analysis level 1
2 parents f30e384 + 83d55e0 commit 8253562

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

src/main/java/com/ibm/cldk/SymbolTable.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import com.github.javaparser.ast.body.*;
1111
import com.github.javaparser.ast.expr.*;
1212
import com.github.javaparser.ast.nodeTypes.NodeWithName;
13-
import com.github.javaparser.ast.stmt.BlockStmt;
13+
import com.github.javaparser.ast.stmt.*;
1414
import com.github.javaparser.ast.type.ReferenceType;
1515
import com.github.javaparser.ast.type.Type;
1616
import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
@@ -273,7 +273,9 @@ private static Pair<String, Callable> processCallableDeclaration(CallableDeclara
273273

274274
// add the complete declaration string, including modifiers, throws, and
275275
// parameter names
276-
callableNode.setDeclaration(callableDecl.getDeclarationAsString(true, true, true).strip());
276+
callableNode.setDeclaration(callableDecl
277+
.getDeclarationAsString(true, true, true)
278+
.strip().replaceAll("//.*\n", ""));
277279

278280
// add information about callable parameters: for each parameter, type, name,
279281
// annotations,
@@ -301,11 +303,32 @@ private static Pair<String, Callable> processCallableDeclaration(CallableDeclara
301303
callableNode.setAccessedFields(getAccessedFields(body, classFields, typeName));
302304
callableNode.setCallSites(getCallSites(body));
303305
callableNode.setVariableDeclarations(getVariableDeclarations(body));
306+
callableNode.setCyclomaticComplexity(getCyclomaticComplexity(callableDecl));
304307

305308
String callableSignature = (callableDecl instanceof MethodDeclaration) ? callableDecl.getSignature().asString() : callableDecl.getSignature().asString().replace(callableDecl.getSignature().getName(), "<init>");
306309
return Pair.of(callableSignature, callableNode);
307310
}
308311

312+
/**
313+
* Computes cyclomatic complexity for the given callable.
314+
*
315+
* @param callableDeclaration Callable to compute cyclomatic complexity for
316+
* @return cyclomatic complexity
317+
*/
318+
private static int getCyclomaticComplexity(CallableDeclaration callableDeclaration) {
319+
int ifStmtCount = callableDeclaration.findAll(IfStmt.class).size();
320+
int loopStmtCount = callableDeclaration.findAll(DoStmt.class).size() +
321+
callableDeclaration.findAll(ForStmt.class).size() +
322+
callableDeclaration.findAll(ForEachStmt.class).size() +
323+
callableDeclaration.findAll(WhileStmt.class).size();
324+
int switchCaseCount = callableDeclaration.findAll(SwitchStmt.class).stream()
325+
.map(stmt -> stmt.getEntries().size())
326+
.reduce(0, Integer::sum);
327+
int conditionalExprCount = callableDeclaration.findAll(ConditionalExpr.class).size();
328+
int catchClauseCount = callableDeclaration.findAll(CatchClause.class).size();
329+
return ifStmtCount + loopStmtCount + switchCaseCount + conditionalExprCount + catchClauseCount + 1;
330+
}
331+
309332
/**
310333
* Processes the given field declaration to extract information about the
311334
* declared field and

src/main/java/com/ibm/cldk/utils/AnalysisUtils.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint;
2424
import com.ibm.wala.ipa.cha.IClassHierarchy;
2525
import com.ibm.wala.ssa.IR;
26+
import com.ibm.wala.ssa.ISSABasicBlock;
2627
import com.ibm.wala.ssa.SSAConditionalBranchInstruction;
2728
import com.ibm.wala.ssa.SSASwitchInstruction;
2829
import com.ibm.wala.types.ClassLoaderReference;
@@ -96,7 +97,11 @@ public static int getCyclomaticComplexity(IR ir) {
9697
int switchBranchCount = Arrays.stream(ir.getInstructions())
9798
.filter(inst -> inst instanceof SSASwitchInstruction)
9899
.map(inst -> ((SSASwitchInstruction) inst).getCasesAndLabels().length).reduce(0, Integer::sum);
99-
return conditionalBranchCount + switchBranchCount + 1;
100+
Iterable<ISSABasicBlock> iterableBasicBlocks = ir::getBlocks;
101+
int catchBlockCount = (int) StreamSupport.stream(iterableBasicBlocks.spliterator(), false)
102+
.filter(ISSABasicBlock::isCatchBlock)
103+
.count();
104+
return conditionalBranchCount + switchBranchCount + catchBlockCount + 1;
100105
}
101106

102107
public static Pair<String, Callable> getCallableFromSymbolTable(IMethod method) {

0 commit comments

Comments
 (0)