Skip to content

Commit 00da8cd

Browse files
committed
Add test classes to system dependency graph with a new flag.
Signed-off-by: Rahul Krishna <i.m.ralk@gmail.com>
1 parent d7e5c5a commit 00da8cd

File tree

3 files changed

+68
-42
lines changed

3 files changed

+68
-42
lines changed

src/main/java/com/ibm/cldk/CodeAnalyzer.java

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class VersionProvider implements CommandLine.IVersionProvider {
4646

4747
public String[] getVersion() throws Exception {
4848
String version = getClass().getPackage().getImplementationVersion();
49-
return new String[]{version != null ? version : "unknown"};
49+
return new String[] { version != null ? version : "unknown" };
5050
}
5151
}
5252

@@ -56,34 +56,43 @@ public String[] getVersion() throws Exception {
5656
@Command(name = "codeanalyzer", mixinStandardHelpOptions = true, sortOptions = false, versionProvider = VersionProvider.class, description = "Analyze java application.")
5757
public class CodeAnalyzer implements Runnable {
5858

59-
@Option(names = {"-i", "--input"}, description = "Path to the project root directory.")
59+
@Option(names = { "-i", "--input" }, description = "Path to the project root directory.")
6060
private static String input;
6161

62-
@Option(names = {"-t", "--target-files"}, description = "Paths to files to be analyzed from the input application.")
62+
@Option(names = { "-t",
63+
"--target-files" }, description = "Paths to files to be analyzed from the input application.")
6364
private static List<String> targetFiles;
6465

65-
@Option(names = {"-s", "--source-analysis"}, description = "Analyze a single string of java source code instead the project.")
66+
@Option(names = { "-s",
67+
"--source-analysis" }, description = "Analyze a single string of java source code instead the project.")
6668
private static String sourceAnalysis;
6769

68-
@Option(names = {"-o", "--output"}, description = "Destination directory to save the output graphs. By default, the SDG formatted as a JSON will be printed to the console.")
70+
@Option(names = { "-o",
71+
"--output" }, description = "Destination directory to save the output graphs. By default, the SDG formatted as a JSON will be printed to the console.")
6972
private static String output;
7073

71-
@Option(names = {"-b", "--build-cmd"}, description = "Custom build command. Defaults to auto build.")
74+
@Option(names = { "-b", "--build-cmd" }, description = "Custom build command. Defaults to auto build.")
7275
private static String build;
7376

74-
@Option(names = {"--no-build"}, description = "Do not build your application. Use this option if you have already built your application.")
77+
@Option(names = {
78+
"--no-build" }, description = "Do not build your application. Use this option if you have already built your application.")
7579
private static boolean noBuild = false;
7680

77-
@Option(names = {"--no-clean-dependencies"}, description = "Do not attempt to auto-clean dependencies")
81+
@Option(names = { "--no-clean-dependencies" }, description = "Do not attempt to auto-clean dependencies")
7882
public static boolean noCleanDependencies = false;
7983

80-
@Option(names = {"-f", "--project-root-path"}, description = "Path to the root pom.xml/build.gradle file of the project.")
84+
@Option(names = { "-f",
85+
"--project-root-path" }, description = "Path to the root pom.xml/build.gradle file of the project.")
8186
public static String projectRootPom;
8287

83-
@Option(names = {"-a", "--analysis-level"}, description = "Level of analysis to perform. Options: 1 (for just symbol table) or 2 (for call graph). Default: 1")
88+
@Option(names = { "-a",
89+
"--analysis-level" }, description = "Level of analysis to perform. Options: 1 (for just symbol table) or 2 (for call graph). Default: 1")
8490
private static int analysisLevel = 1;
8591

86-
@Option(names = {"-v", "--verbose"}, description = "Print logs to console.")
92+
@Option(names = { "--include-test-classes" }, hidden = true, description = "Print logs to console.")
93+
public static boolean includeTestClasses = false;
94+
95+
@Option(names = { "-v", "--verbose" }, description = "Print logs to console.")
8796
private static boolean verbose = false;
8897

8998
private static final String outputFileName = "analysis.json";
@@ -121,11 +130,13 @@ private static void analyze() throws Exception {
121130
JsonObject combinedJsonObject = new JsonObject();
122131
Map<String, JavaCompilationUnit> symbolTable;
123132
projectRootPom = projectRootPom == null ? input : projectRootPom;
124-
// First of all if, sourceAnalysis is provided, we will analyze the source code instead of the project.
133+
// First of all if, sourceAnalysis is provided, we will analyze the source code
134+
// instead of the project.
125135
if (sourceAnalysis != null) {
126136
// Construct symbol table for source code
127137
Log.debug("Single file analysis.");
128-
Pair<Map<String, JavaCompilationUnit>, Map<String, List<Problem>>> symbolTableExtractionResult = SymbolTable.extractSingle(sourceAnalysis);
138+
Pair<Map<String, JavaCompilationUnit>, Map<String, List<Problem>>> symbolTableExtractionResult = SymbolTable
139+
.extractSingle(sourceAnalysis);
129140
symbolTable = symbolTableExtractionResult.getLeft();
130141
} else {
131142
// download library dependencies of project for type resolution
@@ -140,9 +151,11 @@ private static void analyze() throws Exception {
140151
Log.warn("Failed to download library dependencies of project");
141152
}
142153

143-
boolean analysisFileExists = output != null && Files.exists(Paths.get(output + File.separator + outputFileName));
154+
boolean analysisFileExists = output != null
155+
&& Files.exists(Paths.get(output + File.separator + outputFileName));
144156

145-
// if target files are specified, compute symbol table information for the given files
157+
// if target files are specified, compute symbol table information for the given
158+
// files
146159
if (targetFiles != null) {
147160
Log.info(targetFiles.size() + "target files specified for analysis: " + targetFiles);
148161

@@ -154,17 +167,22 @@ private static void analyze() throws Exception {
154167
}
155168

156169
// Previous code was pointing to toList, which has been introduced in Java 16
157-
// symbolTable = SymbolTable.extract(Paths.get(input), targetFiles.stream().map(Paths::get).toList()).getLeft();
170+
// symbolTable = SymbolTable.extract(Paths.get(input),
171+
// targetFiles.stream().map(Paths::get).toList()).getLeft();
158172
// extract symbol table for the specified files
159-
symbolTable = SymbolTable.extract(Paths.get(input), targetFiles.stream().map(Paths::get).collect(Collectors.toList())).getLeft();
173+
symbolTable = SymbolTable
174+
.extract(Paths.get(input), targetFiles.stream().map(Paths::get).collect(Collectors.toList()))
175+
.getLeft();
160176

161-
// if analysis file exists, update it with new symbol table information for the specified fiels
177+
// if analysis file exists, update it with new symbol table information for the
178+
// specified fiels
162179
if (analysisFileExists) {
163180
// read symbol table information from existing analysis file
164181
Map<String, JavaCompilationUnit> existingSymbolTable = readSymbolTableFromFile(
165182
new File(output, outputFileName));
166183
if (existingSymbolTable != null) {
167-
// for each file, tag its symbol table information as "updated" and update existing symbol table
184+
// for each file, tag its symbol table information as "updated" and update
185+
// existing symbol table
168186
for (String targetFile : targetFiles) {
169187
String targetPathAbs = Paths.get(targetFile).toAbsolutePath().toString();
170188
JavaCompilationUnit javaCompilationUnit = symbolTable.get(targetPathAbs);
@@ -175,16 +193,18 @@ private static void analyze() throws Exception {
175193
symbolTable = existingSymbolTable;
176194
}
177195
} else {
178-
// construct symbol table for project, write parse problems to file in output directory if specified
179-
Pair<Map<String, JavaCompilationUnit>, Map<String, List<Problem>>> symbolTableExtractionResult
180-
= SymbolTable.extractAll(Paths.get(input));
196+
// construct symbol table for project, write parse problems to file in output
197+
// directory if specified
198+
Pair<Map<String, JavaCompilationUnit>, Map<String, List<Problem>>> symbolTableExtractionResult = SymbolTable
199+
.extractAll(Paths.get(input));
181200

182201
symbolTable = symbolTableExtractionResult.getLeft();
183202
}
184203

185204
if (analysisLevel > 1) {
186205
// Save SDG, and Call graph as JSON
187-
// If noBuild is not true, and build is also not provided, we will use "auto" as the build command
206+
// If noBuild is not true, and build is also not provided, we will use "auto" as
207+
// the build command
188208
build = build == null ? "auto" : build;
189209
// Is noBuild is true, we will not build the project
190210
build = noBuild ? null : build;

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.ibm.cldk.utils;
22

3-
import com.ibm.cldk.CodeAnalyzer;
4-
53
import java.io.BufferedReader;
64
import java.io.File;
75
import java.io.IOException;
@@ -17,6 +15,7 @@
1715
import static com.ibm.cldk.utils.ProjectDirectoryScanner.classFilesStream;
1816
import static com.ibm.cldk.CodeAnalyzer.projectRootPom;
1917
import static com.ibm.cldk.CodeAnalyzer.noCleanDependencies;
18+
import static com.ibm.cldk.CodeAnalyzer.includeTestClasses;
2019

2120
public class BuildProject {
2221
public static Path libDownloadPath;
@@ -140,7 +139,14 @@ private static boolean mavenBuild(String projectPath) {
140139
Log.info("Checking if Maven is installed.");
141140
return false;
142141
}
143-
String[] mavenCommand = {MAVEN_CMD, "clean", "compile", "-f", projectPath + "/pom.xml", "-B", "-V", "-e", "-Drat.skip", "-Dfindbugs.skip", "-Dcheckstyle.skip", "-Dpmd.skip=true", "-Dspotbugs.skip", "-Denforcer.skip", "-Dmaven.javadoc.skip", "-DskipTests", "-Dmaven.test.skip.exec", "-Dlicense.skip=true", "-Drat.skip=true", "-Dspotless.check.skip=true"};
142+
143+
String[] mavenCommand;
144+
if (includeTestClasses) {
145+
Log.warn("Hidden flag `--include-test-classes` is turned on. We'll including test classes in WALA analysis");
146+
mavenCommand = new String[]{MAVEN_CMD, "clean", "test-compile", "-f", projectPath + "/pom.xml", "-B", "-V", "-e", "-Drat.skip", "-Dfindbugs.skip", "-Dcheckstyle.skip", "-Dpmd.skip=true", "-Dspotbugs.skip", "-Denforcer.skip", "-Dmaven.javadoc.skip", "-DskipTests", "-Dmaven.test.skip.exec", "-Dlicense.skip=true", "-Drat.skip=true", "-Dspotless.check.skip=true"};
147+
}
148+
else
149+
mavenCommand = new String[]{MAVEN_CMD, "clean", "compile", "-f", projectPath + "/pom.xml", "-B", "-V", "-e", "-Drat.skip", "-Dfindbugs.skip", "-Dcheckstyle.skip", "-Dpmd.skip=true", "-Dspotbugs.skip", "-Denforcer.skip", "-Dmaven.javadoc.skip", "-DskipTests", "-Dmaven.test.skip.exec", "-Dlicense.skip=true", "-Drat.skip=true", "-Dspotless.check.skip=true"};
144150

145151
return buildWithTool(mavenCommand);
146152
}
@@ -151,7 +157,12 @@ public static boolean gradleBuild(String projectPath) {
151157
if (GRADLE_CMD.equals("gradlew") || GRADLE_CMD.equals("gradlew.bat")) {
152158
gradleCommand = new String[]{projectPath + File.separator + GRADLE_CMD, "clean", "compileJava", "-p", projectPath};
153159
} else {
154-
gradleCommand = new String[]{GRADLE_CMD, "clean", "compileJava", "-p", projectPath};
160+
if (includeTestClasses) {
161+
Log.warn("Hidden flag `--include-test-classes` is turned on. We'll including test classes in WALA analysis");
162+
gradleCommand = new String[]{GRADLE_CMD, "clean", "compileTestJava", "-p", projectPath};
163+
}
164+
else
165+
gradleCommand = new String[]{GRADLE_CMD, "clean", "compileJava", "-p", projectPath};
155166
}
156167
return buildWithTool(gradleCommand);
157168
}

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

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,15 @@
99
import java.util.stream.Collectors;
1010
import java.util.stream.Stream;
1111

12+
import static com.ibm.cldk.CodeAnalyzer.includeTestClasses;
13+
1214
public class ProjectDirectoryScanner {
1315
public static List<Path> classFilesStream(String projectPath) throws IOException {
1416
Path projectDir = Paths.get(projectPath).toAbsolutePath();
1517
Log.info("Finding *.class files in " + projectDir);
1618
if (Files.exists(projectDir)) {
1719
try (Stream<Path> paths = Files.walk(projectDir)) {
18-
return paths.filter(file -> !Files.isDirectory(file) && file.toString().endsWith(".class"))
19-
.filter(file -> {
20-
// Let's find the path relative to the project directory
21-
Path relativePath = projectDir.relativize(file.toAbsolutePath());
22-
String relativePathAsString = relativePath.toString().replace("\\", "/"); // Windows fix
23-
return !relativePathAsString.contains("test/resources/") && !relativePathAsString.contains("main/resources/");
24-
})
25-
.collect(Collectors.toList());
20+
return paths.filter(file -> !Files.isDirectory(file) && file.toString().endsWith(".class")).collect(Collectors.toList());
2621
}
2722
}
2823
return null;
@@ -47,13 +42,13 @@ public static List<Path> sourceFilesStream(String projectPath) throws IOExceptio
4742
if (Files.exists(projectDir)) {
4843
try (Stream<Path> paths = Files.walk(projectDir)) {
4944
return paths
50-
.filter(file -> !Files.isDirectory(file))
51-
.filter(file -> file.toString().endsWith(".java"))
52-
.filter(file -> !file.toAbsolutePath().toString().contains("build/"))
53-
.filter(file -> !file.toAbsolutePath().toString().contains("target/"))
54-
.filter(file -> !file.toAbsolutePath().toString().contains("main/resources/"))
55-
.filter(file -> !file.toAbsolutePath().toString().contains("test/resources/"))
56-
.collect(Collectors.toList());
45+
.filter(file -> !Files.isDirectory(file))
46+
.filter(file -> file.toString().endsWith(".java"))
47+
.filter(file -> !file.toAbsolutePath().toString().contains("build/"))
48+
.filter(file -> !file.toAbsolutePath().toString().contains("target/"))
49+
.filter(file -> !file.toAbsolutePath().toString().contains("main/resources/"))
50+
.filter(file -> !file.toAbsolutePath().toString().contains("test/resources/"))
51+
.collect(Collectors.toList());
5752
}
5853
}
5954
return null;

0 commit comments

Comments
 (0)