@@ -171,13 +171,13 @@ module API {
171
171
* Gets a node such that there is an edge in the API graph between this node and the other
172
172
* one, and that edge is labeled with `lbl`.
173
173
*/
174
- Node getASuccessor ( string lbl ) { Impl:: edge ( this , lbl , result ) }
174
+ Node getASuccessor ( Label :: ApiLabel lbl ) { Impl:: edge ( this , lbl , result ) }
175
175
176
176
/**
177
177
* Gets a node such that there is an edge in the API graph between that other node and
178
178
* this one, and that edge is labeled with `lbl`
179
179
*/
180
- Node getAPredecessor ( string lbl ) { this = result .getASuccessor ( lbl ) }
180
+ Node getAPredecessor ( Label :: ApiLabel lbl ) { this = result .getASuccessor ( lbl ) }
181
181
182
182
/**
183
183
* Gets a node such that there is an edge in the API graph between this node and the other
@@ -225,9 +225,8 @@ module API {
225
225
length = 0 and
226
226
result = ""
227
227
or
228
- exists ( Node pred , string lbl , string predpath |
228
+ exists ( Node pred , Label :: ApiLabel lbl , string predpath |
229
229
Impl:: edge ( pred , lbl , this ) and
230
- lbl != "" and
231
230
predpath = pred .getAPath ( length - 1 ) and
232
231
exists ( string dot | if length = 1 then dot = "" else dot = "." |
233
232
result = predpath + dot + lbl and
@@ -328,7 +327,7 @@ module API {
328
327
* node labeled `lbl` in the API graph.
329
328
*/
330
329
pragma [ nomagic]
331
- private predicate useRoot ( string lbl , DataFlow:: Node ref ) {
330
+ private predicate useRoot ( Label :: ApiLabel lbl , DataFlow:: Node ref ) {
332
331
exists ( string name , ConstantReadAccess read |
333
332
read = ref .asExpr ( ) .getExpr ( ) and
334
333
lbl = Label:: member ( read .getName ( ) )
@@ -345,7 +344,7 @@ module API {
345
344
* Holds if `ref` is a use of a node that should have an incoming edge labeled `lbl`,
346
345
* from a use node that flows to `node`.
347
346
*/
348
- private predicate useStep ( string lbl , DataFlow:: Node node , DataFlow:: Node ref ) {
347
+ private predicate useStep ( Label :: ApiLabel lbl , DataFlow:: Node node , DataFlow:: Node ref ) {
349
348
// // Referring to an attribute on a node that is a use of `base`:
350
349
// pred = `Rails` part of `Rails::Whatever`
351
350
// lbl = `Whatever`
@@ -433,7 +432,7 @@ module API {
433
432
/** Gets a data flow node that flows to the RHS of a def-node. */
434
433
private DataFlow:: LocalSourceNode defCand ( ) { result = defCand ( TypeBackTracker:: end ( ) ) }
435
434
436
- private string getLabelFromArgumentPosition ( DataFlowDispatch:: ArgumentPosition pos ) {
435
+ private Label :: ApiLabel getLabelFromArgumentPosition ( DataFlowDispatch:: ArgumentPosition pos ) {
437
436
exists ( int n |
438
437
pos .isPositional ( n ) and
439
438
result = Label:: parameter ( n )
@@ -448,7 +447,7 @@ module API {
448
447
result = Label:: blockParameter ( )
449
448
}
450
449
451
- private string getLabelFromParameterPosition ( DataFlowDispatch:: ParameterPosition pos ) {
450
+ private Label :: ApiLabel getLabelFromParameterPosition ( DataFlowDispatch:: ParameterPosition pos ) {
452
451
exists ( int n |
453
452
pos .isPositional ( n ) and
454
453
result = Label:: parameter ( n )
@@ -468,7 +467,7 @@ module API {
468
467
*/
469
468
pragma [ nomagic]
470
469
private predicate argumentStep (
471
- string lbl , DataFlow:: CallNode call , DataFlowPrivate:: ArgumentNode argument
470
+ Label :: ApiLabel lbl , DataFlow:: CallNode call , DataFlowPrivate:: ArgumentNode argument
472
471
) {
473
472
exists ( DataFlowDispatch:: ArgumentPosition argPos |
474
473
argument .sourceArgumentOf ( call .asExpr ( ) , argPos ) and
@@ -481,7 +480,7 @@ module API {
481
480
*/
482
481
pragma [ nomagic]
483
482
private predicate parameterStep (
484
- string lbl , DataFlow:: Node callable , DataFlowPrivate:: ParameterNodeImpl paramNode
483
+ Label :: ApiLabel lbl , DataFlow:: Node callable , DataFlowPrivate:: ParameterNodeImpl paramNode
485
484
) {
486
485
exists ( DataFlowDispatch:: ParameterPosition paramPos |
487
486
paramNode .isSourceParameterOf ( callable .asExpr ( ) .getExpr ( ) , paramPos ) and
@@ -541,7 +540,7 @@ module API {
541
540
* Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`.
542
541
*/
543
542
cached
544
- predicate edge ( TApiNode pred , string lbl , TApiNode succ ) {
543
+ predicate edge ( TApiNode pred , Label :: ApiLabel lbl , TApiNode succ ) {
545
544
/* Every node that is a use of an API component is itself added to the API graph. */
546
545
exists ( DataFlow:: LocalSourceNode ref | succ = MkUse ( ref ) |
547
546
pred = MkRoot ( ) and
@@ -601,49 +600,140 @@ module API {
601
600
/** Gets the shortest distance from the root to `nd` in the API graph. */
602
601
cached
603
602
int distanceFromRoot ( TApiNode nd ) = shortestDistances( MkRoot / 0 , edge / 2 ) ( _, nd , result )
604
- }
605
- }
606
603
607
- private module Label {
608
- /** Gets the `member` edge label for member `m`. */
609
- bindingset [ m]
610
- bindingset [ result ]
611
- string member ( string m ) { result = "getMember(\"" + m + "\")" }
612
-
613
- /** Gets the `member` edge label for the unknown member. */
614
- string unknownMember ( ) { result = "getUnknownMember()" }
615
-
616
- /** Gets the `method` edge label. */
617
- bindingset [ m]
618
- bindingset [ result ]
619
- string method ( string m ) { result = "getMethod(\"" + m + "\")" }
620
-
621
- /** Gets the `return` edge label. */
622
- string return ( ) { result = "getReturn()" }
623
-
624
- string subclass ( ) { result = "getASubclass()" }
625
-
626
- /** Gets the label representing the given keword argument/parameter. */
627
- bindingset [ name]
628
- bindingset [ result ]
629
- string keywordParameter ( string name ) { result = "getKeywordParameter(\"" + name + "\")" }
630
-
631
- /** Gets the label representing the `n`th positional argument/parameter. */
632
- bindingset [ n]
633
- bindingset [ result ]
634
- string parameter ( int n ) {
635
- exists ( string s |
636
- result = parameterByStr ( s ) and
637
- n = s .toInt ( ) and
638
- s = n .toString ( )
639
- )
604
+ /** All the possible labels in the API graph. */
605
+ cached
606
+ newtype TLabel =
607
+ MkLabelMember ( string member ) { member = any ( ConstantReadAccess a ) .getName ( ) } or
608
+ MkLabelUnknownMember ( ) or
609
+ MkLabelMethod ( string m ) { m = any ( DataFlow:: CallNode c ) .getMethodName ( ) } or
610
+ MkLabelReturn ( ) or
611
+ MkLabelSubclass ( ) or
612
+ MkLabelKeywordParameter ( string name ) {
613
+ any ( DataFlowDispatch:: ArgumentPosition arg ) .isKeyword ( name )
614
+ or
615
+ any ( DataFlowDispatch:: ParameterPosition arg ) .isKeyword ( name )
616
+ } or
617
+ MkLabelParameter ( int n ) {
618
+ any ( DataFlowDispatch:: ArgumentPosition c ) .isPositional ( n )
619
+ or
620
+ any ( DataFlowDispatch:: ParameterPosition c ) .isPositional ( n )
621
+ } or
622
+ MkLabelBlockParameter ( )
640
623
}
641
624
642
- /** Gets the label representing the `n`th positional argument/parameter. */
643
- bindingset [ n]
644
- bindingset [ result ]
645
- string parameterByStr ( string n ) { result = "getParameter(" + n + ")" }
625
+ /** Provides classes modeling the various edges (labels) in the API graph. */
626
+ module Label {
627
+ /** A label in the API-graph */
628
+ class ApiLabel extends Impl:: TLabel {
629
+ /** Gets a string representation of this label. */
630
+ string toString ( ) { result = "???" }
631
+ }
632
+
633
+ private import LabelImpl
634
+
635
+ private module LabelImpl {
636
+ private import Impl
637
+
638
+ /** A label for a member, for example a constant. */
639
+ class LabelMember extends ApiLabel {
640
+ private string member ;
641
+
642
+ LabelMember ( ) { this = MkLabelMember ( member ) }
643
+
644
+ /** Gets the member name associated with this label. */
645
+ string getMember ( ) { result = member }
646
+
647
+ override string toString ( ) { result = "getMember(\"" + member + "\")" }
648
+ }
649
+
650
+ /** A label for a member with an unknown name. */
651
+ class LabelUnknownMember extends ApiLabel {
652
+ LabelUnknownMember ( ) { this = MkLabelUnknownMember ( ) }
653
+
654
+ override string toString ( ) { result = "getUnknownMember()" }
655
+ }
656
+
657
+ /** A label for a method. */
658
+ class LabelMethod extends ApiLabel {
659
+ private string method ;
660
+
661
+ LabelMethod ( ) { this = MkLabelMethod ( method ) }
662
+
663
+ /** Gets the method name associated with this label. */
664
+ string getMethod ( ) { result = method }
665
+
666
+ override string toString ( ) { result = "getMethod(\"" + method + "\")" }
667
+ }
668
+
669
+ /** A label for the return value of a method. */
670
+ class LabelReturn extends ApiLabel {
671
+ LabelReturn ( ) { this = MkLabelReturn ( ) }
672
+
673
+ override string toString ( ) { result = "getReturn()" }
674
+ }
675
+
676
+ /** A label for the subclass relationship. */
677
+ class LabelSubclass extends ApiLabel {
678
+ LabelSubclass ( ) { this = MkLabelSubclass ( ) }
646
679
647
- /** Gets the label representing the block argument/parameter. */
648
- string blockParameter ( ) { result = "getBlock()" }
680
+ override string toString ( ) { result = "getASubclass()" }
681
+ }
682
+
683
+ /** A label for a keyword parameter. */
684
+ class LabelKeywordParameter extends ApiLabel {
685
+ private string name ;
686
+
687
+ LabelKeywordParameter ( ) { this = MkLabelKeywordParameter ( name ) }
688
+
689
+ /** Gets the name of the keyword parameter associated with this label. */
690
+ string getName ( ) { result = name }
691
+
692
+ override string toString ( ) { result = "getKeywordParameter(\"" + name + "\")" }
693
+ }
694
+
695
+ /** A label for a parameter. */
696
+ class LabelParameter extends ApiLabel {
697
+ private int n ;
698
+
699
+ LabelParameter ( ) { this = MkLabelParameter ( n ) }
700
+
701
+ /** Gets the parameter number associated with this label. */
702
+ int getIndex ( ) { result = n }
703
+
704
+ override string toString ( ) { result = "getParameter(" + n + ")" }
705
+ }
706
+
707
+ /** A label for a block parameter. */
708
+ class LabelBlockParameter extends ApiLabel {
709
+ LabelBlockParameter ( ) { this = MkLabelBlockParameter ( ) }
710
+
711
+ override string toString ( ) { result = "getBlock()" }
712
+ }
713
+ }
714
+
715
+ /** Gets the `member` edge label for member `m`. */
716
+ LabelMember member ( string m ) { result .getMember ( ) = m }
717
+
718
+ /** Gets the `member` edge label for the unknown member. */
719
+ LabelUnknownMember unknownMember ( ) { any ( ) }
720
+
721
+ /** Gets the `method` edge label. */
722
+ LabelMethod method ( string m ) { result .getMethod ( ) = m }
723
+
724
+ /** Gets the `return` edge label. */
725
+ LabelReturn return ( ) { any ( ) }
726
+
727
+ /** Gets the `subclass` edge label. */
728
+ LabelSubclass subclass ( ) { any ( ) }
729
+
730
+ /** Gets the label representing the given keword argument/parameter. */
731
+ LabelKeywordParameter keywordParameter ( string name ) { result .getName ( ) = name }
732
+
733
+ /** Gets the label representing the `n`th positional argument/parameter. */
734
+ LabelParameter parameter ( int n ) { result .getIndex ( ) = n }
735
+
736
+ /** Gets the label representing the block argument/parameter. */
737
+ LabelBlockParameter blockParameter ( ) { any ( ) }
738
+ }
649
739
}
0 commit comments