@@ -352,7 +352,29 @@ class CallableValue extends Value {
352352 result = this .( CallableObjectInternal ) .getParameterByName ( name )
353353 }
354354
355- /** Gets the argument corresponding to the `n'th parameter node of this callable. */
355+ /**
356+ * Gets the argument in `call` corresponding to the `n`'th positional parameter of this callable.
357+ *
358+ * Use this method instead of `call.getArg(n)` to handle the fact that this function might be used as
359+ * a bound-method, such that argument `n` of the call corresponds to the `n+1` parameter of the callable.
360+ *
361+ * This method also gives results when the argument is passed as a keyword argument in `call`, as long
362+ * as `this` is not a builtin function or a builtin method.
363+ *
364+ * Examples:
365+ *
366+ * - if `this` represents the `PythonFunctionValue` for `def func(a, b):`, and `call` represents
367+ * `func(10, 20)`, then `getArgumentForCall(call, 0)` will give the `ControlFlowNode` for `10`.
368+ *
369+ * - with `call` representing `func(b=20, a=10)`, `getArgumentForCall(call, 0)` will give
370+ * the `ControlFlowNode` for `10`.
371+ *
372+ * - if `this` represents the `PythonFunctionValue` for `def func(self, a, b):`, and `call`
373+ * represents `foo.func(10, 20)`, then `getArgumentForCall(call, 1)` will give the
374+ * `ControlFlowNode` for `10`.
375+ * Note: There will also exist a `BoundMethodValue bm` where `bm.getArgumentForCall(call, 0)`
376+ * will give the `ControlFlowNode` for `10` (notice the shift in index used).
377+ */
356378 cached
357379 ControlFlowNode getArgumentForCall ( CallNode call , int n ) {
358380 exists ( ObjectInternal called , int offset |
@@ -363,7 +385,7 @@ class CallableValue extends Value {
363385 or
364386 exists ( string name |
365387 call .getArgByName ( name ) = result and
366- this .( PythonFunctionObjectInternal ) . getScope ( ) . getArg ( n + offset ) . getName ( ) = name
388+ this .getParameter ( n ) . getId ( ) = name
367389 )
368390 or
369391 called instanceof BoundMethodObjectInternal and
@@ -373,21 +395,37 @@ class CallableValue extends Value {
373395 )
374396 }
375397
376- /** Gets the argument corresponding to the `name`d parameter node of this callable. */
398+ /**
399+ * Gets the argument in `call` corresponding to the `name`d keyword parameter of this callable.
400+ *
401+ * This method also gives results when the argument is passed as a positional argument in `call`, as long
402+ * as `this` is not a builtin function or a builtin method.
403+ *
404+ * Examples:
405+ *
406+ * - if `this` represents the `PythonFunctionValue` for `def func(a, b):`, and `call` represents
407+ * `func(10, 20)`, then `getNamedArgumentForCall(call, "a")` will give the `ControlFlowNode` for `10`.
408+ *
409+ * - with `call` representing `func(b=20, a=10)`, `getNamedArgumentForCall(call, "a")` will give
410+ * the `ControlFlowNode` for `10`.
411+ *
412+ * - if `this` represents the `PythonFunctionValue` for `def func(self, a, b):`, and `call`
413+ * represents `foo.func(10, 20)`, then `getNamedArgumentForCall(call, "a")` will give the
414+ * `ControlFlowNode` for `10`.
415+ */
377416 cached
378417 ControlFlowNode getNamedArgumentForCall ( CallNode call , string name ) {
379418 exists ( CallableObjectInternal called , int offset |
380419 PointsToInternal:: pointsTo ( call .getFunction ( ) , _, called , _) and
381420 called .functionAndOffset ( this , offset )
382421 |
422+ call .getArgByName ( name ) = result
423+ or
383424 exists ( int n |
384425 call .getArg ( n ) = result and
385- this .( PythonFunctionObjectInternal ) . getScope ( ) . getArg ( n + offset ) .getName ( ) = name
426+ this .getParameter ( n + offset ) .getId ( ) = name
386427 )
387428 or
388- call .getArgByName ( name ) = result and
389- exists ( this .( PythonFunctionObjectInternal ) .getScope ( ) .getArgByName ( name ) )
390- or
391429 called instanceof BoundMethodObjectInternal and
392430 offset = 1 and
393431 name = "self" and
@@ -396,6 +434,29 @@ class CallableValue extends Value {
396434 }
397435}
398436
437+ /**
438+ * Class representing bound-methods, such as `o.func`, where `o` is an instance
439+ * of a class that has a callable attribute `func`.
440+ */
441+ class BoundMethodValue extends CallableValue {
442+ BoundMethodValue ( ) { this instanceof BoundMethodObjectInternal }
443+
444+ /**
445+ * Gets the callable that will be used when `this` is called.
446+ * The actual callable for `func` in `o.func`.
447+ */
448+ CallableValue getFunction ( ) { result = this .( BoundMethodObjectInternal ) .getFunction ( ) }
449+
450+ /**
451+ * Gets the value that will be used for the `self` parameter when `this` is called.
452+ * The value for `o` in `o.func`.
453+ */
454+ Value getSelf ( ) { result = this .( BoundMethodObjectInternal ) .getSelf ( ) }
455+
456+ /** Gets the parameter node that will be used for `self`. */
457+ NameNode getSelfParameter ( ) { result = this .( BoundMethodObjectInternal ) .getSelfParameter ( ) }
458+ }
459+
399460/**
400461 * Class representing classes in the Python program, both Python and built-in.
401462 */
@@ -663,11 +724,13 @@ class PythonFunctionValue extends FunctionValue {
663724 ControlFlowNode getAReturnedNode ( ) { result = this .getScope ( ) .getAReturnValueFlowNode ( ) }
664725
665726 override ClassValue getARaisedType ( ) { scope_raises ( result , this .getScope ( ) ) }
666-
727+
667728 override ClassValue getAnInferredReturnType ( ) {
668- /* We have to do a special version of this because builtin functions have no
729+ /*
730+ * We have to do a special version of this because builtin functions have no
669731 * explicit return nodes that we can query and get the class of.
670732 */
733+
671734 result = this .getAReturnedNode ( ) .pointsTo ( ) .getClass ( )
672735 }
673736}
@@ -690,9 +753,11 @@ class BuiltinFunctionValue extends FunctionValue {
690753 }
691754
692755 override ClassValue getAnInferredReturnType ( ) {
693- /* We have to do a special version of this because builtin functions have no
756+ /*
757+ * We have to do a special version of this because builtin functions have no
694758 * explicit return nodes that we can query and get the class of.
695759 */
760+
696761 result = TBuiltinClassObject ( this .( BuiltinFunctionObjectInternal ) .getReturnType ( ) )
697762 }
698763}
@@ -719,7 +784,7 @@ class BuiltinMethodValue extends FunctionValue {
719784 /* Information is unavailable for C code in general */
720785 none ( )
721786 }
722-
787+
723788 override ClassValue getAnInferredReturnType ( ) {
724789 result = TBuiltinClassObject ( this .( BuiltinMethodObjectInternal ) .getReturnType ( ) )
725790 }
0 commit comments