@@ -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
@@ -306,7 +305,7 @@ module API {
306305 * shortest length.
307306 */
308307 cached
309- private module Impl {
308+ module Impl {
310309 cached
311310 newtype TApiNode =
312311 /** The root of the API graph. */
@@ -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
@@ -602,48 +601,133 @@ module API {
602601 cached
603602 int distanceFromRoot ( TApiNode nd ) = shortestDistances( MkRoot / 0 , edge / 2 ) ( _, nd , result )
604603 }
605- }
606604
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- )
640- }
605+ module Label {
606+ /** A label in the API-graph */
607+ class ApiLabel extends TLabel {
608+ /** Gets a string representation of this label. */
609+ string toString ( ) { result = "???" }
610+ }
611+
612+ private import LabelImpl
613+
614+ private module LabelImpl {
615+ newtype TLabel =
616+ MkLabelMember ( string member ) { member = any ( ConstantReadAccess a ) .getName ( ) } or
617+ MkLabelUnknownMember ( ) or
618+ MkLabelMethod ( string m ) { m = any ( DataFlow:: CallNode c ) .getMethodName ( ) } or
619+ MkLabelReturn ( ) or
620+ MkLabelSubclass ( ) or
621+ MkLabelKeywordParameter ( string name ) {
622+ any ( DataFlowDispatch:: ArgumentPosition arg ) .isKeyword ( name )
623+ or
624+ any ( DataFlowDispatch:: ParameterPosition arg ) .isKeyword ( name )
625+ } or
626+ MkLabelParameter ( int n ) {
627+ any ( DataFlowDispatch:: ArgumentPosition c ) .isPositional ( n )
628+ or
629+ any ( DataFlowDispatch:: ParameterPosition c ) .isPositional ( n )
630+ } or
631+ MkLabelBlockParameter ( )
632+
633+ /** A label for the member named `prop`. */
634+ class LabelMember extends ApiLabel {
635+ string member ;
636+
637+ LabelMember ( ) { this = MkLabelMember ( member ) }
638+
639+ /** Gets the property associated with this label. */
640+ string getMember ( ) { result = member }
641+
642+ override string toString ( ) { result = "getMember(\"" + member + "\")" }
643+ }
644+
645+ /** A label for a member with an unknown name. */
646+ class LabelUnknownMember extends ApiLabel {
647+ LabelUnknownMember ( ) { this = MkLabelUnknownMember ( ) }
648+
649+ override string toString ( ) { result = "getUnknownMember()" }
650+ }
651+
652+ /** A label for the method named `method`. */
653+ class LabelMethod extends ApiLabel {
654+ string method ;
655+
656+ LabelMethod ( ) { this = MkLabelMethod ( method ) }
657+
658+ /** Gets the method name associated with this label. */
659+ string getMethod ( ) { result = method }
660+
661+ override string toString ( ) { result = "getMethod(\"" + method + "\")" }
662+ }
663+
664+ /** A label for the return value of a method. */
665+ class LabelReturn extends ApiLabel {
666+ LabelReturn ( ) { this = MkLabelReturn ( ) }
667+
668+ override string toString ( ) { result = "getReturn()" }
669+ }
670+
671+ /** A label for the subclass relationship. */
672+ class LabelSubclass extends ApiLabel {
673+ LabelSubclass ( ) { this = MkLabelSubclass ( ) }
641674
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 + ")" }
675+ override string toString ( ) { result = "getASubclass()" }
676+ }
646677
647- /** Gets the label representing the block argument/parameter. */
648- string blockParameter ( ) { result = "getBlock()" }
678+ /** A label for a keyword parameter. */
679+ class LabelKeywordParameter extends ApiLabel {
680+ string name ;
681+
682+ LabelKeywordParameter ( ) { this = MkLabelKeywordParameter ( name ) }
683+
684+ /** Gets the name of the keyword parameter associated with this label. */
685+ string getName ( ) { result = name }
686+
687+ override string toString ( ) { result = "getKeywordParameter(\"" + name + "\")" }
688+ }
689+
690+ /** A label for a parameter. */
691+ class LabelParameter extends ApiLabel {
692+ int n ;
693+
694+ LabelParameter ( ) { this = MkLabelParameter ( n ) }
695+
696+ /** Gets the parameter number associated with this label. */
697+ int getIndex ( ) { result = n }
698+
699+ override string toString ( ) { result = "getParameter(" + n + ")" }
700+ }
701+
702+ /** A label for a block parameter. */
703+ class LabelBlockParameter extends ApiLabel {
704+ LabelBlockParameter ( ) { this = MkLabelBlockParameter ( ) }
705+
706+ override string toString ( ) { result = "getBlock()" }
707+ }
708+ }
709+
710+ /** Gets the `member` edge label for member `m`. */
711+ LabelMember member ( string m ) { result .getMember ( ) = m }
712+
713+ /** Gets the `member` edge label for the unknown member. */
714+ LabelUnknownMember unknownMember ( ) { any ( ) }
715+
716+ /** Gets the `method` edge label. */
717+ LabelMethod method ( string m ) { result .getMethod ( ) = m }
718+
719+ /** Gets the `return` edge label. */
720+ LabelReturn return ( ) { any ( ) }
721+
722+ LabelSubclass subclass ( ) { any ( ) }
723+
724+ /** Gets the label representing the given keword argument/parameter. */
725+ LabelKeywordParameter keywordParameter ( string name ) { result .getName ( ) = name }
726+
727+ /** Gets the label representing the `n`th positional argument/parameter. */
728+ LabelParameter parameter ( int n ) { result .getIndex ( ) = n }
729+
730+ /** Gets the label representing the block argument/parameter. */
731+ LabelBlockParameter blockParameter ( ) { any ( ) }
732+ }
649733}
0 commit comments