Skip to content

Commit 6de0f65

Browse files
committed
Initial commit
0 parents  commit 6de0f65

File tree

9 files changed

+456
-0
lines changed

9 files changed

+456
-0
lines changed

.gitignore

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Created by .ignore support plugin (hsz.mobi)
2+
### JetBrains template
3+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
4+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
5+
6+
# User-specific stuff
7+
.idea/**/workspace.xml
8+
.idea/**/tasks.xml
9+
.idea/**/usage.statistics.xml
10+
.idea/**/dictionaries
11+
.idea/**/shelf
12+
13+
# Generated files
14+
.idea/**/contentModel.xml
15+
16+
# Sensitive or high-churn files
17+
.idea/**/dataSources/
18+
.idea/**/dataSources.ids
19+
.idea/**/dataSources.local.xml
20+
.idea/**/sqlDataSources.xml
21+
.idea/**/dynamic.xml
22+
.idea/**/uiDesigner.xml
23+
.idea/**/dbnavigator.xml
24+
25+
# Gradle
26+
.idea/**/gradle.xml
27+
.idea/**/libraries
28+
29+
# Gradle and Maven with auto-import
30+
# When using Gradle or Maven with auto-import, you should exclude module files,
31+
# since they will be recreated, and may cause churn. Uncomment if using
32+
# auto-import.
33+
# .idea/artifacts
34+
# .idea/compiler.xml
35+
# .idea/jarRepositories.xml
36+
# .idea/modules.xml
37+
# .idea/*.iml
38+
# .idea/modules
39+
# *.iml
40+
# *.ipr
41+
42+
# CMake
43+
cmake-build-*/
44+
45+
# Mongo Explorer plugin
46+
.idea/**/mongoSettings.xml
47+
48+
# File-based project format
49+
*.iws
50+
51+
# IntelliJ
52+
out/
53+
54+
# mpeltonen/sbt-idea plugin
55+
.idea_modules/
56+
57+
# JIRA plugin
58+
atlassian-ide-plugin.xml
59+
60+
# Cursive Clojure plugin
61+
.idea/replstate.xml
62+
63+
# Crashlytics plugin (for Android Studio and IntelliJ)
64+
com_crashlytics_export_strings.xml
65+
crashlytics.properties
66+
crashlytics-build.properties
67+
fabric.properties
68+
69+
# Editor-based Rest Client
70+
.idea/httpRequests
71+
72+
# Android studio 3.1+ serialized cache file
73+
.idea/caches/build_file_checksums.ser
74+
75+
### Java template
76+
# Compiled class file
77+
*.class
78+
79+
# Log file
80+
*.log
81+
82+
# BlueJ files
83+
*.ctxt
84+
85+
# Mobile Tools for Java (J2ME)
86+
.mtj.tmp/
87+
88+
# Package Files #
89+
*.jar
90+
*.war
91+
*.nar
92+
*.ear
93+
*.zip
94+
*.tar.gz
95+
*.rar
96+
97+
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
98+
hs_err_pid*
99+
100+
101+
# Project exclude paths
102+
/target/

java-source-code-analyzer.iml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="JAVA_MODULE" version="4" />

pom.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>org.codeplay</groupId>
8+
<artifactId>java-source-code-analyzer</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<properties>
12+
<maven.compiler.source>8</maven.compiler.source>
13+
<maven.compiler.target>8</maven.compiler.target>
14+
</properties>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>com.github.javaparser</groupId>
19+
<artifactId>javaparser-symbol-solver-core</artifactId>
20+
<version>3.20.2</version>
21+
</dependency>
22+
</dependencies>
23+
24+
</project>

src/main/java/Main.java

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import com.github.javaparser.StaticJavaParser;
2+
import com.github.javaparser.ast.CompilationUnit;
3+
import com.github.javaparser.ast.body.MethodDeclaration;
4+
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
5+
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
6+
import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
7+
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
8+
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
9+
import visitors.MethodCallVisitor;
10+
11+
import java.io.File;
12+
import java.io.IOException;
13+
import java.util.Arrays;
14+
import java.util.List;
15+
16+
/**
17+
* @author coldilock
18+
*/
19+
public class Main {
20+
public static void main(String[] args) throws IOException {
21+
String javaFilePath = "src/main/resources/testcase/test1.java";
22+
getMethodCalls(javaFilePath);
23+
}
24+
25+
/**
26+
* get all method calls of a java source file
27+
* @param javaFilePath java source file path
28+
* @throws IOException
29+
*/
30+
public static void getMethodCalls(String javaFilePath) throws IOException {
31+
JavaSymbolSolver symbolSolver = configureJavaSymbolSolver(true, true, true);
32+
StaticJavaParser.getConfiguration().setSymbolResolver(symbolSolver);
33+
34+
// cu is the AST root
35+
CompilationUnit cu = StaticJavaParser.parse(new File(javaFilePath));
36+
// find all methods in the java file, and get all method invocations for each method
37+
cu.findAll(MethodDeclaration.class).forEach(method -> {
38+
MethodCallVisitor visitor = new MethodCallVisitor();
39+
method.accept(visitor, null);
40+
});
41+
}
42+
43+
/**
44+
* Configure the JavaSymbolSolver
45+
* @param isResolvingJdkAPI resolve types from JDK API or not
46+
* @param isResolvingThirdPartyAPI resolve types from Third Party APIs or not
47+
* @param isResolvingUserDefinedAPI resolve types from User-defined Classes or not
48+
* @throws IOException
49+
*/
50+
public static JavaSymbolSolver configureJavaSymbolSolver(boolean isResolvingJdkAPI, boolean isResolvingThirdPartyAPI, boolean isResolvingUserDefinedAPI) throws IOException {
51+
CombinedTypeSolver typeSolver = new CombinedTypeSolver();
52+
53+
/*
54+
* Resolve qualified types/names from JDK API
55+
* e.g. String str -> the type of "str" is 'java.lang.String'
56+
*/
57+
if(isResolvingJdkAPI){
58+
typeSolver.add(new ReflectionTypeSolver());
59+
}
60+
/*
61+
* Resolve qualified types/names from Third Party APIs
62+
* e.g. CollectionUtils.emptyIfNull(xxx) -> org.apache.commons.collections4.CollectionUtils.emptyIfNull(java.util.Collection<T>)
63+
*/
64+
if(isResolvingThirdPartyAPI){
65+
List<String> jarFileList = Arrays.asList(
66+
"src/main/resources/jarfiles/commons-collections4-4.4.jar",
67+
"src/main/resources/jarfiles/javaparser-core-3.16.1.jar"
68+
);
69+
// set the jar file paths to JarTypeSolver
70+
for(String jarFilePath : jarFileList){
71+
typeSolver.add(JarTypeSolver.getJarTypeSolver(jarFilePath));
72+
}
73+
}
74+
/*
75+
* Resolve qualified types/names from User-defined Classes and Methods.
76+
*/
77+
if(isResolvingUserDefinedAPI){
78+
// Specify the source root path where the target file is located
79+
String projectSrcPath = "src/main/java";
80+
typeSolver.add(new JavaParserTypeSolver(new File(projectSrcPath)));
81+
}
82+
83+
return new JavaSymbolSolver(typeSolver);
84+
}
85+
}

src/main/java/utils/StringUtils.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package utils;
2+
3+
/**
4+
* @author coldilock
5+
*/
6+
public class StringUtils {
7+
public static boolean isValidMethodName(String str){
8+
return !str.isEmpty() && !str.startsWith(".") && !str.startsWith("UnsolvedType.");
9+
}
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package visitors;
2+
3+
/**
4+
* @author coldilock
5+
*
6+
* Extract all member variables and methods in the specified class
7+
*/
8+
public class ClassMemeberVisitor {
9+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package visitors;
2+
3+
import com.github.javaparser.ast.body.MethodDeclaration;
4+
import com.github.javaparser.ast.expr.MethodCallExpr;
5+
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
6+
import utils.StringUtils;
7+
8+
/**
9+
* @author coldilock
10+
*
11+
* Extract method calls in java source code.
12+
*/
13+
public class MethodCallVisitor extends VoidVisitorAdapter {
14+
15+
/**
16+
* Method declaration in a java file. That is, the calling method of the method invocation
17+
* @param n
18+
* @param arg
19+
*/
20+
@Override
21+
public void visit(MethodDeclaration n, Object arg) {
22+
// get the name of the calling method
23+
String methodName = n.getNameAsString();
24+
// get the return type of the calling method
25+
String methodReturnType = n.getType().toString();
26+
String methodSignature;
27+
try{
28+
// get the qualified signature of the calling method using JavaSymbolSolver
29+
methodSignature = n.resolve().getQualifiedSignature();
30+
} catch (Exception e){
31+
methodSignature = "UnsolvedType.In.MethodDeclaration.method()";
32+
}
33+
34+
if(StringUtils.isValidMethodName(methodSignature)){
35+
// System.out.printf("[callingMethodName]: %s [returnType]: %s [methodSignature]: %s%n", methodName, methodReturnType, methodSignature);
36+
System.out.printf("[Calling Method]: %s\t[returnType]: %s%n", methodSignature, methodReturnType);
37+
}
38+
39+
super.visit(n, arg);
40+
}
41+
42+
/**
43+
* Method call in a method. That is, the called method of the method invocation
44+
* @param n
45+
* @param arg
46+
*/
47+
@Override
48+
public void visit(MethodCallExpr n, Object arg) {
49+
/*
50+
* Calling the visit method first of the super class can handle the following situations:
51+
* (1) If the parameter of the method call is also a method call, the parameter will be processed first.
52+
* (2) If there are continuous method calls, process these called methods from left to right.
53+
*/
54+
super.visit(n, arg);
55+
56+
// get the name of theOr if called method
57+
String methodName = n.getNameAsString();
58+
String methodReturnType = "";
59+
String methodSignature;
60+
try{
61+
// get the qualified signature and return type of the called method using JavaSymbolSolver
62+
methodSignature = n.resolve().getQualifiedSignature();
63+
methodReturnType = n.resolve().getReturnType().describe();
64+
} catch (Exception e){
65+
methodSignature = "UnsolvedType.In.MethodCallExpr.method()";
66+
}
67+
68+
if(StringUtils.isValidMethodName(methodSignature)){
69+
// System.out.printf("\t[calledMethodName]: %s [returnType]: %s [methodSignature]: %s%n", methodName, methodReturnType, methodSignature);
70+
System.out.printf("\t[Called Method]: %s\t[returnType]: %s%n", methodSignature, methodReturnType);
71+
}
72+
}
73+
74+
}

0 commit comments

Comments
 (0)