13
13
import java .util .function .Predicate ;
14
14
import java .util .logging .Logger ;
15
15
import java .util .stream .BaseStream ;
16
+ import java .util .stream .Collectors ;
16
17
17
18
import org .eclipse .jdt .core .IJavaProject ;
18
19
import org .eclipse .jdt .core .IType ;
@@ -215,7 +216,10 @@ public static Set<Entrypoint> findEntryPoints(IClassHierarchy classHierarchy) {
215
216
final Set <Entrypoint > result = new HashSet <>();
216
217
217
218
for (IClass klass : classHierarchy )
218
- if (!AnalysisUtils .isJDKClass (klass ))
219
+ if (!AnalysisUtils .isJDKClass (klass )) {
220
+ boolean entryPointClass = false ;
221
+ boolean addedInstanceMethod = false ;
222
+
219
223
// iterate over all declared methods
220
224
for (com .ibm .wala .classLoader .IMethod method : klass .getDeclaredMethods ()) {
221
225
// if method has an annotation
@@ -226,6 +230,12 @@ public static Set<Entrypoint> findEntryPoints(IClassHierarchy classHierarchy) {
226
230
for (Annotation annotation : ((ShrikeCTMethod ) method ).getAnnotations (true ))
227
231
if (isEntryPointClass (annotation .getType ().getName ())) {
228
232
addEntryPoint (result , method , classHierarchy );
233
+ entryPointClass = true ;
234
+
235
+ // if the method is an instance method.
236
+ if (!method .isStatic ())
237
+ addedInstanceMethod = true ;
238
+
229
239
break ;
230
240
}
231
241
} catch (InvalidClassFileException e ) {
@@ -234,9 +244,47 @@ public static Set<Entrypoint> findEntryPoints(IClassHierarchy classHierarchy) {
234
244
}
235
245
}
236
246
247
+ if (entryPointClass ) {
248
+ // add any static initializers since the class will be loaded.
249
+ addEntryPoint (result , klass .getClassInitializer (), classHierarchy );
250
+
251
+ if (addedInstanceMethod ) {
252
+ // add a constructor.
253
+ IMethod ctor = getUniqueConstructor (klass );
254
+ addEntryPoint (result , ctor , classHierarchy );
255
+ }
256
+ }
257
+ }
258
+
237
259
return result ;
238
260
}
239
261
262
+ /**
263
+ * A null get value means that there is no unique ctor.
264
+ *
265
+ * @param klass
266
+ * The {@link IClass} to find a unique ctor.
267
+ * @return The one and only ctor for klass and <code>null</code> if it doesn't
268
+ * exist.
269
+ */
270
+ private static IMethod getUniqueConstructor (IClass klass ) {
271
+ // try to find the default ctor.
272
+ IMethod ctor = klass .getMethod (MethodReference .initSelector );
273
+
274
+ // if not found, get all constructors.
275
+ if (ctor == null ) {
276
+ Set <IMethod > allDeclaredConstructors = klass .getDeclaredMethods ().stream ()
277
+ .filter (m -> m .getName ().startsWith (MethodReference .initAtom )).collect (Collectors .toSet ());
278
+
279
+ // if there is a unique one.
280
+ if (allDeclaredConstructors .size () == 1 )
281
+ // use that.
282
+ ctor = allDeclaredConstructors .iterator ().next ();
283
+ }
284
+
285
+ return ctor ;
286
+ }
287
+
240
288
static Set <ITypeBinding > getAllInterfaces (ITypeBinding type ) {
241
289
Set <ITypeBinding > ret = new HashSet <>();
242
290
ITypeBinding [] interfaces = type .getInterfaces ();
0 commit comments