Skip to content

Commit 035d3b8

Browse files
authored
Merge pull request #138 from ml-in-programming/integration2
Integration of features extraction, generation and algorithms evaluation
2 parents 51b6dec + 9ce94f6 commit 035d3b8

File tree

186 files changed

+5863
-547
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

186 files changed

+5863
-547
lines changed

ArchitectureReloaded.iml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<content url="file://$MODULE_DIR$">
66
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
77
<excludeFolder url="file://$MODULE_DIR$/build" />
8+
<excludeFolder url="file://$MODULE_DIR$/out" />
89
</content>
910
<orderEntry type="inheritedJdk" />
1011
<orderEntry type="sourceFolder" forTests="false" />

MetricsReloaded/src/main/java/com/sixrr/metrics/metricModel/MetricsExecutionContextImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ public void onCancel() {
7979

8080
public void calculateMetrics(MetricsProfile profile, final MetricsResultsHolder resultsHolder) {
8181
final ProgressIndicator indicator;
82-
if (ApplicationManager.getApplication().isUnitTestMode()) {
82+
83+
if (ApplicationManager.getApplication().isUnitTestMode() || ApplicationManager.getApplication().isHeadlessEnvironment()) {
8384
indicator = new EmptyProgressIndicator();
8485
} else {
8586
indicator = ProgressManager.getInstance().getProgressIndicator();

MetricsReloaded/src/test/java/com/sixrr/metrics/ui/SearchUtilTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020

2121
import java.util.Arrays;
2222
import java.util.List;
23-
import java.util.Set;
2423

25-
import static org.junit.Assert.*;
26-
import static com.sixrr.metrics.ui.SearchUtil.*;
24+
import static com.sixrr.metrics.ui.SearchUtil.tokenizeFilter;
25+
import static org.junit.Assert.assertEquals;
2726

2827
/**
2928
* @author Bas Leijdekkers

MetricsReloaded/utils/src/main/java/com/sixrr/metrics/utils/MethodUtils.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.jetbrains.annotations.Nullable;
2727

2828
import java.util.*;
29+
import java.util.regex.Pattern;
2930

3031
public final class MethodUtils {
3132

@@ -64,6 +65,14 @@ public static boolean isStatic(PsiModifierListOwner unit) {
6465
return unit.hasModifierProperty(PsiModifier.STATIC);
6566
}
6667

68+
public static boolean isSynchronized(PsiModifierListOwner unit) {
69+
return unit.hasModifierProperty(PsiModifier.SYNCHRONIZED);
70+
}
71+
72+
public static boolean isOverriding(PsiMethod method) {
73+
return method.findSuperMethods().length != 0;
74+
}
75+
6776
public static boolean isPrivate(PsiModifierListOwner unit) {
6877
return unit.hasModifierProperty(PsiModifier.PRIVATE);
6978
}
@@ -223,8 +232,24 @@ private static boolean hasField(@NotNull final PsiClass aClass,
223232
return false;
224233
}
225234

226-
public static boolean isOverriding(PsiMethod method) {
227-
return method.findSuperMethods().length != 0;
235+
public static boolean isPublic(PsiMethod method) {
236+
if (method.hasModifierProperty(PsiModifier.PUBLIC)) {
237+
return true;
238+
}
239+
240+
PsiClass containingClass = method.getContainingClass();
241+
242+
return containingClass != null && containingClass.isInterface();
243+
}
244+
245+
public static String extractMethodDeclaration(final @NotNull PsiMethod method) {
246+
String code = method.getText();
247+
248+
code = Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL).matcher(code).replaceAll("");
249+
code = Pattern.compile("//.*?$", Pattern.DOTALL | Pattern.MULTILINE).matcher(code).replaceAll("");
250+
251+
code = Pattern.compile("\\{.*}", Pattern.DOTALL).matcher(code).replaceAll("");
252+
return code.trim();
228253
}
229254

230255
/**
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.sixrr.metrics.utils;
2+
3+
import com.intellij.ide.impl.ProjectUtil;
4+
import com.intellij.openapi.project.Project;
5+
import com.intellij.openapi.project.ProjectManager;
6+
import com.intellij.openapi.roots.ProjectRootManager;
7+
import com.intellij.openapi.util.Disposer;
8+
import org.jetbrains.annotations.Nullable;
9+
10+
import java.nio.file.Path;
11+
12+
public class ProjectUtils {
13+
private ProjectUtils() {
14+
}
15+
16+
@Nullable
17+
public static Project loadProjectWithAllDependencies(Path projectPath) {
18+
for (Project openedProject : ProjectManager.getInstance().getOpenProjects()) {
19+
if (!ProjectManager.getInstance().closeProject(openedProject)) {
20+
throw new IllegalStateException("Cannot close previous project");
21+
}
22+
Disposer.dispose(openedProject);
23+
if (!openedProject.isDisposed()) {
24+
throw new IllegalStateException("Cannot dispose project");
25+
}
26+
}
27+
final Project project = ProjectUtil.openOrImport(projectPath.toAbsolutePath().toString(),
28+
null, false);
29+
return project == null ||
30+
ProjectRootManager.getInstance(project).getProjectSdk() == null ||
31+
!project.isInitialized() ?
32+
null : project;
33+
}
34+
}

MetricsReloaded/utils/src/main/java/org/jetbrains/research/groups/ml_methods/utils/PSIUtil.java

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package org.jetbrains.research.groups.ml_methods.utils;
22

3-
import com.intellij.psi.PsiClass;
4-
import com.intellij.psi.PsiElement;
5-
import com.intellij.psi.PsiMethod;
3+
import com.intellij.openapi.fileTypes.StdFileTypes;
4+
import com.intellij.openapi.project.Project;
5+
import com.intellij.openapi.roots.ProjectRootManager;
6+
import com.intellij.openapi.roots.TestSourcesFilter;
7+
import com.intellij.openapi.vfs.VirtualFile;
8+
import com.intellij.psi.*;
69
import com.intellij.psi.util.PsiTreeUtil;
710
import org.jetbrains.annotations.NotNull;
11+
import org.jetbrains.annotations.Nullable;
812

9-
import java.util.HashSet;
10-
import java.util.Optional;
11-
import java.util.Set;
13+
import java.util.*;
14+
15+
import static com.sixrr.metrics.utils.MethodUtils.calculateSignature;
1216

1317
public final class PSIUtil {
1418
private PSIUtil() {
@@ -87,4 +91,44 @@ public static boolean isOverriding(PsiMethod method) {
8791

8892
return Optional.of(parent);
8993
}
94+
95+
public static String getHumanReadableName(@Nullable PsiElement element) {
96+
if (element instanceof PsiMethod) {
97+
return calculateSignature((PsiMethod) element);
98+
} else if (element instanceof PsiClass) {
99+
if (element instanceof PsiAnonymousClass) {
100+
return getHumanReadableName(((PsiAnonymousClass) element).getBaseClassReference().resolve());
101+
}
102+
return ((PsiClass) element).getQualifiedName();
103+
} else if (element instanceof PsiField) {
104+
final PsiMember field = (PsiMember) element;
105+
return getHumanReadableName(field.getContainingClass()) + "." + field.getName();
106+
}
107+
return "???";
108+
}
109+
110+
public static List<VirtualFile> getAllJavaFiles(Project project, boolean includeTestSources) {
111+
List<VirtualFile> javaVirtualFiles = new ArrayList<>();
112+
ProjectRootManager projectRootManager = ProjectRootManager.getInstance(project);
113+
projectRootManager.getFileIndex().iterateContent(virtualFile -> {
114+
if (isJavaFile(virtualFile)) {
115+
if (includeTestSources && TestSourcesFilter.isTestSources(virtualFile, project)) {
116+
javaVirtualFiles.add(virtualFile);
117+
}
118+
if (!TestSourcesFilter.isTestSources(virtualFile, project)) {
119+
javaVirtualFiles.add(virtualFile);
120+
}
121+
}
122+
return true;
123+
});
124+
return javaVirtualFiles;
125+
}
126+
127+
public static int getNumberOfJavaFiles(Project project, boolean includeTestSources) {
128+
return getAllJavaFiles(project, includeTestSources).size();
129+
}
130+
131+
public static boolean isJavaFile(VirtualFile virtualFile) {
132+
return virtualFile.getFileType().equals(StdFileTypes.JAVA);
133+
}
90134
}

algorithms-evaluation/build.gradle

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
repositories {
2+
mavenCentral()
3+
}
4+
5+
apply plugin: 'idea'
6+
7+
dependencies {
8+
compile project(':core')
9+
compile project(':features-extraction')
10+
11+
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.19.1'
12+
}
13+
14+
task runAlgorithmsEvaluation(dependsOn: runIde) {}
15+
16+
gradle.taskGraph.whenReady { graph ->
17+
if (graph.hasTask(runAlgorithmsEvaluation)) {
18+
runIde.args 'algorithms-evaluation', "$pathToDataset", "$algorithmsNames", "$pathToSaveResults"
19+
runIde.jvmArgs '-Djava.awt.headless=true', '-Xmx4096m'
20+
}
21+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.jetbrains.research.groups.ml_methods.evaluation;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
import org.jetbrains.research.groups.ml_methods.algorithm.Algorithm;
5+
6+
import java.util.EnumMap;
7+
import java.util.function.Supplier;
8+
9+
import static java.lang.Math.pow;
10+
11+
public abstract class AbstractEvaluationResult implements EvaluationResult {
12+
private final @NotNull EnumMap<Evaluation, Supplier<Double>> evaluationFunctions =
13+
new EnumMap<>(Evaluation.class);
14+
private final @NotNull Algorithm evaluatingAlgorithm;
15+
16+
{
17+
evaluationFunctions.put(Evaluation.GOOD_PRECISION, this::getGoodPrecision);
18+
evaluationFunctions.put(Evaluation.GOOD_RECALL, this::getGoodRecall);
19+
evaluationFunctions.put(Evaluation.BAD_PRECISION, this::getBadPrecision);
20+
evaluationFunctions.put(Evaluation.BAD_RECALL, this::getBadRecall);
21+
evaluationFunctions.put(Evaluation.MSE, this::getMSE);
22+
evaluationFunctions.put(Evaluation.ME, this::getME);
23+
}
24+
25+
AbstractEvaluationResult(@NotNull Algorithm evaluatingAlgorithm) {
26+
this.evaluatingAlgorithm = evaluatingAlgorithm;
27+
}
28+
29+
@Override
30+
public Algorithm getAlgorithm() {
31+
return evaluatingAlgorithm;
32+
}
33+
34+
@Override
35+
public double getGoodPrecision() {
36+
return (double) getNumberOfFoundGood() / getNumberOfFoundBadAndGood();
37+
}
38+
39+
@Override
40+
public double getGoodRecall() {
41+
return (double) getNumberOfFoundGood() / getNumberOfGood();
42+
}
43+
44+
@Override
45+
public double getBadPrecision() {
46+
return (double) (getNumberOfBad() - getNumberOfFoundBad()) / (getNumberOfBadAndGood() - getNumberOfFoundBadAndGood());
47+
}
48+
49+
@Override
50+
public double getBadRecall() {
51+
return (double) (getNumberOfBad() - getNumberOfFoundBad()) / getNumberOfBad();
52+
}
53+
54+
@Override
55+
public double getMSE() {
56+
return getErrors().stream().mapToDouble(Double::doubleValue).map(operand -> pow(operand, 2)).sum() / getErrors().size();
57+
}
58+
59+
@Override
60+
public double getME() {
61+
return getErrors().stream().mapToDouble(Double::doubleValue).sum() / getErrors().size();
62+
}
63+
64+
private int getNumberOfBadAndGood() {
65+
return getNumberOfBad() + getNumberOfGood();
66+
}
67+
68+
private int getNumberOfFoundBadAndGood() {
69+
return getNumberOfFoundBad() + getNumberOfFoundGood();
70+
}
71+
72+
@Override
73+
public Supplier<Double> getEvaluation(Evaluation evaluation) {
74+
return evaluationFunctions.get(evaluation);
75+
}
76+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.jetbrains.research.groups.ml_methods.evaluation;
2+
3+
import com.intellij.analysis.AnalysisScope;
4+
import com.intellij.openapi.project.Project;
5+
import com.sixrr.metrics.profile.MetricsProfile;
6+
import org.jetbrains.annotations.NotNull;
7+
import org.jetbrains.research.groups.ml_methods.algorithm.Algorithm;
8+
import org.jetbrains.research.groups.ml_methods.algorithm.RefactoringExecutionContext;
9+
import org.jetbrains.research.groups.ml_methods.refactoring.CalculatedRefactoring;
10+
import org.jetbrains.research.groups.ml_methods.refactoring.MoveToClassRefactoring;
11+
import org.jetbrains.research.groups.ml_methods.utils.MetricsProfilesUtil;
12+
13+
import java.util.Collections;
14+
import java.util.List;
15+
16+
public class AlgorithmEvaluator {
17+
@NotNull
18+
static EvaluationResult evaluate(@NotNull AnalysisScope scope, @NotNull Algorithm algorithm,
19+
@NotNull List<MoveToClassRefactoring> good, @NotNull List<MoveToClassRefactoring> bad) {
20+
MetricsProfile profile =
21+
MetricsProfilesUtil.createProfile("evaluation_profile", algorithm.requiredMetrics());
22+
RefactoringExecutionContext context = new RefactoringExecutionContext(scope.getProject(), scope, profile,
23+
Collections.singletonList(algorithm), false, null);
24+
25+
context.executeSynchronously();
26+
27+
List<CalculatedRefactoring> foundRefactorings = context.getAlgorithmResults().get(0).getRefactorings();
28+
return new ProjectEvaluationResult(foundRefactorings, good, bad, algorithm);
29+
}
30+
31+
@NotNull
32+
static EvaluationResult evaluate(@NotNull Project project, @NotNull Algorithm algorithm,
33+
@NotNull List<MoveToClassRefactoring> good, @NotNull List<MoveToClassRefactoring> bad) {
34+
return evaluate(new AnalysisScope(project), algorithm, good, bad);
35+
}
36+
37+
@NotNull
38+
static EvaluationResult evaluate(@NotNull ProjectToEvaluate projectToEvaluate,
39+
@NotNull Algorithm algorithm) {
40+
return evaluate(projectToEvaluate.getProject(),
41+
algorithm,
42+
projectToEvaluate.getGoodRefactorings(),
43+
projectToEvaluate.getBadRefactorings());
44+
}
45+
}

0 commit comments

Comments
 (0)