Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cohesion recalculated faster
  • Loading branch information
olgalupuleac committed May 19, 2018
commit ce8c9c166b578395864a3206b503cebb64d2b043
21 changes: 18 additions & 3 deletions src/main/java/org/ml_methods_group/algorithm/QMove.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ protected List<Refactoring> calculateRefactorings(
.map(x -> (QMoveClassEntity)x)
.peek(entity -> qMoveClassesByName.put(entity.getName(), entity))
.forEach(classes::add);

calculateMetrics();
ArrayList<Refactoring> refactorings = new ArrayList<>();

for(QMoveMethodEntity methodEntity : methodEntities){
Expand All @@ -82,7 +82,8 @@ protected List<Refactoring> calculateRefactorings(

private List<Refactoring> findBestMoveForMethod(QMoveMethodEntity method,
List<Refactoring> refactorings){
double bestFitness = fitness();
double initFitness = fitness();
double bestFitness = initFitness;
QMoveClassEntity targetForThisMethod = null;
for(QMoveClassEntity targetClass : classes){
QMoveClassEntity containingClass = qMoveClassesByName.get(
Expand All @@ -98,6 +99,9 @@ private List<Refactoring> findBestMoveForMethod(QMoveMethodEntity method,
}
moveMethod(method, containingClass, targetClass);
double fitness = fitness();
if(fitness != initFitness){
System.err.println("ERROR");
}
}
if(targetForThisMethod != null){
refactorings.add(new Refactoring(method.getName(),
Expand All @@ -121,6 +125,17 @@ private void calculateMetrics(){
inheritance = classes.stream().mapToDouble(QMoveClassEntity::getInheritance).sum();
}

private void recalculateMetrics(){
double coup = coupling;
coupling = classes.stream().mapToDouble(QMoveClassEntity::getCoupling).sum();
double mess = messaging;
messaging = classes.stream().mapToDouble(QMoveClassEntity::getMessaging).sum();
double coh = cohesion;
cohesion = classes.stream().mapToDouble(QMoveClassEntity::getCohesion).sum();
double inh = inheritance;
inheritance = classes.stream().mapToDouble(QMoveClassEntity::getInheritance).sum();
}

private double reusability() {
return -0.25 * coupling + 0.25 * cohesion + 0.5 * messaging
+ 0.5 * size;
Expand Down Expand Up @@ -153,7 +168,7 @@ private double effectiveness() {
}

private double fitness(){
calculateMetrics();
recalculateMetrics();
return reusability() + flexibility() + understandability() +
functionality() + extendibility() + effectiveness();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import java.util.stream.Stream;

public class QMoveClassEntity extends ClassEntity {
static Set<PsiClass> userDefinedClasses = new HashSet<>();
static Map<PsiClass, List<QMoveMethodEntity>> allNoneStaticMethods = new HashMap<>();
private double complexity;
private double polymorphism;
private double abstraction;
Expand All @@ -43,10 +43,13 @@ public class QMoveClassEntity extends ClassEntity {
private double composition;
private double inheritance;

private int numOfAllMethods;
private double numOfAllMethods;
private int numOfNoneStaticMethods;
private PsiClass psiClass;
private double sumIntersection;
private Map<String, PsiMethod> methods;
private Map<PsiClass, Integer> relatedClasses = new HashMap<>();
private Map<PsiType, Integer> parametersOfMethods = new HashMap<>();

private static final VectorCalculator QMOOD_CALCULATOR = new VectorCalculator()
.addMetricDependence(NumMethodsClassMetric.class) //Complexity 0
Expand All @@ -63,8 +66,6 @@ public class QMoveClassEntity extends ClassEntity {
QMoveClassEntity(PsiClass psiClass) {
super(psiClass);
this.psiClass = psiClass;
methods = Stream.of(psiClass.getMethods())
.collect(Collectors.toMap(PsiSearchUtil::getHumanReadableName, Function.identity()));
}

@Override
Expand All @@ -79,8 +80,14 @@ void calculateVector(MetricsRun metricsRun) {
cohesion = vector[7];
composition = vector[8];
inheritance = vector[1];
numOfAllMethods = psiClass.getAllMethods().length;
coupling = calculateRelatedClasses();

numOfAllMethods = inheritance + complexity;

Stream.of(psiClass.getAllMethods()).forEach(x -> System.out.println(x.getName()));
methods = Stream.of(psiClass.getMethods()).collect(
Collectors.toMap(PsiSearchUtil::getHumanReadableName, Function.identity())
);
coupling = calculateCoupling();
}

@Override
Expand Down Expand Up @@ -117,6 +124,12 @@ public double getAbstraction() {
}

public double getCohesion() {
if(parametersOfMethods.isEmpty()){
double coh = calculateCohesion();
if(coh != cohesion){
System.err.println("Wrong cohesion");
}
}
return cohesion;
}

Expand Down Expand Up @@ -163,10 +176,31 @@ public void addMethod(QMoveMethodEntity entity) {
messaging++;
}
recalculateCoupling(entity, true);
recalculateCohesion();
recalculateCohesion(entity, true);
numOfAllMethods++;
}

private void recalculateCohesion(QMoveMethodEntity entity, boolean add) {
if(entity.getPsiMethod().hasModifierProperty(PsiModifier.STATIC)){
return;
}
if(add){
numOfNoneStaticMethods++;
sumIntersection += entity.getParameters().size();
QMoveUtil.addToUnion(parametersOfMethods, entity.getParameters());
}
else {
numOfNoneStaticMethods--;
sumIntersection -= entity.getParameters().size();
QMoveUtil.removeFromUnion(parametersOfMethods, entity.getParameters());
}
if(parametersOfMethods.size() == 0){
cohesion = 0;
return;
}
cohesion = sumIntersection / numOfNoneStaticMethods * parametersOfMethods.size();
}

public void removeMethod(QMoveMethodEntity methodEntity){
methods.remove(methodEntity.getName());
complexity--;
Expand All @@ -175,7 +209,7 @@ public void removeMethod(QMoveMethodEntity methodEntity){
messaging--;
}
recalculateCoupling(methodEntity, false);
recalculateCohesion();
recalculateCohesion(methodEntity, false);
numOfAllMethods--;
}

Expand All @@ -189,7 +223,8 @@ private void recalculateCoupling(QMoveMethodEntity entity, boolean add) {
coupling = relatedClasses.size();
}

private int calculateRelatedClasses() {
private int calculateCoupling() {
QMoveUtil.incrementMapValue(psiClass, relatedClasses);
PsiField[] fields = psiClass.getFields();
for (PsiField field : fields) {
if (!field.isPhysical()) {
Expand All @@ -200,8 +235,7 @@ private int calculateRelatedClasses() {
if (classInType == null) {
continue;
}
relatedClasses.put(classInType,
relatedClasses.getOrDefault(classInType, 0));
QMoveUtil.incrementMapValue(classInType, relatedClasses);
}
for (Map.Entry<String, PsiMethod> method : methods.entrySet()) {
QMoveUtil.calculateRelatedClasses(method.getValue(), relatedClasses);
Expand All @@ -210,26 +244,25 @@ private int calculateRelatedClasses() {
}


private void recalculateCohesion(){
double sumIntersection = 0;
int numMethods = 0;
Set<PsiType> parameters = new HashSet<>();
private double calculateCohesion(){
sumIntersection = allNoneStaticMethods.entrySet().stream()
.filter(x -> x.getKey().equals(psiClass))
.map(Map.Entry::getValue)
.flatMap(List::stream)
.peek(x -> System.err.println(x.getName()))
.mapToInt(x -> x.getParameters().size()).sum();
for(Map.Entry<String, PsiMethod> methodEntry : methods.entrySet()){
PsiMethod method = methodEntry.getValue();
if(method.isConstructor() || method.hasModifierProperty(PsiModifier.STATIC)){
continue;
}
numMethods++;
Set<PsiType> parametersInMethod = Stream.of(method.getParameterList()).
flatMap(x -> Stream.of(x.getParameters())).
map(PsiVariable::getType).collect(Collectors.toSet());
sumIntersection += parametersInMethod.size();
parameters.addAll(parametersInMethod);
QMoveUtil.calculateMethodParameters(method, parametersOfMethods);
numOfNoneStaticMethods++;
}
if(parameters.size() == 0){
return;
if(parametersOfMethods.size() == 0){
return 0;
}
cohesion = sumIntersection / numMethods * parameters.size();
return sumIntersection / numOfNoneStaticMethods * parametersOfMethods.size();
}

public void recalculateInheritance(boolean increment){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ private QMoveEntitySearchResult prepareResult(MetricsRun metricsRun) {
try {
entity.calculateVector(metricsRun);
} catch (Exception e) {
e.printStackTrace();
LOGGER.warn("Failed to calculate vector for " + entity.getName());
continue;
}
Expand All @@ -97,6 +98,14 @@ private QMoveEntitySearchResult prepareResult(MetricsRun metricsRun) {
break;
case Method:
methods.add((MethodEntity) entity);
if(((QMoveMethodEntity)entity).getPsiMethod().hasModifierProperty(PsiModifier.STATIC)){
break;
}
PsiClass containingClass = ((QMoveMethodEntity)entity).getPsiMethod().getContainingClass();
if(!QMoveClassEntity.allNoneStaticMethods.containsKey(containingClass)){
QMoveClassEntity.allNoneStaticMethods.put(containingClass, new ArrayList<>());
}
QMoveClassEntity.allNoneStaticMethods.get(containingClass).add((QMoveMethodEntity) entity);
break;
default:
fields.add((FieldEntity) entity);
Expand Down Expand Up @@ -129,7 +138,6 @@ public void visitClass(PsiClass aClass) {
return;
}
entities.put(aClass, new QMoveClassEntity(aClass));
QMoveClassEntity.userDefinedClasses.add(aClass);
super.visitClass(aClass);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public class QMoveMethodEntity extends MethodEntity {
private boolean isContainsOnlyPublicCalls;

private Map<PsiClass, Integer> relatedClasses = new HashMap<>();
private Map<PsiType, Integer> parameters = new HashMap<>();


QMoveMethodEntity(PsiMethod method) {
super(method);
Expand All @@ -42,12 +44,18 @@ public class QMoveMethodEntity extends MethodEntity {
@Override
void calculateVector(MetricsRun metricsRun) {
QMoveUtil.calculateRelatedClasses(psiMethod, relatedClasses);
QMoveUtil.calculateMethodParameters(psiMethod, parameters);
//assert res == parameters.size();
}

public PsiMethod getPsiMethod() {
PsiMethod getPsiMethod() {
return psiMethod;
}

Map<PsiType, Integer> getParameters(){
return parameters;
}

public boolean isValidMoveToClass(PsiClass targetClass){
if(!isMovable){
return false;
Expand Down
17 changes: 14 additions & 3 deletions src/main/java/org/ml_methods_group/utils/QMoveUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.intellij.psi.util.PsiUtil;

import java.util.Map;
import java.util.stream.Stream;

public class QMoveUtil {
public static void calculateRelatedClasses(PsiMethod method, Map<PsiClass, Integer> relatedClasses){
Expand All @@ -34,8 +35,7 @@ public static void calculateRelatedClasses(PsiMethod method, Map<PsiClass, Integ
if (classInType == null) {
continue;
}
relatedClasses.put(classInType,
relatedClasses.getOrDefault(classInType, 0) + 1);
incrementMapValue(classInType, relatedClasses);
}
}

Expand All @@ -56,9 +56,20 @@ public static <T> void removeFromUnion(Map<T, Integer> union, Map<T, Integer> s
public static <T> void addToUnion(Map<T, Integer> union, Map<T, Integer> set){
for(Map.Entry<T, Integer> item : set.entrySet()){
int add = item.getValue();
T key = item.getKey();
T key = item.getKey();
int present = union.getOrDefault(key, 0);
union.put(key, present + add);
}
}

public static <T> void incrementMapValue(T t, Map<T, Integer> map){
map.put(t,
map.getOrDefault(t, 0) + 1);
}

public static void calculateMethodParameters(PsiMethod method, Map<PsiType, Integer> parameters){
Stream.of(method.getParameterList()).
flatMap(x -> Stream.of(x.getParameters())).
map(PsiVariable::getType).forEach(x -> incrementMapValue(x, parameters));
}
}