Skip to content

Commit

Permalink
Merge pull request #92 from IBM/fix-issue-87
Browse files Browse the repository at this point in the history
Fix issue 87, 88, 90, and 91
  • Loading branch information
rahlk authored Jan 18, 2025
2 parents 1ad2b92 + ff1184b commit 8bdbace
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 15 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=1.0.8
version=1.0.9
27 changes: 25 additions & 2 deletions src/main/java/com/ibm/cldk/SymbolTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -273,7 +273,9 @@ private static Pair<String, Callable> 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,
Expand Down Expand Up @@ -301,11 +303,32 @@ private static Pair<String, Callable> 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(), "<init>");
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
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/com/ibm/cldk/utils/AnalysisUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<ISSABasicBlock> iterableBasicBlocks = ir::getBlocks;
int catchBlockCount = (int) StreamSupport.stream(iterableBasicBlocks.spliterator(), false)
.filter(ISSABasicBlock::isCatchBlock)
.count();
return conditionalBranchCount + switchBranchCount + catchBlockCount + 1;
}

public static Pair<String, Callable> getCallableFromSymbolTable(IMethod method) {
Expand Down
50 changes: 39 additions & 11 deletions src/main/java/com/ibm/cldk/utils/BuildProject.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -54,7 +55,7 @@ private static String getGradleCmd() {
String gradleWrapperExists = new File(projectRootPom, gradleWrapper).exists() ? "true" : "false";

if (new File(projectRootPom, gradleWrapper).exists()) {
GRADLE_CMD = gradleWrapper;
GRADLE_CMD = String.valueOf(new File(projectRootPom, gradleWrapper));
} else {
GRADLE_CMD = gradle;
}
Expand Down Expand Up @@ -88,19 +89,44 @@ private static String getGradleCmd() {
" }\n" +
"}";

private static boolean commandExists(String command) {
private static AbstractMap.SimpleEntry<Boolean, String> commandExists(String command) {
StringBuilder output = new StringBuilder();
try {
Process process = new ProcessBuilder(command, "--version").start();
Process process = new ProcessBuilder().directory(new File(projectRootPom)).command(command, "--version").start();
// Read the output stream
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream())
);
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}

// Read the error stream
BufferedReader errorReader = new BufferedReader(
new InputStreamReader(process.getErrorStream())
);
while ((line = errorReader.readLine()) != null) {
output.append(line).append("\n");
}


int exitCode = process.waitFor();
return exitCode == 0;
return new AbstractMap.SimpleEntry<>(
exitCode == 0,
output.toString().trim()
);
} catch (IOException | InterruptedException exceptions) {
return false;
return new AbstractMap.SimpleEntry<>(
false,
exceptions.getMessage()
);
}
}

private static boolean buildWithTool(String[] buildCommand) {
Log.info("Building the project using " + buildCommand[0] + ".");
ProcessBuilder processBuilder = new ProcessBuilder(buildCommand);
ProcessBuilder processBuilder = new ProcessBuilder().directory(new File(projectRootPom)).command(buildCommand);

try {
Process process = processBuilder.start();
Expand All @@ -125,7 +151,7 @@ private static boolean buildWithTool(String[] buildCommand) {
* @return true if Maven is installed, false otherwise.
*/
private static boolean isMavenInstalled() {
ProcessBuilder processBuilder = new ProcessBuilder(MAVEN_CMD, "--version");
ProcessBuilder processBuilder = new ProcessBuilder().directory(new File(projectRootPom)).command(MAVEN_CMD, "--version");
try {
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
Expand Down Expand Up @@ -227,8 +253,9 @@ public static boolean downloadLibraryDependencies(String projectPath, String pro
File pomFile = new File(projectRoot, "pom.xml");
if (pomFile.exists()) {
Log.info("Found pom.xml in the project directory. Using Maven to download dependencies.");
if (!commandExists(MAVEN_CMD))
throw new IllegalStateException("Could not find a valid maven command. I did not find " + MAVEN_CMD + " in the project directory or in the system PATH.");
AbstractMap.SimpleEntry<Boolean, String> mavenCheck = commandExists(MAVEN_CMD);
if (!mavenCheck.getKey())
throw new IllegalStateException("Unable to execute Maven command. Attempt failed with message\n" + mavenCheck.getValue());

String[] mavenCommand = {
MAVEN_CMD, "--no-transfer-progress", "-f",
Expand All @@ -239,8 +266,9 @@ public static boolean downloadLibraryDependencies(String projectPath, String pro
return buildWithTool(mavenCommand);
} else if (new File(projectRoot, "build.gradle").exists() || new File(projectRoot, "build.gradle.kts").exists()) {
Log.info("Found build.gradle or build.gradle.kts in the project directory. Using gradle to download dependencies.");
if (!commandExists(GRADLE_CMD))
throw new IllegalStateException("Could not find a valid Gradle command. I did not find " + GRADLE_CMD + " in the project directory or in the system PATH.");
AbstractMap.SimpleEntry<Boolean, String> gradleCheck = commandExists(GRADLE_CMD);
if (!gradleCheck.getKey())
throw new IllegalStateException("Could not execute Gradle command. Attempt failed with message\n" + gradleCheck.getValue());

Log.info("Found build.gradle[.kts] in the project directory. Using Gradle to download dependencies.");
tempInitScript = Files.writeString(tempInitScript, GRADLE_DEPENDENCIES_TASK);
Expand Down

0 comments on commit 8bdbace

Please sign in to comment.