Skip to content

Commit 8bdbace

Browse files
authored
Merge pull request #92 from IBM/fix-issue-87
Fix issue 87, 88, 90, and 91
2 parents 1ad2b92 + ff1184b commit 8bdbace

File tree

4 files changed

+71
-15
lines changed

4 files changed

+71
-15
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=1.0.8
1+
version=1.0.9

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) {

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

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.nio.file.Files;
1010
import java.nio.file.Path;
1111
import java.nio.file.Paths;
12+
import java.util.AbstractMap;
1213
import java.util.ArrayList;
1314
import java.util.Arrays;
1415
import java.util.List;
@@ -54,7 +55,7 @@ private static String getGradleCmd() {
5455
String gradleWrapperExists = new File(projectRootPom, gradleWrapper).exists() ? "true" : "false";
5556

5657
if (new File(projectRootPom, gradleWrapper).exists()) {
57-
GRADLE_CMD = gradleWrapper;
58+
GRADLE_CMD = String.valueOf(new File(projectRootPom, gradleWrapper));
5859
} else {
5960
GRADLE_CMD = gradle;
6061
}
@@ -88,19 +89,44 @@ private static String getGradleCmd() {
8889
" }\n" +
8990
"}";
9091

91-
private static boolean commandExists(String command) {
92+
private static AbstractMap.SimpleEntry<Boolean, String> commandExists(String command) {
93+
StringBuilder output = new StringBuilder();
9294
try {
93-
Process process = new ProcessBuilder(command, "--version").start();
95+
Process process = new ProcessBuilder().directory(new File(projectRootPom)).command(command, "--version").start();
96+
// Read the output stream
97+
BufferedReader reader = new BufferedReader(
98+
new InputStreamReader(process.getInputStream())
99+
);
100+
String line;
101+
while ((line = reader.readLine()) != null) {
102+
output.append(line).append("\n");
103+
}
104+
105+
// Read the error stream
106+
BufferedReader errorReader = new BufferedReader(
107+
new InputStreamReader(process.getErrorStream())
108+
);
109+
while ((line = errorReader.readLine()) != null) {
110+
output.append(line).append("\n");
111+
}
112+
113+
94114
int exitCode = process.waitFor();
95-
return exitCode == 0;
115+
return new AbstractMap.SimpleEntry<>(
116+
exitCode == 0,
117+
output.toString().trim()
118+
);
96119
} catch (IOException | InterruptedException exceptions) {
97-
return false;
120+
return new AbstractMap.SimpleEntry<>(
121+
false,
122+
exceptions.getMessage()
123+
);
98124
}
99125
}
100126

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

105131
try {
106132
Process process = processBuilder.start();
@@ -125,7 +151,7 @@ private static boolean buildWithTool(String[] buildCommand) {
125151
* @return true if Maven is installed, false otherwise.
126152
*/
127153
private static boolean isMavenInstalled() {
128-
ProcessBuilder processBuilder = new ProcessBuilder(MAVEN_CMD, "--version");
154+
ProcessBuilder processBuilder = new ProcessBuilder().directory(new File(projectRootPom)).command(MAVEN_CMD, "--version");
129155
try {
130156
Process process = processBuilder.start();
131157
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
@@ -227,8 +253,9 @@ public static boolean downloadLibraryDependencies(String projectPath, String pro
227253
File pomFile = new File(projectRoot, "pom.xml");
228254
if (pomFile.exists()) {
229255
Log.info("Found pom.xml in the project directory. Using Maven to download dependencies.");
230-
if (!commandExists(MAVEN_CMD))
231-
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.");
256+
AbstractMap.SimpleEntry<Boolean, String> mavenCheck = commandExists(MAVEN_CMD);
257+
if (!mavenCheck.getKey())
258+
throw new IllegalStateException("Unable to execute Maven command. Attempt failed with message\n" + mavenCheck.getValue());
232259

233260
String[] mavenCommand = {
234261
MAVEN_CMD, "--no-transfer-progress", "-f",
@@ -239,8 +266,9 @@ public static boolean downloadLibraryDependencies(String projectPath, String pro
239266
return buildWithTool(mavenCommand);
240267
} else if (new File(projectRoot, "build.gradle").exists() || new File(projectRoot, "build.gradle.kts").exists()) {
241268
Log.info("Found build.gradle or build.gradle.kts in the project directory. Using gradle to download dependencies.");
242-
if (!commandExists(GRADLE_CMD))
243-
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.");
269+
AbstractMap.SimpleEntry<Boolean, String> gradleCheck = commandExists(GRADLE_CMD);
270+
if (!gradleCheck.getKey())
271+
throw new IllegalStateException("Could not execute Gradle command. Attempt failed with message\n" + gradleCheck.getValue());
244272

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

0 commit comments

Comments
 (0)