4
4
5
5
import java .io .IOException ;
6
6
import java .util .Collection ;
7
+ import java .util .HashMap ;
7
8
import java .util .HashSet ;
8
9
import java .util .Iterator ;
9
10
import java .util .Map ;
23
24
import com .ibm .safe .internal .exceptions .PropertiesException ;
24
25
import com .ibm .wala .ipa .callgraph .AnalysisOptions ;
25
26
import com .ibm .wala .ipa .callgraph .AnalysisOptions .ReflectionOptions ;
27
+ import com .ibm .wala .ipa .callgraph .CallGraph ;
26
28
import com .ibm .wala .ipa .callgraph .CallGraphBuilderCancelException ;
27
29
import com .ibm .wala .ipa .callgraph .Entrypoint ;
28
30
import com .ibm .wala .ipa .callgraph .propagation .InstanceKey ;
@@ -46,15 +48,18 @@ private static void addImplicitEntryPoints(Collection<Entrypoint> target, Iterab
46
48
LOGGER .info (() -> "Adding implicit entry point: " + implicitEntryPoint );
47
49
}
48
50
49
- private Set <EclipseProjectAnalysisEngine <InstanceKey >> enginesWithBuiltCallGraphs = new HashSet <>();
51
+ /**
52
+ * Map from {@link EclipseProjectAnalysisEngine}s that have their
53
+ * {@link CallGraph}s built to the {@link Entrypoint}s that were used to build
54
+ * the graph.
55
+ */
56
+ private Map <EclipseProjectAnalysisEngine <InstanceKey >, Collection <Entrypoint >> enginesWithBuiltCallGraphsToEntrypointsUsed = new HashMap <>();
50
57
51
58
private boolean findImplicitEntryPoints = true ;
52
59
53
60
private boolean findImplicitTestEntryPoints ;
54
61
55
62
private Set <Stream > streamSet = new HashSet <>();
56
-
57
- private Set <Entrypoint > entryPoints = new HashSet <>();
58
63
59
64
public StreamAnalyzer () {
60
65
this (false );
@@ -74,7 +79,14 @@ public StreamAnalyzer(boolean visitDocTags, boolean findImplicitEntryPoints, boo
74
79
this .findImplicitTestEntryPoints = findImplicitTestEntryPoints ;
75
80
}
76
81
77
- public void analyze () throws CoreException {
82
+ /**
83
+ * Analyzes this {@link StreamAnalyzer}'s streams.
84
+ *
85
+ * @return {@link Map} of project's analyzed along with the entry points used.
86
+ */
87
+ public Map <IJavaProject , Collection <Entrypoint >> analyze () throws CoreException {
88
+ Map <IJavaProject , Collection <Entrypoint >> ret = new HashMap <>();
89
+
78
90
// collect the projects to be analyzed.
79
91
Map <IJavaProject , Set <Stream >> projectToStreams = this .getStreamSet ().stream ().filter (s -> s .getStatus ().isOK ())
80
92
.collect (Collectors .groupingBy (Stream ::getCreationJavaProject , Collectors .toSet ()));
@@ -92,21 +104,24 @@ public void analyze() throws CoreException {
92
104
}
93
105
94
106
// build the call graph for the project.
107
+ Collection <Entrypoint > entryPoints = null ;
95
108
try {
96
- this .buildCallGraph (engine );
97
- } catch (NoEntryPointException e ) {
98
- LOGGER .log (Level .WARNING ,
99
- "No entry point exception caught while processing: " + engine .getProject ().getElementName (), e );
109
+ entryPoints = this .buildCallGraph (engine );
110
+ } catch (IOException | CoreException | CancelException e ) {
111
+ LOGGER .log (Level .SEVERE ,
112
+ "Exception encountered while building call graph for: " + project .getElementName () + "." , e );
113
+ throw new RuntimeException (e );
114
+ }
115
+
116
+ // save the entry points.
117
+ ret .put (project , entryPoints );
100
118
119
+ if (entryPoints .isEmpty ()) {
101
120
// add a status entry for each stream in the project
102
121
for (Stream stream : projectToStreams .get (project ))
103
122
stream .addStatusEntry (PreconditionFailure .NO_ENTRY_POINT ,
104
123
"Project: " + engine .getProject ().getElementName () + " has no entry points." );
105
- return ;
106
- } catch (IOException | CoreException | CancelException e ) {
107
- LOGGER .log (Level .SEVERE ,
108
- "Exception encountered while building call graph for: " + project .getElementName () + "." , e );
109
- throw new RuntimeException (e );
124
+ return ret ;
110
125
}
111
126
112
127
OrderingInference orderingInference = new OrderingInference (engine .getClassHierarchy ());
@@ -149,12 +164,23 @@ public void analyze() throws CoreException {
149
164
.collect (Collectors .toSet ()))
150
165
stream .check ();
151
166
} // end for each stream.
167
+
168
+ return ret ;
152
169
}
153
170
154
- protected void buildCallGraph (EclipseProjectAnalysisEngine <InstanceKey > engine )
155
- throws IOException , CoreException , CallGraphBuilderCancelException , CancelException , NoEntryPointException {
171
+ /**
172
+ * Builds the call graph that is part of the
173
+ * {@link EclipseProjectAnalysisEngine}.
174
+ *
175
+ * @param engine
176
+ * The EclipseProjectAnalysisEngine for which to build the call
177
+ * graph.
178
+ * @return The {@link Entrypoint}s used in building the {@link CallGraph}.
179
+ */
180
+ protected Collection <Entrypoint > buildCallGraph (EclipseProjectAnalysisEngine <InstanceKey > engine )
181
+ throws IOException , CoreException , CallGraphBuilderCancelException , CancelException {
156
182
// if we haven't built the call graph yet.
157
- if (!this .enginesWithBuiltCallGraphs .contains (engine )) {
183
+ if (!this .enginesWithBuiltCallGraphsToEntrypointsUsed . keySet () .contains (engine )) {
158
184
// find explicit entry points.
159
185
Set <Entrypoint > entryPoints = Util .findEntryPoints (engine .getClassHierarchy ());
160
186
entryPoints .forEach (ep -> LOGGER .info (() -> "Adding explicit entry point: " + ep ));
@@ -177,8 +203,7 @@ protected void buildCallGraph(EclipseProjectAnalysisEngine<InstanceKey> engine)
177
203
}
178
204
179
205
if (entryPoints .isEmpty ())
180
- throw new NoEntryPointException (
181
- "Project: " + engine .getProject ().getElementName () + " has no entry points." );
206
+ LOGGER .warning (() -> "Project: " + engine .getProject ().getElementName () + " has no entry points." );
182
207
183
208
// set options.
184
209
AnalysisOptions options = engine .getDefaultOptions (entryPoints );
@@ -195,10 +220,9 @@ protected void buildCallGraph(EclipseProjectAnalysisEngine<InstanceKey> engine)
195
220
}
196
221
// TODO: Can I slice the graph so that only nodes relevant to the
197
222
// instance in question are present?
198
- this .enginesWithBuiltCallGraphs .add (engine );
199
-
200
- setEntryPoints (entryPoints );
223
+ this .enginesWithBuiltCallGraphsToEntrypointsUsed .put (engine , entryPoints );
201
224
}
225
+ return this .enginesWithBuiltCallGraphsToEntrypointsUsed .get (engine );
202
226
}
203
227
204
228
public Set <Stream > getStreamSet () {
@@ -252,13 +276,4 @@ public boolean visit(MethodInvocation node) {
252
276
253
277
return super .visit (node );
254
278
}
255
-
256
- protected void setEntryPoints (Set <Entrypoint > entryPoints ) {
257
- this .entryPoints = entryPoints ;
258
- }
259
-
260
- public Set <Entrypoint > getEntryPoints () {
261
- return this .entryPoints ;
262
- }
263
-
264
279
}
0 commit comments