diff --git a/src/main/java/com/ibm/cldk/SymbolTable.java b/src/main/java/com/ibm/cldk/SymbolTable.java index 7abe086d..32e68694 100644 --- a/src/main/java/com/ibm/cldk/SymbolTable.java +++ b/src/main/java/com/ibm/cldk/SymbolTable.java @@ -10,7 +10,7 @@ import com.github.javaparser.ast.body.*; import com.github.javaparser.ast.expr.*; import com.github.javaparser.ast.nodeTypes.NodeWithName; -import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.type.ReferenceType; import com.github.javaparser.ast.type.Type; import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; @@ -273,7 +273,9 @@ private static Pair processCallableDeclaration(CallableDeclara // add the complete declaration string, including modifiers, throws, and // parameter names - callableNode.setDeclaration(callableDecl.getDeclarationAsString(true, true, true).strip()); + callableNode.setDeclaration(callableDecl + .getDeclarationAsString(true, true, true) + .strip().replaceAll("//.*\n", "")); // add information about callable parameters: for each parameter, type, name, // annotations, @@ -301,11 +303,32 @@ private static Pair processCallableDeclaration(CallableDeclara callableNode.setAccessedFields(getAccessedFields(body, classFields, typeName)); callableNode.setCallSites(getCallSites(body)); callableNode.setVariableDeclarations(getVariableDeclarations(body)); + callableNode.setCyclomaticComplexity(getCyclomaticComplexity(callableDecl)); String callableSignature = (callableDecl instanceof MethodDeclaration) ? callableDecl.getSignature().asString() : callableDecl.getSignature().asString().replace(callableDecl.getSignature().getName(), ""); return Pair.of(callableSignature, callableNode); } + /** + * Computes cyclomatic complexity for the given callable. + * + * @param callableDeclaration Callable to compute cyclomatic complexity for + * @return cyclomatic complexity + */ + private static int getCyclomaticComplexity(CallableDeclaration callableDeclaration) { + int ifStmtCount = callableDeclaration.findAll(IfStmt.class).size(); + int loopStmtCount = callableDeclaration.findAll(DoStmt.class).size() + + callableDeclaration.findAll(ForStmt.class).size() + + callableDeclaration.findAll(ForEachStmt.class).size() + + callableDeclaration.findAll(WhileStmt.class).size(); + int switchCaseCount = callableDeclaration.findAll(SwitchStmt.class).stream() + .map(stmt -> stmt.getEntries().size()) + .reduce(0, Integer::sum); + int conditionalExprCount = callableDeclaration.findAll(ConditionalExpr.class).size(); + int catchClauseCount = callableDeclaration.findAll(CatchClause.class).size(); + return ifStmtCount + loopStmtCount + switchCaseCount + conditionalExprCount + catchClauseCount + 1; + } + /** * Processes the given field declaration to extract information about the * declared field and diff --git a/src/main/java/com/ibm/cldk/utils/AnalysisUtils.java b/src/main/java/com/ibm/cldk/utils/AnalysisUtils.java index 89bc0f80..a9e3e8f3 100644 --- a/src/main/java/com/ibm/cldk/utils/AnalysisUtils.java +++ b/src/main/java/com/ibm/cldk/utils/AnalysisUtils.java @@ -23,6 +23,7 @@ import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ssa.IR; +import com.ibm.wala.ssa.ISSABasicBlock; import com.ibm.wala.ssa.SSAConditionalBranchInstruction; import com.ibm.wala.ssa.SSASwitchInstruction; import com.ibm.wala.types.ClassLoaderReference; @@ -96,7 +97,11 @@ public static int getCyclomaticComplexity(IR ir) { int switchBranchCount = Arrays.stream(ir.getInstructions()) .filter(inst -> inst instanceof SSASwitchInstruction) .map(inst -> ((SSASwitchInstruction) inst).getCasesAndLabels().length).reduce(0, Integer::sum); - return conditionalBranchCount + switchBranchCount + 1; + Iterable iterableBasicBlocks = ir::getBlocks; + int catchBlockCount = (int) StreamSupport.stream(iterableBasicBlocks.spliterator(), false) + .filter(ISSABasicBlock::isCatchBlock) + .count(); + return conditionalBranchCount + switchBranchCount + catchBlockCount + 1; } public static Pair getCallableFromSymbolTable(IMethod method) {