Skip to content

Commit 720d04a

Browse files
committed
Merge branch 'integration2' of https://github.com/ml-in-programming/ArchitectureReloaded into smartPsiElementPointer_integration
# Conflicts: # core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmsRepository.java # core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/RefactoringExecutionContext.java # core/src/main/java/org/jetbrains/research/groups/ml_methods/utils/PsiSearchUtil.java # core/src/test/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmAbstractTest.java # src/main/java/org/jetbrains/research/groups/ml_methods/intention/RefactoringAnnotator.java # src/main/java/org/jetbrains/research/groups/ml_methods/ui/AlgorithmsSelectionPanel.java # src/main/java/org/jetbrains/research/groups/ml_methods/ui/ClassRefactoringPanel.java
2 parents dc0da69 + 0d57bcd commit 720d04a

File tree

141 files changed

+5334
-55
lines changed

Some content is hidden

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

141 files changed

+5334
-55
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/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+
}

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.refactoring.CalculatedRefactoring;
9+
import org.jetbrains.research.groups.ml_methods.refactoring.MoveToClassRefactoring;
10+
import org.jetbrains.research.groups.ml_methods.algorithm.RefactoringExecutionContext;
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package org.jetbrains.research.groups.ml_methods.evaluation;
2+
3+
import com.intellij.openapi.application.ApplicationManager;
4+
import com.intellij.openapi.application.ApplicationStarter;
5+
import com.intellij.openapi.application.ex.ApplicationEx;
6+
import org.apache.log4j.ConsoleAppender;
7+
import org.apache.log4j.Level;
8+
import org.apache.log4j.Logger;
9+
import org.apache.log4j.PatternLayout;
10+
import org.jetbrains.annotations.NotNull;
11+
import org.jetbrains.research.groups.ml_methods.algorithm.Algorithm;
12+
import org.jetbrains.research.groups.ml_methods.algorithm.AlgorithmsRepository;
13+
14+
import java.nio.file.Path;
15+
import java.nio.file.Paths;
16+
import java.util.ArrayList;
17+
import java.util.Arrays;
18+
import java.util.List;
19+
import java.util.stream.Collectors;
20+
21+
22+
public class AlgorithmsEvaluationApplicationStarter implements ApplicationStarter {
23+
private static final ApplicationEx APPLICATION = (ApplicationEx) ApplicationManager.getApplication();
24+
private static final int NUMBER_OF_ARGUMENTS = 4;
25+
private static final @NotNull Logger LOGGER =
26+
Logger.getLogger(AlgorithmsEvaluationApplicationStarter.class);
27+
28+
static {
29+
LOGGER.setLevel(Level.INFO);
30+
LOGGER.addAppender(new ConsoleAppender(new PatternLayout("%p %m%n")));
31+
}
32+
33+
private static void checkCommandLineArguments(@NotNull String[] args) {
34+
if (args.length != NUMBER_OF_ARGUMENTS) {
35+
printUsage();
36+
APPLICATION.exit(true, true);
37+
}
38+
}
39+
40+
private static void printUsage() {
41+
System.out.println("Usage: algorithms-evaluation <path to dataset folder> <algorithms names> <pathToSaveResults>");
42+
}
43+
44+
@Override
45+
public String getCommandName() {
46+
return "algorithms-evaluation";
47+
}
48+
49+
@Override
50+
public void premain(String[] args) {
51+
}
52+
53+
public void main(String[] args) {
54+
try {
55+
checkCommandLineArguments(args);
56+
Path datasetPath = Paths.get(args[1]);
57+
List<String> algorithmsNames = Arrays.asList(args[2].split(","));
58+
Path pathToSaveResults = Paths.get(args[3]);
59+
List<Algorithm> algorithmsToEvaluate;
60+
if (algorithmsNames.get(0).equals("")) {
61+
algorithmsToEvaluate = AlgorithmsRepository.getAvailableAlgorithms();
62+
} else {
63+
algorithmsToEvaluate = algorithmsNames.stream()
64+
.map(algorithmName -> AlgorithmsRepository.getAlgorithmByName(algorithmName)
65+
.orElseThrow(() -> new IllegalArgumentException("No such algorithm")))
66+
.collect(Collectors.toList());
67+
}
68+
List<EvaluationResult> evaluationResults = new ArrayList<>();
69+
for (Algorithm algorithm : algorithmsToEvaluate) {
70+
evaluationResults.add(JBAlgorithmEvaluator.evaluateDataset(datasetPath, algorithm));
71+
}
72+
evaluationResults.forEach(this::printEvaluationResult);
73+
if (!pathToSaveResults.toString().equals("")) {
74+
EvaluationResultsWriter.writeTable(evaluationResults, pathToSaveResults);
75+
}
76+
} catch (Throwable throwable) {
77+
System.out.println(throwable.getClass().getSimpleName() + ": " + throwable.getMessage());
78+
throwable.printStackTrace();
79+
} finally {
80+
APPLICATION.exit(true, true);
81+
}
82+
}
83+
84+
private void printEvaluationResult(EvaluationResult evaluationResult) {
85+
System.out.println("==================");
86+
System.out.println("EVALUATION RESULT FOR " + evaluationResult.getAlgorithm().getDescriptionString());
87+
System.out.println("Number of good: " + evaluationResult.getNumberOfGood());
88+
System.out.println("Number of found good: " + evaluationResult.getNumberOfFoundGood());
89+
System.out.println("Number of bad: " + evaluationResult.getNumberOfBad());
90+
System.out.println("Number of found bad: " + evaluationResult.getNumberOfFoundBad());
91+
System.out.println("Number of found others: " + evaluationResult.getNumberOfFoundOthers());
92+
System.out.println("Good precision: " + evaluationResult.getGoodPrecision());
93+
System.out.println("Bad precision: " + evaluationResult.getBadPrecision());
94+
System.out.println("Good recall: " + evaluationResult.getGoodRecall());
95+
System.out.println("Bad recall: " + evaluationResult.getBadRecall());
96+
System.out.println("Mean squared error (MSE): " + evaluationResult.getMSE());
97+
System.out.println("Mean error (ME): " + evaluationResult.getME());
98+
}
99+
}

0 commit comments

Comments
 (0)