Skip to content

Commit

Permalink
Merge pull request #14 from sinha108/main
Browse files Browse the repository at this point in the history
Computation of cyclomatic complexity for callables
  • Loading branch information
rahlk authored May 3, 2024
2 parents d15f332 + 58b8105 commit 147e449
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 9 deletions.
11 changes: 6 additions & 5 deletions src/main/java/com/ibm/northstar/CodeAnalyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,7 @@ private static void analyze() throws IOException, ClassHierarchyException, CallG
gson.toJson(symbolTableExtractionResult.getRight(), new FileWriter(new File(outputPath.toString(), "parse_errors.json")));
}

// Convert the JavaCompilationUnit to JSON
String symbolTableJSONString = gson.toJson(symbolTable);
JsonElement symbolTableJSON = gson.fromJson(symbolTableJSONString, JsonElement.class);

JsonObject combinedJsonObject = new JsonObject();
combinedJsonObject.add("symbol_table", symbolTableJSON);
if (analysisLevel > 1) {
// Save SDG, IPCFG, and Call graph as JSON
// If noBuild is not true, and build is also not provided, we will use "auto" as the build command
Expand All @@ -138,6 +133,12 @@ private static void analyze() throws IOException, ClassHierarchyException, CallG
combinedJsonObject.add("system_dependency_graph", edges);

}

// Convert the JavaCompilationUnit to JSON and add to consolidated json object
String symbolTableJSONString = gson.toJson(symbolTable);
JsonElement symbolTableJSON = gson.fromJson(symbolTableJSONString, JsonElement.class);
combinedJsonObject.add("symbol_table", symbolTableJSON);

String consolidatedJSONString = gson.toJson(combinedJsonObject);
emit(consolidatedJSONString);
}
Expand Down
23 changes: 19 additions & 4 deletions src/main/java/com/ibm/northstar/SystemDependencyGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@

package com.ibm.northstar;

import com.ibm.northstar.entities.AbstractGraphEdge;
import com.ibm.northstar.entities.CallEdge;
import com.ibm.northstar.entities.Callable;
import com.ibm.northstar.entities.SystemDepEdge;
import com.ibm.northstar.utils.AnalysisUtils;
import com.ibm.northstar.utils.Log;
import com.ibm.northstar.entities.*;
import com.ibm.northstar.utils.ScopeUtils;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.java.client.impl.ZeroCFABuilderFactory;
import com.ibm.wala.cast.java.translator.jdt.ecj.ECJClassLoaderFactory;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.*;
import com.ibm.wala.ipa.callgraph.AnalysisOptions.ReflectionOptions;
import com.ibm.wala.ipa.callgraph.impl.Util;
Expand Down Expand Up @@ -51,8 +55,7 @@
import java.util.function.Supplier;

import static com.ibm.northstar.CodeAnalyzer.gson;
import static com.ibm.northstar.utils.AnalysisUtils.getCallableFromSymbolTable;
import static com.ibm.northstar.utils.AnalysisUtils.createAndPutNewCallableInSymbolTable;
import static com.ibm.northstar.utils.AnalysisUtils.*;

/**
* The type Sdg 2 json.
Expand Down Expand Up @@ -223,6 +226,18 @@ public static String construct(
IAnalysisCacheView cache = new AnalysisCacheImpl(AstIRFactory.makeDefaultFactory(),
options.getSSAOptions());

// set cyclomatic complexity for callables in the symbol table
int numClasses = cha.getNumberOfClasses();
for (Iterator<IClass> classIter = cha.iterator(); classIter.hasNext(); ) {
IClass cls = classIter.next();
for (IMethod method: cls.getAllMethods()) {
Callable callable = getCallableFromSymbolTable(method).getRight();
if (callable != null) {
callable.setCyclomaticComplexity(getCyclomaticComplexity(cache.getIR(method)));
}
}
}

// Build call graph
Log.info("Building call graph.");

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/ibm/northstar/entities/Callable.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ public class Callable {
private List<String> calledMethodDeclaringTypes;
private List<CallSite> callSites;
private List<VariableDeclaration> variableDeclarations;
private int cyclomaticComplexity;
}
15 changes: 15 additions & 0 deletions src/main/java/com/ibm/northstar/utils/AnalysisUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.ibm.wala.ipa.callgraph.Entrypoint;
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.SSAConditionalBranchInstruction;
import com.ibm.wala.types.ClassLoaderReference;

import java.util.*;
Expand Down Expand Up @@ -77,6 +79,19 @@ public static Pair<String, Callable> createAndPutNewCallableInSymbolTable(IMetho
return Pair.of(declaringClassSignature, newCallable);
}

/**
* Computes and returns cyclomatic complexity for the given IR (for a method or constructor).
*
* @param ir IR for method or constructor
* @return int Cyclomatic complexity for method/constructor
*/
public static int getCyclomaticComplexity(IR ir) {
int branchCount = (int)Arrays.stream(ir.getInstructions())
.filter(inst -> inst instanceof SSAConditionalBranchInstruction)
.count();
return branchCount + 1;
}

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

// Get the class name, with a . representation.
Expand Down

0 comments on commit 147e449

Please sign in to comment.