├── .DS_Store
├── .gitignore
├── .idea
├── compiler.xml
├── jarRepositories.xml
├── misc.xml
├── uiDesigner.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── pom.xml
├── src
├── .DS_Store
├── main
│ ├── .DS_Store
│ ├── java
│ │ ├── .DS_Store
│ │ └── com
│ │ │ └── se
│ │ │ ├── DAO
│ │ │ ├── BuildConnection.java
│ │ │ ├── ClassAssetDAO.java
│ │ │ ├── ClassInfoDAO.java
│ │ │ ├── MethodInfoDAO.java
│ │ │ ├── MethodInvocationDAO.java
│ │ │ └── MethodInvocationInViewDAO.java
│ │ │ ├── config
│ │ │ └── DataConfig.java
│ │ │ ├── container
│ │ │ ├── MethodCallContainer.java
│ │ │ └── MethodInfoContainer.java
│ │ │ ├── entity
│ │ │ ├── ClassAsset.java
│ │ │ ├── ClassInfo.java
│ │ │ ├── GraphNode.java
│ │ │ ├── MeasureIndex.java
│ │ │ ├── Method.java
│ │ │ ├── MethodAsset.java
│ │ │ ├── MethodCall.java
│ │ │ ├── MethodInfo.java
│ │ │ ├── MethodInvocation.java
│ │ │ ├── MethodInvocationInView.java
│ │ │ ├── SetEnum.java
│ │ │ └── Variable.java
│ │ │ ├── godclass
│ │ │ └── GodClassCalculator.java
│ │ │ ├── metrics
│ │ │ ├── MetricCalculator.java
│ │ │ ├── calculators
│ │ │ │ ├── ATFDCalculator.java
│ │ │ │ ├── MCCCalculator.java
│ │ │ │ ├── TCCCalculator.java
│ │ │ │ └── WMCCalculator.java
│ │ │ ├── exceptions
│ │ │ │ ├── ATFDException.java
│ │ │ │ ├── MCCException.java
│ │ │ │ └── TCCException.java
│ │ │ └── visitors
│ │ │ │ ├── ATFDVisitor.java
│ │ │ │ ├── MCCVisitor.java
│ │ │ │ ├── TCCConnectionsVisitor.java
│ │ │ │ ├── TCCVariablesMethodsVisitor.java
│ │ │ │ └── WMCVisitor.java
│ │ │ ├── process
│ │ │ ├── CloneMining.java
│ │ │ ├── CountInvocation.java
│ │ │ ├── CountInvocationInMethodGra.java
│ │ │ ├── FilterMethodInvocation.java
│ │ │ ├── GetMethodInvocation.java
│ │ │ ├── GetMethodInvocationPlus.java
│ │ │ ├── GodClassProcess.java
│ │ │ ├── Process.java
│ │ │ ├── SimilarityEntityDetect.java
│ │ │ └── StructureDetect.java
│ │ │ ├── utils
│ │ │ ├── CalculateUtil.java
│ │ │ ├── ExtensionFileFilter.java
│ │ │ ├── FileHandler.java
│ │ │ ├── FileHelper.java
│ │ │ ├── FileUtils.java
│ │ │ ├── GodClassUtils.java
│ │ │ ├── ListUtils.java
│ │ │ ├── MethodUtils.java
│ │ │ ├── Pair.java
│ │ │ ├── StringUtil.java
│ │ │ ├── TimeUtil.java
│ │ │ └── TreeNode.java
│ │ │ └── visitors
│ │ │ ├── ClassVisitor.java
│ │ │ ├── LayerVisitor.java
│ │ │ └── MethodVisitor.java
│ └── resources
│ │ ├── .DS_Store
│ │ └── MiningResult
│ │ ├── discardClassPath.txt
│ │ └── godClassPath.txt
└── test
│ └── java
│ ├── ClassInfoDAOTest.java
│ ├── ClassVisitorTest.java
│ ├── FileProcessTest.java
│ └── MethodInfoDAOTest.java
└── target
├── classes
└── com
│ └── se
│ ├── DAO
│ ├── BuildConnection.class
│ ├── ClassInfoDAO.class
│ ├── MethodInfoDAO.class
│ ├── MethodInvocationDAO.class
│ └── MethodInvocationInViewDAO.class
│ ├── config
│ └── DataConfig.class
│ ├── container
│ └── MethodCallContainer.class
│ ├── entity
│ ├── ClassInfo.class
│ ├── GraphNode.class
│ ├── Method.class
│ ├── MethodCall.class
│ ├── MethodInfo.class
│ ├── MethodInvocation.class
│ ├── MethodInvocationInView.class
│ └── Variable.class
│ ├── process
│ ├── CountInvocation.class
│ └── Process.class
│ ├── utils
│ ├── ExtensionFileFilter.class
│ ├── FileHandler.class
│ ├── FileHelper.class
│ ├── MethodUtils.class
│ └── StringUtil.class
│ └── visitors
│ ├── ClassVisitor.class
│ └── MethodVisitor.class
└── test-classes
└── FileProcessTest.class
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdgdsffdsfff/JavaMethodCallGraph/e27956aba732345c32f25c5a52f6770d48ac63dd/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Java template
3 | # Compiled class file
4 | *.class
5 |
6 | # Log file
7 | *.log
8 |
9 | # BlueJ files
10 | *.ctxt
11 |
12 | # Mobile Tools for Java (J2ME)
13 | .mtj.tmp/
14 |
15 | # Package Files #
16 | *.jar
17 | *.war
18 | *.nar
19 | *.ear
20 | *.zip
21 | *.tar.gz
22 | *.rar
23 |
24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
25 | hs_err_pid*
26 |
27 | /.idea/
28 | /target/
29 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JavaMethodCallGraph
2 |
3 | ## 程序的入口类在process包里面
4 | ## FileProcess是提取方法调用信息到MySQL数据库
5 | ## FilterMethodInvocation是过滤数据库中已经提取的方法调用信息,同时进行匹配,便于进行可视化。
6 |
7 | ## StructDetect类实现违反mvc设计架构的检测
8 | ### 检测模式:serviceImpl调controller、controller调dao、dao调service、dao调controller
9 | ### 运行说明:
10 | #### 1.在com/se/config/DataConfig.java中修改配置
11 | projectName 项目名
12 | projectPath 项目路径
13 | layer_dao dao层包名,eg:dao
14 | layer_serviceImpl service的实现类包名 eg:impl
15 | layer_controller controller包名 eg:controller
16 | layer_service service包名
17 | #### 注意:包名要与检测的项目包名一致
18 | #### 2.进入StructDetect类中运行主方法
19 | #### 3.结果将在com/se/config/DataConfig.java中的structDetectResult对应的路径(需要的话可修改),目前配置为src/main/resources/DetectResult/structureDetectResult.txt
20 | #### 注意:每次运行时都会清理上一次写入的结果
21 |
22 | ## SimilarityEntityDetect类实现实体类的重复检测
23 | ### 检测过程:
24 | #### 1.某一实体包下的所有类两两进行比对
25 | #### 2.先检测相同类型的字段,设置一个阈值,然后计算对比的两个类中相同类型的字段个数与各自类字段的总个数相比,如果两个类中的比值都大于设置的阈值,则初步判定两个类可能重复,然后用相同的方法判断类型、参数相等的方法,再与阈值比较
26 | ### 运行说明:目前阈值设为0.6(如需修改,请修改下面列出的threshold对应的值)
27 | #### 1.在com/se/config/DataConfig.java中修改配置
28 | projectName 项目名
29 | projectPath 项目路径
30 | layer_dao dao层包名,eg:dao
31 | layer_vo vo包名,eg:pojo、vo等
32 | threshold 比对的阈值
33 | #### 注意:目前只设置了一次检测两个包,layer_dao和layer_vo包
34 | #### 2.进入SimilarityEntityDetectResult类中运行主方法
35 | #### 3.结果将在com/se/config/DataConfig.java中的SimilarityEntityDetectResult对应的路径(需要的话可修改),目前配置为src/main/resources/DetectResult/similarityEntityDetectResult.txt
36 | #### 注意:每次运行时都会清理上一次写入的结果
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.example
8 | JavaMethodCallGraph
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 8
13 | 8
14 |
15 |
16 |
17 |
18 | com.github.javaparser
19 | javaparser-symbol-solver-core
20 | 3.13.10
21 |
22 |
23 | commons-io
24 | commons-io
25 | 2.4
26 |
27 |
28 | commons-lang
29 | commons-lang
30 | 2.6
31 |
32 |
33 |
34 | com.alibaba
35 | fastjson
36 | 1.2.32
37 |
38 |
39 | mysql
40 | mysql-connector-java
41 | 8.0.11
42 |
43 |
44 | junit
45 | junit
46 | 4.12
47 | test
48 |
49 |
50 | org.apache.commons
51 | commons-lang3
52 | 3.7
53 |
54 |
55 | org.eclipse.jdt
56 | org.eclipse.jdt.core
57 | 3.12.3
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdgdsffdsfff/JavaMethodCallGraph/e27956aba732345c32f25c5a52f6770d48ac63dd/src/.DS_Store
--------------------------------------------------------------------------------
/src/main/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdgdsffdsfff/JavaMethodCallGraph/e27956aba732345c32f25c5a52f6770d48ac63dd/src/main/.DS_Store
--------------------------------------------------------------------------------
/src/main/java/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdgdsffdsfff/JavaMethodCallGraph/e27956aba732345c32f25c5a52f6770d48ac63dd/src/main/java/.DS_Store
--------------------------------------------------------------------------------
/src/main/java/com/se/DAO/BuildConnection.java:
--------------------------------------------------------------------------------
1 | package com.se.DAO;
2 |
3 | import java.sql.Connection;
4 | import java.sql.DriverManager;
5 | import java.sql.SQLException;
6 | import com.se.config.DataConfig;
7 |
8 | public class BuildConnection {
9 |
10 | private String url = DataConfig.url;
11 | private String driver = DataConfig.driver;
12 | private String user = DataConfig.user;
13 | private String password = DataConfig.password;
14 |
15 | public Connection buildConnect(){
16 | Connection conn = null;
17 | // MySQL的JDBC URL编写方式:jdbc:mysql://主机名称:连接端口/数据库的名称
18 | try {
19 | Class.forName(driver);
20 | conn = DriverManager.getConnection(url, user, password);
21 | }catch (ClassNotFoundException | SQLException e) {
22 | e.printStackTrace();
23 | }
24 | return conn;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/se/DAO/ClassAssetDAO.java:
--------------------------------------------------------------------------------
1 | package com.se.DAO;
2 |
3 | import com.se.entity.ClassAsset;
4 |
5 | import java.sql.Connection;
6 | import java.sql.PreparedStatement;
7 | import java.sql.SQLException;
8 | import java.util.List;
9 |
10 | public class ClassAssetDAO {
11 |
12 | public static void saveClassAsset(List classAssets, Connection connection) throws SQLException {
13 | String sql = "insert into classasset (projectName,className,isInterface,fileName) values (?,?,?,?)";
14 | if(classAssets != null && !classAssets.isEmpty()){
15 | PreparedStatement pst = connection.prepareStatement(sql);
16 | for(ClassAsset classAsset : classAssets){
17 |
18 | pst.addBatch();
19 | }
20 | pst.executeBatch();
21 | pst.clearBatch();
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/se/DAO/MethodInvocationDAO.java:
--------------------------------------------------------------------------------
1 | package com.se.DAO;
2 |
3 | import com.se.entity.Method;
4 | import com.se.entity.MethodCall;
5 | import com.se.entity.MethodInvocation;
6 | import java.sql.Connection;
7 | import java.sql.PreparedStatement;
8 | import java.sql.ResultSet;
9 | import java.sql.SQLException;
10 | import java.util.*;
11 |
12 | public class MethodInvocationDAO {
13 |
14 |
15 | //todo:过滤掉JDK的方法调用,JDK的方法调用不入库
16 | public synchronized static void saveMethodInvocation(String projectName,Map methodCalls, Connection conn){
17 | System.out.println("保存到数据库的项目名为:" + projectName);
18 | String sql = null;
19 | PreparedStatement pst = null;
20 | MethodCall tempMethodCall = null;
21 | Method tempMethod = null;
22 | Date currentDate = new Date();
23 | java.sql.Date currentDateInSql = new java.sql.Date(currentDate.getTime());
24 | try{
25 | sql = "insert into methodinvocationinfo (projectName,callMethodName,calledMethodName,callClassName,calledClassName,callMethodParameters,callMethodReturnType, callClassFilePath, create_time, update_time) values(?,?,?,?,?,?,?,?,?,?)";
26 | if(methodCalls != null && !methodCalls.isEmpty()) {
27 | pst = conn.prepareStatement(sql);//用来执行SQL语句查询,对sql语句进行预编译处理
28 | Collection calls = methodCalls.values();
29 | for(MethodCall call : calls) {
30 | if(call.getCalled() != null && !call.getCalled().isEmpty()){
31 | for(Method calledMethod:call.getCalled()){
32 | String callClassName = call.getCaller().getPackageAndClassName();
33 | String calledClassName = calledMethod.getPackageAndClassName();
34 | if(calledClassName.length()>100||calledClassName.length()<3)continue;
35 | if(calledClassName.contains("{")||calledClassName.contains("}")||calledClassName.contains("(")
36 | ||calledClassName.contains(")"))continue;
37 | if(calledClassName.startsWith("java")||!calledClassName.contains(".")||!callClassName.substring(0,callClassName.indexOf(".")).equals(calledClassName.substring(0,calledClassName.indexOf(".")))){
38 | continue;
39 | }
40 | pst.setString(1,projectName);
41 | pst.setString(2,call.getCaller().getName());
42 | pst.setString(3,calledMethod.getName());
43 | pst.setString(4,call.getCaller().getPackageAndClassName());
44 | pst.setString(5,calledMethod.getPackageAndClassName());
45 | pst.setString(6,call.getCaller().getParamTypeList().toString());
46 | pst.setString(7,call.getCaller().getReturnTypeStr());
47 | pst.setString(8,call.getCaller().getFilePath());
48 | pst.setDate(9, currentDateInSql);
49 | pst.setDate(10, currentDateInSql);
50 | pst.addBatch();
51 |
52 | tempMethodCall = call;
53 | tempMethod = calledMethod;
54 | }
55 | pst.executeBatch();
56 | }
57 | }
58 | }
59 | } catch (SQLException e){
60 | System.out.println(sql);
61 | System.out.println(pst.toString());
62 | System.out.println(tempMethodCall.getCaller().getPackageAndClassName());
63 | System.out.println(tempMethod);
64 | e.printStackTrace();
65 | }
66 |
67 | }
68 |
69 | public static List getAllProjectNameFromDB(Connection conn) throws SQLException {
70 | List projectNameList = new ArrayList<>();
71 | String sql = "select distinct projectName from methodinvocationinfo where is_delete = 0";
72 | PreparedStatement preparedStatement = conn.prepareStatement(sql);
73 | ResultSet resultSet = preparedStatement.executeQuery();
74 | while(resultSet.next()){
75 | projectNameList.add(resultSet.getString("projectName"));
76 | }
77 | return projectNameList;
78 | }
79 |
80 | public static List getMethodInvocationByProjectName(String projectName,Connection conn) throws SQLException {
81 | List methodInvocationList = new ArrayList<>();
82 | // String sql = "select * from methodinvocationinfo where projectName = '" + projectName + "'";
83 |
84 | String sql = "select * from methodinvocationinfo where projectName = ? and is_delete = 0";
85 | PreparedStatement preparedStatement = conn.prepareStatement(sql);
86 | preparedStatement.setString(1, projectName);
87 | ResultSet resultSet = preparedStatement.executeQuery();
88 | while(resultSet.next()){
89 | MethodInvocation methodInvocation = new MethodInvocation();
90 | methodInvocation.setProjectName(projectName);
91 | methodInvocation.setCallClassName(resultSet.getString("callClassName"));
92 | methodInvocation.setCalledClassName(resultSet.getString("calledClassName"));
93 | methodInvocation.setCallMethodName(resultSet.getString("callMethodName"));
94 | methodInvocation.setCalledMethodName(resultSet.getString("calledMethodName"));
95 | methodInvocation.setCallMethodReturnType(resultSet.getString("callMethodReturnType"));
96 | methodInvocation.setCallMethodParameters(resultSet.getString("callMethodParameters"));
97 | methodInvocationList.add(methodInvocation);
98 | }
99 | return methodInvocationList;
100 | }
101 |
102 | public static List getMethodInvocationByProjectNameAndDate(String projectName,Connection conn) throws SQLException {
103 | List methodInvocationList = new ArrayList<>();
104 | Date currentDate = new Date();
105 | java.sql.Date currentDateInSql = new java.sql.Date(currentDate.getTime());
106 | String sql = "select * from methodinvocationinfo where projectName = ? and create_time = ? and is_delete = 0 ";
107 | PreparedStatement preparedStatement = conn.prepareStatement(sql);
108 | preparedStatement.setString(1, projectName);
109 | preparedStatement.setDate(2, currentDateInSql);
110 | ResultSet resultSet = preparedStatement.executeQuery();
111 | while(resultSet.next()){
112 | MethodInvocation methodInvocation = new MethodInvocation();
113 | methodInvocation.setProjectName(projectName);
114 | methodInvocation.setCallClassName(resultSet.getString("callClassName"));
115 | methodInvocation.setCalledClassName(resultSet.getString("calledClassName"));
116 | methodInvocation.setCallMethodName(resultSet.getString("callMethodName"));
117 | methodInvocation.setCalledMethodName(resultSet.getString("calledMethodName"));
118 | methodInvocation.setCallMethodReturnType(resultSet.getString("callMethodReturnType"));
119 | methodInvocation.setCallMethodParameters(resultSet.getString("callMethodParameters"));
120 | methodInvocationList.add(methodInvocation);
121 | }
122 | return methodInvocationList;
123 | }
124 |
125 |
126 | public static Set getDistinctClassName(Connection connection) throws SQLException{
127 | Set classNameSet = new HashSet<>();
128 | String sql = "select callClassName,calledClassName from methodinvocationinfo where is_delete = 0";
129 | PreparedStatement preparedStatement = connection.prepareStatement(sql);
130 | ResultSet resultSet = preparedStatement.executeQuery();
131 | while(resultSet.next()){
132 | classNameSet.add(resultSet.getString("callClassName"));
133 | classNameSet.add(resultSet.getString("calledClassName"));
134 | }
135 | return classNameSet;
136 | }
137 |
138 | public static List getMethodInvocationIDsByClassName(String projectName, String callClassName, Connection conn) throws SQLException {
139 | List methodInvocationIDList = new ArrayList<>();
140 | // String sql = "select * from methodinvocationinfo where projectName = '" + projectName + "'";
141 | String sql = "select * from methodinvocationinfo where projectName = ? and callClassName = ? and is_delete = 0";
142 | PreparedStatement preparedStatement = conn.prepareStatement(sql);
143 | preparedStatement.setString(1, projectName);
144 | preparedStatement.setString(2, callClassName);
145 | ResultSet resultSet = preparedStatement.executeQuery();
146 | while(resultSet.next()){
147 | methodInvocationIDList.add(resultSet.getString("ID"));
148 | }
149 | return methodInvocationIDList;
150 | }
151 |
152 |
153 | public static void deleteMethodInvocationInfoRecords(List deleteMethodInvocationIDs, Connection conn) throws SQLException{
154 | Date currentDate = new Date();
155 | java.sql.Date currentDateInSql = new java.sql.Date(currentDate.getTime());
156 | String mInvocInfoSQL = "update methodinvocationinfo set is_delete = 1, update_time = ? where ID = ?";
157 |
158 | PreparedStatement pst = conn.prepareStatement(mInvocInfoSQL);
159 |
160 | if(deleteMethodInvocationIDs != null){
161 | for(String methodInvocationID : deleteMethodInvocationIDs){
162 | pst.setDate(1, currentDateInSql);
163 | pst.setString(2, methodInvocationID);
164 | pst.addBatch();
165 | }
166 | pst.executeBatch();
167 | pst.clearBatch();
168 | // conn.commit();
169 | }
170 | }
171 |
172 | public static void updateCalledClassFilePath(String projectName, Connection conn) throws SQLException{
173 | String sql = "update methodinvocationinfo m, classinfo c set m.calledClassFilePath = c.filePath where m.calledClassName = c.className and m.projectName = ?";
174 | PreparedStatement pst = conn.prepareStatement(sql);
175 | pst.setString(1, projectName);
176 | pst.executeUpdate();
177 |
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/src/main/java/com/se/DAO/MethodInvocationInViewDAO.java:
--------------------------------------------------------------------------------
1 | package com.se.DAO;
2 |
3 | import com.se.entity.MethodInvocationInView;
4 |
5 | import java.sql.Connection;
6 | import java.sql.PreparedStatement;
7 | import java.sql.ResultSet;
8 | import java.sql.SQLException;
9 | import java.util.ArrayList;
10 | import java.util.Date;
11 | import java.util.List;
12 |
13 | public class MethodInvocationInViewDAO {
14 |
15 | public static void insertMethodInvocationInView(List methodInvocationInViewList, Connection conn) throws SQLException {
16 | String sql = "insert into methodinvocationinview (projectName,callMethodName,calledMethodName,callClassName,calledClassName,callMethodParameters,callMethodReturnType,callMethodID,calledMethodID,callClassID,calledClassID, create_time, update_time) values(?,?,?,?,?,?,?,?,?,?,?,?,?)";
17 | Date currentDate = new Date();
18 | java.sql.Date currentDateInSql = new java.sql.Date(currentDate.getTime());
19 | if(methodInvocationInViewList != null && !methodInvocationInViewList.isEmpty()) {
20 | PreparedStatement pst = conn.prepareStatement(sql);//用来执行SQL语句查询,对sql语句进行预编译处理
21 | for(MethodInvocationInView methodInvocationInView : methodInvocationInViewList) {
22 | if(methodInvocationInView.getCallClassID() == null||methodInvocationInView.getCallClassID().equals("null")||methodInvocationInView.getCalledClassID() == null||methodInvocationInView.getCalledClassID().equals("null"))continue;
23 | pst.setString(1,methodInvocationInView.getProjectName());
24 | pst.setString(2,methodInvocationInView.getCallMethodName());
25 | pst.setString(3,methodInvocationInView.getCalledMethodName());
26 | pst.setString(4,methodInvocationInView.getCallClassName());
27 | pst.setString(5,methodInvocationInView.getCalledClassName());
28 | pst.setString(6,methodInvocationInView.getCallMethodParameters());
29 | pst.setString(7,methodInvocationInView.getCallMethodReturnType());
30 | pst.setString(8,methodInvocationInView.getCallMethodID());
31 | pst.setString(9,methodInvocationInView.getCalledMethodID());
32 | pst.setString(10,methodInvocationInView.getCallClassID());
33 | pst.setString(11,methodInvocationInView.getCalledClassID());
34 | pst.setDate(12, currentDateInSql);
35 | pst.setDate(13, currentDateInSql);
36 | pst.addBatch();
37 | }
38 | pst.executeBatch();
39 | }
40 | }
41 |
42 | public static int selectCalledCountsByClassName(String className, Connection conn) throws SQLException {
43 | String sql = "select ID from methodinvocationinview where calledClassName = '" + className + "' and callClassName != calledClassName and is_delete = 0";
44 | PreparedStatement pst = conn.prepareStatement(sql);
45 | ResultSet resultSet = pst.executeQuery();
46 | int count = 0;
47 | while(resultSet.next()){
48 | count++;
49 | }
50 | return count;
51 | }
52 |
53 | public static int selectCallCountsByClassName(String className, Connection conn) throws SQLException {
54 | String sql = "select ID from methodinvocationinview where callClassName = '" + className + "' and callClassName != calledClassName and is_delete = 0";
55 | PreparedStatement pst = conn.prepareStatement(sql);
56 | ResultSet resultSet = pst.executeQuery();
57 | int count = 0;
58 | while(resultSet.next()){
59 | count++;
60 | }
61 | return count;
62 | }
63 |
64 | public static List selectAllProjectName(Connection conn) throws SQLException {
65 | String sql = "select distinct projectName from methodinvocationinview and is_delete = 0";
66 | PreparedStatement pst = conn.prepareStatement(sql);
67 | ResultSet resultSet = pst.executeQuery();
68 | List projectNameList = new ArrayList<>();
69 | while(resultSet.next()){
70 | projectNameList.add(resultSet.getString("projectName"));
71 | }
72 | return projectNameList;
73 | }
74 |
75 | public static List getMethodInvocationInViewByProjectName(String projectName, Connection conn) throws SQLException {
76 | String sql = "select * from methodinvocationinview where projectName = ? and is_delete = 0";
77 | PreparedStatement pst = conn.prepareStatement(sql);
78 | pst.setString(1, projectName);
79 | ResultSet resultSet = pst.executeQuery();
80 | List methodInvocationInViewList = new ArrayList<>();
81 | while(resultSet.next()){
82 | MethodInvocationInView methodInvocationInView = new MethodInvocationInView();
83 | methodInvocationInView.setID(resultSet.getInt("ID"));
84 | methodInvocationInView.setCallClassName(resultSet.getString("callClassName"));
85 | methodInvocationInView.setCalledClassName(resultSet.getString("calledClassName"));
86 | methodInvocationInView.setCallMethodName(resultSet.getString("callMethodName"));
87 | methodInvocationInView.setCalledMethodName(resultSet.getString("calledMethodName"));
88 | methodInvocationInView.setProjectName(projectName);
89 | methodInvocationInViewList.add(methodInvocationInView);
90 | }
91 | return methodInvocationInViewList;
92 | }
93 |
94 |
95 | public static List getInfoByProjectName(String projectName, Connection conn) throws SQLException {
96 | String sql = "select callClassName,calledClassName from methodinvocationinview where projectName = '" + projectName + "'and is_delete = 0";
97 | PreparedStatement pst = conn.prepareStatement(sql);
98 | ResultSet resultSet = pst.executeQuery();
99 | List methodInvocationInViewList = new ArrayList<>();
100 | while(resultSet.next()){
101 | MethodInvocationInView methodInvocationInView = new MethodInvocationInView();
102 | methodInvocationInView.setCallClassName(resultSet.getString("callClassName"));
103 | methodInvocationInView.setCalledClassName(resultSet.getString("calledClassName"));
104 | methodInvocationInView.setProjectName(projectName);
105 | methodInvocationInViewList.add(methodInvocationInView);
106 | }
107 | return methodInvocationInViewList;
108 | }
109 |
110 | public static List getInvokeInfoByProjectName(String projectName, Connection conn) throws SQLException {
111 | String sql = "select callClassName,calledClassName,callMethodName,calledMethodName from methodinvocationinview where projectName = '" + projectName + "'and is_delete = 0";
112 | PreparedStatement pst = conn.prepareStatement(sql);
113 | ResultSet resultSet = pst.executeQuery();
114 | List methodInvocationInViewList = new ArrayList<>();
115 | while(resultSet.next()){
116 | MethodInvocationInView methodInvocationInView = new MethodInvocationInView();
117 | methodInvocationInView.setCallClassName(resultSet.getString("callClassName"));
118 | methodInvocationInView.setCalledClassName(resultSet.getString("calledClassName"));
119 | methodInvocationInView.setCallMethodName(resultSet.getString("callMethodName"));
120 | methodInvocationInView.setCalledMethodName(resultSet.getString("calledMethodName"));
121 | methodInvocationInView.setProjectName(projectName);
122 | methodInvocationInViewList.add(methodInvocationInView);
123 | }
124 | return methodInvocationInViewList;
125 | }
126 |
127 |
128 | public static void updateIsRecursive(String projectName, Connection conn) throws SQLException {
129 | String sql = "UPDATE methodinvocationinview SET isRecursive = 1 WHERE callMethodID = calledMethodID AND projectName = ? AND is_delete = 0";
130 | PreparedStatement pst = conn.prepareStatement(sql);
131 | pst.setString(1,projectName);
132 | pst.executeUpdate();
133 | }
134 |
135 | public static List getMethodInvocationInViewByCallClassID(String projectName, String callClassID, Connection conn) throws SQLException {
136 | String sql = "select * from methodinvocationinview where projectName = ? and callClassID = ? and is_delete = 0";
137 | PreparedStatement pst = conn.prepareStatement(sql);
138 | pst.setString(1, projectName);
139 | pst.setString(2, callClassID);
140 | ResultSet resultSet = pst.executeQuery();
141 | List methodInvocationInViewIDList = new ArrayList<>();
142 | while(resultSet.next()){
143 | methodInvocationInViewIDList.add(resultSet.getInt("ID"));
144 | }
145 | return methodInvocationInViewIDList;
146 | }
147 |
148 |
149 | public static void deleteMethodInvocationInViewRecords(List deleteMethodInvocationInViewIDs, Connection conn) throws SQLException{
150 | Date currentDate = new Date();
151 | java.sql.Date currentDateInSql = new java.sql.Date(currentDate.getTime());
152 | String mInvocInViewSQL = "update methodinvocationinview set is_delete = 1, update_time = ? where ID = ?";
153 |
154 | PreparedStatement pst = conn.prepareStatement(mInvocInViewSQL);
155 |
156 | if(deleteMethodInvocationInViewIDs != null){
157 | for(Integer methodInvocationInViewID : deleteMethodInvocationInViewIDs){
158 | pst.setDate(1, currentDateInSql);
159 | pst.setInt(2, methodInvocationInViewID);
160 | pst.addBatch();
161 | }
162 | pst.executeBatch();
163 | pst.clearBatch();
164 | }
165 | }
166 |
167 | public static void updateCalledClassID(String projectName, Connection conn) throws SQLException {
168 | String sql = "update methodinvocationinview m inner join classinfo c on m.calledClassName = c.className set m.calledClassID = c.ID, m.update_time = ? where c.update_time = ? and c.projectName = ? and c.is_delete = 0 and m.is_delete = 0";
169 | Date currentDate = new Date();
170 | java.sql.Date currentDateInSql = new java.sql.Date(currentDate.getTime());
171 | PreparedStatement pst = conn.prepareStatement(sql);
172 | pst.setDate(1, currentDateInSql);
173 | pst.setDate(2, currentDateInSql);
174 | pst.setString(3, projectName);
175 | pst.executeUpdate();
176 | }
177 |
178 | public static void updateCalledMethodID(String projectName, Connection conn) throws SQLException {
179 | String sql = "update methodinvocationinview m1 inner join methodinfo m2 on m1.calledMethodName = m2.methodName and m1.calledClassName = m2.className set m1.calledMethodID = m2.ID, m1.update_time = ? where m2.update_time = ? and m2.projectName = ? and m1.is_delete = 0 and m2.is_delete = 0";
180 | Date currentDate = new Date();
181 | java.sql.Date currentDateInSql = new java.sql.Date(currentDate.getTime());
182 | PreparedStatement pst = conn.prepareStatement(sql);
183 | pst.setDate(1, currentDateInSql);
184 | pst.setDate(2, currentDateInSql);
185 | pst.setString(3, projectName);
186 | pst.executeUpdate();
187 | }
188 |
189 |
190 | }
191 |
--------------------------------------------------------------------------------
/src/main/java/com/se/config/DataConfig.java:
--------------------------------------------------------------------------------
1 | package com.se.config;
2 |
3 |
4 | //所有项目的配置信息
5 | public class DataConfig {
6 |
7 | //连接数据库的url
8 | public static final String url = "jdbc:mysql://127.0.0.1:3306/methodinvocation?serverTimezone=UTC&useSSL=false&rewriteBatchedStatements=true";
9 | //数据库驱动
10 | public static final String driver = "com.mysql.cj.jdbc.Driver";
11 | //连接数据库的用户名
12 | public static final String user = "root";
13 | //连接数据库的密码
14 | public static final String password = "root";
15 | //所有待分析项目的父目录
16 | public static final String sourceProjectParentPath = "D:\\java-source";
17 |
18 | public static final String godClassOutputFilePath = "JavaMethodCallGraph\\JavaMethodCallGraph\\src\\main\\resources\\MiningResult\\godClassPath.txt";
19 | //单个待分析项目的目录
20 | public static final String sourceProjectPath = "D:\\java-source\\yuliskov";
21 | //API文档的路径
22 | public static final String API_DOC_PATH = "JavaMethodCallGraph/src/main/resources/docs/api/";
23 | //java.lang文档的路径
24 | public static final String JAVA_LANG_DOC_PATH = "JavaMethodCallGraph/src/main/resources/docs/api/java/lang/";
25 | //是否对单个项目进行分析,为true则分析单个项目,为false则对父目录中所有的项目进行分析
26 | public static final boolean analyseSingleProject = false;
27 | //是否需要对于方法调用链的调用深度和每个类的被调用次数进行统计
28 | public static final boolean analyseInvocationCounts = false;
29 | //方法粒度的measureIndex文件路径
30 | public static final String measureIndexFilePath = "JavaMethodCallGraph\\src\\main\\resources\\clone_result\\MeasureIndex.csv";
31 | //克隆检测的克隆组检测结果文件路径
32 | public static final String cloneGroupFilePath = "JavaMethodCallGraph\\src\\main\\resources\\clone_result\\type123_method_group_result.csv";
33 | //万能类的路径
34 | public static String universalClassPath = "JavaMethodCallGraph/src/main/resources/MiningResult/universalClassPath.txt";
35 | //遗弃类的路径
36 | public static String discardClassPath = "JavaMethodCallGraph/src/main/resources/MiningResult/discardClassPath.txt";
37 | //是否进行增量扫描
38 | public static boolean isAdditionalProcess = false;
39 | //增量文件所在的路径
40 | public static String modifiedFilePath = "";
41 | //是否进行层次处理分析
42 | public static boolean isLayerProcess = true;
43 |
44 | public static String projectName = "ssm2";
45 |
46 | public static String projectPath = "/Users/zhangyue/Downloads/ssm2";
47 |
48 | public static String layer_dao = "dao";
49 |
50 | public static String layer_serviceImpl = "impl";
51 |
52 | public static String layer_controller = "controller";
53 |
54 | public static String layer_service = "service";
55 |
56 | public static String layer_vo = "pojo";
57 |
58 | public static String structDetectResult = "src/main/resources/DetectResult/structureDetectResult.txt";
59 |
60 | public static String SimilarityEntityDetectResult = "src/main/resources/DetectResult/similarityEntityDetectResult.txt";
61 |
62 | public static double threshold = 0.6;
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/se/container/MethodCallContainer.java:
--------------------------------------------------------------------------------
1 | package com.se.container;
2 |
3 | import com.se.entity.Method;
4 | import com.se.entity.MethodCall;
5 |
6 | import java.util.HashMap;
7 | import java.util.Map;
8 | import java.util.concurrent.ConcurrentHashMap;
9 |
10 | public class MethodCallContainer {
11 | private ConcurrentHashMap> projectName2MethodCallMap;
12 | private static MethodCallContainer container;
13 |
14 | private MethodCallContainer() {
15 | projectName2MethodCallMap = new ConcurrentHashMap<>();
16 | }
17 |
18 | public synchronized static MethodCallContainer getContainer() {
19 | if(container == null) {
20 | container = new MethodCallContainer();
21 | }
22 | return container;
23 | }
24 |
25 | public synchronized Map getMethodCallsByProjectName(String projectName)
26 | {
27 | return projectName2MethodCallMap.get(projectName);
28 | }
29 |
30 | public synchronized void addMethodCall(String projectName, Method caller, Method called) {
31 | if(projectName2MethodCallMap.containsKey(projectName)){
32 | Map methodCallMap = projectName2MethodCallMap.get(projectName);
33 | MethodCall methodCall = methodCallMap.get(caller.getQualifiedName());
34 | if(methodCall != null) {
35 | if(!methodCall.containsCalled(called)) {
36 | methodCall.addCalled(called);
37 | methodCallMap.put(caller.getQualifiedName(), methodCall);
38 | }
39 | } else {
40 | methodCall = new MethodCall();
41 | methodCall.setCaller(caller);
42 | methodCall.addCalled(called);
43 | methodCallMap.put(caller.getQualifiedName(), methodCall);
44 | }
45 | projectName2MethodCallMap.put(projectName,methodCallMap);
46 | }else {
47 | Map methodCallMap = new HashMap<>();
48 | MethodCall methodCall = new MethodCall();
49 | methodCall.setCaller(caller);
50 | methodCall.addCalled(called);
51 | methodCallMap.put(caller.getQualifiedName(), methodCall);
52 | projectName2MethodCallMap.put(projectName,methodCallMap);
53 | }
54 | }
55 |
56 | public synchronized MethodCall getMethodCall(String projectName, String caller) {
57 | if(projectName2MethodCallMap.containsKey(projectName)){
58 | return projectName2MethodCallMap.get(projectName).get(caller);
59 | }else {
60 | return null;
61 | }
62 | }
63 |
64 | public synchronized void clearMethodCallByProjectName(String projectName){
65 | if(projectName2MethodCallMap.containsKey(projectName)) {
66 | projectName2MethodCallMap.get(projectName).clear();
67 | projectName2MethodCallMap.remove(projectName);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/se/container/MethodInfoContainer.java:
--------------------------------------------------------------------------------
1 | package com.se.container;
2 |
3 | import com.se.entity.MethodInfo;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.concurrent.ConcurrentHashMap;
7 |
8 | public class MethodInfoContainer {
9 |
10 |
11 | private ConcurrentHashMap> projectName2MethodInfoMap;
12 | private static MethodInfoContainer container;
13 |
14 | private MethodInfoContainer(){
15 | projectName2MethodInfoMap = new ConcurrentHashMap<>();
16 | }
17 |
18 | public synchronized static MethodInfoContainer getContainer(){
19 | if(container == null){
20 | container = new MethodInfoContainer();
21 | }
22 | return container;
23 | }
24 |
25 | public synchronized void addMethodInfo(String projectName, MethodInfo methodInfo){
26 | if(projectName2MethodInfoMap.containsKey(projectName)){
27 | projectName2MethodInfoMap.get(projectName).add(methodInfo);
28 | } else {
29 | List methodInfoList = new ArrayList<>();
30 | methodInfoList.add(methodInfo);
31 | projectName2MethodInfoMap.put(projectName, methodInfoList);
32 | }
33 | }
34 |
35 | public synchronized List getMethodInfoListByProjectName(String projectName){
36 | return projectName2MethodInfoMap.get(projectName);
37 | }
38 |
39 | public synchronized void clearMethodInfoListByProjectName(String projectName){
40 | if(projectName2MethodInfoMap.get(projectName)!=null){
41 | projectName2MethodInfoMap.get(projectName).clear();
42 | projectName2MethodInfoMap.remove(projectName);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/ClassAsset.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | public class ClassAsset {
4 |
5 | private int id;
6 | private String projectName;
7 | private String className;
8 | private String filePath;
9 | private String content;
10 |
11 | public int getId() {
12 | return id;
13 | }
14 |
15 | public void setId(int id) {
16 | this.id = id;
17 | }
18 |
19 | public String getProjectName() {
20 | return projectName;
21 | }
22 |
23 | public void setProjectName(String projectName) {
24 | this.projectName = projectName;
25 | }
26 |
27 | public String getClassName() {
28 | return className;
29 | }
30 |
31 | public void setClassName(String className) {
32 | this.className = className;
33 | }
34 |
35 | public String getFilePath() {
36 | return filePath;
37 | }
38 |
39 | public void setFilePath(String filePath) {
40 | this.filePath = filePath;
41 | }
42 |
43 | public String getContent() {
44 | return content;
45 | }
46 |
47 | public void setContent(String content) {
48 | this.content = content;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/ClassInfo.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | public class ClassInfo {
4 | private int ID;
5 | private String projectName;
6 | private String className;
7 | private Boolean isInterface;
8 | private String filePath;
9 | private int cloneId;
10 | private int invokedCounts;
11 | private int invokeCounts;
12 | private boolean asset;
13 | private String layer;
14 | private String superClass;
15 | private String interfaces;
16 |
17 | public String getProjectName() {
18 | return projectName;
19 | }
20 |
21 | public void setProjectName(String projectName) {
22 | this.projectName = projectName;
23 | }
24 |
25 | public String getClassName() {
26 | return className;
27 | }
28 |
29 | public void setClassName(String className) {
30 | this.className = className;
31 | }
32 |
33 | public Boolean getInterface() {
34 | return isInterface;
35 | }
36 |
37 | public void setInterface(Boolean anInterface) {
38 | isInterface = anInterface;
39 | }
40 |
41 | public String getFilePath() {
42 | return filePath;
43 | }
44 |
45 | public void setFilePath(String filePath) {
46 | this.filePath = filePath;
47 | }
48 |
49 | public int getCloneId() {
50 | return cloneId;
51 | }
52 |
53 | public void setCloneId(int cloneId) {
54 | this.cloneId = cloneId;
55 | }
56 |
57 | public int getID() {
58 | return ID;
59 | }
60 |
61 | public void setID(int ID) {
62 | this.ID = ID;
63 | }
64 |
65 | public int getInvokedCounts() {
66 | return invokedCounts;
67 | }
68 |
69 | public void setInvokedCounts(int invokedCounts) {
70 | this.invokedCounts = invokedCounts;
71 | }
72 |
73 | public int getInvokeCounts() {
74 | return invokeCounts;
75 | }
76 |
77 | public void setInvokeCounts(int invokeCounts) {
78 | this.invokeCounts = invokeCounts;
79 | }
80 |
81 | public boolean isAsset() {
82 | return asset;
83 | }
84 |
85 | public void setAsset(boolean asset) {
86 | this.asset = asset;
87 | }
88 |
89 | public String getLayer() {
90 | return layer;
91 | }
92 |
93 | public void setLayer(String layer) {
94 | this.layer = layer;
95 | }
96 |
97 |
98 | public String getSuperClass() {
99 | return superClass;
100 | }
101 |
102 | public void setSuperClass(String superClass) {
103 | this.superClass = superClass;
104 | }
105 |
106 | public String getInterfaces() {
107 | return interfaces;
108 | }
109 |
110 | public void setInterfaces(String interfaces) {
111 | this.interfaces = interfaces;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/GraphNode.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 |
4 | import java.util.Objects;
5 |
6 | //view object
7 | public class GraphNode {
8 |
9 | private String id;
10 |
11 | private String name;
12 |
13 | private int category;
14 |
15 | private int symbolSize;
16 |
17 | private int value;
18 |
19 | private String qualifiedClassName;
20 |
21 | private int calledCounts;
22 |
23 | private int calledDept;
24 |
25 | public GraphNode() {
26 | }
27 |
28 | public GraphNode(String id, String name, int category, int symbolSize, int value) {
29 | this.id = id;
30 | this.name = name;
31 | this.category = category;
32 | this.symbolSize = symbolSize;
33 | this.value = value;
34 | }
35 |
36 | public GraphNode(String id, String name, int category, int symbolSize) {
37 | this.id = id;
38 | this.name = name;
39 | this.category = category;
40 | this.symbolSize = symbolSize;
41 | }
42 |
43 | public GraphNode(String id, String name, int category) {
44 | this.id = id;
45 | this.name = name;
46 | this.category = category;
47 | this.calledDept = 0;
48 | }
49 |
50 | public GraphNode(String id, String name, String qualifiedClassName, int category, int symbolSize) {
51 | this.id = id;
52 | this.name = name;
53 | this.qualifiedClassName = qualifiedClassName;
54 | this.category = category;
55 | this.symbolSize = symbolSize;
56 | }
57 |
58 | public String getId() {
59 | return id;
60 | }
61 |
62 | public void setId(String id) {
63 | this.id = id;
64 | }
65 |
66 | public String getName() {
67 | return name;
68 | }
69 |
70 | public void setName(String name) {
71 | this.name = name;
72 | }
73 |
74 | public int getCategory() {
75 | return category;
76 | }
77 |
78 | public void setCategory(int category) {
79 | this.category = category;
80 | }
81 |
82 | public int getSymbolSize() {
83 | return symbolSize;
84 | }
85 |
86 | public void setSymbolSize(int symbolSize) {
87 | this.symbolSize = symbolSize;
88 | }
89 |
90 | public int getValue() {
91 | return value;
92 | }
93 |
94 | public void setValue(int value) {
95 | this.value = value;
96 | }
97 |
98 | @Override
99 | public boolean equals(Object o) {
100 | if (this == o) return true;
101 | if (!(o instanceof GraphNode)) return false;
102 | GraphNode graphNode = (GraphNode) o;
103 | return Objects.equals(id, graphNode.id);
104 | }
105 |
106 | @Override
107 | public int hashCode() {
108 | return Objects.hash(id);
109 | }
110 |
111 | public String getQualifiedClassName() {
112 | return qualifiedClassName;
113 | }
114 |
115 | public void setQualifiedClassName(String qualifiedClassName) {
116 | this.qualifiedClassName = qualifiedClassName;
117 | }
118 |
119 | public int getCalledCounts() {
120 | return calledCounts;
121 | }
122 |
123 | public void setCalledCounts(int calledCounts) {
124 | this.calledCounts = calledCounts;
125 | }
126 |
127 | public int getCalledDept() {
128 | return calledDept;
129 | }
130 |
131 | public void setCalledDept(int calledDept) {
132 | this.calledDept = calledDept;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/MeasureIndex.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | public class MeasureIndex {
4 |
5 | public MeasureIndex(int id, String filePath, int beginLine, int endLine,String sourcePath) {
6 | this.id = id;
7 | this.filePath = filePath;
8 | this.beginLine = beginLine;
9 | this.endLine = endLine;
10 | String tempStr = filePath.replace(sourcePath,"");
11 | tempStr = tempStr.substring(1);
12 | this.projectName = tempStr.substring(0,tempStr.indexOf("\\"));
13 | }
14 |
15 | private int id;
16 | private String filePath;
17 | private int beginLine;
18 | private int endLine;
19 | private String projectName;
20 |
21 | public int getId() {
22 | return id;
23 | }
24 |
25 | public void setId(int id) {
26 | this.id = id;
27 | }
28 |
29 | public String getFilePath() {
30 | return filePath;
31 | }
32 |
33 | public void setFilePath(String filePath) {
34 | this.filePath = filePath;
35 | }
36 |
37 | public int getBeginLine() {
38 | return beginLine;
39 | }
40 |
41 | public void setBeginLine(int beginLine) {
42 | this.beginLine = beginLine;
43 | }
44 |
45 | public int getEndLine() {
46 | return endLine;
47 | }
48 |
49 | public void setEndLine(int endLine) {
50 | this.endLine = endLine;
51 | }
52 |
53 |
54 | public String getProjectName() {
55 | return projectName;
56 | }
57 |
58 | public void setProjectName(String projectName) {
59 | this.projectName = projectName;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/Method.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | //import japa.parser.ast.type.Type;
4 | import com.github.javaparser.ast.type.Type;
5 |
6 | import java.util.List;
7 |
8 | public class Method {
9 |
10 | private String name;
11 |
12 | private String clazz;
13 |
14 | private String pkg;
15 |
16 | private Type returnType;
17 |
18 | private String returnTypeStr;
19 |
20 | private List paramTypeList;
21 |
22 | private int beginLine;
23 |
24 | private int endLine;
25 |
26 | private String methodContent;
27 |
28 | private String filePath;
29 |
30 | public String getName() {
31 | return name;
32 | }
33 |
34 | public void setName(String name) {
35 | this.name = name;
36 | }
37 |
38 | public String getClazz() {
39 | return clazz;
40 | }
41 |
42 | public void setClazz(String clazz) {
43 | this.clazz = clazz;
44 | }
45 |
46 | public String getPkg() {
47 | return pkg;
48 | }
49 |
50 | public void setPkg(String pkg) {
51 | this.pkg = pkg;
52 | }
53 |
54 | private Type getReturnType() {
55 | return returnType;
56 | }
57 |
58 | public void setReturnType(Type returnType) {
59 | this.returnType = returnType;
60 | }
61 |
62 | public String getReturnTypeStr() {
63 | if(this.getReturnType().getComment().isPresent()){
64 | this.returnTypeStr = this.getReturnType().toString().replace(this.getReturnType().getComment().get().toString(), "");
65 | } else {
66 | this.returnTypeStr = this.getReturnType().toString();
67 | }
68 | return returnTypeStr;
69 | }
70 |
71 | public List getParamTypeList() {
72 | return paramTypeList;
73 | }
74 |
75 | public void setParamTypeList(List paramTypeList) {
76 | this.paramTypeList = paramTypeList;
77 | }
78 |
79 | public String getQualifiedName() {
80 | StringBuffer buff = new StringBuffer();
81 | //if in default package.
82 | if(pkg != null) {
83 | buff.append(pkg).append(".");
84 | }
85 | buff.append(clazz).append(".").append(name);
86 | return buff.toString();
87 | }
88 |
89 |
90 | @Override
91 | public int hashCode() {
92 | final int prime = 31;
93 | int result = 1;
94 | String qualifiedName = this.getQualifiedName();
95 | result = prime * result + ( ( qualifiedName == null ) ? 0 : qualifiedName.hashCode() );
96 | return result;
97 | }
98 |
99 | @Override
100 | public boolean equals(Object obj) {
101 | if ( this == obj )
102 | return true;
103 | if ( obj == null )
104 | return false;
105 | if ( getClass() != obj.getClass() )
106 | return false;
107 | Method other = (Method)obj;
108 | String qualifiedName = this.getQualifiedName();
109 | String otherQualifiedName = other.getQualifiedName();
110 |
111 | if ( qualifiedName == null ) {
112 | if ( otherQualifiedName != null )
113 | return false;
114 | }
115 | else if ( !qualifiedName.equals(otherQualifiedName) )
116 | return false;
117 | return true;
118 | }
119 |
120 | @Override
121 | public String toString(){
122 | StringBuffer callerMethodParameter = new StringBuffer();
123 | callerMethodParameter.append("(");
124 | for(String paramType : this.getParamTypeList()){
125 | callerMethodParameter.append(paramType).append(",");
126 | }
127 | callerMethodParameter.append(")");
128 |
129 | return this.getQualifiedName().concat(callerMethodParameter.toString());
130 | }
131 |
132 | public String getPackageAndClassName() {
133 | StringBuffer buff = new StringBuffer();
134 | //if in default package.
135 | if(pkg != null) {
136 | buff.append(pkg).append(".");
137 | }
138 | buff.append(clazz);
139 | return buff.toString();
140 | }
141 |
142 |
143 | public int getBeginLine() {
144 | return beginLine;
145 | }
146 |
147 | public void setBeginLine(int beginLine) {
148 | this.beginLine = beginLine;
149 | }
150 |
151 | public int getEndLine() {
152 | return endLine;
153 | }
154 |
155 | public void setEndLine(int endLine) {
156 | this.endLine = endLine;
157 | }
158 |
159 | public String getMethodContent() {
160 | return methodContent;
161 | }
162 |
163 | public void setMethodContent(String methodContent) {
164 | this.methodContent = methodContent;
165 | }
166 |
167 | public String getFilePath() {
168 | return filePath;
169 | }
170 |
171 | public void setFilePath(String filePath) {
172 | this.filePath = filePath;
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/MethodAsset.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | public class MethodAsset {
4 |
5 | private int id;
6 | private String projectName;
7 | private String className;
8 | private String filePath;
9 | private String content;
10 | private String comments;
11 | private String methodParameters;
12 |
13 |
14 | public int getId() {
15 | return id;
16 | }
17 |
18 | public void setId(int id) {
19 | this.id = id;
20 | }
21 |
22 | public String getProjectName() {
23 | return projectName;
24 | }
25 |
26 | public void setProjectName(String projectName) {
27 | this.projectName = projectName;
28 | }
29 |
30 | public String getClassName() {
31 | return className;
32 | }
33 |
34 | public void setClassName(String className) {
35 | this.className = className;
36 | }
37 |
38 | public String getFilePath() {
39 | return filePath;
40 | }
41 |
42 | public void setFilePath(String filePath) {
43 | this.filePath = filePath;
44 | }
45 |
46 | public String getContent() {
47 | return content;
48 | }
49 |
50 | public void setContent(String content) {
51 | this.content = content;
52 | }
53 |
54 | public String getComments() {
55 | return comments;
56 | }
57 |
58 | public void setComments(String comments) {
59 | this.comments = comments;
60 | }
61 |
62 | public String getMethodParameters() {
63 | return methodParameters;
64 | }
65 |
66 | public void setMethodParameters(String methodParameters) {
67 | this.methodParameters = methodParameters;
68 | }
69 |
70 |
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/MethodCall.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONArray;
5 | import com.alibaba.fastjson.JSONObject;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Iterator;
9 | import java.util.List;
10 |
11 | public class MethodCall {
12 | private Method caller;
13 | private List called;
14 |
15 |
16 | public Method getCaller() {
17 | return caller;
18 | }
19 |
20 | public void setCaller(Method caller) {
21 | this.caller = caller;
22 | }
23 |
24 | public List getCalled() {
25 | return called;
26 | }
27 |
28 | public void setCalled(List called) {
29 | this.called = called;
30 | }
31 |
32 | public void addCalled(Method called) {
33 | if(called == null) {
34 | return;
35 | }
36 |
37 | if(this.called == null) {
38 | this.called = new ArrayList();
39 | }
40 | this.called.add(called);
41 | }
42 |
43 | public boolean containsCalled(Method called) {
44 | return this.called != null && this.called.contains(called);
45 | }
46 |
47 | @Override
48 | public String toString() {
49 | StringBuffer buff = new StringBuffer();
50 |
51 | buff.append(" \"caller\": ");
52 |
53 | String callerJsonObject = String.format("{\n\t\"methodname\": \"%s\",\n\t\"paramtype\": \"%s\"\n },\n", caller.getQualifiedName(), caller.getParamTypeList().toString());
54 |
55 | buff.append(callerJsonObject);
56 |
57 | buff.append(" \"callee\": [\n");
58 |
59 | if(called != null && !called.isEmpty()) {
60 |
61 | Iterator it = called.iterator();
62 | while(it.hasNext()){
63 | Method calledMethod = (Method) it.next();
64 | String calledJsonObject = String.format("\t{\"methodname\": \"%s\",\n\t\"paramtype\": \"%s\"}", calledMethod.getQualifiedName(), calledMethod.getParamTypeList());
65 | buff.append(calledJsonObject);
66 | if(it.hasNext())
67 | buff.append(",");
68 | buff.append("\n");
69 | }
70 | }
71 | buff.append(" ]\n");
72 | return buff.toString();
73 | }
74 |
75 | public JSONObject toJSON(){
76 |
77 | JSONObject methodCallObj = new JSONObject();
78 |
79 | JSONObject callerObj = new JSONObject();
80 | //callerObj.put("name", caller.getName());
81 | callerObj.put("clazz", caller.getPackageAndClassName());
82 | JSONArray callerParamArray = JSONArray.parseArray(JSON.toJSONString(caller.getParamTypeList()));
83 | //callerObj.put("params", callerParamArray);
84 |
85 | JSONArray calledArray = new JSONArray();
86 | Iterator it = called.iterator();
87 | while(it.hasNext()){
88 | Method calledMethod = (Method) it.next();
89 | JSONObject calledObj = new JSONObject();
90 | //calledObj.put("name", calledMethod.getName());
91 | calledObj.put("clazz", calledMethod.getPackageAndClassName());
92 | //JSONArray calledParamArray = new JSONArray();
93 | //calledParamArray.addAll(calledMethod.getParamTypeList());
94 | JSONArray calledParamArray = JSONArray.parseArray(JSON.toJSONString(calledMethod.getParamTypeList()));
95 | //calledObj.put("params", calledParamArray);
96 | calledArray.add(calledObj);
97 | }
98 | methodCallObj.put("caller", callerObj);
99 | methodCallObj.put("called", calledArray);
100 | return methodCallObj;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/MethodInfo.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 |
4 | public class MethodInfo {
5 |
6 | public MethodInfo(String projectName, Method method){
7 | this.projectName = projectName;
8 | this.className = method.getPackageAndClassName();
9 | this.methodName = method.getName();
10 | this.returnType = method.getReturnTypeStr();
11 | this.qualifiedName = method.getQualifiedName();
12 | this.methodParameters = method.getParamTypeList().toString();
13 | this.beginLine = method.getBeginLine();
14 | this.endLine = method.getEndLine();
15 | this.methodContent = method.getMethodContent();
16 | }
17 |
18 | public MethodInfo(){
19 |
20 | }
21 |
22 | private String projectName;
23 | private String methodName;
24 | private String className;
25 | private String returnType;
26 | private String methodParameters;
27 | private String qualifiedName;
28 | private String ID;
29 | private int beginLine;
30 | private int endLine;
31 | private boolean asset;
32 | private int cloneGroupId;
33 | private String methodContent;
34 | private int isSameProjectClone;
35 | private String filePath;
36 |
37 |
38 | public String getProjectName() {
39 | return projectName;
40 | }
41 |
42 | public void setProjectName(String projectName) {
43 | this.projectName = projectName;
44 | }
45 |
46 | public String getReturnType() {
47 | return returnType;
48 | }
49 |
50 | public void setReturnType(String returnType) {
51 | this.returnType = returnType;
52 | }
53 |
54 |
55 | public String getMethodParameters() {
56 | return methodParameters;
57 | }
58 |
59 | public void setMethodParameters(String methodParameters) {
60 | this.methodParameters = methodParameters;
61 | }
62 |
63 |
64 | public String getClassName() {
65 | return className;
66 | }
67 |
68 | public void setClassName(String className) {
69 | this.className = className;
70 | }
71 |
72 | public String getQualifiedName() {
73 | return qualifiedName;
74 | }
75 |
76 | public void setQualifiedName(String qualifiedName) {
77 | this.qualifiedName = qualifiedName;
78 | }
79 |
80 | public String getMethodName() {
81 | return methodName;
82 | }
83 |
84 | public void setMethodName(String methodName) {
85 | this.methodName = methodName;
86 | }
87 |
88 |
89 | public int getBeginLine() {
90 | return beginLine;
91 | }
92 |
93 | public void setBeginLine(int beginLine) {
94 | this.beginLine = beginLine;
95 | }
96 |
97 | public int getEndLine() {
98 | return endLine;
99 | }
100 |
101 | public void setEndLine(int endLine) {
102 | this.endLine = endLine;
103 | }
104 |
105 | public String getID() {
106 | return ID;
107 | }
108 |
109 | public void setID(String ID) {
110 | this.ID = ID;
111 | }
112 |
113 | public boolean isAsset() {
114 | return asset;
115 | }
116 |
117 | public void setAsset(boolean asset) {
118 | this.asset = asset;
119 | }
120 |
121 | public int getCloneGroupId() {
122 | return cloneGroupId;
123 | }
124 |
125 | public void setCloneGroupId(int cloneGroupId) {
126 | this.cloneGroupId = cloneGroupId;
127 | }
128 |
129 | public String getMethodContent() {
130 | return methodContent;
131 | }
132 |
133 | public void setMethodContent(String methodContent) {
134 | this.methodContent = methodContent;
135 | }
136 |
137 | public int getIsSameProjectClone() {
138 | return isSameProjectClone;
139 | }
140 |
141 | public void setIsSameProjectClone(int isSameProjectClone) {
142 | this.isSameProjectClone = isSameProjectClone;
143 | }
144 |
145 | public String getFilePath() {
146 | return filePath;
147 | }
148 |
149 | public void setFilePath(String filePath) {
150 | this.filePath = filePath;
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/MethodInvocation.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | public class MethodInvocation
4 | {
5 | private String ID;
6 | private String ProjectName;
7 | private String CallClassName;
8 | private String CalledClassName;
9 | private String CalledMethodName;
10 | private String CallMethodName;
11 | private String CallMethodParameters;
12 | private String CallMethodReturnType;
13 |
14 | public String getID() { return ID; }
15 |
16 | public void setID(String ID) { this.ID = ID; }
17 |
18 | public String getQualifiedCallMethodName(){
19 | return getCallClassName() + "." + getCallMethodName();
20 | }
21 |
22 | public String getQualifiedCalledMethodName(){
23 | return getCalledClassName() + "." + getCalledMethodName();
24 | }
25 |
26 | public String getCallClassName() {
27 | return CallClassName;
28 | }
29 |
30 | public void setCallClassName(String callClassName) {
31 | CallClassName = callClassName;
32 | }
33 |
34 | public String getCalledClassName() {
35 | return CalledClassName.replaceAll("'","\'");
36 | }
37 |
38 | public void setCalledClassName(String calledClassName) {
39 | CalledClassName = calledClassName;
40 | }
41 |
42 | public String getProjectName() {
43 | return ProjectName;
44 | }
45 |
46 | public void setProjectName(String projectName) {
47 | ProjectName = projectName;
48 | }
49 |
50 | public String getCalledMethodName() {
51 | return CalledMethodName;
52 | }
53 |
54 | public void setCalledMethodName(String calledMethodName) {
55 | CalledMethodName = calledMethodName;
56 | }
57 |
58 | public String getCallMethodName() {
59 | return CallMethodName;
60 | }
61 |
62 | public void setCallMethodName(String callMethodName) {
63 | CallMethodName = callMethodName;
64 | }
65 |
66 | public String getCallMethodParameters() {
67 | return CallMethodParameters;
68 | }
69 |
70 | public void setCallMethodParameters(String callMethodParameters) {
71 | CallMethodParameters = callMethodParameters;
72 | }
73 |
74 | public String getCallMethodReturnType() {
75 | return CallMethodReturnType;
76 | }
77 |
78 | public void setCallMethodReturnType(String callMethodReturnType) {
79 | CallMethodReturnType = callMethodReturnType;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/MethodInvocationInView.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | public class MethodInvocationInView {
4 |
5 | private int ID;
6 | private String projectName;
7 | private String callClassName;
8 | private String calledClassName;
9 | private String calledMethodName;
10 | private String callMethodName;
11 | private String callMethodParameters;
12 | private String callMethodReturnType;
13 | private String callMethodID;
14 | private String calledMethodID;
15 | private String callClassID;
16 | private String calledClassID;
17 |
18 | public int getID() {
19 | return ID;
20 | }
21 |
22 | public void setID(int ID) {
23 | this.ID = ID;
24 | }
25 |
26 | public String getCallMethodID() {
27 | return callMethodID;
28 | }
29 |
30 | public void setCallMethodID(String callMethodID) {
31 | this.callMethodID = callMethodID;
32 | }
33 |
34 | public String getCalledMethodID() {
35 | return calledMethodID;
36 | }
37 |
38 | public void setCalledMethodID(String calledMethodID) {
39 | this.calledMethodID = calledMethodID;
40 | }
41 |
42 | public String getProjectName() {
43 | return projectName;
44 | }
45 |
46 | public void setProjectName(String projectName) {
47 | this.projectName = projectName;
48 | }
49 |
50 | public String getCallClassName() {
51 | return callClassName;
52 | }
53 |
54 | public void setCallClassName(String callClassName) {
55 | this.callClassName = callClassName;
56 | }
57 |
58 | public String getCalledClassName() {
59 | return calledClassName;
60 | }
61 |
62 | public void setCalledClassName(String calledClassName) {
63 | this.calledClassName = calledClassName;
64 | }
65 |
66 | public String getCalledMethodName() {
67 | return calledMethodName;
68 | }
69 |
70 | public void setCalledMethodName(String calledMethodName) {
71 | this.calledMethodName = calledMethodName;
72 | }
73 |
74 | public String getCallMethodName() {
75 | return callMethodName;
76 | }
77 |
78 | public String getQualifiedCallMethodName(){
79 | return callClassName + "." + callMethodName;
80 | }
81 |
82 | public String getQualifiedCalledMethodName(){
83 | return calledClassName + "." + calledMethodName;
84 | }
85 |
86 | public void setCallMethodName(String callMethodName) {
87 | this.callMethodName = callMethodName;
88 | }
89 |
90 | public String getCallMethodParameters() {
91 | return callMethodParameters;
92 | }
93 |
94 | public void setCallMethodParameters(String callMethodParameters) {
95 | this.callMethodParameters = callMethodParameters;
96 | }
97 |
98 | public String getCallMethodReturnType() {
99 | return callMethodReturnType;
100 | }
101 |
102 | public void setCallMethodReturnType(String callMethodReturnType) {
103 | this.callMethodReturnType = callMethodReturnType;
104 | }
105 |
106 | public String getCallClassID() {
107 | return callClassID;
108 | }
109 |
110 | public void setCallClassID(String callClassID) {
111 | this.callClassID = callClassID;
112 | }
113 |
114 | public String getCalledClassID() {
115 | return calledClassID;
116 | }
117 |
118 | public void setCalledClassID(String calledClassID) {
119 | this.calledClassID = calledClassID;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/SetEnum.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | import java.util.HashSet;
4 | import java.util.Set;
5 |
6 | /**
7 | * @author wangjiwen
8 | * @create 2020/8/3
9 | */
10 | public class SetEnum {
11 | public Set controlEnum = new HashSet<>();
12 | public Set serviceEnum = new HashSet<>();
13 | public Set daoEnum = new HashSet<>();
14 | public Set otherEnum = new HashSet<>();
15 |
16 | public SetEnum() {
17 | controlEnum.add("Controller");
18 | controlEnum.add("RestController");
19 | controlEnum.add("RequestMapping");
20 | controlEnum.add("GetMapping");
21 | controlEnum.add("PostMapping");
22 | controlEnum.add("PutMapping");
23 | controlEnum.add("DeleteMapping");
24 | controlEnum.add("PatchMapping");
25 | controlEnum.add("PathVariable");
26 | controlEnum.add("RequestParam");
27 | controlEnum.add("RequestBody");
28 | controlEnum.add("ResponseBody");
29 |
30 | serviceEnum.add("Service");
31 |
32 | daoEnum.add("Repository");
33 | daoEnum.add("Table");
34 | daoEnum.add("ID");
35 | daoEnum.add("column");
36 | daoEnum.add("Query");
37 | daoEnum.add("Transactional");
38 | daoEnum.add("Modifying");
39 | daoEnum.add("GeneratedValue");
40 | daoEnum.add("GenericGenerator");
41 | daoEnum.add("Transient");
42 | daoEnum.add("Lob");
43 | daoEnum.add("Enumerated");
44 | daoEnum.add("OneToOne");
45 | daoEnum.add("OneToMany");
46 | daoEnum.add("ManyToOne");
47 | daoEnum.add("ManyToMany");
48 |
49 | otherEnum.add("SpringBootApplication");
50 | otherEnum.add("Configuration");
51 | otherEnum.add("EnableAutoConfiguration");
52 | otherEnum.add("ComponentScan");
53 | otherEnum.add("Autowired");
54 | otherEnum.add("value");
55 | otherEnum.add("ConfigurationProperties");
56 | otherEnum.add("PropertySource");
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/se/entity/Variable.java:
--------------------------------------------------------------------------------
1 | package com.se.entity;
2 |
3 | public class Variable {
4 | private String name;
5 |
6 | private String clazz;
7 |
8 | private String pkg;
9 |
10 | private boolean staticVar;
11 |
12 | private String genericType;
13 |
14 | public String getName() {
15 | return name;
16 | }
17 |
18 | public void setName(String name) {
19 | this.name = name;
20 | }
21 |
22 | public String getClazz() {
23 | return clazz;
24 | }
25 |
26 | public void setClazz(String clazz) {
27 | this.clazz = clazz;
28 | }
29 |
30 | public String getPkg() {
31 | return pkg;
32 | }
33 |
34 | public void setPkg(String pkg) {
35 | this.pkg = pkg;
36 | }
37 |
38 | public boolean isStaticVar() {
39 | return staticVar;
40 | }
41 |
42 | public void setStaticVar(boolean staticVar) {
43 | this.staticVar = staticVar;
44 | }
45 |
46 | public String getQualifiedName() {
47 | return this.clazz + "." + this.name;
48 | }
49 |
50 | public void setGenericType(String genericType) {
51 | this.genericType = genericType;
52 | }
53 |
54 | public String getGenericType() {
55 | return genericType;
56 | }
57 |
58 | public String getID(){
59 | if(this.pkg!=null){
60 | return this.pkg + "." + this.clazz;
61 | }else {
62 | return this.clazz;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/se/godclass/GodClassCalculator.java:
--------------------------------------------------------------------------------
1 | package com.se.godclass;
2 |
3 | import com.github.javaparser.ast.CompilationUnit;
4 | import com.se.metrics.calculators.ATFDCalculator;
5 | import com.se.metrics.calculators.MCCCalculator;
6 | import com.se.metrics.calculators.TCCCalculator;
7 | import com.se.metrics.calculators.WMCCalculator;
8 |
9 | public class GodClassCalculator {
10 |
11 | public static double DEFAULT_ATFD_LIMIT;
12 | public static double DEFAULT_WMC_LIMIT;
13 | public static double DEFAULT_MCC_LIMIT;
14 | public static double DEFAULT_TCC_LIMIT;
15 |
16 | static {
17 | DEFAULT_ATFD_LIMIT = 4;
18 | DEFAULT_WMC_LIMIT = 15;
19 | DEFAULT_MCC_LIMIT = 47;
20 | DEFAULT_TCC_LIMIT = 1.0/3.0;
21 |
22 | // DEFAULT_ATFD_LIMIT = 4;
23 | // DEFAULT_WMC_LIMIT = 15;
24 | // DEFAULT_MCC_LIMIT = 150;
25 | // DEFAULT_TCC_LIMIT = 1.0/4.0;
26 | }
27 |
28 | protected WMCCalculator wmcCalculator;
29 | protected MCCCalculator mccCalculator;
30 | protected TCCCalculator tccCalculator;
31 | protected ATFDCalculator atfdCalculator;
32 |
33 | protected double wmcLimit;
34 | protected double mccLimit;
35 | protected double tccLimit;
36 | protected double atfdLimit;
37 |
38 | public GodClassCalculator(double WMCLimit, double MCCLimit, double TCCLimit, double ATFDLimit) {
39 | this.wmcCalculator = new WMCCalculator();
40 | this.mccCalculator = new MCCCalculator();
41 | this.tccCalculator = new TCCCalculator();
42 | this.atfdCalculator = new ATFDCalculator();
43 |
44 | this.wmcLimit = WMCLimit;
45 | this.mccLimit = MCCLimit;
46 | this.tccLimit = TCCLimit;
47 | this.atfdLimit = ATFDLimit;
48 | }
49 |
50 | public void calculate(final CompilationUnit cu) {
51 |
52 | this.wmcCalculator.reset();
53 | this.wmcCalculator.calculate(cu);
54 |
55 | this.mccCalculator.reset();
56 | this.mccCalculator.calculate(cu);
57 |
58 | this.tccCalculator.reset();
59 | this.tccCalculator.calculate(cu);
60 |
61 | this.atfdCalculator.reset();
62 | this.atfdCalculator.calculate(cu);
63 | }
64 |
65 | public boolean isGodClass() {
66 | return this.getATFD() > this.atfdLimit &&
67 | this.getWMC() >= this.wmcLimit &&
68 | this.getMCC() >= this.mccLimit &&
69 | this.getTCC() < this.tccLimit;
70 | }
71 |
72 | public double getWMC()
73 | {
74 | return this.wmcCalculator.getMetric();
75 | }
76 |
77 | public WMCCalculator getWMCCalculator()
78 | {
79 | return this.wmcCalculator;
80 | }
81 |
82 | public double getWMCLimit()
83 | {
84 | return this.wmcLimit;
85 | }
86 |
87 | public void setWMCLimit(double wmcLimit)
88 | {
89 | this.wmcLimit = wmcLimit;
90 | }
91 |
92 | public double getMCC()
93 | {
94 | return this.mccCalculator.getMetric();
95 | }
96 |
97 | public MCCCalculator getMCCCalculator()
98 | {
99 | return this.mccCalculator;
100 | }
101 |
102 | public double getMCCLimit()
103 | {
104 | return this.mccLimit;
105 | }
106 |
107 | public void setMCCLimit(double mccLimit)
108 | {
109 | this.mccLimit = mccLimit;
110 | }
111 |
112 | public double getTCC()
113 | {
114 | return this.tccCalculator.getMetric();
115 | }
116 |
117 | public TCCCalculator getTCCCalculator()
118 | {
119 | return this.tccCalculator;
120 | }
121 |
122 | public double getTCCLimit()
123 | {
124 | return this.tccLimit;
125 | }
126 |
127 | public void setTCCLimit(double tccLimit)
128 | {
129 | this.tccLimit = tccLimit;
130 | }
131 |
132 | public double getATFD() {
133 | return this.atfdCalculator.getMetric();
134 | }
135 |
136 | public ATFDCalculator getATFDCalculator()
137 | {
138 | return this.atfdCalculator;
139 | }
140 |
141 | public double getATFDLimit()
142 | {
143 | return this.atfdLimit;
144 | }
145 |
146 | public void setATFDLimit(double atfdLimit)
147 | {
148 | this.atfdLimit = atfdLimit;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/MetricCalculator.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics;
2 |
3 | import com.github.javaparser.ast.CompilationUnit;
4 |
5 | public abstract class MetricCalculator {
6 |
7 | protected double metric;
8 |
9 | protected MetricCalculator()
10 | {
11 | this.metric = 0.0;
12 | }
13 |
14 | public double getMetric()
15 | {
16 | return this.metric;
17 | }
18 |
19 | public void reset() {
20 | this.metric = 0.0;
21 | }
22 |
23 | public abstract void calculate(final CompilationUnit cu);
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/calculators/ATFDCalculator.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.calculators;
2 |
3 | import com.github.javaparser.ast.CompilationUnit;
4 | import com.github.javaparser.ast.body.Parameter;
5 | import com.github.javaparser.ast.body.VariableDeclarator;
6 | import com.github.javaparser.ast.type.Type;
7 | import com.se.metrics.MetricCalculator;
8 | import com.se.metrics.visitors.ATFDVisitor;
9 |
10 | import java.util.*;
11 |
12 | public class ATFDCalculator extends MetricCalculator {
13 | protected ATFDVisitor visitor;
14 |
15 | // 变量的类型是内部类或者当前类
16 | protected Set classesToRemove;
17 | // 变量的类型是外部类
18 | protected Set externalClasses;
19 | // 变量的类型还无法确定
20 | protected Set unknownClassesVariables;
21 |
22 | protected Map memberVariables;
23 | protected Map localVariables;
24 |
25 | public ATFDCalculator() {
26 | super();
27 | this.visitor = new ATFDVisitor();
28 | this.classesToRemove = new HashSet<>();
29 | this.externalClasses = new HashSet<>();
30 | this.unknownClassesVariables = new HashSet<>();
31 | this.memberVariables = new HashMap<>();
32 | this.localVariables = new HashMap<>();
33 | }
34 |
35 | @Override
36 | public void calculate(CompilationUnit cu) {
37 | this.visitor.visit(cu, this);
38 |
39 | // 对unknownClassesVariables中的变量重新判断类型(主要是针对放在了class末尾声明的成员变量)
40 | this.checkClassOfUnknownClassVariable();
41 |
42 | // 将内部类和当前类从externalClasses中移除
43 | // System.out.println("[ATFD] Remove the following classes from External Classes List: " + this.classesToRemove);
44 | this.externalClasses.removeAll(this.classesToRemove);
45 |
46 | // 计算当前类访问的外部类的个数
47 | this.metric = (double)this.externalClasses.size();
48 | }
49 |
50 | @Override
51 | public void reset() {
52 | super.reset();
53 |
54 | this.classesToRemove.clear();
55 | this.externalClasses.clear();
56 | this.unknownClassesVariables.clear();
57 | this.memberVariables.clear();
58 | this.localVariables.clear();
59 | }
60 |
61 | public Type getTypeOfVariable(String variable) {
62 | // 先从局部变量Map中找
63 | for(Map.Entry variableType : this.localVariables.entrySet())
64 | if (variableType.getKey().equals(variable))
65 | return variableType.getValue();
66 |
67 | // 再从成员变量Map中找
68 | for(Map.Entry variableType : this.memberVariables.entrySet())
69 | if (variableType.getKey().equals(variable))
70 | return variableType.getValue();
71 |
72 | // 变量未找到
73 | return null;
74 | }
75 |
76 | public void addClassToRemove(final String classeName) {
77 | this.classesToRemove.add(classeName);
78 | }
79 |
80 | public Set getClassesToRemove()
81 | {
82 | return this.classesToRemove;
83 | }
84 |
85 | public boolean addExternalClass(final String className) {
86 | return this.externalClasses.add(className);
87 | }
88 |
89 | public Set getExternalClasses()
90 | {
91 | return this.externalClasses;
92 | }
93 |
94 | public boolean addExternalClassOfVariable(final String variableName) {
95 | // 获取变量的类型(即Class)
96 | Type classType = this.getTypeOfVariable(variableName);
97 |
98 | // 如果获取到了变量的类型,将类型其加入到externalClasses
99 | if (classType != null)
100 | return this.addExternalClass(classType.toString());
101 |
102 | // 当成员变量的声明放在了class的末尾时,暂时将无法获取到变量的类型,所以先保存到unknownClassesVariables
103 | return this.addUnknownClassVariable(variableName);
104 | }
105 |
106 | public boolean addUnknownClassVariable(String variableName) {
107 | return this.unknownClassesVariables.add(variableName);
108 | }
109 |
110 | public void addMemberVariable(final String variable, final Type type)
111 | {
112 | this.memberVariables.put(variable, type);
113 | }
114 |
115 | public void addMemberVariables(final List variables, final Type type) {
116 | for(VariableDeclarator variable : variables)
117 | this.addMemberVariable(variable.toString(), type);
118 | }
119 |
120 | public void addLocalVariable(final String variable, final Type type)
121 | {
122 | this.localVariables.put(variable, type);
123 | }
124 |
125 | public void addLocalVariables(final List variables) {
126 | for(Parameter variable : variables)
127 | this.addLocalVariable(variable.getName().toString(), variable.getType());
128 | }
129 |
130 | public void addLocalVariables(final List variables, final Type type) {
131 | for(VariableDeclarator variable : variables)
132 | this.addLocalVariable(variable.getName().toString(), type);
133 | }
134 |
135 | public void clearLocalVariables()
136 | {
137 | this.localVariables.clear();
138 | }
139 |
140 | private void checkClassOfUnknownClassVariable() {
141 | for (String variable : this.unknownClassesVariables) {
142 | Type classType = this.getTypeOfVariable(variable);
143 |
144 | if (classType != null)
145 | this.addExternalClass(classType.toString());
146 | }
147 | }
148 |
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/calculators/MCCCalculator.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.calculators;
2 |
3 | import com.github.javaparser.ast.CompilationUnit;
4 | import com.se.metrics.MetricCalculator;
5 | import com.se.metrics.exceptions.MCCException;
6 | import com.se.metrics.visitors.MCCVisitor;
7 |
8 | import java.util.HashMap;
9 | import java.util.Map;
10 | import java.util.Map.Entry;
11 |
12 | public class MCCCalculator extends MetricCalculator {
13 |
14 | protected MCCVisitor visitor;
15 |
16 | // 当前方法的圈复杂度
17 | protected int currentMethodCyclomaticComplexity;
18 | // 记录每一个方法的圈复杂度
19 | protected Map methodsCyclomaticComplexity;
20 |
21 | public MCCCalculator() {
22 | super();
23 |
24 | this.visitor = new MCCVisitor();
25 | this.methodsCyclomaticComplexity = new HashMap<>();
26 | this.currentMethodCyclomaticComplexity = 0;
27 | }
28 |
29 | @Override
30 | public void calculate(CompilationUnit cu) {
31 | this.visitor.visit(cu, this);
32 |
33 | this.metric = (double)this.getSumOfCyclomaticComplexity();
34 | }
35 |
36 | @Override
37 | public void reset() {
38 | // Reset general calculator variables
39 | super.reset();
40 |
41 | // Reset McCabe specific variables
42 | this.currentMethodCyclomaticComplexity = 0;
43 | this.methodsCyclomaticComplexity.clear();
44 | }
45 |
46 | public int getCurrentMethodCyclomaticComplexity() {
47 | return currentMethodCyclomaticComplexity;
48 | }
49 |
50 | public void setCurrentMethodCyclomaticComplexity(int currentMethodCyclomaticComplexity) {
51 | this.currentMethodCyclomaticComplexity = currentMethodCyclomaticComplexity;
52 | }
53 |
54 | public void startNewCyclomaticComplexity() {
55 | this.currentMethodCyclomaticComplexity = 1;
56 | }
57 |
58 | public void increaseCyclomaticComplexity()
59 | {
60 | this.currentMethodCyclomaticComplexity++;
61 | }
62 |
63 | public void increaseCyclomaticComplexity(int value)
64 | {
65 | this.currentMethodCyclomaticComplexity += value;
66 | }
67 |
68 | public void saveMethodCyclomaticComplexity(final String methodDeclaration) {
69 | this.methodsCyclomaticComplexity.put(methodDeclaration, this.currentMethodCyclomaticComplexity);
70 | this.currentMethodCyclomaticComplexity = 0;
71 | }
72 |
73 | public int getMethodCount()
74 | {
75 | return this.methodsCyclomaticComplexity.size();
76 | }
77 |
78 | public int getCyclomaticComplexity(String methodDeclaration) throws MCCException {
79 | for (String key : this.methodsCyclomaticComplexity.keySet())
80 | if (key.endsWith(methodDeclaration))
81 | return this.methodsCyclomaticComplexity.get(key);
82 |
83 | // 找不到这个method
84 | throw new MCCException("Method " + methodDeclaration + " not found");
85 | }
86 |
87 | public int getSumOfCyclomaticComplexity() {
88 | int v_G = 0;
89 |
90 | for(Entry entry: this.methodsCyclomaticComplexity.entrySet())
91 | v_G += entry.getValue() /* -1 ???*/;
92 |
93 | return v_G;
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/calculators/WMCCalculator.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.calculators;
2 |
3 | import com.github.javaparser.ast.CompilationUnit;
4 | import com.se.metrics.MetricCalculator;
5 | import com.se.metrics.visitors.WMCVisitor;
6 |
7 | public class WMCCalculator extends MetricCalculator
8 | {
9 |
10 | protected WMCVisitor visitor;
11 |
12 | public WMCCalculator() {
13 | super();
14 | this.visitor = new WMCVisitor();
15 | }
16 |
17 | @Override
18 | public void calculate(CompilationUnit cu) {
19 | this.visitor.visit(cu, this);
20 | }
21 |
22 | public int getMethodCount()
23 | {
24 | return (int)this.metric;
25 | }
26 |
27 | public void setMethodCount(int methodCount)
28 | {
29 | this.metric = (double)methodCount;
30 | }
31 |
32 | public void increaseMethodCount() {
33 | this.metric++;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/exceptions/ATFDException.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.exceptions;
2 |
3 | public class ATFDException extends Exception {
4 | public ATFDException(String string)
5 | {
6 | super(string);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/exceptions/MCCException.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.exceptions;
2 |
3 | public class MCCException extends Exception {
4 | public MCCException(String string)
5 | {
6 | super(string);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/exceptions/TCCException.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.exceptions;
2 |
3 | public class TCCException extends Exception {
4 | public TCCException(String message)
5 | {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/visitors/ATFDVisitor.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.visitors;
2 |
3 | import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
4 | import com.github.javaparser.ast.body.FieldDeclaration;
5 | import com.github.javaparser.ast.body.MethodDeclaration;
6 | import com.github.javaparser.ast.body.VariableDeclarator;
7 | import com.github.javaparser.ast.expr.Expression;
8 | import com.github.javaparser.ast.expr.FieldAccessExpr;
9 | import com.github.javaparser.ast.expr.MethodCallExpr;
10 | import com.github.javaparser.ast.expr.VariableDeclarationExpr;
11 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
12 | import com.se.metrics.calculators.ATFDCalculator;
13 |
14 | import java.util.List;
15 |
16 | public class ATFDVisitor extends VoidVisitorAdapter
17 | {
18 |
19 | @Override
20 | public void visit(ClassOrInterfaceDeclaration classOrInterfaceDeclaration, ATFDCalculator calculator) {
21 | // 如果是class
22 | if (!classOrInterfaceDeclaration.isInterface()) {
23 | // System.out.println("[ATFD] New class declaration = " + classOrInterfaceDeclaration.getName());
24 |
25 | calculator.addClassToRemove(classOrInterfaceDeclaration.getName().toString());
26 | }
27 |
28 | super.visit(classOrInterfaceDeclaration, calculator);
29 | }
30 |
31 | @Override
32 | public void visit(FieldDeclaration fieldDeclaration, ATFDCalculator calculator) {
33 | List variables = fieldDeclaration.getVariables();
34 |
35 | // for(VariableDeclarator var : variables)
36 | // System.out.println("[ATFD] New variable member = " + fieldDeclaration.getType().toString() + " " + var.getId().getName());
37 |
38 | calculator.addMemberVariables(variables, fieldDeclaration.getCommonType());
39 |
40 | super.visit(fieldDeclaration, calculator);
41 | }
42 |
43 | @Override
44 | public void visit(MethodDeclaration methodDeclaration, ATFDCalculator calculator) {
45 | // System.out.println("[ATFD] New method = " + methodDeclaration.getName());
46 |
47 | if (!methodDeclaration.getParameters().isEmpty()) {
48 | // System.out.println("[ATFD] Saving parameter ");
49 | calculator.addLocalVariables(methodDeclaration.getParameters());
50 | }
51 |
52 | super.visit(methodDeclaration, calculator);
53 |
54 | // 清除当前方法的局部变量
55 | calculator.clearLocalVariables();
56 | }
57 |
58 | @Override
59 | public void visit(FieldAccessExpr fieldAccessExpr, ATFDCalculator calculator) {
60 | // System.out.println("[ATFD] New attribute accesses = " + fieldAccessExpr.toString());
61 |
62 | // getScope的值被视为变量名
63 | calculator.addExternalClassOfVariable(fieldAccessExpr.getScope().toString());
64 |
65 | super.visit(fieldAccessExpr, calculator);
66 | }
67 |
68 | @Override
69 | public void visit(VariableDeclarationExpr variableDeclarationExpr, ATFDCalculator calculator) {
70 | // System.out.println("[ATFD] New local variable = " + variableDeclarationExpr.toString());
71 |
72 | calculator.addLocalVariables(variableDeclarationExpr.getVariables(), variableDeclarationExpr.getCommonType());
73 |
74 | super.visit(variableDeclarationExpr, calculator);
75 | }
76 |
77 | @Override
78 | public void visit(MethodCallExpr methodCallExpr, ATFDCalculator calculator) {
79 | Expression scope = null;
80 | if(methodCallExpr.getScope().isPresent())
81 | scope = methodCallExpr.getScope().get();
82 |
83 | // scope是null或this,表示调用了成员方法,
84 | if (scope != null && !scope.toString().startsWith("this")) {
85 | String methodName = methodCallExpr.getName().toString().toUpperCase();
86 |
87 | // 对于setter和getter
88 | if (methodName.startsWith("GET") || methodName.startsWith("SET")) {
89 | // System.out.println("[ATFD] New call of an accessor = " + methodCallExpr.toString());
90 | calculator.addExternalClassOfVariable(scope.toString());
91 | }
92 | }
93 |
94 | super.visit(methodCallExpr, calculator);
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/visitors/MCCVisitor.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.visitors;
2 |
3 | import com.github.javaparser.ast.body.ConstructorDeclaration;
4 | import com.github.javaparser.ast.body.MethodDeclaration;
5 | import com.github.javaparser.ast.expr.BinaryExpr;
6 | import com.github.javaparser.ast.expr.BinaryExpr.Operator;
7 | import com.github.javaparser.ast.stmt.*;
8 | import com.github.javaparser.ast.type.ReferenceType;
9 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
10 | import com.se.metrics.calculators.MCCCalculator;
11 | import java.util.List;
12 |
13 | /**
14 | * McCabe Cyclomatic Complexity (MCC) Visitor
15 | * 圈复杂度
16 | */
17 | public class MCCVisitor extends VoidVisitorAdapter {
18 |
19 | @Override
20 | public void visit(ConstructorDeclaration constructorDeclaration, MCCCalculator mCCCalculator) {
21 | // 当前构造方法的圈复杂度初值设置为1
22 | this.initializeMethodCyclomaticComplexity(constructorDeclaration.getThrownExceptions(),
23 | mCCCalculator);
24 |
25 | // visit构造方法的方法体
26 | super.visit(constructorDeclaration, mCCCalculator);
27 |
28 | // 保存当前构造方法的圈复杂度
29 | try{
30 | this.validateMethodCyclomaticComplexity(constructorDeclaration.asMethodDeclaration(), mCCCalculator);
31 | }catch (Exception e){
32 |
33 | }
34 | }
35 |
36 | @Override
37 | public void visit(MethodDeclaration methodDeclaration, MCCCalculator mCCCalculator) {
38 | // 当前方法的圈复杂度初值设置为1
39 | this.initializeMethodCyclomaticComplexity(methodDeclaration.getThrownExceptions(), mCCCalculator);
40 |
41 | // visit方法体
42 | super.visit(methodDeclaration, mCCCalculator);
43 |
44 | // 保存当前方法的圈复杂度
45 | this.validateMethodCyclomaticComplexity(methodDeclaration, mCCCalculator);
46 | }
47 |
48 | @Override
49 | public void visit(IfStmt ifStmt, MCCCalculator mcCabeCalculator) {
50 | // System.out.println("[McCabe] if statement --> Complexity + 1 ");
51 |
52 | // 对每一个if语句圈复杂度+1
53 | mcCabeCalculator.increaseCyclomaticComplexity();
54 |
55 | super.visit(ifStmt, mcCabeCalculator);
56 | }
57 |
58 | @Override
59 | public void visit(WhileStmt whileStmt, MCCCalculator mCCCalculator) {
60 | // System.out.println("[McCabe] while statement --> Complexity + 1");
61 |
62 | // 对每一个while语句圈复杂度+1
63 | mCCCalculator.increaseCyclomaticComplexity();
64 |
65 | super.visit(whileStmt, mCCCalculator);
66 | }
67 |
68 | @Override
69 | public void visit(DoStmt doStmt, MCCCalculator mCCCalculator) {
70 | // System.out.println("[McCabe] do...while statement --> Complexity + 1");
71 |
72 | // 对每一个do...while语句圈复杂度+1
73 | mCCCalculator.increaseCyclomaticComplexity();
74 |
75 | super.visit(doStmt, mCCCalculator);
76 | }
77 |
78 | @Override
79 | public void visit(ForStmt forStmt, MCCCalculator mCCCalculator) {
80 | // System.out.println("[McCabe] for statement --> Complexity + 1");
81 |
82 | // 对每一个while语句圈复杂度+1
83 | mCCCalculator.increaseCyclomaticComplexity();
84 |
85 | super.visit(forStmt, mCCCalculator);
86 | }
87 |
88 | @Override
89 | public void visit(ForEachStmt foreachStmt, MCCCalculator mCCCalculator) {
90 | // System.out.println("[McCabe] foreach statement --> Complexity + 1");
91 |
92 | // 对每一个foreach语句圈复杂度+1
93 | mCCCalculator.increaseCyclomaticComplexity();
94 |
95 | super.visit(foreachStmt, mCCCalculator);
96 | }
97 |
98 | @Override
99 | public void visit(SwitchStmt switchStmt, MCCCalculator mCCCalculator) {
100 | // System.out.println("[McCabe] switch statement --> Complexity + 1 ");
101 |
102 | // 对每一个switch语句圈复杂度+1
103 | mCCCalculator.increaseCyclomaticComplexity();
104 |
105 | super.visit(switchStmt, mCCCalculator);
106 | }
107 |
108 | @Override
109 | public void visit(SwitchEntry switchEntryStmt, MCCCalculator mCCCalculator) {
110 | /*
111 | * Add one for each catch clause
112 | * 对switch case中的每一个"case"语句圈复杂度+1,但是不对"default"语句增加
113 | */
114 | if (switchEntryStmt.getLabels() != null) {
115 | // System.out.println("[McCabe] case statement --> Complexity + 1 ");
116 | mCCCalculator.increaseCyclomaticComplexity();
117 | }
118 |
119 | super.visit(switchEntryStmt, mCCCalculator);
120 | }
121 |
122 | @Override
123 | public void visit(CatchClause catchClause, MCCCalculator mCCCalculator) {
124 | // System.out.println("[McCabe] catch clause --> Complexity + 1 ");
125 |
126 | // 对每一个catch语句圈复杂度+1
127 | mCCCalculator.increaseCyclomaticComplexity();
128 |
129 | super.visit(catchClause, mCCCalculator);
130 | }
131 |
132 | @Override
133 | public void visit(BinaryExpr binaryExpr, MCCCalculator mcCabeCalculator) {
134 | Operator operator = binaryExpr.getOperator();
135 | if (operator == Operator.AND || operator == Operator.OR) {
136 | // System.out.println("[McCabe] logical expression && or || --> Complexity + 1");
137 |
138 | // 对每一个逻辑表达式 && 或者 || 圈复杂度+1
139 | mcCabeCalculator.increaseCyclomaticComplexity();
140 | }
141 |
142 | super.visit(binaryExpr, mcCabeCalculator);
143 | }
144 |
145 | @Override
146 | public void visit(ThrowStmt throwStmt, MCCCalculator mcCabeCalculator) {
147 | // System.out.println("[McCabe] throw statement --> Complexity + 1");
148 |
149 | // 对每一个throw语句圈复杂度+1
150 | mcCabeCalculator.increaseCyclomaticComplexity();
151 |
152 | super.visit(throwStmt, mcCabeCalculator);
153 | }
154 |
155 | private void initializeMethodCyclomaticComplexity(List throwsClauses, MCCCalculator mCCCalculator) {
156 |
157 | // 一个方法的圈复杂度初始值为1
158 | mCCCalculator.startNewCyclomaticComplexity();
159 |
160 | // 对每一个throws圈复杂度 + 1
161 | if (!throwsClauses.isEmpty()) {
162 | mCCCalculator.increaseCyclomaticComplexity(throwsClauses.size());
163 |
164 | // for (NameExpr nameExpr : throwsClauses)
165 | // System.out.println("[McCabe] throws clause = " + nameExpr.getName() + " --> Complexity + 1");
166 | }
167 | }
168 |
169 | private void validateMethodCyclomaticComplexity(MethodDeclaration methodDeclaration, MCCCalculator mCCCalculator) {
170 | // 保存当前方法的圈复杂度
171 | // System.out.println("[McCabe] Final Cyclomatic Complexity of method = " + mCCCalculator.getCurrentMethodCyclomaticComplexity());
172 | mCCCalculator.saveMethodCyclomaticComplexity(methodDeclaration.getDeclarationAsString(false, true));
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/visitors/TCCConnectionsVisitor.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.visitors;
2 |
3 | import com.github.javaparser.ast.body.MethodDeclaration;
4 | import com.github.javaparser.ast.body.Parameter;
5 | import com.github.javaparser.ast.expr.AssignExpr;
6 | import com.github.javaparser.ast.expr.Expression;
7 | import com.github.javaparser.ast.expr.MethodCallExpr;
8 | import com.github.javaparser.ast.expr.VariableDeclarationExpr;
9 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
10 | import com.se.metrics.calculators.TCCCalculator;
11 | import com.se.metrics.exceptions.TCCException;
12 |
13 | import java.util.List;
14 |
15 | public class TCCConnectionsVisitor extends VoidVisitorAdapter {
16 | @Override
17 | public void visit(MethodDeclaration methodDeclaration, TCCCalculator calculator) {
18 | String methodDeclarationString = methodDeclaration.getDeclarationAsString(true, false, false);
19 |
20 | // 不需要访问private方法
21 | if (methodDeclarationString.startsWith("private"))
22 | return;
23 |
24 | // 方法名的表示格式为 : "name type1 type2 ..."
25 | String methodPrototype = methodDeclaration.getName().toString();
26 | for(Parameter parameter : methodDeclaration.getParameters())
27 | methodPrototype += " " + parameter.getType();
28 |
29 | try {
30 | // 设置当前访问的方法名
31 | calculator.setCurrentMethod(methodPrototype);
32 |
33 | // 将方法的参数加入到局部变量list中
34 | if (!methodDeclaration.getParameters().isEmpty()) {
35 | // System.out.println("[TCC] Saving parameter");
36 | calculator.addLocalVariables(methodDeclaration.getParameters());
37 | }
38 |
39 | // 访问方法体
40 | super.visit(methodDeclaration, calculator);
41 | } catch (TCCException ex) {
42 | // System.out.println("[TCC] Error with current method : " + ex.getMessage());
43 | }
44 | }
45 |
46 | @Override
47 | public void visit(VariableDeclarationExpr variableDeclarationExpr, TCCCalculator calculator) {
48 | // 保存当前方法中创建的局部变量
49 | calculator.addLocalVariables(variableDeclarationExpr.getVariables(), variableDeclarationExpr.getCommonType());
50 |
51 | super.visit(variableDeclarationExpr, calculator);
52 | }
53 |
54 | @Override
55 | public void visit(MethodCallExpr methodCallExpr, TCCCalculator calculator) {
56 |
57 | /* 方法调用表达式的作用域可能是:
58 | * 1) null 或者 this: 对当前类的方法成员进行调用
59 | * 2) 当前类的成员变量: 当前方法直接访问成员变量
60 | * 3) 方法内创建的局部变量/对象: do nothing
61 | * 所有情况中,都要检查成员变量是否被作为参数传递
62 | */
63 | Expression scope = null;
64 | if(methodCallExpr.getScope().isPresent())
65 | scope = methodCallExpr.getScope().get();
66 |
67 | // 1) 被调用者为null或者调用了成员方法
68 | if (scope == null || scope.toString().equals("this"))
69 | this.memberMethodCalled(methodCallExpr, calculator);
70 | // 2) 被调用者为成员变量
71 | else if (calculator.containsMemberVariable(scope.toString()))
72 | this.memberVariableAccessed(scope.toString(), calculator);
73 |
74 | /* 检查被调用方法的参数是否为成员变量 */
75 | List args = methodCallExpr.getArguments();
76 | if (args != null && !args.isEmpty()) {
77 | for(Expression arg : args) {
78 | String argString = arg.toString();
79 |
80 | // 移除 "this."
81 | if(argString.startsWith("this"))
82 | argString = argString.substring(argString.lastIndexOf(".") +1);
83 |
84 | // 判断参数是否为成员变量
85 | if (calculator.isMemberVariable(argString))
86 | this.memberVariableAccessed(argString, calculator);
87 | }
88 | }
89 |
90 | super.visit(methodCallExpr, calculator);
91 | }
92 |
93 | @Override
94 | public void visit(AssignExpr assignExpr, TCCCalculator calculator) {
95 | // 等号左侧的表达式
96 | String expression = assignExpr.getTarget().toString();
97 |
98 | // 移除 "this."
99 | if(expression.startsWith("this"))
100 | expression = expression.substring(expression.lastIndexOf(".") +1);
101 |
102 | // 判断等号左侧的表达式是否为成员变量
103 | if (calculator.isMemberVariable(expression))
104 | this.memberVariableAccessed(expression, calculator);
105 |
106 |
107 | // 等号右侧的表达式
108 | expression = assignExpr.getValue().toString();
109 |
110 | // 移除 "this."
111 | if(expression.startsWith("this"))
112 | expression = expression.substring(expression.lastIndexOf(".") +1);
113 |
114 | // 判断等号右侧的表达式是否为成员变量
115 | if (calculator.isMemberVariable(expression))
116 | this.memberVariableAccessed(expression, calculator);
117 |
118 | super.visit(assignExpr, calculator);
119 | }
120 |
121 | private void memberMethodCalled(MethodCallExpr methodCallExpr, TCCCalculator calculator) {
122 | // 当前方法调用了成员方法
123 | String calledMethodPrototype = methodCallExpr.getName().toString();
124 |
125 | try {
126 | // 获取获取被调用方法的参数类型
127 | List args = methodCallExpr.getArguments();
128 | if (args != null && !args.isEmpty())
129 | for(Expression arg : args)
130 | calledMethodPrototype += " " + calculator.getTypeOfVariable(arg.toString());
131 |
132 | // System.out.println("[TCC] method \"" + calculator.getCurrentMethod() + "\" invoke method \"" + calledMethodPrototype + "\"");
133 |
134 | calculator.addMemberMethodCall(calledMethodPrototype);
135 | }
136 | catch (TCCException ex) {
137 | // System.out.println("[TCC] Error in the construction of the prototype" + " of the method member " + methodCallExpr.getName() + " : " + ex.getMessage());
138 | }
139 | }
140 |
141 | private void memberVariableAccessed(String variable, TCCCalculator calculator) {
142 | try {
143 | // System.out.println("[TCC] method \"" + calculator.getCurrentMethod() + "\" access the variable \"" + variable + "\"");
144 |
145 | calculator.addMemberVariableAccess(variable);
146 | }
147 | catch (TCCException ex) {
148 | // System.out.println("[TCC] Error filling in a method" + " accessed a member variable : " + ex.getMessage());
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/visitors/TCCVariablesMethodsVisitor.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.visitors;
2 |
3 | import com.github.javaparser.ast.body.FieldDeclaration;
4 | import com.github.javaparser.ast.body.MethodDeclaration;
5 | import com.github.javaparser.ast.body.Parameter;
6 | import com.github.javaparser.ast.body.VariableDeclarator;
7 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
8 | import com.se.metrics.calculators.TCCCalculator;
9 |
10 | import java.util.List;
11 |
12 | public class TCCVariablesMethodsVisitor extends VoidVisitorAdapter {
13 | @Override
14 | public void visit(FieldDeclaration fieldDeclaration, TCCCalculator tccCalculator) {
15 | List variables = fieldDeclaration.getVariables();
16 |
17 | // for(VariableDeclarator variable : variables)
18 | // System.out.println("[TCC] New variable member = " + fieldDeclaration.getType().toString() + " " + variable);
19 |
20 | tccCalculator.addMemberVariables(variables, fieldDeclaration.getCommonType());
21 |
22 | //super.visit(fieldDeclaration, tccCalculator);
23 | }
24 |
25 | @Override
26 | public void visit(MethodDeclaration methodDeclaration, TCCCalculator tccCalculator) {
27 | String methodDeclarationString = methodDeclaration.getDeclarationAsString(true, false, false);
28 |
29 | // 对于TCC和LCC,只考虑非private的方法
30 | if (methodDeclarationString.startsWith("private"))
31 | return;
32 |
33 | // 构造方法名,格式为 : "name type1 type2 ..."
34 | String methodName = methodDeclaration.getName().toString();
35 | for(Parameter parameter : methodDeclaration.getParameters())
36 | methodName += " " + parameter.getType();
37 |
38 | // System.out.println("[TCC] New visible method = " + methodName);
39 |
40 | tccCalculator.addVisibleMethod(methodName);
41 |
42 | // 不需要访问这个方法的方法体
43 | //super.visit(methodDeclaration, tccCalculator);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/se/metrics/visitors/WMCVisitor.java:
--------------------------------------------------------------------------------
1 | package com.se.metrics.visitors;
2 |
3 | import com.github.javaparser.ast.body.ConstructorDeclaration;
4 | import com.github.javaparser.ast.body.MethodDeclaration;
5 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
6 | import com.se.metrics.calculators.WMCCalculator;
7 |
8 | public class WMCVisitor extends VoidVisitorAdapter {
9 | @Override
10 | public void visit(MethodDeclaration methodDeclaration, WMCCalculator wmcCalculator) {
11 | super.visit(methodDeclaration, wmcCalculator);
12 |
13 | // 方法数量
14 | // System.out.println("[WMC] New method = " + methodDeclaration.getName());
15 | wmcCalculator.increaseMethodCount();
16 | }
17 |
18 | @Override
19 | public void visit(ConstructorDeclaration constructorDeclaration, WMCCalculator wmcCalculator) {
20 | super.visit(constructorDeclaration, wmcCalculator);
21 |
22 | // System.out.println("[WMC] New constructor = " + constructorDeclaration.getName());
23 | wmcCalculator.increaseMethodCount();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/se/process/CloneMining.java:
--------------------------------------------------------------------------------
1 | package com.se.process;
2 | import com.se.DAO.BuildConnection;
3 | import com.se.DAO.ClassInfoDAO;
4 | import com.se.DAO.MethodInfoDAO;
5 | import com.se.config.DataConfig;
6 | import com.se.entity.ClassInfo;
7 | import com.se.entity.MeasureIndex;
8 | import com.se.entity.MethodInfo;
9 | import com.se.utils.CalculateUtil;
10 | import com.se.utils.FileHelper;
11 | import java.io.IOException;
12 | import java.sql.Connection;
13 | import java.sql.SQLException;
14 | import java.util.*;
15 |
16 | public class CloneMining {
17 |
18 | Set measureIndexSet = new HashSet<>();
19 |
20 | private void linkCloneDataAndModel(Connection connection) throws IOException, SQLException {
21 | Map> measureMap = FileHelper.readMeasureIndex(DataConfig.measureIndexFilePath);
22 | Set projectNameSet = measureMap.keySet();
23 | //对于每个measureIndex中的方法,去匹配抽取的程序数据
24 | Map cloneIdMap = new HashMap<>();
25 | System.out.println("正在进行克隆检测结果与数据库数据的匹配");
26 | MethodInfoDAO methodInfoDAO = new MethodInfoDAO();
27 | for(String projectName:projectNameSet){
28 | System.out.println("正在匹配的项目为:" + projectName);
29 | List measureIndexList = measureMap.get(projectName);
30 | List methodInfoList = methodInfoDAO.getMethodIdListByProjectName(projectName,connection);
31 | List classInfoList = ClassInfoDAO.getClassListByProjectName(projectName,connection);
32 | Map classInfoMap = new HashMap<>();
33 | Map> methodInfoListMap = new HashMap<>();
34 | for(ClassInfo classInfo:classInfoList){
35 | classInfoMap.put(classInfo.getClassName(),classInfo);
36 | }
37 | for(MethodInfo methodInfo:methodInfoList){
38 | if(classInfoMap.get(methodInfo.getClassName())!=null){
39 | methodInfo.setFilePath(classInfoMap.get(methodInfo.getClassName()).getFilePath());
40 | List list = methodInfoListMap.getOrDefault(methodInfo.getFilePath(),new ArrayList<>());
41 | list.add(methodInfo);
42 | methodInfoListMap.put(methodInfo.getFilePath(),list);
43 | }
44 | }
45 | for(MeasureIndex measureIndex:measureIndexList){
46 | String filePath = measureIndex.getFilePath();
47 | filePath = filePath.replace("\\","|");
48 | List methodInfoList1 = methodInfoListMap.getOrDefault(filePath,new ArrayList<>());
49 | for(MethodInfo methodInfo:methodInfoList1){
50 | //如果匹配成功,则进行更新
51 | if(Math.abs(methodInfo.getBeginLine() - measureIndex.getBeginLine())<=2 && Math.abs(methodInfo.getEndLine()-measureIndex.getEndLine())<=2){
52 | cloneIdMap.put(Integer.parseInt(methodInfo.getID()),measureIndex.getId());
53 | measureIndexSet.add(measureIndex.getId());
54 | }
55 | }
56 | }
57 | methodInfoDAO.updateCloneId(cloneIdMap,connection);
58 | }
59 | }
60 |
61 |
62 | public static void main(String[] args) throws IOException, SQLException {
63 | BuildConnection buildConnection = new BuildConnection();
64 | Connection connection = buildConnection.buildConnect();
65 | CloneMining cloneMining = new CloneMining();
66 | cloneMining.linkCloneDataAndModel(connection);
67 | List methodInfoList= new ArrayList<>();
68 | List> cloneGroupList = FileHelper.readCloneGroupToList(DataConfig.cloneGroupFilePath);
69 | System.out.println("正在从克隆检测信息中挖掘代码资产");
70 | int count = 1;
71 | MethodInfoDAO methodInfoDAO = new MethodInfoDAO();
72 | Map> classInvokeMap = ClassInfoDAO.getAllClassInvokeInfo(connection);
73 | Map methodInfoMap = methodInfoDAO.getAllMethodInfo(connection);
74 | for(List list:cloneGroupList){
75 | System.out.println("正在处理的克隆组的编号是:" + count++);
76 | Set projectNameSet = new HashSet<>();
77 | List GroupMethodList = new ArrayList<>();
78 | for(Integer id:list){
79 | if(!cloneMining.measureIndexSet.contains(id))continue;
80 | MethodInfo methodInfo = methodInfoMap.get(id);
81 | projectNameSet.add(methodInfo.getProjectName());
82 | List invokeList = classInvokeMap.get(methodInfo.getClassName());
83 | if(invokeList == null)continue;
84 | if(CalculateUtil.CalCouplingRate(invokeList.get(0),invokeList.get(1)))
85 | methodInfo.setAsset(true);
86 | else
87 | methodInfo.setAsset(false);
88 | methodInfo.setCloneGroupId(count);
89 | GroupMethodList.add(methodInfo);
90 | }
91 | if(projectNameSet.size()>1){
92 | for(MethodInfo methodInfo:GroupMethodList){
93 | methodInfo.setIsSameProjectClone(0);
94 | }
95 | }else {
96 | for(MethodInfo methodInfo:GroupMethodList){
97 | methodInfo.setIsSameProjectClone(1);
98 | }
99 | }
100 | methodInfoList.addAll(GroupMethodList);
101 | //每挖掘出500个资产进行一次数据库update操作
102 | if(methodInfoList.size()%500 == 0){
103 | methodInfoDAO.updateAsset(methodInfoList,connection);
104 | methodInfoList.clear();
105 | }
106 | }
107 | methodInfoDAO.updateAsset(methodInfoList,connection);
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/com/se/process/CountInvocationInMethodGra.java:
--------------------------------------------------------------------------------
1 | package com.se.process;
2 |
3 | import com.se.DAO.BuildConnection;
4 | import com.se.DAO.ClassInfoDAO;
5 | import com.se.DAO.MethodInfoDAO;
6 | import com.se.DAO.MethodInvocationInViewDAO;
7 | import com.se.entity.MethodInvocationInView;
8 | import java.sql.Connection;
9 | import java.sql.SQLException;
10 | import java.util.*;
11 |
12 | public class CountInvocationInMethodGra {
13 |
14 | public static void countInvokeCounts(List projectNameList, Connection conn) throws SQLException {
15 | System.out.println("正在进行调用次数统计");
16 | for(String projectName:projectNameList){
17 | MethodInfoDAO methodInfoDAO = new MethodInfoDAO();
18 | System.out.println("正在进行调用次数统计的项目名称为:" + projectName);
19 | Map idMap = methodInfoDAO.getMethodInfoByProjectName(projectName,conn);
20 | List> invokeInfoList = new ArrayList<>();
21 | List methodInvocationInViewList = MethodInvocationInViewDAO.getMethodInvocationInViewByProjectName(projectName,conn);
22 | HashMap callCountsMap = new HashMap<>();
23 | HashMap calledCountsMap = new HashMap<>();
24 | for(MethodInvocationInView methodInvocationInView:methodInvocationInViewList){
25 | String callMethodName = methodInvocationInView.getQualifiedCallMethodName();
26 | String calledMethodName = methodInvocationInView.getQualifiedCalledMethodName();
27 | if(callCountsMap.containsKey(callMethodName)){
28 | int count = callCountsMap.get(callMethodName);
29 | callCountsMap.put(callMethodName,count+1);
30 | }else {
31 | callCountsMap.put(callMethodName,1);
32 | }
33 | if(calledCountsMap.containsKey(calledMethodName)){
34 | int count = calledCountsMap.get(calledMethodName);
35 | calledCountsMap.put(calledMethodName,count+1);
36 | }else {
37 | calledCountsMap.put(calledMethodName,1);
38 | }
39 | }
40 | for(Integer Id:idMap.keySet()){
41 | List list = new ArrayList<>();
42 | String methodName = idMap.get(Id);
43 | int invokedCount = 0,invokeCount = 0;
44 | if(calledCountsMap.containsKey(methodName)){
45 | invokedCount = calledCountsMap.get(methodName);
46 | }
47 | if(callCountsMap.containsKey(methodName)){
48 | invokeCount = callCountsMap.get(methodName);
49 | }
50 | list.add(invokedCount);
51 | list.add(invokeCount);
52 | list.add(Id);
53 | invokeInfoList.add(list);
54 | }
55 | methodInfoDAO.updateInvokeCounts(invokeInfoList,conn);
56 | }
57 | }
58 |
59 |
60 | public static void countInvocationDept(List projectNameList,Connection conn) throws SQLException {
61 | System.out.println("正在统计调用深度");
62 | MethodInfoDAO methodInfoDAO = new MethodInfoDAO();
63 | for(String projectName:projectNameList){
64 | System.out.println("正在统计调用深度的项目为:" + projectName);
65 | List methodInvocationInViewList = MethodInvocationInViewDAO.getInvokeInfoByProjectName(projectName,conn);
66 | Set callMethodSet = new HashSet<>();
67 | Set calledMethodSet = new HashSet<>();
68 | Map> callTree = new HashMap<>();
69 | for(MethodInvocationInView methodInvocationInView:methodInvocationInViewList){
70 | String callMethodName = methodInvocationInView.getQualifiedCallMethodName();
71 | String calledMethodName = methodInvocationInView.getQualifiedCalledMethodName();
72 | String callClassName = methodInvocationInView.getCallClassName();
73 | String calledClassName = methodInvocationInView.getCalledClassName();
74 | if(callMethodName.equals(calledMethodName)||callClassName.equals(calledClassName))continue;
75 | callMethodSet.add(callMethodName);
76 | calledMethodSet.add(calledMethodName);
77 | if(callTree.containsKey(callMethodName)){
78 | List calledMethodList = callTree.get(callMethodName);
79 | calledMethodList.add(calledMethodName);
80 | callTree.put(callMethodName,calledMethodList);
81 | }else {
82 | List calledMethodList = new ArrayList<>();
83 | calledMethodList.add(calledMethodName);
84 | callTree.put(callMethodName,calledMethodList);
85 | }
86 | }
87 | Map methodNodeMap = new HashMap<>();
88 | for(String name:callMethodSet){
89 | methodNodeMap.put(name,0);
90 | }
91 | callMethodSet.removeAll(calledMethodSet);
92 | Queue rootNodeQueue = new LinkedList<>(callMethodSet);
93 | HashSet nodeSet = new HashSet<>(callMethodSet);
94 | while(!rootNodeQueue.isEmpty()){
95 | String rootNodeName = rootNodeQueue.poll();
96 | int dept = methodNodeMap.getOrDefault(rootNodeName,0);
97 | List calledClassList = callTree.get(rootNodeName);
98 | if(calledClassList == null||dept>10)continue;
99 | for(String name:calledClassList){
100 | if(methodNodeMap.getOrDefault(name,0) projectNameList = ClassInfoDAO.getAllProjectNameFromDB(connection);
120 | CountInvocationInMethodGra.countInvokeCounts(projectNameList,connection);
121 | CountInvocationInMethodGra.countInvocationDept(projectNameList,connection);
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/com/se/process/GetMethodInvocation.java:
--------------------------------------------------------------------------------
1 | package com.se.process;
2 |
3 | import com.github.javaparser.StaticJavaParser;
4 | import com.github.javaparser.ast.CompilationUnit;
5 | import com.se.DAO.ClassInfoDAO;
6 | import com.se.DAO.MethodInfoDAO;
7 | import com.se.DAO.MethodInvocationDAO;
8 | import com.se.config.DataConfig;
9 | import com.se.container.MethodCallContainer;
10 | import com.se.container.MethodInfoContainer;
11 | import com.se.entity.ClassInfo;
12 | import com.se.utils.FileHelper;
13 | import com.se.visitors.ClassVisitor;
14 | import com.se.visitors.LayerVisitor;
15 | import com.se.visitors.MethodVisitor;
16 |
17 | import java.io.File;
18 | import java.sql.Connection;
19 | import java.sql.SQLException;
20 | import java.util.ArrayList;
21 | import java.util.List;
22 |
23 | public class GetMethodInvocation implements Runnable {
24 |
25 | private String projectName;
26 |
27 | private static String getProjectNameFromProjectPath(String projectPath)
28 | {
29 | return new File(projectPath).getName();
30 | }
31 | private Connection connection;
32 | private List folders;
33 |
34 | public GetMethodInvocation(List folders, Connection connection){
35 | this.folders = folders;
36 | this.connection = connection;
37 | }
38 |
39 | /**
40 | * 将类信息、方法信息、方法调用信息存储到数据库中
41 | * @param conn
42 | * @throws SQLException
43 | */
44 | public void getMethodInvocation(List projectNameList,Connection conn) throws SQLException {
45 | System.out.println("线程处理的项目数为:" + projectNameList.size());
46 | //获取数据库中已有的项目名列表
47 | for(String f:folders) {
48 | int fileSize = 0;
49 | projectName = getProjectNameFromProjectPath(f);
50 | System.out.println("正在处理的项目为:" + f);
51 | List classInfosContainer = new ArrayList<>();
52 | for (String filePath : FileHelper.getSubFile(f, "java")) {
53 | if(filePath.contains("\\test")){
54 | continue;
55 | }
56 | File file = new File(filePath);
57 | //存储类
58 | processClassInfo(file, classInfosContainer);
59 | }
60 | //存储当前项目中的所有类
61 | ClassInfoDAO.saveClassInfoList(classInfosContainer, conn);
62 | //从获取该项目中的所有类
63 | List classInfoList = ClassInfoDAO.getAllClassInfoList(projectName, conn);
64 | for (String filePath : FileHelper.getSubFile(f, "java")) {
65 | if(filePath.contains("\\test")){
66 | continue;
67 | }
68 | //System.out.println("正在处理的文件为:" + filePath);
69 | fileSize++;
70 | File file = new File(filePath);
71 | //获取方法调用
72 | processMethodCallTree(file, classInfoList);
73 | }
74 | //存储当前项目中的所有方法
75 | MethodInfoDAO methodInfoDAO = new MethodInfoDAO();
76 | methodInfoDAO.saveMethodInfoList(MethodInfoContainer.getContainer().getMethodInfoListByProjectName(projectName), conn);
77 | //存储当前项目中的所有方法调用
78 | MethodInvocationDAO.saveMethodInvocation(projectName, MethodCallContainer.getContainer().getMethodCallsByProjectName(projectName),conn);
79 | // 更新calledClassFilePath
80 | MethodInvocationDAO.updateCalledClassFilePath(projectName, conn);
81 | MethodInfoContainer.getContainer().clearMethodInfoListByProjectName(projectName);
82 | MethodCallContainer.getContainer().clearMethodCallByProjectName(projectName);
83 | System.out.println("项目中的文件数为:" + fileSize);
84 | }
85 | System.out.println("数据处理完成...");
86 | }
87 |
88 | /**
89 | * 使用JavaParser获取项目中所有的类
90 | * @param file
91 | */
92 | private void processClassInfo(File file,List classInfos){
93 | ClassVisitor visitor = new ClassVisitor(projectName,file.getPath());
94 | try{
95 | CompilationUnit cu = StaticJavaParser.parse(file);
96 | visitor.visit(cu, null);
97 | if(DataConfig.isLayerProcess){
98 | List classInfoList = visitor.getClassInfoList();
99 | for(ClassInfo classInfo : classInfoList){
100 | classInfo.setLayer(LayerVisitor.splitLayer(cu));
101 | }
102 | }
103 | }catch (Exception ex){
104 | //ex.printStackTrace();
105 | }
106 | classInfos.addAll(visitor.getClassInfoList());
107 | }
108 |
109 | /**
110 | * 使用JavaParser获取方法调用
111 | * @param file
112 | */
113 | private void processMethodCallTree(File file, List classInfoList){
114 | // MethodVisitor visitor = new MethodVisitor(projectName, classInfoList);
115 | MethodVisitor visitor = new MethodVisitor(projectName, classInfoList, file.getAbsolutePath(), this.connection);
116 | try{
117 | CompilationUnit cu = StaticJavaParser.parse(file);
118 | visitor.visit(cu, null);
119 | }catch (Exception ex){
120 | //ex.printStackTrace();
121 | }
122 | }
123 |
124 | @Override
125 | public void run() {
126 | try {
127 | List oldProjectNameList = ClassInfoDAO.getAllProjectNameFromDB(connection);
128 | List newProjectNameList = new ArrayList<>();
129 | List newFolders = new ArrayList<>();
130 | //过滤数据库中已有项目
131 | for(String folder:folders){
132 | String name = getProjectNameFromProjectPath(folder);
133 | if(!oldProjectNameList.contains(name)){
134 | newFolders.add(folder);
135 | newProjectNameList.add(name);
136 | }
137 | }
138 | this.folders = newFolders;
139 | getMethodInvocation(newProjectNameList,connection);
140 | //匹配方法调用关系
141 | FilterMethodInvocation.doFilter(this.connection,newProjectNameList);
142 | //根据配置信息决定是否需要统计调用次数和调用深度
143 | if(DataConfig.analyseInvocationCounts){
144 | CountInvocation.countInvokeCounts(newProjectNameList,this.connection);
145 | }
146 | } catch (SQLException e) {
147 | e.printStackTrace();
148 | }
149 | }
150 | }
--------------------------------------------------------------------------------
/src/main/java/com/se/process/GetMethodInvocationPlus.java:
--------------------------------------------------------------------------------
1 | package com.se.process;
2 |
3 | import com.github.javaparser.StaticJavaParser;
4 | import com.github.javaparser.ast.CompilationUnit;
5 | import com.se.DAO.ClassInfoDAO;
6 | import com.se.DAO.MethodInfoDAO;
7 | import com.se.DAO.MethodInvocationDAO;
8 | import com.se.DAO.MethodInvocationInViewDAO;
9 | import com.se.config.DataConfig;
10 | import com.se.container.MethodCallContainer;
11 | import com.se.container.MethodInfoContainer;
12 | import com.se.entity.ClassInfo;
13 | import com.se.entity.MethodInfo;
14 | import com.se.entity.MethodInvocation;
15 | import com.se.entity.MethodInvocationInView;
16 | import com.se.visitors.ClassVisitor;
17 | import com.se.visitors.MethodVisitor;
18 |
19 | import java.io.File;
20 | import java.sql.Connection;
21 | import java.sql.SQLException;
22 | import java.util.ArrayList;
23 | import java.util.List;
24 | import java.util.Map;
25 | import java.util.stream.Collectors;
26 |
27 | public class GetMethodInvocationPlus implements Runnable {
28 |
29 | private String projectName;
30 | private Connection connection;
31 | private List projectFolders; //用于增量扫描的项目根目录List
32 | private Map> modifiedFileMap; //项目中修改的文件路径
33 | private Map deletedID2ClassNameMap; // key: ClassInfoID value: ClassName
34 | private Map className2IDMap; // key: ClassName value: ClassInfoID
35 |
36 | /**
37 | *
38 | * @param projectFolders 用于增量扫描的项目根目录List
39 | * @param modifiedFileMap key:项目根目录 value:修改的文件路径List
40 | * @param connection
41 | */
42 | public GetMethodInvocationPlus(List projectFolders, Map> modifiedFileMap, Connection connection){
43 | this.projectFolders = projectFolders;
44 | this.modifiedFileMap = modifiedFileMap;
45 | this.connection = connection;
46 | }
47 |
48 | private static String getProjectNameFromProjectPath(String projectPath) {
49 | return new File(projectPath).getName();
50 | }
51 |
52 | /**
53 | * 处理删除的文件
54 | * @param projectName
55 | * @param deleteFilePaths
56 | * @param conn
57 | * @return list中存储 被调用方法 来自 被删除类 的 方法调用
58 | * @throws SQLException
59 | */
60 | public List processDeletedFile(String projectName, List deleteFilePaths, Connection conn) throws SQLException{
61 | //获取要被删除的ClassInfo(ID, className)
62 | long time0 = System.currentTimeMillis();
63 |
64 | List deleteClassInfos = new ArrayList<>();
65 | List deleteClassNames = new ArrayList<>();
66 | // deletedID2ClassNameMap = new HashMap<>();
67 | List allClassInfoList = ClassInfoDAO.getClassListByProjectName(projectName, conn);
68 | for(ClassInfo classInfo : allClassInfoList){
69 | if(deleteFilePaths.contains(classInfo.getFilePath())){
70 | deleteClassInfos.add(classInfo.getID());
71 | deleteClassNames.add(classInfo.getClassName());
72 | // deletedID2ClassNameMap.put(classInfo.getID(), classInfo.getClassName());
73 | }
74 | }
75 | allClassInfoList.clear();
76 |
77 | //获取要被删除的MethodInfo(ID)、MethodInvocationInfo(ID)和MethodInvocationInfoInView(ID)
78 | List deleteMethodIDs = new ArrayList<>();
79 | List allMethodInfoList = MethodInfoDAO.getMethodInfoListByProjectName(projectName, conn);
80 | for(MethodInfo methodInfo : allMethodInfoList){
81 | if(deleteClassNames.contains(methodInfo.getClassName())){
82 | deleteMethodIDs.add(methodInfo.getID());
83 | }
84 | }
85 | allMethodInfoList.clear();
86 |
87 |
88 | List deleteMethodInvocationIDs = new ArrayList<>();
89 | List methodInvocationWithDeletedClass = new ArrayList<>(); // list中存储 被调用方法 来自 被删除类 的 方法调用
90 | List allMethodInvocationList = MethodInvocationDAO.getMethodInvocationByProjectName(projectName,conn);
91 | for(MethodInvocation methodInvocation : allMethodInvocationList){
92 | if(deleteClassNames.contains(methodInvocation.getCallClassName())){
93 | deleteMethodInvocationIDs.add(methodInvocation.getID());
94 | } else if (deleteClassNames.contains(methodInvocation.getCalledClassName())){
95 | methodInvocationWithDeletedClass.add(methodInvocation);
96 | }
97 | }
98 | allMethodInvocationList.clear();
99 |
100 |
101 | List deleteMethodInvocationInViewIDs = new ArrayList<>();
102 | List allMethodInvocationInViewList = MethodInvocationInViewDAO.getMethodInvocationInViewByProjectName(projectName,conn);
103 |
104 | for(MethodInvocationInView methodInvocationInView : allMethodInvocationInViewList){
105 | // 作为调用类或者被调用类都要删除
106 | if(deleteClassNames.contains(methodInvocationInView.getCallClassName()) || deleteClassNames.contains(methodInvocationInView.getCalledClassName())){
107 | deleteMethodInvocationInViewIDs.add(methodInvocationInView.getID());
108 | }
109 | }
110 |
111 | //根据list中的ID进行删除
112 | ClassInfoDAO.deleteClassInfoRecords(deleteClassInfos, conn);
113 |
114 | MethodInfoDAO.deleteMethodInfoRecords(deleteMethodIDs, conn);
115 |
116 | MethodInvocationDAO.deleteMethodInvocationInfoRecords(deleteMethodInvocationIDs, conn);
117 |
118 | // 更新calledClassFilePath
119 | MethodInvocationDAO.updateCalledClassFilePath(projectName, conn);
120 |
121 | MethodInvocationInViewDAO.deleteMethodInvocationInViewRecords(deleteMethodInvocationInViewIDs, conn);
122 |
123 | return methodInvocationWithDeletedClass;
124 | }
125 |
126 | /**
127 | * 处理新增的文件
128 | * @param projectName
129 | * @param addedFilePaths
130 | * @param conn
131 | * @throws SQLException
132 | */
133 | public void processAddedFile(String projectName, List addedFilePaths, Connection conn) throws SQLException{
134 | List addedClassInfosContainer = new ArrayList<>();
135 | for(String filePath : addedFilePaths){
136 | File file = new File(filePath);
137 | //获取新增文件的class info
138 | if(file.exists())
139 | processClassInfo(file, addedClassInfosContainer);
140 | }
141 | //存储新增文件中的类
142 | ClassInfoDAO.saveClassInfoList(addedClassInfosContainer, conn);
143 | //从db中获取该项中的所有类
144 | List classInfoList = ClassInfoDAO.getAllClassInfoList(projectName, conn);
145 | for(String filePath : addedFilePaths){
146 | File file = new File(filePath);
147 | //获取新增文件的method info
148 | if(file.exists())
149 | processMethodCallTree(file, classInfoList);
150 | }
151 | //存储当前项目中的所有方法
152 | MethodInfoDAO methodInfoDAO = new MethodInfoDAO();
153 | methodInfoDAO.saveMethodInfoList(MethodInfoContainer.getContainer().getMethodInfoListByProjectName(projectName), conn);
154 | //存储当前项目中的所有方法调用
155 | MethodInvocationDAO.saveMethodInvocation(projectName, MethodCallContainer.getContainer().getMethodCallsByProjectName(projectName),conn);
156 | }
157 |
158 |
159 | /**
160 | * 处理修改的文件
161 | * @param projectName
162 | * @param modifiedFilePaths
163 | * @param conn
164 | * @throws SQLException
165 | */
166 | public void processModifiedFile(String projectName, List modifiedFilePaths, Connection conn) throws SQLException {
167 |
168 | List methodInvocationWithDeletedClass = processDeletedFile(projectName, modifiedFilePaths, conn);
169 |
170 | processAddedFile(projectName, modifiedFilePaths, conn);
171 |
172 | // 通过重新插入的方式更新methodinvocationinview表里的calledClassID和calledMethodID
173 | FilterMethodInvocation.doFilterPlus(projectName, methodInvocationWithDeletedClass, conn);
174 | }
175 |
176 | /**
177 | * 使用JavaParser获取项目中所有的类
178 | * @param file
179 | */
180 | private void processClassInfo(File file,List classInfos){
181 | ClassVisitor visitor = new ClassVisitor(projectName,file.getPath());
182 | try{
183 | CompilationUnit cu = StaticJavaParser.parse(file);
184 | visitor.visit(cu, null);
185 | }catch (Exception ex){
186 | //ex.printStackTrace();
187 | }
188 | classInfos.addAll(visitor.getClassInfoList());
189 | }
190 |
191 | /**
192 | * 使用JavaParser获取方法调用
193 | * @param file
194 | */
195 | private void processMethodCallTree(File file, List classInfoList){
196 | // MethodVisitor visitor = new MethodVisitor(projectName, classInfoList);
197 | MethodVisitor visitor = new MethodVisitor(projectName, classInfoList, file.getAbsolutePath(), this.connection);
198 | try{
199 | CompilationUnit cu = StaticJavaParser.parse(file);
200 | visitor.visit(cu, null);
201 | }catch (Exception ex){
202 | //ex.printStackTrace();
203 | }
204 | }
205 |
206 | @Override
207 | public void run() {
208 | try{
209 | //对所有修改文件进行方法调用处理
210 | for (Map.Entry> entry : modifiedFileMap.entrySet()) {
211 | String projectRootPath = entry.getKey();
212 | List modifiedFilePaths = this.modifiedFileMap.get(projectRootPath);
213 | projectName = getProjectNameFromProjectPath(projectRootPath);
214 |
215 | if(modifiedFilePaths == null || modifiedFilePaths.isEmpty()) continue;
216 | processModifiedFile(projectName, modifiedFilePaths, this.connection);
217 | }
218 |
219 | //将项目根目录list转化为项目名list
220 | List projectNames = projectFolders.stream()
221 | .map(GetMethodInvocationPlus::getProjectNameFromProjectPath)
222 | .collect(Collectors.toList());
223 |
224 | //匹配方法调用关系
225 | // FilterMethodInvocation.doFilterX(this.connection, projectNames, true);
226 | for(String currentProjectName : projectNames){
227 | List methodInvocationList = MethodInvocationDAO.getMethodInvocationByProjectNameAndDate(projectName, this.connection);
228 | FilterMethodInvocation.doFilterPlus(currentProjectName, methodInvocationList, this.connection);
229 | }
230 |
231 | //根据配置信息决定是否需要统计调用次数和调用深度
232 | if(DataConfig.analyseInvocationCounts){
233 | CountInvocation.countInvokeCounts(projectNames,this.connection);
234 | }
235 | } catch (SQLException throwables) {
236 | throwables.printStackTrace();
237 | }
238 |
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/src/main/java/com/se/process/GodClassProcess.java:
--------------------------------------------------------------------------------
1 | package com.se.process;
2 | import com.github.javaparser.ParseException;
3 | import com.github.javaparser.StaticJavaParser;
4 | import com.github.javaparser.ast.CompilationUnit;
5 | import com.se.DAO.BuildConnection;
6 | import com.se.DAO.ClassInfoDAO;
7 | import com.se.config.DataConfig;
8 | import com.se.godclass.GodClassCalculator;
9 | import com.se.utils.FileHelper;
10 |
11 | import java.io.File;
12 | import java.io.FileInputStream;
13 | import java.io.FileNotFoundException;
14 | import java.sql.Connection;
15 | import java.sql.SQLException;
16 | import java.util.*;
17 |
18 | public class GodClassProcess {
19 |
20 | private static Map> godClassInProjectMap = new HashMap<>();
21 | private static String currentProjectName;
22 | private static int count = 0;
23 |
24 | public static void calculate(String filePath) {
25 |
26 | GodClassCalculator calculator = new GodClassCalculator(
27 | GodClassCalculator.DEFAULT_WMC_LIMIT,
28 | GodClassCalculator.DEFAULT_MCC_LIMIT,
29 | GodClassCalculator.DEFAULT_TCC_LIMIT,
30 | GodClassCalculator.DEFAULT_ATFD_LIMIT);
31 |
32 | // System.out.println("* MCCCalculatorTest: testCalculate()");
33 |
34 | try {
35 | File fileMCC = new File(filePath);
36 |
37 | FileInputStream in = new FileInputStream(fileMCC);
38 | CompilationUnit cu;
39 |
40 | // Parse the file
41 | cu = StaticJavaParser.parse(in);
42 |
43 | calculator.calculate(cu);
44 |
45 |
46 | System.out.println("ATFD:" + calculator.getATFD());
47 | System.out.println("WMC:" + calculator.getWMC());
48 | System.out.println("MCC:" + calculator.getMCC());
49 | System.out.println("TCC:" + calculator.getTCC());
50 | System.out.println("is God Class:" + calculator.isGodClass());
51 |
52 | if(calculator.isGodClass()) {
53 | godClassInProjectMap.computeIfAbsent(currentProjectName, k -> new ArrayList<>()).add(filePath);
54 | count++;
55 | }
56 |
57 |
58 | } catch (FileNotFoundException ex) {
59 | System.out.println(filePath);
60 | System.out.println("MCCCalculatorTest : " + ex.getMessage());
61 | }
62 | }
63 |
64 | public static void main(String[] args) throws SQLException {
65 |
66 | File dir = new File(DataConfig.sourceProjectParentPath);
67 | LinkedList folders = new LinkedList<>();
68 | FileHelper.getFolders(dir,folders);
69 |
70 | for(String projectRootPath : folders){
71 | currentProjectName = new File(projectRootPath).getName();
72 | for (String filePath : FileHelper.getSubFile(projectRootPath, "java")) {
73 | calculate(filePath);
74 | }
75 | }
76 |
77 | FileHelper.writeFile(DataConfig.godClassOutputFilePath, godClassInProjectMap);
78 | BuildConnection buildConnection = new BuildConnection();
79 | Connection connection = buildConnection.buildConnect();
80 | for(List classPathList:godClassInProjectMap.values()){
81 | ClassInfoDAO.updateGodClass(classPathList,connection);
82 | }
83 | System.out.println("god class count:"+count);
84 |
85 | }
86 |
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/com/se/process/Process.java:
--------------------------------------------------------------------------------
1 | package com.se.process;
2 |
3 | import com.se.DAO.BuildConnection;
4 | import com.se.config.DataConfig;
5 | import com.se.utils.FileHandler;
6 | import com.se.utils.FileHelper;
7 | import com.se.utils.ListUtils;
8 | import com.se.utils.TimeUtil;
9 |
10 | import java.io.File;
11 | import java.sql.Connection;
12 | import java.util.*;
13 | import java.util.concurrent.ExecutorService;
14 | import java.util.concurrent.Executors;
15 | import java.util.stream.Collectors;
16 |
17 | public class Process {
18 |
19 | //线程数量
20 | private static int threadNum = 1;
21 |
22 | public static void main(String[] args){
23 | Map> allModifiedFileMap = new HashMap<>();
24 | //建立数据库连接
25 | BuildConnection buildConnection = new BuildConnection();
26 | ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
27 | if(!DataConfig.analyseSingleProject){
28 | LinkedList folders = new LinkedList<>();
29 | File dir = new File(DataConfig.sourceProjectParentPath);
30 | FileHandler.getFolders(dir,folders);
31 | System.out.println("项目数为:"+folders.size());
32 | List> folderList = ListUtils.divideList(folders,threadNum);
33 | if(DataConfig.isAdditionalProcess)
34 | allModifiedFileMap = prepareModifiedFileMap(DataConfig.modifiedFilePath, folders);
35 | //分析源项目代码,抽取需要的信息
36 | for(int i = 0;i> modifiedFileMap = new HashMap<>();
40 | for(String projectRootPath : folderList.get(i)){
41 | modifiedFileMap.put(projectRootPath, allModifiedFileMap.get(projectRootPath));
42 | }
43 | cachedThreadPool.execute(new GetMethodInvocationPlus(folderList.get(i), modifiedFileMap, conn));
44 | } else {
45 | cachedThreadPool.execute(new GetMethodInvocation(folderList.get(i),conn));
46 | }
47 | }
48 | cachedThreadPool.shutdown();
49 | }else {
50 | System.out.println("对单个项目进行分析");
51 | LinkedList folders = new LinkedList<>();
52 | folders.add(DataConfig.sourceProjectPath);
53 | Connection conn = buildConnection.buildConnect();
54 | if(DataConfig.isAdditionalProcess){
55 | allModifiedFileMap = prepareModifiedFileMap(DataConfig.modifiedFilePath, folders);
56 | cachedThreadPool.execute(new GetMethodInvocationPlus(folders, allModifiedFileMap, conn));
57 | } else {
58 | cachedThreadPool.execute(new GetMethodInvocation(folders,conn));
59 | }
60 | cachedThreadPool.shutdown();
61 | }
62 | }
63 |
64 |
65 | public static Map> prepareModifiedFileMap(String txtFilePath, LinkedList folders){
66 | //从txt文件中读取修改过的文件列表
67 | List modifiedFileList = FileHelper.readFile(txtFilePath);
68 | //过滤非java文件和测试文件
69 | modifiedFileList = modifiedFileList.stream()
70 | .filter(f -> f.endsWith(".java") && !f.contains("\\test"))
71 | .collect(Collectors.toList());
72 |
73 | //将文件列表映射到项目根路径
74 | Map> modifiedFileMap = new HashMap<>();
75 | for(String projectRootPath : folders){
76 | List filePathInProject = modifiedFileList.stream()
77 | .filter(filePath -> filePath.startsWith(projectRootPath))
78 | .collect(Collectors.toList());
79 | modifiedFileMap.put(projectRootPath, filePathInProject);
80 | }
81 |
82 | //检查txt中是否有未被加入到map的路径
83 | List filteredFilePaths = new ArrayList<>();
84 | for (Map.Entry> entry : modifiedFileMap.entrySet()) {
85 | filteredFilePaths.addAll(entry.getValue());
86 | }
87 | modifiedFileList.removeAll(filteredFilePaths);
88 | if(modifiedFileList.size() > 0){
89 | System.out.println("无法处理以下新增文件,请检查文件路径是否正确:");
90 | modifiedFileList.forEach(System.out::println);
91 | }
92 | return modifiedFileMap;
93 | }
94 |
95 | }
--------------------------------------------------------------------------------
/src/main/java/com/se/process/StructureDetect.java:
--------------------------------------------------------------------------------
1 | package com.se.process;
2 |
3 | import com.github.javaparser.StaticJavaParser;
4 | import com.github.javaparser.ast.CompilationUnit;
5 | import com.se.config.DataConfig;
6 | import com.se.utils.FileUtils;
7 | import com.se.visitors.ClassVisitor;
8 |
9 | import java.io.File;
10 | import java.io.FileNotFoundException;
11 | import java.util.ArrayList;
12 | import java.util.HashMap;
13 | import java.util.List;
14 | import java.util.Map;
15 |
16 | import static com.se.config.DataConfig.layer_dao;
17 |
18 | /**
19 | * Created by zhangyue on 2020/11/11
20 | */
21 | public class StructureDetect {
22 |
23 | public static Map javaPathOfDao = null;
24 | public static Map javaPathOfServiceImpl = null;
25 | public static Map javaPathOfController = null;
26 | public static Map javaPathOfService = null;
27 |
28 |
29 | public static Map classNameOfDao = null;
30 | public static Map classNameOfServiceImpl = null;
31 | public static Map classNameOfController = null;
32 | public static Map classNameOfService = null;
33 |
34 | public static void main(String[] args) throws FileNotFoundException {
35 | FileUtils.clearInfoForFile(DataConfig.structDetectResult);
36 | init();
37 | int count=0;
38 |
39 | //dao中调用service、controller
40 | judge(javaPathOfDao,classNameOfService,classNameOfController,count);
41 |
42 | //service中调用controller
43 | judge(javaPathOfService,classNameOfController,new HashMap<>(),count);
44 |
45 | //serviceImpl中调用controller
46 | judge(javaPathOfServiceImpl,classNameOfController,new HashMap<>(),count);
47 |
48 | //controller中调用dao
49 | judge(javaPathOfController,classNameOfDao,new HashMap<>(),count);
50 |
51 | if (count>0){
52 | // System.out.println("该项目不存在违背MVC设计模式的情况......");
53 | String out = "该项目不存在违背MVC设计模式的情况......";
54 | List list=new ArrayList<>();
55 | list.add(out);
56 | FileUtils.write(DataConfig.structDetectResult,list);
57 | }
58 | }
59 |
60 | public static void init(){
61 | //这里项目路径后面加src是因为target等包中也有dao等文件夹,这样先遍历到target就会返回错误结果
62 | javaPathOfDao= FileUtils.getJavaFilePath(DataConfig.projectPath +"/src",layer_dao);
63 | javaPathOfServiceImpl= FileUtils.getJavaFilePath(DataConfig.projectPath+"/src",DataConfig.layer_serviceImpl);
64 | javaPathOfController= FileUtils.getJavaFilePath(DataConfig.projectPath+"/src",DataConfig.layer_controller);
65 | javaPathOfService= FileUtils.getJavaFilePath(DataConfig.projectPath+"/src",DataConfig.layer_service);
66 |
67 | classNameOfDao = FileUtils.getAllClassName(javaPathOfDao);
68 | classNameOfServiceImpl = FileUtils.getAllClassName(javaPathOfServiceImpl);
69 | classNameOfController = FileUtils.getAllClassName(javaPathOfController);
70 | classNameOfService = FileUtils.getAllClassName(javaPathOfService);
71 | }
72 |
73 |
74 | /**
75 | * 使用JavaParser获取一个类中的所有字段以及所属类型
76 | * @param path Java文件路径
77 | * @return
78 | * @throws FileNotFoundException
79 | */
80 | public static Map getClassNameBypath(String path) throws FileNotFoundException {
81 | ClassVisitor visitor=new ClassVisitor(DataConfig.projectName,path);
82 | File file = new File(path);
83 | CompilationUnit cu = StaticJavaParser.parse(file);
84 | visitor.visit(cu,null);
85 | return visitor.getFieldMap();
86 | }
87 |
88 |
89 | /**
90 | * 判断是否存在违规并输出.
91 | * eg:(pathMap->dao下的Java文件,classname1->service下的类,classname2->controller下的类)--->dao里调用service、controller的情况
92 | * @param pathMap 待检测的某一包下的Java文件列表
93 | * @param classname1 违规调用类1参考
94 | * @param classname2 违规调用类2参考
95 | * @param count 计数多少次违反MVC设计模式
96 | * @throws FileNotFoundException
97 | */
98 | public static void judge(Map pathMap,Map classname1,Map classname2,int count) throws FileNotFoundException {
99 |
100 | for (Map.Entry entry : pathMap.entrySet()){
101 | Map map = getClassNameBypath(entry.getKey().toString());
102 | for (Map.Entry entry1 : map.entrySet()){
103 | if (classname1.get(entry1.getValue())!=null||classname2.get(entry1.getValue())!=null){
104 | List list=new ArrayList<>();
105 | ++count;
106 | System.out.println("存在类违背MVC设计架构......");
107 | String out = "存在类违背MVC设计架构......";
108 | list.add(out);
109 | //FileUtils.write(DataConfig.structDetectResult,"存在类违背MVC设计架构......");
110 | if (classname1.get(entry1.getValue())!=null){
111 | String out1 = "在" + entry.getValue() + "中调用了" + classname1.get(entry1.getValue());
112 | list.add(out1);
113 | System.out.println("在" + entry.getValue() + "中调用了" + classname1.get(entry1.getValue()) + "中的" + entry1.getValue());
114 | //FileUtils.write(DataConfig.structDetectResult,out1);
115 | }
116 | if (classname2.get(entry1.getValue())!=null){
117 | System.out.println("在" + entry.getValue() + "中调用了" + classname2.get(entry1.getValue()) + "中的" + entry1.getValue());
118 | String out1 = "在" + entry.getValue() + "中调用了" + classname2.get(entry1.getValue()) + "中的" + entry1.getValue();
119 | list.add(out1);
120 | //FileUtils.write(DataConfig.structDetectResult,out1);
121 | }
122 | System.out.println("该类的路径为:" + entry.getKey());
123 | String out2 = "该类的路径为:" + entry.getKey();
124 | list.add(out2);
125 | System.out.print("该语句为:" + entry1.getValue() + " " + entry1.getKey());
126 | String out3 = "该语句为:" + entry1.getValue() + " " + entry1.getKey();
127 | list.add(out3);
128 | System.out.println("\n");
129 | String out4 = "\n";
130 | list.add(out4);
131 | FileUtils.write(DataConfig.structDetectResult,list);
132 |
133 |
134 |
135 | }
136 | }
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/CalculateUtil.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | public class CalculateUtil {
4 |
5 | private static double rateThreshold = 1.5;
6 |
7 | public static boolean CalCouplingRate(int invokeCounts, int invokedCounts){
8 | double invoke,invoked;
9 | if(invokeCounts == 0){
10 | invoke = 0.1;
11 | }else {
12 | invoke = invokeCounts;
13 | }
14 | if(invokedCounts == 0){
15 | invoked = 0.1;
16 | }else {
17 | invoked = invokedCounts;
18 | }
19 | double rate = invoked/invoke;
20 | return rate > rateThreshold;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/ExtensionFileFilter.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import java.io.File;
4 | import java.io.FileFilter;
5 |
6 | class ExtensionFileFilter implements FileFilter {
7 | private String acceptedExtension;
8 |
9 | ExtensionFileFilter(String acceptedExtension)
10 | {
11 | this.acceptedExtension = acceptedExtension;
12 | }
13 |
14 | public boolean accept(File pathname)
15 | {
16 | return pathname.getName().endsWith(acceptedExtension)
17 | || pathname.isDirectory();
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/FileHandler.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.util.LinkedList;
8 | import java.util.Scanner;
9 |
10 | public class FileHandler {
11 |
12 | public FileHandler() {
13 | }
14 |
15 | public static String getSourceCode(String filepath){
16 | StringBuilder sc = new StringBuilder();
17 | try {
18 | BufferedReader reader = new BufferedReader(new FileReader(filepath));
19 | Scanner scanner = new Scanner(reader);
20 | while(scanner.hasNextLine()){
21 | sc.append(scanner.nextLine());
22 | }
23 | scanner.close();
24 | reader.close();
25 | } catch (IOException e) {
26 | e.printStackTrace();
27 | }
28 | return sc.toString();
29 | }
30 |
31 | public static LinkedList getFilePaths(String pathsDir) {
32 | LinkedList paths = new LinkedList<>();
33 | try {
34 | BufferedReader reader = null;
35 | reader = new BufferedReader(new FileReader(pathsDir));
36 |
37 | Scanner scanner = new Scanner(reader);
38 | while (scanner.hasNextLine()){
39 | paths.addLast(scanner.nextLine());
40 | }
41 |
42 | scanner.close();
43 | reader.close();
44 | } catch (IOException e) {
45 | e.printStackTrace();
46 | }
47 | return paths;
48 | }
49 |
50 | public static void getFilePaths(File file,LinkedList files) {
51 | if(file.isDirectory() && file.listFiles() != null){
52 | File[] fs = file.listFiles();
53 | for (File f : fs){
54 | getFilePaths(f, files);
55 | }
56 | }
57 | else if(file.isFile() && file.getPath().endsWith(".java")){
58 | files.addLast(file.getPath());
59 | }
60 | }
61 |
62 | public static File getFile(String path) {
63 | return new File(path);
64 | }
65 |
66 | // public static void getFolders(File file,LinkedList files)
67 | // {
68 | // File[] fs = file.listFiles();
69 | // for(File f:fs)
70 | // {
71 | // if(file.isDirectory()&&file.listFiles()!=null)
72 | // {
73 | // files.addLast(f.getPath());
74 | // }
75 | // }
76 | // }
77 | public static void getFolders(File file,LinkedList files)
78 | {
79 | File[] fs = file.listFiles();
80 | for(File f: fs)
81 | {
82 | if(f.isDirectory()&&f.listFiles()!=null)
83 | {
84 | files.addLast(f.getPath());
85 | }
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/FileHelper.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import com.se.config.DataConfig;
4 | import com.se.entity.MeasureIndex;
5 |
6 | import java.io.*;
7 | import java.util.*;
8 |
9 | public class FileHelper {
10 |
11 | public static String NewLine = System.getProperty("line.separator");
12 | private static String PNG = "png";
13 | private List getSubFile(String path, FileFilter filter)
14 | {
15 | List result = new ArrayList();
16 | File file = new File(path);
17 | if( file.isDirectory())
18 | {
19 | for(File subFile :file.listFiles(filter))
20 | {
21 | result.addAll(getSubFile(subFile.getAbsolutePath(), filter));
22 | }
23 | }
24 | else
25 | {
26 | result.add(file.getAbsolutePath());
27 | }
28 | return result;
29 |
30 | }
31 | /**
32 | * 在文件夹中,获取所有指定后缀后的文件
33 | * @param path
34 | * @param extension
35 | * @return
36 | */
37 | public static List getSubFile(String path, String extension)
38 | {
39 | FileFilter fileFilter = new ExtensionFileFilter(extension);
40 | FileHelper fileHelper = new FileHelper();
41 | return fileHelper.getSubFile(path, fileFilter);
42 | }
43 |
44 | public static Map readProjectClone(String filePath){
45 | Map cloneMap = new HashMap<>();
46 | File csv = new File(filePath);
47 | BufferedReader br = null;
48 | try {
49 | br = new BufferedReader(new FileReader(csv));
50 | } catch (FileNotFoundException e) {
51 | e.printStackTrace();
52 | }
53 | String line = "";
54 | try {
55 | while ((line = br.readLine()) != null) // 读取到的内容给line变量
56 | {
57 | String[] content = line.split(",");
58 | for(int i =0;i> readCloneGroupToList(String cloneGroupFilePath) throws IOException {
70 | List> cloneGroupList = new ArrayList<>();
71 | File file = new File(cloneGroupFilePath);
72 | FileReader fileReader = new FileReader(file);
73 | BufferedReader bufferedReader = new BufferedReader(fileReader);
74 | String line = "";
75 | while((line = bufferedReader.readLine())!=null){
76 | List list = new ArrayList<>();
77 | String[] cloneGroup = line.split(",");
78 | for(String str:cloneGroup){
79 | list.add(Integer.valueOf(str));
80 | }
81 | cloneGroupList.add(list);
82 | }
83 | return cloneGroupList;
84 | }
85 |
86 | public static Map> readMeasureIndex(String measureIndexPath) throws IOException {
87 | Map> measureMap = new HashMap<>();
88 | File file = new File(measureIndexPath);
89 | FileReader fileReader = new FileReader(file);
90 | BufferedReader bufferedReader = new BufferedReader(fileReader);
91 | String line = "";
92 | while((line = bufferedReader.readLine())!=null){
93 | String[] strings = line.split(",");
94 | int id = Integer.parseInt(strings[0]);
95 | String filePath = strings[1];
96 | int beginLine = Integer.parseInt(strings[2]);
97 | int endLine = Integer.parseInt(strings[3]);
98 | MeasureIndex measureIndex;
99 | if(DataConfig.analyseSingleProject){
100 | measureIndex = new MeasureIndex(id,filePath,beginLine,endLine,DataConfig.sourceProjectPath);
101 | }else {
102 | measureIndex = new MeasureIndex(id,filePath,beginLine,endLine,DataConfig.sourceProjectParentPath);
103 | }
104 | List list = measureMap.getOrDefault(measureIndex.getProjectName(),new ArrayList<>());
105 | list.add(measureIndex);
106 | measureMap.put(measureIndex.getProjectName(),list);
107 | }
108 | return measureMap;
109 | }
110 |
111 | public static void writeClassPathToFile(List universalClassList,String path) throws IOException {
112 | File file = new File(path);
113 | FileWriter fileWriter = new FileWriter(file);
114 | BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
115 | for(String filePath:universalClassList){
116 | bufferedWriter.write(filePath);
117 | bufferedWriter.newLine();
118 | }
119 | bufferedWriter.close();
120 | fileWriter.close();
121 | }
122 |
123 | public static void writeClassPathToFile(Map universalClassMap,String path) throws IOException {
124 | File file = new File(path);
125 | FileWriter fileWriter = new FileWriter(file);
126 | BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
127 | for(String filePath:universalClassMap.values()){
128 | bufferedWriter.write(filePath);
129 | bufferedWriter.newLine();
130 | }
131 | bufferedWriter.close();
132 | fileWriter.close();
133 | }
134 |
135 | public static List readFile(String filePath){
136 | List arrayList = new ArrayList<>();
137 | try{
138 | FileReader fr = new FileReader(filePath);
139 | BufferedReader bf = new BufferedReader(fr);
140 | String str;
141 | while((str = bf.readLine()) != null){
142 | arrayList.add(str);
143 | }
144 | bf.close();
145 | fr.close();
146 | } catch (IOException e) {
147 | e.printStackTrace();
148 | }
149 | return arrayList;
150 | }
151 |
152 |
153 | public static void getFolders(File file, LinkedList files) {
154 | File[] fs = file.listFiles();
155 | for(File f: fs) {
156 | if(f.isDirectory()&&f.listFiles()!=null)
157 | {
158 | files.addLast(f.getPath());
159 | }
160 | }
161 | }
162 |
163 |
164 | public static void writeFile(String filePath, Map> resultMap){
165 |
166 | try{
167 | File writename = new File(filePath);
168 | writename.createNewFile(); // 创建新文件
169 |
170 | BufferedWriter bw = new BufferedWriter(new FileWriter(writename));
171 |
172 | for (Map.Entry> entry : resultMap.entrySet()) {
173 | //System.out.println(entry.getKey() + ":" + entry.getValue());
174 | String projectName = entry.getKey();
175 | List godClassList = entry.getValue();
176 | bw.write(projectName + "\n");
177 | for(String godClassPath : godClassList){
178 | bw.write(godClassPath + "\n");
179 | }
180 | bw.write("\n\n\n\n");
181 | }
182 |
183 | bw.flush();
184 | bw.close();
185 |
186 | } catch (Exception e) {
187 | e.printStackTrace();
188 | }
189 | }
190 | }
191 |
192 |
193 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/FileUtils.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import java.io.*;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | /**
9 | * Created by zhangyue on 2020/11/11 1:57 下午
10 | */
11 | public class FileUtils {
12 |
13 | /**
14 | * 获得type文件夹下所有Java文件的路径
15 | * @param rootPath 根路径
16 | * @param type 目标文件夹,如controller、serviceImpl、dao等
17 | * @return map<类路径,该类所属的层次,比如dao、controller>
18 | */
19 | public static Map getJavaFilePath(String rootPath,String type){
20 | Map map=new HashMap<>();
21 | File rootFile=new File(rootPath);
22 | if (rootFile.exists()&&rootFile.isDirectory()){
23 | File[] files=rootFile.listFiles();
24 | if (rootFile.getName().equals(type)){
25 | if (files!=null){
26 | for (File file:files){
27 | if (!file.isDirectory()){
28 | if (file.getName().endsWith(".java")){
29 | map.put(file.getAbsolutePath(),type);
30 | }
31 | }
32 | }
33 | return map;
34 | }
35 | }else {
36 | if (files!=null){
37 | for (File file:files){
38 | if (file.isDirectory()){
39 | map=getJavaFilePath(file.getAbsolutePath(),type);
40 | if (map!=null){
41 | return map;
42 | }
43 | }
44 | }
45 | }
46 | }
47 | }
48 | return null;
49 | }
50 |
51 | /**
52 | * 由java路径List获取classname的map
53 | * @param map <类路径,该类所属的层次,比如dao、controller>
54 | * @return map<类名,该类所属的层次,比如dao、controller>
55 | */
56 | public static Map getAllClassName(Map map){
57 | Map stringMap=new HashMap<>();
58 | if (map!=null){
59 | for (Map.Entry path:map.entrySet()){
60 | //获取 xxx.java
61 | String[] tempList= path.getKey().toString().split("/");
62 | //获取类名,分割xxx.java
63 | String javapath=tempList[tempList.length-1];
64 | String[] tempList1=javapath.split("\\.");
65 | stringMap.put(tempList1[0],path.getValue().toString());
66 | }
67 | }
68 | return stringMap;
69 | }
70 |
71 | public static void write(String path, List text) {
72 | try {
73 | File file = new File(path);
74 | FileOutputStream fos = null;
75 | if (!file.exists()) {//判断文件是否存在,如果不存在就新建文件
76 | file.createNewFile();
77 | fos = new FileOutputStream(file);
78 | } else {
79 | fos = new FileOutputStream(file, true);//如果文件已经存在,就直接在文件末尾添加新的信息
80 | }
81 | OutputStreamWriter osw = new OutputStreamWriter(fos);
82 | for (String s : text) {
83 | osw.write(s + "\n");
84 | }
85 | osw.close();
86 | } catch (Exception e) {
87 | System.out.println(e);
88 | }
89 | }
90 |
91 | public static void clearInfoForFile(String fileName) {
92 | File file =new File(fileName);
93 | try {
94 | if(!file.exists()) {
95 | return;
96 | }
97 | FileWriter fileWriter =new FileWriter(file);
98 | fileWriter.write("");
99 | fileWriter.flush();
100 | fileWriter.close();
101 | } catch (IOException e) {
102 | e.printStackTrace();
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/GodClassUtils.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 |
4 |
5 | public class GodClassUtils {
6 |
7 | //使用WMC, TCC, ATFD这三个指标进行判断一个类是否为God Class
8 | private final int veryHigh = 47;
9 | private final int few = 5;
10 | private final double calRate = 0.33;
11 | //类的圈复杂度
12 | private double WMC;
13 | //类中通过访问相同属性而发生连接的方法对的个数
14 | private double TCC;
15 | //被检测类所访问的外部类属性的个数
16 | private double ATFD;
17 |
18 |
19 | public double getWMC() {
20 | return WMC;
21 | }
22 |
23 | public void setWMC(double WMC) {
24 | this.WMC = WMC;
25 | }
26 |
27 | public double getTCC() {
28 | return TCC;
29 | }
30 |
31 | public void setTCC(double TCC) {
32 | this.TCC = TCC;
33 | }
34 |
35 | public double getATFD() {
36 | return ATFD;
37 | }
38 |
39 | public void setATFD(double ATFD) {
40 | this.ATFD = ATFD;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/ListUtils.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class ListUtils {
7 |
8 | //将一个list中的元素平均分为n组
9 | public static List> divideList(List list,int n){
10 | if(list == null||list.size() == 0||n<=0)return null;
11 | int size = list.size();
12 | List> result = new ArrayList<>();
13 | int remainder = size%n;
14 | int divide = size/n;
15 | int offset = 0;
16 | for(int i =0;i value;
18 | if(remainder>0){
19 | value = list.subList(i*divide + offset,(i+1)*divide+ offset +1);
20 | remainder--;
21 | offset++;
22 | }else {
23 | value = list.subList(i*divide + offset,(i+1)*divide+ offset);
24 | }
25 | result.add(value);
26 | }
27 | return result;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/MethodUtils.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import com.se.config.DataConfig;
4 | import java.io.File;
5 |
6 | public class MethodUtils {
7 |
8 | private static final String API_DOC_PATH = DataConfig.API_DOC_PATH;
9 | private static final String JAVA_LANG_DOC_PATH = DataConfig.JAVA_LANG_DOC_PATH;
10 | private static String[] basicType = {"byte","short","int","long","float","double","boolean","char"};
11 |
12 |
13 | public static boolean isJDKMethod(String className) {
14 | //? java.lang.StringBuilder ??? java/lang/StringBuilder
15 | className = className.replaceAll("\\.", "/");
16 | className = className.replaceAll("\\$", ".");
17 | String fileName = API_DOC_PATH + className + ".html";
18 | File file = new File(fileName);
19 | return file.exists();
20 | }
21 |
22 | public static boolean isJavaLang(String className) {
23 | if(className.contains("[]"))className = className.substring(0,className.indexOf('['));
24 | String newName;
25 | if(className.contains(".")){
26 | newName = className.substring(className.lastIndexOf('.')+1);
27 | }else {
28 | newName = className;
29 | }
30 | //System.out.println(newName);
31 | String fileName1 = JAVA_LANG_DOC_PATH + newName + ".html";
32 | File file1 = new File(fileName1);
33 | if(file1.exists()){
34 | return true;
35 | }else {
36 | className = className.replaceAll("\\.", "/");
37 | className = className.replaceAll("\\$", ".");
38 | String fileName2 = JAVA_LANG_DOC_PATH + className + ".html";
39 | File file2 = new File(fileName2);
40 | return file2.exists();
41 | }
42 | }
43 |
44 |
45 | public static boolean isJavaBasicType(String classname){
46 | if(classname.contains("[]"))classname = classname.substring(0,classname.indexOf('['));
47 | for(String type : basicType){
48 | if(classname.equals(type))return true;
49 | }
50 | return false;
51 | }
52 |
53 | public static String basicToLange(String name){
54 | switch (name){
55 | case "int":
56 | return "Integer";
57 | case "byte":
58 | return "Byte";
59 | case "short":
60 | return "Short";
61 | case "long":
62 | return "Long";
63 | case "float":
64 | return "Float";
65 | case "double":
66 | return "Double";
67 | case "char":
68 | return "Character";
69 | case "boolean" :
70 | return "Boolean";
71 | default:
72 | return "False";
73 | }
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/Pair.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import java.util.Objects;
4 |
5 | public class Pair {
6 | protected final F first; // pair中的第一个元素
7 | protected final S second; // pair中的第二个元素
8 |
9 | public static Pair create(A a, B b)
10 | {
11 | return new Pair<>(a, b);
12 | }
13 |
14 | public Pair(F first, S second) {
15 | this.first = first;
16 | this.second = second;
17 | }
18 |
19 | public F getFirst() {
20 | return first;
21 | }
22 |
23 | public S getSecond() {
24 | return second;
25 | }
26 |
27 | @Override
28 | public String toString()
29 | {
30 | return "[First = " + first + ", Second = " + second + "]";
31 | }
32 |
33 | @Override
34 | public boolean equals(Object obj) {
35 | if (!(obj instanceof Pair))
36 | return false;
37 |
38 | Pair, ?> p = (Pair, ?>)obj;
39 |
40 | return (Objects.equals(p.first, this.first) && Objects.equals(p.second, this.second)) ||
41 | (Objects.equals(p.first, this.second) && Objects.equals(p.second, this.first));
42 | }
43 |
44 | @Override
45 | public int hashCode() {
46 | return (first == null ? 0 : first.hashCode()) ^
47 | (second == null ? 0 : second.hashCode());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/StringUtil.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import java.util.List;
4 | import java.util.UUID;
5 |
6 | public class StringUtil {
7 | public static boolean isEmpty(String s){
8 | return s == null || "".equals(s.trim());
9 | }
10 |
11 | public static String UUID(){
12 | return UUID.randomUUID().toString().replaceAll("-","");
13 | }
14 |
15 | public static String trimFirstLastChar(String str){
16 | return str.substring(1,str.length() - 1);
17 | }
18 |
19 | /**
20 | *
21 | * @param name 可以是包含完整名称的类名、方法名、属性名
22 | * @return
23 | */
24 | public static String getNameWithoutPackage(String name){
25 | return name.substring(name.lastIndexOf(".") + 1);
26 | }
27 |
28 | /**
29 | * @param name
30 | * @return
31 | */
32 | public static String getClassNameWithoutMethodName(String name){
33 | return name.substring(0, name.lastIndexOf("."));
34 | }
35 |
36 |
37 | public static boolean isListEqual(List list1, List list2) {
38 | // 两个list引用相同(包括两者都为空指针的情况)
39 | if (list1 == list2) {
40 | return true;
41 | }
42 |
43 | // 两个list都为空(包括空指针、元素个数为0)
44 | if ((list1 == null && list2 != null && list2.size() == 0)
45 | || (list2 == null && list1 != null && list1.size() == 0)) {
46 | return true;
47 | }
48 |
49 | // 两个list元素个数不相同
50 | if (list1.size() != list2.size()) {
51 | return false;
52 | }
53 |
54 | // 两个list元素个数已经相同,再比较两者内容
55 | // 采用这种可以忽略list中的元素的顺序
56 | // 涉及到对象的比较是否相同时,确保实现了equals()方法
57 | if (!list1.containsAll(list2)) {
58 | return false;
59 | }
60 |
61 | return true;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/TimeUtil.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import org.apache.commons.lang.time.StopWatch;
4 |
5 | public class TimeUtil {
6 |
7 | private static StopWatch stopWatch = new StopWatch();
8 |
9 | public static void startTimer(){
10 | stopWatch.start();
11 | }
12 |
13 | public static String stopAndGetTime(){
14 | stopWatch.stop();
15 | String time = String.valueOf(stopWatch.getTime());
16 | stopWatch.reset();
17 | return time;
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/se/utils/TreeNode.java:
--------------------------------------------------------------------------------
1 | package com.se.utils;
2 |
3 | import java.util.*;
4 |
5 | public class TreeNode {
6 | protected TreeNode parent;
7 | protected List> children;
8 | protected N value;
9 |
10 | public TreeNode(N value) {
11 | this.parent = null;
12 | this.children = new ArrayList<>();
13 | this.value = value;
14 | }
15 |
16 | public boolean forgetParent() {
17 | if(this.parent != null)
18 | return parent.removeChild(this);
19 | return true;
20 | }
21 |
22 | public boolean removeChild(TreeNode child) {
23 | if (this.children.contains(child)) {
24 | child.parent = null;
25 | return this.children.remove(child);
26 | }
27 |
28 | return false;
29 | }
30 |
31 | public TreeNode removeChildAt(int index) throws IndexOutOfBoundsException {
32 | return this.children.remove(index);
33 | }
34 |
35 | public void removeChildren() {
36 | for(TreeNode child : this.children)
37 | child.parent = null;
38 |
39 | this.children.clear();
40 | }
41 |
42 | public boolean addChildNode(TreeNode child) {
43 | if (!children.contains(child))
44 | {
45 | child.forgetParent();
46 |
47 | child.parent = this;
48 | return children.add(child);
49 | }
50 |
51 | return false;
52 | }
53 |
54 | public TreeNode deepCopy() {
55 | TreeNode newNode = new TreeNode(this.value);
56 |
57 | for (TreeNode child : this.children)
58 | newNode.addChildNode(child.deepCopy());
59 |
60 | return newNode;
61 | }
62 |
63 | public int getLevel() {
64 | int level = 0;
65 | TreeNode p = this.parent;
66 |
67 | while(p != null)
68 | {
69 | ++level;
70 | p = p.parent;
71 | }
72 |
73 | return level;
74 | }
75 |
76 | public List> getChildren() {
77 | return this.children;
78 | }
79 |
80 | public List> getLeaves() {
81 | List> leaves = new ArrayList<>();
82 |
83 | DepthFirstIterator it = this.new DepthFirstIterator();
84 | while (it.hasNext())
85 | {
86 | TreeNode node = it.next();
87 | if(node.isLeaf())
88 | leaves.add(node);
89 | }
90 |
91 | return leaves;
92 | }
93 |
94 | public int childrenCount()
95 | {
96 | return this.children.size();
97 | }
98 |
99 | public TreeNode getParent()
100 | {
101 | return this.parent;
102 | }
103 |
104 | public N getValue()
105 | {
106 | return this.value;
107 | }
108 |
109 | public void setValue(N value)
110 | {
111 | this.value = value;
112 | }
113 |
114 | public boolean isLeaf()
115 | {
116 | return this.children.isEmpty();
117 | }
118 |
119 | public class DepthFirstIterator implements Iterator> {
120 | protected Stack> fringe;
121 |
122 | public DepthFirstIterator() {
123 | this.fringe = new Stack<>();
124 | fringe.push(TreeNode.this);
125 | }
126 |
127 | @Override
128 | public boolean hasNext()
129 | {
130 | return !this.fringe.isEmpty();
131 | }
132 |
133 | @Override
134 | public TreeNode next() {
135 | if(!this.hasNext())
136 | throw new NoSuchElementException("Tree ran out of elements");
137 |
138 | TreeNode node = fringe.pop();
139 |
140 | for(TreeNode childNode : node.children)
141 | this.fringe.push(childNode);
142 |
143 | return node;
144 | }
145 |
146 | @Override
147 | public void remove() {
148 | throw new UnsupportedOperationException();
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/main/java/com/se/visitors/ClassVisitor.java:
--------------------------------------------------------------------------------
1 | package com.se.visitors;
2 |
3 | import com.github.javaparser.ast.PackageDeclaration;
4 | import com.github.javaparser.ast.body.*;
5 | import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
6 | import com.se.entity.ClassInfo;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | public class ClassVisitor extends VoidVisitorAdapter {
14 |
15 | private String projectName;
16 | private String filePath;
17 | private String pkg; //包名
18 | private String clazz; //类名
19 | private List classInfoList;
20 |
21 | private Map fieldAndType;
22 | private Map> methodAndParameter;
23 | private Map methodAndType;
24 |
25 | public String getClazz() {
26 | return clazz;
27 | }
28 |
29 | public Map> getMethodAndParameter() {
30 | return methodAndParameter;
31 | }
32 |
33 | public Map getMethodAndType() {
34 | return methodAndType;
35 | }
36 |
37 | public ClassVisitor(String projectName, String filePath){
38 | this.projectName = projectName;
39 | this.filePath = filePath;
40 | this.classInfoList = new ArrayList<>();
41 | this.fieldAndType=new HashMap<>();
42 | this.methodAndParameter = new HashMap<>();
43 | this.methodAndType = new HashMap<>();
44 | }
45 |
46 | /**
47 | * package
48 | * example -> com.se.entity
49 | * @param pkgDec
50 | * @param arg
51 | */
52 | @Override
53 | public void visit(PackageDeclaration pkgDec, Object arg) {
54 | String pkgDecString = pkgDec.toString();
55 | String[] tokens = pkgDecString.split(" ");
56 | String pkgToken = tokens[tokens.length - 1].trim();
57 | this.pkg = pkgToken.substring(0, pkgToken.length() - 1);
58 | super.visit(pkgDec, arg);
59 | }
60 |
61 | /**
62 | * class name
63 | * example -> MethodVisitor
64 | * @param n
65 | * @param arg
66 | */
67 | @Override
68 | public void visit(ClassOrInterfaceDeclaration n, Object arg) {
69 | this.clazz = this.dollaryName(n);
70 | ClassInfo classInfo = new ClassInfo();
71 | classInfo.setClassName(this.pkg +"."+ this.clazz);
72 | classInfo.setInterface(n.isInterface());
73 | classInfo.setProjectName(this.projectName);
74 | this.filePath = this.filePath.replace("\\","|");
75 | classInfo.setFilePath(this.filePath);
76 | this.classInfoList.add(classInfo);
77 | super.visit(n, arg);
78 | }
79 |
80 | @Override
81 | public void visit(FieldDeclaration n, Object arg) {
82 | this.fieldAndType.put(n.getVariable(0).toString(),n.getVariable(0).getTypeAsString());
83 | super.visit(n, arg);
84 | }
85 |
86 | @Override
87 | public void visit(MethodDeclaration n, Object arg) {
88 | if (n.getNameAsString()!=this.clazz){
89 | this.methodAndType.put(n.getNameAsString(),n.getTypeAsString());
90 | if (n.getParameters().size()==0){
91 | this.methodAndParameter.put(n.getNameAsString(),new ArrayList<>());
92 | }else {
93 | this.methodAndParameter.put(n.getNameAsString(),n.getParameters());
94 | }
95 | }
96 |
97 | super.visit(n, arg);
98 | }
99 |
100 | private String dollaryName(TypeDeclaration> n) {
101 | if (n.isNestedType()) {
102 | return dollaryName((TypeDeclaration>) n.getParentNode().get()) + "$" + n.getNameAsString();
103 | }
104 | return n.getNameAsString();
105 | }
106 | public List getClassInfoList() {
107 | return this.classInfoList;
108 | }
109 |
110 | public void setClassInfoList(List classInfoList) {
111 | this.classInfoList = classInfoList;
112 | }
113 |
114 | public Map getFieldMap() {
115 | return this.fieldAndType;
116 | }
117 | }
--------------------------------------------------------------------------------
/src/main/java/com/se/visitors/LayerVisitor.java:
--------------------------------------------------------------------------------
1 | package com.se.visitors;
2 |
3 | import com.github.javaparser.JavaParser;
4 | import com.github.javaparser.ast.CompilationUnit;
5 | import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
6 | import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
7 | import com.se.entity.SetEnum;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import java.util.Set;
11 |
12 | /**
13 | * @author wangjiwen
14 | * @create 2020/8/4
15 | */
16 | public class LayerVisitor {
17 | static boolean isMatch = false;
18 |
19 | static String level = "";
20 |
21 | public static String splitLayer(CompilationUnit cu){
22 | SetEnum setEnum = new SetEnum();
23 | Set daoEnum = setEnum.daoEnum;
24 | /** 类上、方法上的注解 */
25 | List markerAnnotationExprs = cu.findAll(MarkerAnnotationExpr.class);
26 | List markerAnnotationList = new ArrayList<>(markerAnnotationExprs.size());
27 | for (int i = 0; i < markerAnnotationExprs.size(); i++) {
28 | markerAnnotationList.add(markerAnnotationExprs.get(i).getNameAsString());
29 | }
30 |
31 | /** 方法参数上的注解 */
32 | List singleMemberAnnotationExprs = cu.findAll(SingleMemberAnnotationExpr.class);
33 | List singleAnnotationList = new ArrayList<>();
34 | for (int i = 0; i < singleMemberAnnotationExprs.size(); i++) {
35 | singleAnnotationList.add(singleMemberAnnotationExprs.get(i).getNameAsString());
36 | }
37 | help(markerAnnotationList, setEnum);
38 | return level;
39 | }
40 |
41 | private static void help(List annotationList, SetEnum setEnum) {
42 | if (annotationList == null || annotationList.size() == 0) {
43 | return;
44 | }
45 | Set controlEnum = setEnum.controlEnum;
46 | Set serviceEnum = setEnum.serviceEnum;
47 | Set daoEnum = setEnum.daoEnum;
48 | Set