From 392d12a88822dd3136e071e57bd81e4f8643f7e6 Mon Sep 17 00:00:00 2001 From: Saurabh Sinha Date: Mon, 13 Jan 2025 12:58:16 -0500 Subject: [PATCH 1/3] Cyclomatic complexity computation for analysis level 1 Signed-off-by: Saurabh Sinha --- src/main/java/com/ibm/cldk/SymbolTable.java | 24 ++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ibm/cldk/SymbolTable.java b/src/main/java/com/ibm/cldk/SymbolTable.java index 7abe086d..4ecfb8a1 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; @@ -301,11 +301,33 @@ 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(); + int cyclomaticComplexity = ifStmtCount + loopStmtCount + switchCaseCount + conditionalExprCount + catchClauseCount + 1; + return cyclomaticComplexity; + } + /** * Processes the given field declaration to extract information about the * declared field and From ebe64b60f97223c2f6fba0e724a37809fbd827be Mon Sep 17 00:00:00 2001 From: Saurabh Sinha Date: Mon, 13 Jan 2025 14:05:15 -0500 Subject: [PATCH 2/3] Added catch clause count to computation of cyclomatic complexity for analysis level 2 Signed-off-by: Saurabh Sinha --- src/main/java/com/ibm/cldk/SymbolTable.java | 3 +-- src/main/java/com/ibm/cldk/utils/AnalysisUtils.java | 7 ++++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ibm/cldk/SymbolTable.java b/src/main/java/com/ibm/cldk/SymbolTable.java index 4ecfb8a1..b767d39c 100644 --- a/src/main/java/com/ibm/cldk/SymbolTable.java +++ b/src/main/java/com/ibm/cldk/SymbolTable.java @@ -324,8 +324,7 @@ private static int getCyclomaticComplexity(CallableDeclaration callableDeclarati .reduce(0, Integer::sum); int conditionalExprCount = callableDeclaration.findAll(ConditionalExpr.class).size(); int catchClauseCount = callableDeclaration.findAll(CatchClause.class).size(); - int cyclomaticComplexity = ifStmtCount + loopStmtCount + switchCaseCount + conditionalExprCount + catchClauseCount + 1; - return cyclomaticComplexity; + return ifStmtCount + loopStmtCount + switchCaseCount + conditionalExprCount + catchClauseCount + 1; } /** 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) { From 83d55e090908ec92af2961da84671e0e5a82c99c Mon Sep 17 00:00:00 2001 From: Saurabh Sinha Date: Wed, 15 Jan 2025 17:31:38 -0500 Subject: [PATCH 3/3] Clean up callable declaration string to remove embedded comments. Signed-off-by: Saurabh Sinha --- src/main/java/com/ibm/cldk/SymbolTable.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/ibm/cldk/SymbolTable.java b/src/main/java/com/ibm/cldk/SymbolTable.java index b767d39c..32e68694 100644 --- a/src/main/java/com/ibm/cldk/SymbolTable.java +++ b/src/main/java/com/ibm/cldk/SymbolTable.java @@ -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,