@@ -430,6 +430,29 @@ class ClassValue extends Value {
430
430
this .hasAttribute ( "__getitem__" )
431
431
}
432
432
433
+ /** Holds if this class is an iterator. */
434
+ predicate isIterator ( ) {
435
+ this .hasAttribute ( "__iter__" ) and
436
+ (
437
+ major_version ( ) = 3 and this .hasAttribute ( "__next__" )
438
+ or
439
+ /*
440
+ * Because 'next' is a common method name we need to check that an __iter__
441
+ * method actually returns this class. This is not needed for Py3 as the
442
+ * '__next__' method exists to define a class as an iterator.
443
+ */
444
+
445
+ major_version ( ) = 2 and
446
+ this .hasAttribute ( "next" ) and
447
+ exists ( ClassValue other , FunctionValue iter | other .declaredAttribute ( "__iter__" ) = iter |
448
+ iter .getAnInferredReturnType ( ) = this
449
+ )
450
+ )
451
+ or
452
+ /* This will be redundant when we have C class information */
453
+ this = ClassValue:: generator ( )
454
+ }
455
+
433
456
/** Holds if this class is a container(). That is, does it have a __getitem__ method. */
434
457
predicate isContainer ( ) { exists ( this .lookup ( "__getitem__" ) ) }
435
458
@@ -583,11 +606,7 @@ abstract class FunctionValue extends CallableValue {
583
606
}
584
607
585
608
/** Gets a class that this function may return */
586
- ClassValue getAnInferredReturnType ( ) {
587
- result = TBuiltinClassObject ( this .( BuiltinFunctionObjectInternal ) .getReturnType ( ) )
588
- or
589
- result = TBuiltinClassObject ( this .( BuiltinMethodObjectInternal ) .getReturnType ( ) )
590
- }
609
+ abstract ClassValue getAnInferredReturnType ( ) ;
591
610
}
592
611
593
612
/** Class representing Python functions */
@@ -616,6 +635,13 @@ class PythonFunctionValue extends FunctionValue {
616
635
617
636
/** Gets a control flow node corresponding to a return statement in this function */
618
637
ControlFlowNode getAReturnedNode ( ) { result = this .getScope ( ) .getAReturnValueFlowNode ( ) }
638
+
639
+ override ClassValue getAnInferredReturnType ( ) {
640
+ /* We have to do a special version of this because builtin functions have no
641
+ * explicit return nodes that we can query and get the class of.
642
+ */
643
+ result = this .getAReturnedNode ( ) .pointsTo ( ) .getClass ( )
644
+ }
619
645
}
620
646
621
647
/** Class representing builtin functions, such as `len` or `print` */
@@ -627,6 +653,13 @@ class BuiltinFunctionValue extends FunctionValue {
627
653
override int minParameters ( ) { none ( ) }
628
654
629
655
override int maxParameters ( ) { none ( ) }
656
+
657
+ override ClassValue getAnInferredReturnType ( ) {
658
+ /* We have to do a special version of this because builtin functions have no
659
+ * explicit return nodes that we can query and get the class of.
660
+ */
661
+ result = TBuiltinClassObject ( this .( BuiltinFunctionObjectInternal ) .getReturnType ( ) )
662
+ }
630
663
}
631
664
632
665
/** Class representing builtin methods, such as `list.append` or `set.add` */
@@ -644,6 +677,10 @@ class BuiltinMethodValue extends FunctionValue {
644
677
override int minParameters ( ) { none ( ) }
645
678
646
679
override int maxParameters ( ) { none ( ) }
680
+
681
+ override ClassValue getAnInferredReturnType ( ) {
682
+ result = TBuiltinClassObject ( this .( BuiltinMethodObjectInternal ) .getReturnType ( ) )
683
+ }
647
684
}
648
685
649
686
/**
0 commit comments