@@ -378,6 +378,10 @@ module API {
378
378
*
379
379
* Anything in the global scope is considered to be an entry point, but
380
380
* additional entry points may be added by extending this class.
381
+ *
382
+ * By default, instances of this class will have a single edge from the root
383
+ * of the API graph. If you wish to construct more complex paths to an entry
384
+ * point, override the `edge` predicate.
381
385
*/
382
386
abstract class EntryPoint extends string {
383
387
bindingset [ this ]
@@ -400,6 +404,41 @@ module API {
400
404
401
405
/** Gets an API-node for this entry point. */
402
406
API:: Node getANode ( ) { result = root ( ) .getASuccessor ( Label:: entryPoint ( this ) ) }
407
+
408
+ /**
409
+ * Holds if there is an edge from `pred` to this entry point, with label
410
+ * `lbl`. Override this predicate to define new paths to this entry point.
411
+ *
412
+ * For example, to define an entry point for `ActiveStorage::Attachment` we
413
+ * can use an intermediate entry point for `ActiveStorage`:
414
+ *
415
+ * ```ql
416
+ * class ActiveStorage extends EntryPoint {
417
+ * ActiveStorage() { this = "ActiveStorage" }
418
+ *
419
+ * override predicate edge(Node pred, Label::ApiLabel lbl) {
420
+ * pred = root() and lbl = Label::member("ActiveStorage")
421
+ * }
422
+ * }
423
+ *
424
+ * class Attachment extends EntryPoint {
425
+ * Attachment() { this = "ActiveStorage::Attachment" }
426
+ *
427
+ * override predicate edge(Node pred, Label::ApiLabel lbl) {
428
+ * pred = getTopLevelMember("ActiveStorage") and
429
+ * lbl = Label::member("Attachment")
430
+ * }
431
+ *
432
+ * override DataFlow::LocalSourceNode getAUse() { result = customAttachmentPredicate() }
433
+ * }
434
+ * ```
435
+ *
436
+ * This means that
437
+ * `getTopLevelMember("ActiveStorage").getMember("Attachment")` will return
438
+ * results from `customAttachmentPredicate()`, even if there are no
439
+ * references to `ActiveStorage` or `Attachment` in the codebase.
440
+ */
441
+ predicate edge ( API:: Node pred , Label:: ApiLabel lbl ) { none ( ) }
403
442
}
404
443
405
444
// Ensure all entry points are imported from ApiGraphs.qll
@@ -718,6 +757,8 @@ module API {
718
757
exists ( EntryPoint entry |
719
758
pred = root ( ) and
720
759
lbl = Label:: entryPoint ( entry )
760
+ or
761
+ entry .edge ( pred , lbl )
721
762
|
722
763
succ = MkDef ( entry .getASink ( ) )
723
764
or
0 commit comments