@@ -352,7 +352,29 @@ class CallableValue extends Value {
352
352
result = this .( CallableObjectInternal ) .getParameterByName ( name )
353
353
}
354
354
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
+ */
356
378
cached
357
379
ControlFlowNode getArgumentForCall ( CallNode call , int n ) {
358
380
exists ( ObjectInternal called , int offset |
@@ -363,7 +385,7 @@ class CallableValue extends Value {
363
385
or
364
386
exists ( string name |
365
387
call .getArgByName ( name ) = result and
366
- this .( PythonFunctionObjectInternal ) . getScope ( ) . getArg ( n + offset ) . getName ( ) = name
388
+ this .getParameter ( n ) . getId ( ) = name
367
389
)
368
390
or
369
391
called instanceof BoundMethodObjectInternal and
@@ -373,21 +395,37 @@ class CallableValue extends Value {
373
395
)
374
396
}
375
397
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
+ */
377
416
cached
378
417
ControlFlowNode getNamedArgumentForCall ( CallNode call , string name ) {
379
418
exists ( CallableObjectInternal called , int offset |
380
419
PointsToInternal:: pointsTo ( call .getFunction ( ) , _, called , _) and
381
420
called .functionAndOffset ( this , offset )
382
421
|
422
+ call .getArgByName ( name ) = result
423
+ or
383
424
exists ( int n |
384
425
call .getArg ( n ) = result and
385
- this .( PythonFunctionObjectInternal ) . getScope ( ) . getArg ( n + offset ) .getName ( ) = name
426
+ this .getParameter ( n + offset ) .getId ( ) = name
386
427
)
387
428
or
388
- call .getArgByName ( name ) = result and
389
- exists ( this .( PythonFunctionObjectInternal ) .getScope ( ) .getArgByName ( name ) )
390
- or
391
429
called instanceof BoundMethodObjectInternal and
392
430
offset = 1 and
393
431
name = "self" and
@@ -396,6 +434,29 @@ class CallableValue extends Value {
396
434
}
397
435
}
398
436
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
+
399
460
/**
400
461
* Class representing classes in the Python program, both Python and built-in.
401
462
*/
@@ -663,11 +724,13 @@ class PythonFunctionValue extends FunctionValue {
663
724
ControlFlowNode getAReturnedNode ( ) { result = this .getScope ( ) .getAReturnValueFlowNode ( ) }
664
725
665
726
override ClassValue getARaisedType ( ) { scope_raises ( result , this .getScope ( ) ) }
666
-
727
+
667
728
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
669
731
* explicit return nodes that we can query and get the class of.
670
732
*/
733
+
671
734
result = this .getAReturnedNode ( ) .pointsTo ( ) .getClass ( )
672
735
}
673
736
}
@@ -690,9 +753,11 @@ class BuiltinFunctionValue extends FunctionValue {
690
753
}
691
754
692
755
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
694
758
* explicit return nodes that we can query and get the class of.
695
759
*/
760
+
696
761
result = TBuiltinClassObject ( this .( BuiltinFunctionObjectInternal ) .getReturnType ( ) )
697
762
}
698
763
}
@@ -719,7 +784,7 @@ class BuiltinMethodValue extends FunctionValue {
719
784
/* Information is unavailable for C code in general */
720
785
none ( )
721
786
}
722
-
787
+
723
788
override ClassValue getAnInferredReturnType ( ) {
724
789
result = TBuiltinClassObject ( this .( BuiltinMethodObjectInternal ) .getReturnType ( ) )
725
790
}
0 commit comments