god-2022: part 1 done
This commit is contained in:
commit
8a37418ebb
4 changed files with 82 additions and 0 deletions
2
proj2022/.gitignore
vendored
Normal file
2
proj2022/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
xerces2/
|
||||||
|
env/
|
15
proj2022/README.md
Normal file
15
proj2022/README.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# IMA - God classes project
|
||||||
|
|
||||||
|
## Xerces2
|
||||||
|
|
||||||
|
Downloaded from: https://dlcdn.apache.org//xerces/j/source/Xerces-J-src.2.12.2.zip
|
||||||
|
|
||||||
|
## Install dependencies
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# create venv
|
||||||
|
python -m venv env
|
||||||
|
source env/bin/activate
|
||||||
|
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
```
|
63
proj2022/find_god_classes.py
Executable file
63
proj2022/find_god_classes.py
Executable file
|
@ -0,0 +1,63 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import javalang
|
||||||
|
import os
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
DIR: str = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
SOURCES: str = DIR + '/xerces2/src'
|
||||||
|
|
||||||
|
# God class if:
|
||||||
|
# |M(C)| > E(M) + 6 V(M)
|
||||||
|
# (number of methods greater than average across all classes plus 6 times the
|
||||||
|
# standard deviation)
|
||||||
|
|
||||||
|
def parse(path: str) -> list[tuple[str, str]]:
|
||||||
|
# Get the AST of the file
|
||||||
|
with open(path) as file:
|
||||||
|
data = file.read()
|
||||||
|
tree = javalang.parse.parse(data)
|
||||||
|
|
||||||
|
# Fetch package name from package declaration
|
||||||
|
# if node is missing, assuming default package ('')
|
||||||
|
package_name = ''
|
||||||
|
for _, node in tree.filter(javalang.tree.PackageDeclaration):
|
||||||
|
package_name = node.name
|
||||||
|
break
|
||||||
|
|
||||||
|
# Get all classes and number of methods for each one
|
||||||
|
rows: list[tuple[str, str]] = []
|
||||||
|
for _, node in tree.filter(javalang.tree.ClassDeclaration):
|
||||||
|
fqdn = package_name + '.' + node.name
|
||||||
|
rows.append((fqdn, len(node.methods),))
|
||||||
|
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
|
def create_df(root) -> pd.DataFrame:
|
||||||
|
frame = pd.DataFrame(columns=['class_name', 'method_num'])
|
||||||
|
|
||||||
|
i: int = 0
|
||||||
|
for path, dirs, files in os.walk(root):
|
||||||
|
for f in files:
|
||||||
|
if f.endswith('.java'):
|
||||||
|
# for each java file, add all entries found to dataframe
|
||||||
|
for row in parse(path + '/' + f):
|
||||||
|
frame.loc[i] = row
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return frame
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
df = create_df(SOURCES)
|
||||||
|
|
||||||
|
mean = df.loc[:, 'method_num'].mean()
|
||||||
|
std = df.loc[:, 'method_num'].std()
|
||||||
|
treshold = mean + 6 * std
|
||||||
|
|
||||||
|
god_classes_df = df[df['method_num'] > treshold]
|
||||||
|
print(god_classes_df)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
2
proj2022/requirements.txt
Normal file
2
proj2022/requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
javalang==0.13.0
|
||||||
|
pandas==1.5.2
|
Reference in a new issue