Skip to content

Commit a3e70e5

Browse files
committed
Add stream method call counting.
1 parent 63775f2 commit a3e70e5

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed

edu.cuny.hunter.streamrefactoring.eval/plugin.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
description="Evaluates the Convert Stream to Parallel refactoring"
88
id="edu.cuny.hunter.evaluate.convert.stream.to.parallel.refactoring.command"
99
name="Evaluate Convert Stream To Parallel Refactoring"/>
10+
<command
11+
categoryId="org.eclipse.jdt.ui.category.source"
12+
defaultHandler="edu.cuny.hunter.streamrefactoring.eval.handlers.StreamMethodCallFinder"
13+
description="Counts the number of methods called that are stream methods"
14+
id="edu.cuny.hunter.count.stream.methods.command"
15+
name="Count the number of stream methods called">
16+
</command>
1017
</extension>
1118
<extension point="org.eclipse.ui.handlers">
1219
<handler
@@ -20,5 +27,21 @@
2027
</with>
2128
</activeWhen>
2229
</handler>
30+
<handler
31+
class="edu.cuny.hunter.streamrefactoring.eval.handlers.StreamMethodCallFinder"
32+
commandId="edu.cuny.hunter.count.stream.methods.command">
33+
<activeWhen>
34+
<with
35+
variable="selection">
36+
<iterate
37+
ifEmpty="false"
38+
operator="or">
39+
<instanceof
40+
value="org.eclipse.jdt.core.IJavaProject">
41+
</instanceof>
42+
</iterate>
43+
</with>
44+
</activeWhen>
45+
</handler>
2346
</extension>
2447
</plugin>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package edu.cuny.hunter.streamrefactoring.eval.handlers;
2+
3+
import java.io.FileWriter;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
import java.util.Map.Entry;
7+
8+
import org.apache.commons.csv.CSVFormat;
9+
import org.apache.commons.csv.CSVPrinter;
10+
import org.eclipse.core.commands.AbstractHandler;
11+
import org.eclipse.core.commands.ExecutionEvent;
12+
import org.eclipse.core.commands.ExecutionException;
13+
import org.eclipse.core.runtime.IStatus;
14+
import org.eclipse.core.runtime.Status;
15+
import org.eclipse.core.runtime.SubMonitor;
16+
import org.eclipse.core.runtime.jobs.Job;
17+
import org.eclipse.jdt.core.ICompilationUnit;
18+
import org.eclipse.jdt.core.IJavaElement;
19+
import org.eclipse.jdt.core.IJavaProject;
20+
import org.eclipse.jdt.core.IPackageFragment;
21+
import org.eclipse.jdt.core.IPackageFragmentRoot;
22+
import org.eclipse.jdt.core.JavaModelException;
23+
import org.eclipse.jdt.core.dom.AST;
24+
import org.eclipse.jdt.core.dom.ASTNode;
25+
import org.eclipse.jdt.core.dom.ASTParser;
26+
import org.eclipse.jdt.core.dom.ASTVisitor;
27+
import org.eclipse.jdt.core.dom.ITypeBinding;
28+
import org.eclipse.jdt.core.dom.MethodInvocation;
29+
import org.eclipse.jdt.core.dom.SimpleName;
30+
import org.osgi.framework.FrameworkUtil;
31+
32+
import edu.cuny.hunter.streamrefactoring.eval.utils.Util;
33+
34+
public class StreamMethodCallFinder extends AbstractHandler {
35+
36+
private static int getNumberOfCompilationUnits(IJavaProject[] javaProjects) throws JavaModelException {
37+
int ret = 0;
38+
for (IJavaProject javaProject : javaProjects) {
39+
IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
40+
41+
for (IPackageFragmentRoot root : roots) {
42+
IJavaElement[] children = root.getChildren();
43+
44+
for (IJavaElement child : children)
45+
if (child.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
46+
IPackageFragment fragment = (IPackageFragment) child;
47+
ICompilationUnit[] units = fragment.getCompilationUnits();
48+
ret += units.length;
49+
}
50+
}
51+
}
52+
return ret;
53+
}
54+
55+
@Override
56+
public Object execute(ExecutionEvent event) throws ExecutionException {
57+
Job.create("Finding stream method calls...", monitor -> {
58+
try (CSVPrinter printer = new CSVPrinter(new FileWriter("stream_calls.csv"),
59+
CSVFormat.DEFAULT.withHeader("subject", "method", "calls"))) {
60+
61+
IJavaProject[] javaProjects = Util.getSelectedJavaProjectsFromEvent(event);
62+
63+
int work = getNumberOfCompilationUnits(javaProjects);
64+
65+
SubMonitor subMonitor = SubMonitor.convert(monitor, "Analyzing projects.", work);
66+
67+
for (IJavaProject javaProject : javaProjects) {
68+
if (!javaProject.isStructureKnown())
69+
throw new IllegalStateException(
70+
String.format("Project: %s should compile beforehand.", javaProject.getElementName()));
71+
72+
Map<String, Integer> calledMethodNameToCount = new HashMap<>();
73+
74+
IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
75+
76+
for (IPackageFragmentRoot root : roots) {
77+
IJavaElement[] children = root.getChildren();
78+
79+
for (IJavaElement child : children)
80+
if (child.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
81+
IPackageFragment fragment = (IPackageFragment) child;
82+
ICompilationUnit[] units = fragment.getCompilationUnits();
83+
84+
for (ICompilationUnit unit : units) {
85+
ASTParser parser = ASTParser.newParser(AST.JLS12);
86+
parser.setSource(unit);
87+
parser.setResolveBindings(true);
88+
ASTNode node = parser.createAST(subMonitor.split(1));
89+
90+
node.accept(new ASTVisitor(false) {
91+
92+
@Override
93+
public boolean visit(MethodInvocation node) {
94+
ITypeBinding declaringClass = node.resolveMethodBinding()
95+
.getDeclaringClass().getErasure();
96+
97+
if (declaringClass.getPackage().getName().startsWith("java.util.stream")) {
98+
String declaringClassName = declaringClass.getQualifiedName();
99+
SimpleName methodName = node.getName();
100+
String qualfiedMethodName = declaringClassName + "." + methodName;
101+
102+
calledMethodNameToCount.merge(qualfiedMethodName, 1, Integer::sum);
103+
}
104+
return super.visit(node);
105+
}
106+
});
107+
}
108+
}
109+
}
110+
111+
for (Entry<String, Integer> entry : calledMethodNameToCount.entrySet())
112+
printer.printRecord(javaProject.getElementName(), entry.getKey(), entry.getValue());
113+
}
114+
115+
} catch (Exception e) {
116+
return new Status(IStatus.ERROR, FrameworkUtil.getBundle(this.getClass()).getSymbolicName(),
117+
"Encountered exception during evaluation", e);
118+
} finally {
119+
SubMonitor.done(monitor);
120+
}
121+
122+
return new Status(IStatus.OK, FrameworkUtil.getBundle(this.getClass()).getSymbolicName(),
123+
"Finding successful.");
124+
}).schedule();
125+
126+
return null;
127+
}
128+
}

0 commit comments

Comments
 (0)