@@ -171,13 +171,13 @@ module API {
171171 * Gets a node such that there is an edge in the API graph between this node and the other
172172 * one, and that edge is labeled with `lbl`.
173173 */
174- Node getASuccessor ( string lbl ) { Impl:: edge ( this , lbl , result ) }
174+ Node getASuccessor ( Label :: ApiLabel lbl ) { Impl:: edge ( this , lbl , result ) }
175175
176176 /**
177177 * Gets a node such that there is an edge in the API graph between that other node and
178178 * this one, and that edge is labeled with `lbl`
179179 */
180- Node getAPredecessor ( string lbl ) { this = result .getASuccessor ( lbl ) }
180+ Node getAPredecessor ( Label :: ApiLabel lbl ) { this = result .getASuccessor ( lbl ) }
181181
182182 /**
183183 * 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 {
225225 length = 0 and
226226 result = ""
227227 or
228- exists ( Node pred , string lbl , string predpath |
228+ exists ( Node pred , Label :: ApiLabel lbl , string predpath |
229229 Impl:: edge ( pred , lbl , this ) and
230- lbl != "" and
231230 predpath = pred .getAPath ( length - 1 ) and
232231 exists ( string dot | if length = 1 then dot = "" else dot = "." |
233232 result = predpath + dot + lbl and
@@ -328,7 +327,7 @@ module API {
328327 * node labeled `lbl` in the API graph.
329328 */
330329 pragma [ nomagic]
331- private predicate useRoot ( string lbl , DataFlow:: Node ref ) {
330+ private predicate useRoot ( Label :: ApiLabel lbl , DataFlow:: Node ref ) {
332331 exists ( string name , ConstantReadAccess read |
333332 read = ref .asExpr ( ) .getExpr ( ) and
334333 lbl = Label:: member ( read .getName ( ) )
@@ -345,7 +344,7 @@ module API {
345344 * Holds if `ref` is a use of a node that should have an incoming edge labeled `lbl`,
346345 * from a use node that flows to `node`.
347346 */
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 ) {
349348 // // Referring to an attribute on a node that is a use of `base`:
350349 // pred = `Rails` part of `Rails::Whatever`
351350 // lbl = `Whatever`
@@ -433,7 +432,7 @@ module API {
433432 /** Gets a data flow node that flows to the RHS of a def-node. */
434433 private DataFlow:: LocalSourceNode defCand ( ) { result = defCand ( TypeBackTracker:: end ( ) ) }
435434
436- private string getLabelFromArgumentPosition ( DataFlowDispatch:: ArgumentPosition pos ) {
435+ private Label :: ApiLabel getLabelFromArgumentPosition ( DataFlowDispatch:: ArgumentPosition pos ) {
437436 exists ( int n |
438437 pos .isPositional ( n ) and
439438 result = Label:: parameter ( n )
@@ -448,7 +447,7 @@ module API {
448447 result = Label:: blockParameter ( )
449448 }
450449
451- private string getLabelFromParameterPosition ( DataFlowDispatch:: ParameterPosition pos ) {
450+ private Label :: ApiLabel getLabelFromParameterPosition ( DataFlowDispatch:: ParameterPosition pos ) {
452451 exists ( int n |
453452 pos .isPositional ( n ) and
454453 result = Label:: parameter ( n )
@@ -468,7 +467,7 @@ module API {
468467 */
469468 pragma [ nomagic]
470469 private predicate argumentStep (
471- string lbl , DataFlow:: CallNode call , DataFlowPrivate:: ArgumentNode argument
470+ Label :: ApiLabel lbl , DataFlow:: CallNode call , DataFlowPrivate:: ArgumentNode argument
472471 ) {
473472 exists ( DataFlowDispatch:: ArgumentPosition argPos |
474473 argument .sourceArgumentOf ( call .asExpr ( ) , argPos ) and
@@ -481,7 +480,7 @@ module API {
481480 */
482481 pragma [ nomagic]
483482 private predicate parameterStep (
484- string lbl , DataFlow:: Node callable , DataFlowPrivate:: ParameterNodeImpl paramNode
483+ Label :: ApiLabel lbl , DataFlow:: Node callable , DataFlowPrivate:: ParameterNodeImpl paramNode
485484 ) {
486485 exists ( DataFlowDispatch:: ParameterPosition paramPos |
487486 paramNode .isSourceParameterOf ( callable .asExpr ( ) .getExpr ( ) , paramPos ) and
@@ -541,7 +540,7 @@ module API {
541540 * Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`.
542541 */
543542 cached
544- predicate edge ( TApiNode pred , string lbl , TApiNode succ ) {
543+ predicate edge ( TApiNode pred , Label :: ApiLabel lbl , TApiNode succ ) {
545544 /* Every node that is a use of an API component is itself added to the API graph. */
546545 exists ( DataFlow:: LocalSourceNode ref | succ = MkUse ( ref ) |
547546 pred = MkRoot ( ) and
@@ -601,49 +600,140 @@ module API {
601600 /** Gets the shortest distance from the root to `nd` in the API graph. */
602601 cached
603602 int distanceFromRoot ( TApiNode nd ) = shortestDistances( MkRoot / 0 , edge / 2 ) ( _, nd , result )
604- }
605- }
606603
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 ( )
640623 }
641624
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 ( ) }
646679
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+ }
649739}
0 commit comments